mirror of https://github.com/astral-sh/ruff
[ty] Add tests for implicit submodule references (#21793)
## Summary I realized we don't really test `DefinitionKind::ImportFromSubmodule` in the IDE at all, so here's a bunch of them, just recording our current behaviour. ## Test Plan *stares at the camera*
This commit is contained in:
parent
9d4f1c6ae2
commit
cccb0bbaa4
|
|
@ -1906,4 +1906,211 @@ func<CURSOR>_alias()
|
||||||
|
|
|
|
||||||
");
|
");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn references_submodule_import_from_use() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"mypackage/__init__.py",
|
||||||
|
r#"
|
||||||
|
from .subpkg.submod import val
|
||||||
|
|
||||||
|
x = sub<CURSOR>pkg
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source("mypackage/subpkg/__init__.py", r#""#)
|
||||||
|
.source(
|
||||||
|
"mypackage/subpkg/submod.py",
|
||||||
|
r#"
|
||||||
|
val: int = 0
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// TODO(submodule-imports): this should light up both instances of `subpkg`
|
||||||
|
assert_snapshot!(test.references(), @r"
|
||||||
|
info[references]: Reference 1
|
||||||
|
--> mypackage/__init__.py:4:5
|
||||||
|
|
|
||||||
|
2 | from .subpkg.submod import val
|
||||||
|
3 |
|
||||||
|
4 | x = subpkg
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn references_submodule_import_from_def() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"mypackage/__init__.py",
|
||||||
|
r#"
|
||||||
|
from .sub<CURSOR>pkg.submod import val
|
||||||
|
|
||||||
|
x = subpkg
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source("mypackage/subpkg/__init__.py", r#""#)
|
||||||
|
.source(
|
||||||
|
"mypackage/subpkg/submod.py",
|
||||||
|
r#"
|
||||||
|
val: int = 0
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// TODO(submodule-imports): this should light up both instances of `subpkg`
|
||||||
|
assert_snapshot!(test.references(), @"No references found");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn references_submodule_import_from_wrong_use() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"mypackage/__init__.py",
|
||||||
|
r#"
|
||||||
|
from .subpkg.submod import val
|
||||||
|
|
||||||
|
x = sub<CURSOR>mod
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source("mypackage/subpkg/__init__.py", r#""#)
|
||||||
|
.source(
|
||||||
|
"mypackage/subpkg/submod.py",
|
||||||
|
r#"
|
||||||
|
val: int = 0
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// No references is actually correct (or it should only see itself)
|
||||||
|
assert_snapshot!(test.references(), @"No references found");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn references_submodule_import_from_wrong_def() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"mypackage/__init__.py",
|
||||||
|
r#"
|
||||||
|
from .subpkg.sub<CURSOR>mod import val
|
||||||
|
|
||||||
|
x = submod
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source("mypackage/subpkg/__init__.py", r#""#)
|
||||||
|
.source(
|
||||||
|
"mypackage/subpkg/submod.py",
|
||||||
|
r#"
|
||||||
|
val: int = 0
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// No references is actually correct (or it should only see itself)
|
||||||
|
assert_snapshot!(test.references(), @"No references found");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn references_submodule_import_from_confusing_shadowed_def() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"mypackage/__init__.py",
|
||||||
|
r#"
|
||||||
|
from .sub<CURSOR>pkg import subpkg
|
||||||
|
|
||||||
|
x = subpkg
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mypackage/subpkg/__init__.py",
|
||||||
|
r#"
|
||||||
|
subpkg: int = 10
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// No references is actually correct (or it should only see itself)
|
||||||
|
assert_snapshot!(test.references(), @"No references found");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn references_submodule_import_from_confusing_real_def() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"mypackage/__init__.py",
|
||||||
|
r#"
|
||||||
|
from .subpkg import sub<CURSOR>pkg
|
||||||
|
|
||||||
|
x = subpkg
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mypackage/subpkg/__init__.py",
|
||||||
|
r#"
|
||||||
|
subpkg: int = 10
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assert_snapshot!(test.references(), @r"
|
||||||
|
info[references]: Reference 1
|
||||||
|
--> mypackage/__init__.py:2:21
|
||||||
|
|
|
||||||
|
2 | from .subpkg import subpkg
|
||||||
|
| ^^^^^^
|
||||||
|
3 |
|
||||||
|
4 | x = subpkg
|
||||||
|
|
|
||||||
|
|
||||||
|
info[references]: Reference 2
|
||||||
|
--> mypackage/__init__.py:4:5
|
||||||
|
|
|
||||||
|
2 | from .subpkg import subpkg
|
||||||
|
3 |
|
||||||
|
4 | x = subpkg
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
|
||||||
|
info[references]: Reference 3
|
||||||
|
--> mypackage/subpkg/__init__.py:2:1
|
||||||
|
|
|
||||||
|
2 | subpkg: int = 10
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn references_submodule_import_from_confusing_use() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"mypackage/__init__.py",
|
||||||
|
r#"
|
||||||
|
from .subpkg import subpkg
|
||||||
|
|
||||||
|
x = sub<CURSOR>pkg
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mypackage/subpkg/__init__.py",
|
||||||
|
r#"
|
||||||
|
subpkg: int = 10
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// TODO: this should also highlight the RHS subpkg in the import
|
||||||
|
assert_snapshot!(test.references(), @r"
|
||||||
|
info[references]: Reference 1
|
||||||
|
--> mypackage/__init__.py:4:5
|
||||||
|
|
|
||||||
|
2 | from .subpkg import subpkg
|
||||||
|
3 |
|
||||||
|
4 | x = subpkg
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2602,6 +2602,298 @@ def ab(a: int, *, c: int): ...
|
||||||
");
|
");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn goto_declaration_submodule_import_from_use() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"mypackage/__init__.py",
|
||||||
|
r#"
|
||||||
|
from .subpkg.submod import val
|
||||||
|
|
||||||
|
x = sub<CURSOR>pkg
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source("mypackage/subpkg/__init__.py", r#""#)
|
||||||
|
.source(
|
||||||
|
"mypackage/subpkg/submod.py",
|
||||||
|
r#"
|
||||||
|
val: int = 0
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// TODO(submodule-imports): this should only highlight `subpkg` in the import statement
|
||||||
|
// This happens because DefinitionKind::ImportFromSubmodule claims the entire ImportFrom node,
|
||||||
|
// which is correct but unhelpful. Unfortunately even if it only claimed the LHS identifier it
|
||||||
|
// would highlight `subpkg.submod` which is strictly better but still isn't what we want.
|
||||||
|
assert_snapshot!(test.goto_declaration(), @r"
|
||||||
|
info[goto-declaration]: Declaration
|
||||||
|
--> mypackage/__init__.py:2:1
|
||||||
|
|
|
||||||
|
2 | from .subpkg.submod import val
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
3 |
|
||||||
|
4 | x = subpkg
|
||||||
|
|
|
||||||
|
info: Source
|
||||||
|
--> mypackage/__init__.py:4:5
|
||||||
|
|
|
||||||
|
2 | from .subpkg.submod import val
|
||||||
|
3 |
|
||||||
|
4 | x = subpkg
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn goto_declaration_submodule_import_from_def() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"mypackage/__init__.py",
|
||||||
|
r#"
|
||||||
|
from .sub<CURSOR>pkg.submod import val
|
||||||
|
|
||||||
|
x = subpkg
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source("mypackage/subpkg/__init__.py", r#""#)
|
||||||
|
.source(
|
||||||
|
"mypackage/subpkg/submod.py",
|
||||||
|
r#"
|
||||||
|
val: int = 0
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// TODO(submodule-imports): I don't *think* this is what we want..?
|
||||||
|
// It's a bit confusing because this symbol is essentially the LHS *and* RHS of
|
||||||
|
// `subpkg = mypackage.subpkg`. As in, it's both defining a local `subpkg` and
|
||||||
|
// loading the module `mypackage.subpkg`, so, it's understandable to get confused!
|
||||||
|
assert_snapshot!(test.goto_declaration(), @r"
|
||||||
|
info[goto-declaration]: Declaration
|
||||||
|
--> mypackage/subpkg/__init__.py:1:1
|
||||||
|
|
|
||||||
|
|
|
||||||
|
info: Source
|
||||||
|
--> mypackage/__init__.py:2:7
|
||||||
|
|
|
||||||
|
2 | from .subpkg.submod import val
|
||||||
|
| ^^^^^^
|
||||||
|
3 |
|
||||||
|
4 | x = subpkg
|
||||||
|
|
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn goto_declaration_submodule_import_from_wrong_use() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"mypackage/__init__.py",
|
||||||
|
r#"
|
||||||
|
from .subpkg.submod import val
|
||||||
|
|
||||||
|
x = sub<CURSOR>mod
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source("mypackage/subpkg/__init__.py", r#""#)
|
||||||
|
.source(
|
||||||
|
"mypackage/subpkg/submod.py",
|
||||||
|
r#"
|
||||||
|
val: int = 0
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// No result is correct!
|
||||||
|
assert_snapshot!(test.goto_declaration(), @"No goto target found");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn goto_declaration_submodule_import_from_wrong_def() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"mypackage/__init__.py",
|
||||||
|
r#"
|
||||||
|
from .subpkg.sub<CURSOR>mod import val
|
||||||
|
|
||||||
|
x = submod
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source("mypackage/subpkg/__init__.py", r#""#)
|
||||||
|
.source(
|
||||||
|
"mypackage/subpkg/submod.py",
|
||||||
|
r#"
|
||||||
|
val: int = 0
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Going to the submod module is correct!
|
||||||
|
assert_snapshot!(test.goto_declaration(), @r"
|
||||||
|
info[goto-declaration]: Declaration
|
||||||
|
--> mypackage/subpkg/submod.py:1:1
|
||||||
|
|
|
||||||
|
1 |
|
||||||
|
| ^
|
||||||
|
2 | val: int = 0
|
||||||
|
|
|
||||||
|
info: Source
|
||||||
|
--> mypackage/__init__.py:2:14
|
||||||
|
|
|
||||||
|
2 | from .subpkg.submod import val
|
||||||
|
| ^^^^^^
|
||||||
|
3 |
|
||||||
|
4 | x = submod
|
||||||
|
|
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn goto_declaration_submodule_import_from_confusing_shadowed_def() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"mypackage/__init__.py",
|
||||||
|
r#"
|
||||||
|
from .sub<CURSOR>pkg import subpkg
|
||||||
|
|
||||||
|
x = subpkg
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mypackage/subpkg/__init__.py",
|
||||||
|
r#"
|
||||||
|
subpkg: int = 10
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Going to the subpkg module is correct!
|
||||||
|
assert_snapshot!(test.goto_declaration(), @r"
|
||||||
|
info[goto-declaration]: Declaration
|
||||||
|
--> mypackage/subpkg/__init__.py:1:1
|
||||||
|
|
|
||||||
|
1 |
|
||||||
|
| ^
|
||||||
|
2 | subpkg: int = 10
|
||||||
|
|
|
||||||
|
info: Source
|
||||||
|
--> mypackage/__init__.py:2:7
|
||||||
|
|
|
||||||
|
2 | from .subpkg import subpkg
|
||||||
|
| ^^^^^^
|
||||||
|
3 |
|
||||||
|
4 | x = subpkg
|
||||||
|
|
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn goto_declaration_submodule_import_from_confusing_real_def() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"mypackage/__init__.py",
|
||||||
|
r#"
|
||||||
|
from .subpkg import sub<CURSOR>pkg
|
||||||
|
|
||||||
|
x = subpkg
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mypackage/subpkg/__init__.py",
|
||||||
|
r#"
|
||||||
|
subpkg: int = 10
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Going to the subpkg `int` is correct!
|
||||||
|
assert_snapshot!(test.goto_declaration(), @r"
|
||||||
|
info[goto-declaration]: Declaration
|
||||||
|
--> mypackage/subpkg/__init__.py:2:1
|
||||||
|
|
|
||||||
|
2 | subpkg: int = 10
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
info: Source
|
||||||
|
--> mypackage/__init__.py:2:21
|
||||||
|
|
|
||||||
|
2 | from .subpkg import subpkg
|
||||||
|
| ^^^^^^
|
||||||
|
3 |
|
||||||
|
4 | x = subpkg
|
||||||
|
|
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn goto_declaration_submodule_import_from_confusing_use() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"mypackage/__init__.py",
|
||||||
|
r#"
|
||||||
|
from .subpkg import subpkg
|
||||||
|
|
||||||
|
x = sub<CURSOR>pkg
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mypackage/subpkg/__init__.py",
|
||||||
|
r#"
|
||||||
|
subpkg: int = 10
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// TODO(submodule-imports): Ok this one is FASCINATING and it's kinda right but confusing!
|
||||||
|
//
|
||||||
|
// So there's 3 relevant definitions here:
|
||||||
|
//
|
||||||
|
// * `subpkg: int = 10` in the other file is in fact the original definition
|
||||||
|
//
|
||||||
|
// * the LHS `subpkg` in the import is an instance of `subpkg = ...`
|
||||||
|
// because it's a `DefinitionKind::ImportFromSubmodle`.
|
||||||
|
// This is the span that covers the entire import.
|
||||||
|
//
|
||||||
|
// * `the RHS `subpkg` in the import is a second instance of `subpkg = ...`
|
||||||
|
// that *immediately* overwrites the `ImportFromSubmodule`'s definition
|
||||||
|
// This span seemingly doesn't appear at all!? Is it getting hidden by the LHS span?
|
||||||
|
assert_snapshot!(test.goto_declaration(), @r"
|
||||||
|
info[goto-declaration]: Declaration
|
||||||
|
--> mypackage/__init__.py:2:1
|
||||||
|
|
|
||||||
|
2 | from .subpkg import subpkg
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
3 |
|
||||||
|
4 | x = subpkg
|
||||||
|
|
|
||||||
|
info: Source
|
||||||
|
--> mypackage/__init__.py:4:5
|
||||||
|
|
|
||||||
|
2 | from .subpkg import subpkg
|
||||||
|
3 |
|
||||||
|
4 | x = subpkg
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
|
||||||
|
info[goto-declaration]: Declaration
|
||||||
|
--> mypackage/subpkg/__init__.py:2:1
|
||||||
|
|
|
||||||
|
2 | subpkg: int = 10
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
info: Source
|
||||||
|
--> mypackage/__init__.py:4:5
|
||||||
|
|
|
||||||
|
2 | from .subpkg import subpkg
|
||||||
|
3 |
|
||||||
|
4 | x = subpkg
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
impl CursorTest {
|
impl CursorTest {
|
||||||
fn goto_declaration(&self) -> String {
|
fn goto_declaration(&self) -> String {
|
||||||
let Some(targets) = goto_declaration(&self.db, self.cursor.file, self.cursor.offset)
|
let Some(targets) = goto_declaration(&self.db, self.cursor.file, self.cursor.offset)
|
||||||
|
|
|
||||||
|
|
@ -1672,6 +1672,283 @@ def function():
|
||||||
"#);
|
"#);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn goto_type_submodule_import_from_use() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"mypackage/__init__.py",
|
||||||
|
r#"
|
||||||
|
from .subpkg.submod import val
|
||||||
|
|
||||||
|
x = sub<CURSOR>pkg
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source("mypackage/subpkg/__init__.py", r#""#)
|
||||||
|
.source(
|
||||||
|
"mypackage/subpkg/submod.py",
|
||||||
|
r#"
|
||||||
|
val: int = 0
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// The module is the correct type definition
|
||||||
|
assert_snapshot!(test.goto_type_definition(), @r"
|
||||||
|
info[goto-type-definition]: Type definition
|
||||||
|
--> mypackage/subpkg/__init__.py:1:1
|
||||||
|
|
|
||||||
|
|
|
||||||
|
info: Source
|
||||||
|
--> mypackage/__init__.py:4:5
|
||||||
|
|
|
||||||
|
2 | from .subpkg.submod import val
|
||||||
|
3 |
|
||||||
|
4 | x = subpkg
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn goto_type_submodule_import_from_def() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"mypackage/__init__.py",
|
||||||
|
r#"
|
||||||
|
from .sub<CURSOR>pkg.submod import val
|
||||||
|
|
||||||
|
x = subpkg
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source("mypackage/subpkg/__init__.py", r#""#)
|
||||||
|
.source(
|
||||||
|
"mypackage/subpkg/submod.py",
|
||||||
|
r#"
|
||||||
|
val: int = 0
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// The module is the correct type definition
|
||||||
|
assert_snapshot!(test.goto_type_definition(), @r"
|
||||||
|
info[goto-type-definition]: Type definition
|
||||||
|
--> mypackage/subpkg/__init__.py:1:1
|
||||||
|
|
|
||||||
|
|
|
||||||
|
info: Source
|
||||||
|
--> mypackage/__init__.py:2:7
|
||||||
|
|
|
||||||
|
2 | from .subpkg.submod import val
|
||||||
|
| ^^^^^^
|
||||||
|
3 |
|
||||||
|
4 | x = subpkg
|
||||||
|
|
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn goto_type_submodule_import_from_wrong_use() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"mypackage/__init__.py",
|
||||||
|
r#"
|
||||||
|
from .subpkg.submod import val
|
||||||
|
|
||||||
|
x = sub<CURSOR>mod
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source("mypackage/subpkg/__init__.py", r#""#)
|
||||||
|
.source(
|
||||||
|
"mypackage/subpkg/submod.py",
|
||||||
|
r#"
|
||||||
|
val: int = 0
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Unknown is correct, `submod` is not in scope
|
||||||
|
assert_snapshot!(test.goto_type_definition(), @r"
|
||||||
|
info[goto-type-definition]: Type definition
|
||||||
|
--> stdlib/ty_extensions.pyi:20:1
|
||||||
|
|
|
||||||
|
19 | # Types
|
||||||
|
20 | Unknown = object()
|
||||||
|
| ^^^^^^^
|
||||||
|
21 | AlwaysTruthy = object()
|
||||||
|
22 | AlwaysFalsy = object()
|
||||||
|
|
|
||||||
|
info: Source
|
||||||
|
--> mypackage/__init__.py:4:5
|
||||||
|
|
|
||||||
|
2 | from .subpkg.submod import val
|
||||||
|
3 |
|
||||||
|
4 | x = submod
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn goto_type_submodule_import_from_wrong_def() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"mypackage/__init__.py",
|
||||||
|
r#"
|
||||||
|
from .subpkg.sub<CURSOR>mod import val
|
||||||
|
|
||||||
|
x = submod
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source("mypackage/subpkg/__init__.py", r#""#)
|
||||||
|
.source(
|
||||||
|
"mypackage/subpkg/submod.py",
|
||||||
|
r#"
|
||||||
|
val: int = 0
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// The module is correct
|
||||||
|
assert_snapshot!(test.goto_type_definition(), @r"
|
||||||
|
info[goto-type-definition]: Type definition
|
||||||
|
--> mypackage/subpkg/submod.py:1:1
|
||||||
|
|
|
||||||
|
1 | /
|
||||||
|
2 | | val: int = 0
|
||||||
|
| |_____________^
|
||||||
|
|
|
||||||
|
info: Source
|
||||||
|
--> mypackage/__init__.py:2:14
|
||||||
|
|
|
||||||
|
2 | from .subpkg.submod import val
|
||||||
|
| ^^^^^^
|
||||||
|
3 |
|
||||||
|
4 | x = submod
|
||||||
|
|
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn goto_type_submodule_import_from_confusing_shadowed_def() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"mypackage/__init__.py",
|
||||||
|
r#"
|
||||||
|
from .sub<CURSOR>pkg import subpkg
|
||||||
|
|
||||||
|
x = subpkg
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mypackage/subpkg/__init__.py",
|
||||||
|
r#"
|
||||||
|
subpkg: int = 10
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// The module is correct
|
||||||
|
assert_snapshot!(test.goto_type_definition(), @r"
|
||||||
|
info[goto-type-definition]: Type definition
|
||||||
|
--> mypackage/subpkg/__init__.py:1:1
|
||||||
|
|
|
||||||
|
1 | /
|
||||||
|
2 | | subpkg: int = 10
|
||||||
|
| |_________________^
|
||||||
|
|
|
||||||
|
info: Source
|
||||||
|
--> mypackage/__init__.py:2:7
|
||||||
|
|
|
||||||
|
2 | from .subpkg import subpkg
|
||||||
|
| ^^^^^^
|
||||||
|
3 |
|
||||||
|
4 | x = subpkg
|
||||||
|
|
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn goto_type_submodule_import_from_confusing_real_def() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"mypackage/__init__.py",
|
||||||
|
r#"
|
||||||
|
from .subpkg import sub<CURSOR>pkg
|
||||||
|
|
||||||
|
x = subpkg
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mypackage/subpkg/__init__.py",
|
||||||
|
r#"
|
||||||
|
subpkg: int = 10
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// `int` is correct
|
||||||
|
assert_snapshot!(test.goto_type_definition(), @r#"
|
||||||
|
info[goto-type-definition]: Type definition
|
||||||
|
--> stdlib/builtins.pyi:348:7
|
||||||
|
|
|
||||||
|
347 | @disjoint_base
|
||||||
|
348 | class int:
|
||||||
|
| ^^^
|
||||||
|
349 | """int([x]) -> integer
|
||||||
|
350 | int(x, base=10) -> integer
|
||||||
|
|
|
||||||
|
info: Source
|
||||||
|
--> mypackage/__init__.py:2:21
|
||||||
|
|
|
||||||
|
2 | from .subpkg import subpkg
|
||||||
|
| ^^^^^^
|
||||||
|
3 |
|
||||||
|
4 | x = subpkg
|
||||||
|
|
|
||||||
|
"#);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn goto_type_submodule_import_from_confusing_use() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"mypackage/__init__.py",
|
||||||
|
r#"
|
||||||
|
from .subpkg import subpkg
|
||||||
|
|
||||||
|
x = sub<CURSOR>pkg
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mypackage/subpkg/__init__.py",
|
||||||
|
r#"
|
||||||
|
subpkg: int = 10
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// `int` is correct
|
||||||
|
assert_snapshot!(test.goto_type_definition(), @r#"
|
||||||
|
info[goto-type-definition]: Type definition
|
||||||
|
--> stdlib/builtins.pyi:348:7
|
||||||
|
|
|
||||||
|
347 | @disjoint_base
|
||||||
|
348 | class int:
|
||||||
|
| ^^^
|
||||||
|
349 | """int([x]) -> integer
|
||||||
|
350 | int(x, base=10) -> integer
|
||||||
|
|
|
||||||
|
info: Source
|
||||||
|
--> mypackage/__init__.py:4:5
|
||||||
|
|
|
||||||
|
2 | from .subpkg import subpkg
|
||||||
|
3 |
|
||||||
|
4 | x = subpkg
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
"#);
|
||||||
|
}
|
||||||
|
|
||||||
impl CursorTest {
|
impl CursorTest {
|
||||||
fn goto_type_definition(&self) -> String {
|
fn goto_type_definition(&self) -> String {
|
||||||
let Some(targets) =
|
let Some(targets) =
|
||||||
|
|
|
||||||
|
|
@ -3321,6 +3321,297 @@ def function():
|
||||||
");
|
");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn hover_submodule_import_from_use() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"mypackage/__init__.py",
|
||||||
|
r#"
|
||||||
|
from .subpkg.submod import val
|
||||||
|
|
||||||
|
x = sub<CURSOR>pkg
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source("mypackage/subpkg/__init__.py", r#""#)
|
||||||
|
.source(
|
||||||
|
"mypackage/subpkg/submod.py",
|
||||||
|
r#"
|
||||||
|
val: int = 0
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// The module is correct
|
||||||
|
assert_snapshot!(test.hover(), @r"
|
||||||
|
<module 'mypackage.subpkg'>
|
||||||
|
---------------------------------------------
|
||||||
|
```python
|
||||||
|
<module 'mypackage.subpkg'>
|
||||||
|
```
|
||||||
|
---------------------------------------------
|
||||||
|
info[hover]: Hovered content is
|
||||||
|
--> mypackage/__init__.py:4:5
|
||||||
|
|
|
||||||
|
2 | from .subpkg.submod import val
|
||||||
|
3 |
|
||||||
|
4 | x = subpkg
|
||||||
|
| ^^^-^^
|
||||||
|
| | |
|
||||||
|
| | Cursor offset
|
||||||
|
| source
|
||||||
|
|
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn hover_submodule_import_from_def() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"mypackage/__init__.py",
|
||||||
|
r#"
|
||||||
|
from .sub<CURSOR>pkg.submod import val
|
||||||
|
|
||||||
|
x = subpkg
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source("mypackage/subpkg/__init__.py", r#""#)
|
||||||
|
.source(
|
||||||
|
"mypackage/subpkg/submod.py",
|
||||||
|
r#"
|
||||||
|
val: int = 0
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// The module is correct
|
||||||
|
assert_snapshot!(test.hover(), @r"
|
||||||
|
<module 'mypackage.subpkg'>
|
||||||
|
---------------------------------------------
|
||||||
|
```python
|
||||||
|
<module 'mypackage.subpkg'>
|
||||||
|
```
|
||||||
|
---------------------------------------------
|
||||||
|
info[hover]: Hovered content is
|
||||||
|
--> mypackage/__init__.py:2:7
|
||||||
|
|
|
||||||
|
2 | from .subpkg.submod import val
|
||||||
|
| ^^^-^^
|
||||||
|
| | |
|
||||||
|
| | Cursor offset
|
||||||
|
| source
|
||||||
|
3 |
|
||||||
|
4 | x = subpkg
|
||||||
|
|
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn hover_submodule_import_from_wrong_use() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"mypackage/__init__.py",
|
||||||
|
r#"
|
||||||
|
from .subpkg.submod import val
|
||||||
|
|
||||||
|
x = sub<CURSOR>mod
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source("mypackage/subpkg/__init__.py", r#""#)
|
||||||
|
.source(
|
||||||
|
"mypackage/subpkg/submod.py",
|
||||||
|
r#"
|
||||||
|
val: int = 0
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Unknown is correct
|
||||||
|
assert_snapshot!(test.hover(), @r"
|
||||||
|
Unknown
|
||||||
|
---------------------------------------------
|
||||||
|
```python
|
||||||
|
Unknown
|
||||||
|
```
|
||||||
|
---------------------------------------------
|
||||||
|
info[hover]: Hovered content is
|
||||||
|
--> mypackage/__init__.py:4:5
|
||||||
|
|
|
||||||
|
2 | from .subpkg.submod import val
|
||||||
|
3 |
|
||||||
|
4 | x = submod
|
||||||
|
| ^^^-^^
|
||||||
|
| | |
|
||||||
|
| | Cursor offset
|
||||||
|
| source
|
||||||
|
|
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn hover_submodule_import_from_wrong_def() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"mypackage/__init__.py",
|
||||||
|
r#"
|
||||||
|
from .subpkg.sub<CURSOR>mod import val
|
||||||
|
|
||||||
|
x = submod
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source("mypackage/subpkg/__init__.py", r#""#)
|
||||||
|
.source(
|
||||||
|
"mypackage/subpkg/submod.py",
|
||||||
|
r#"
|
||||||
|
val: int = 0
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// The submodule is correct
|
||||||
|
assert_snapshot!(test.hover(), @r"
|
||||||
|
<module 'mypackage.subpkg.submod'>
|
||||||
|
---------------------------------------------
|
||||||
|
```python
|
||||||
|
<module 'mypackage.subpkg.submod'>
|
||||||
|
```
|
||||||
|
---------------------------------------------
|
||||||
|
info[hover]: Hovered content is
|
||||||
|
--> mypackage/__init__.py:2:14
|
||||||
|
|
|
||||||
|
2 | from .subpkg.submod import val
|
||||||
|
| ^^^-^^
|
||||||
|
| | |
|
||||||
|
| | Cursor offset
|
||||||
|
| source
|
||||||
|
3 |
|
||||||
|
4 | x = submod
|
||||||
|
|
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn hover_submodule_import_from_confusing_shadowed_def() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"mypackage/__init__.py",
|
||||||
|
r#"
|
||||||
|
from .sub<CURSOR>pkg import subpkg
|
||||||
|
|
||||||
|
x = subpkg
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mypackage/subpkg/__init__.py",
|
||||||
|
r#"
|
||||||
|
subpkg: int = 10
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// The module is correct
|
||||||
|
assert_snapshot!(test.hover(), @r"
|
||||||
|
<module 'mypackage.subpkg'>
|
||||||
|
---------------------------------------------
|
||||||
|
```python
|
||||||
|
<module 'mypackage.subpkg'>
|
||||||
|
```
|
||||||
|
---------------------------------------------
|
||||||
|
info[hover]: Hovered content is
|
||||||
|
--> mypackage/__init__.py:2:7
|
||||||
|
|
|
||||||
|
2 | from .subpkg import subpkg
|
||||||
|
| ^^^-^^
|
||||||
|
| | |
|
||||||
|
| | Cursor offset
|
||||||
|
| source
|
||||||
|
3 |
|
||||||
|
4 | x = subpkg
|
||||||
|
|
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn hover_submodule_import_from_confusing_real_def() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"mypackage/__init__.py",
|
||||||
|
r#"
|
||||||
|
from .subpkg import sub<CURSOR>pkg
|
||||||
|
|
||||||
|
x = subpkg
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mypackage/subpkg/__init__.py",
|
||||||
|
r#"
|
||||||
|
subpkg: int = 10
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// int is correct
|
||||||
|
assert_snapshot!(test.hover(), @r"
|
||||||
|
int
|
||||||
|
---------------------------------------------
|
||||||
|
```python
|
||||||
|
int
|
||||||
|
```
|
||||||
|
---------------------------------------------
|
||||||
|
info[hover]: Hovered content is
|
||||||
|
--> mypackage/__init__.py:2:21
|
||||||
|
|
|
||||||
|
2 | from .subpkg import subpkg
|
||||||
|
| ^^^-^^
|
||||||
|
| | |
|
||||||
|
| | Cursor offset
|
||||||
|
| source
|
||||||
|
3 |
|
||||||
|
4 | x = subpkg
|
||||||
|
|
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn hover_submodule_import_from_confusing_use() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"mypackage/__init__.py",
|
||||||
|
r#"
|
||||||
|
from .subpkg import subpkg
|
||||||
|
|
||||||
|
x = sub<CURSOR>pkg
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mypackage/subpkg/__init__.py",
|
||||||
|
r#"
|
||||||
|
subpkg: int = 10
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// int is correct
|
||||||
|
assert_snapshot!(test.hover(), @r"
|
||||||
|
int
|
||||||
|
---------------------------------------------
|
||||||
|
```python
|
||||||
|
int
|
||||||
|
```
|
||||||
|
---------------------------------------------
|
||||||
|
info[hover]: Hovered content is
|
||||||
|
--> mypackage/__init__.py:4:5
|
||||||
|
|
|
||||||
|
2 | from .subpkg import subpkg
|
||||||
|
3 |
|
||||||
|
4 | x = subpkg
|
||||||
|
| ^^^-^^
|
||||||
|
| | |
|
||||||
|
| | Cursor offset
|
||||||
|
| source
|
||||||
|
|
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
impl CursorTest {
|
impl CursorTest {
|
||||||
fn hover(&self) -> String {
|
fn hover(&self) -> String {
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
|
|
||||||
|
|
@ -1223,4 +1223,207 @@ result = func(10, y=20)
|
||||||
|
|
||||||
assert_snapshot!(test.rename("z"), @"Cannot rename");
|
assert_snapshot!(test.rename("z"), @"Cannot rename");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rename_submodule_import_from_use() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"mypackage/__init__.py",
|
||||||
|
r#"
|
||||||
|
from .subpkg.submod import val
|
||||||
|
|
||||||
|
x = sub<CURSOR>pkg
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source("mypackage/subpkg/__init__.py", r#""#)
|
||||||
|
.source(
|
||||||
|
"mypackage/subpkg/submod.py",
|
||||||
|
r#"
|
||||||
|
val: int = 0
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// TODO(submodule-imports): we should refuse to rename this (it's the name of a module)
|
||||||
|
assert_snapshot!(test.rename("mypkg"), @r"
|
||||||
|
info[rename]: Rename symbol (found 1 locations)
|
||||||
|
--> mypackage/__init__.py:4:5
|
||||||
|
|
|
||||||
|
2 | from .subpkg.submod import val
|
||||||
|
3 |
|
||||||
|
4 | x = subpkg
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rename_submodule_import_from_def() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"mypackage/__init__.py",
|
||||||
|
r#"
|
||||||
|
from .sub<CURSOR>pkg.submod import val
|
||||||
|
|
||||||
|
x = subpkg
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source("mypackage/subpkg/__init__.py", r#""#)
|
||||||
|
.source(
|
||||||
|
"mypackage/subpkg/submod.py",
|
||||||
|
r#"
|
||||||
|
val: int = 0
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Refusing to rename is correct
|
||||||
|
assert_snapshot!(test.rename("mypkg"), @"Cannot rename");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rename_submodule_import_from_wrong_use() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"mypackage/__init__.py",
|
||||||
|
r#"
|
||||||
|
from .subpkg.submod import val
|
||||||
|
|
||||||
|
x = sub<CURSOR>mod
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source("mypackage/subpkg/__init__.py", r#""#)
|
||||||
|
.source(
|
||||||
|
"mypackage/subpkg/submod.py",
|
||||||
|
r#"
|
||||||
|
val: int = 0
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Refusing to rename is good/fine here, it's an undefined reference
|
||||||
|
assert_snapshot!(test.rename("mypkg"), @"Cannot rename");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rename_submodule_import_from_wrong_def() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"mypackage/__init__.py",
|
||||||
|
r#"
|
||||||
|
from .subpkg.sub<CURSOR>mod import val
|
||||||
|
|
||||||
|
x = submod
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source("mypackage/subpkg/__init__.py", r#""#)
|
||||||
|
.source(
|
||||||
|
"mypackage/subpkg/submod.py",
|
||||||
|
r#"
|
||||||
|
val: int = 0
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Refusing to rename is good here, it's a module name
|
||||||
|
assert_snapshot!(test.rename("mypkg"), @"Cannot rename");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rename_submodule_import_from_confusing_shadowed_def() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"mypackage/__init__.py",
|
||||||
|
r#"
|
||||||
|
from .sub<CURSOR>pkg import subpkg
|
||||||
|
|
||||||
|
x = subpkg
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mypackage/subpkg/__init__.py",
|
||||||
|
r#"
|
||||||
|
subpkg: int = 10
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Refusing to rename is good here, it's the name of a module
|
||||||
|
assert_snapshot!(test.rename("mypkg"), @"Cannot rename");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rename_submodule_import_from_confusing_real_def() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"mypackage/__init__.py",
|
||||||
|
r#"
|
||||||
|
from .subpkg import sub<CURSOR>pkg
|
||||||
|
|
||||||
|
x = subpkg
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mypackage/subpkg/__init__.py",
|
||||||
|
r#"
|
||||||
|
subpkg: int = 10
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Renaming the integer is correct
|
||||||
|
assert_snapshot!(test.rename("mypkg"), @r"
|
||||||
|
info[rename]: Rename symbol (found 3 locations)
|
||||||
|
--> mypackage/__init__.py:2:21
|
||||||
|
|
|
||||||
|
2 | from .subpkg import subpkg
|
||||||
|
| ^^^^^^
|
||||||
|
3 |
|
||||||
|
4 | x = subpkg
|
||||||
|
| ------
|
||||||
|
|
|
||||||
|
::: mypackage/subpkg/__init__.py:2:1
|
||||||
|
|
|
||||||
|
2 | subpkg: int = 10
|
||||||
|
| ------
|
||||||
|
|
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rename_submodule_import_from_confusing_use() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"mypackage/__init__.py",
|
||||||
|
r#"
|
||||||
|
from .subpkg import subpkg
|
||||||
|
|
||||||
|
x = sub<CURSOR>pkg
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mypackage/subpkg/__init__.py",
|
||||||
|
r#"
|
||||||
|
subpkg: int = 10
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// TODO(submodule-imports): this is incorrect, we should rename the `subpkg` int
|
||||||
|
// and the RHS of the import statement (but *not* rename the LHS).
|
||||||
|
//
|
||||||
|
// However us being cautious here *would* be good as the rename will actually
|
||||||
|
// result in a `subpkg` variable still existing in this code, as the import's LHS
|
||||||
|
// `DefinitionKind::ImportFromSubmodule` would stop being overwritten by the RHS!
|
||||||
|
assert_snapshot!(test.rename("mypkg"), @r"
|
||||||
|
info[rename]: Rename symbol (found 1 locations)
|
||||||
|
--> mypackage/__init__.py:4:5
|
||||||
|
|
|
||||||
|
2 | from .subpkg import subpkg
|
||||||
|
3 |
|
||||||
|
4 | x = subpkg
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue