mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-30 22:01:18 +00:00
[ty] add more lsp tests for overloads (#20148)
I decided to split out the addition of these tests from other PRs so that it's easier to follow changes to the LSP's function call handling. I'm not particularly concerned with whether the results produced by these tests are "good" or "bad" in this PR, I'm just establishing a baseline.
This commit is contained in:
parent
bbfcf6e111
commit
f40a0b3800
4 changed files with 1656 additions and 2 deletions
|
@ -1355,6 +1355,462 @@ class MyClass:
|
||||||
"#);
|
"#);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn goto_declaration_overload_type_disambiguated1() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"main.py",
|
||||||
|
"
|
||||||
|
from mymodule import ab
|
||||||
|
|
||||||
|
a<CURSOR>b(1)
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.py",
|
||||||
|
r#"
|
||||||
|
def ab(a):
|
||||||
|
"""the real implementation!"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.pyi",
|
||||||
|
r#"
|
||||||
|
from typing import overload
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int): ...
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: str): ...
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assert_snapshot!(test.goto_declaration(), @r"
|
||||||
|
info[goto-declaration]: Declaration
|
||||||
|
--> mymodule.pyi:5:5
|
||||||
|
|
|
||||||
|
4 | @overload
|
||||||
|
5 | def ab(a: int): ...
|
||||||
|
| ^^
|
||||||
|
6 |
|
||||||
|
7 | @overload
|
||||||
|
|
|
||||||
|
info: Source
|
||||||
|
--> main.py:4:1
|
||||||
|
|
|
||||||
|
2 | from mymodule import ab
|
||||||
|
3 |
|
||||||
|
4 | ab(1)
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
|
||||||
|
info[goto-declaration]: Declaration
|
||||||
|
--> mymodule.pyi:8:5
|
||||||
|
|
|
||||||
|
7 | @overload
|
||||||
|
8 | def ab(a: str): ...
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
info: Source
|
||||||
|
--> main.py:4:1
|
||||||
|
|
|
||||||
|
2 | from mymodule import ab
|
||||||
|
3 |
|
||||||
|
4 | ab(1)
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn goto_declaration_overload_type_disambiguated2() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"main.py",
|
||||||
|
r#"
|
||||||
|
from mymodule import ab
|
||||||
|
|
||||||
|
a<CURSOR>b("hello")
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.py",
|
||||||
|
r#"
|
||||||
|
def ab(a):
|
||||||
|
"""the real implementation!"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.pyi",
|
||||||
|
r#"
|
||||||
|
from typing import overload
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int): ...
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: str): ...
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assert_snapshot!(test.goto_declaration(), @r#"
|
||||||
|
info[goto-declaration]: Declaration
|
||||||
|
--> mymodule.pyi:5:5
|
||||||
|
|
|
||||||
|
4 | @overload
|
||||||
|
5 | def ab(a: int): ...
|
||||||
|
| ^^
|
||||||
|
6 |
|
||||||
|
7 | @overload
|
||||||
|
|
|
||||||
|
info: Source
|
||||||
|
--> main.py:4:1
|
||||||
|
|
|
||||||
|
2 | from mymodule import ab
|
||||||
|
3 |
|
||||||
|
4 | ab("hello")
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
|
||||||
|
info[goto-declaration]: Declaration
|
||||||
|
--> mymodule.pyi:8:5
|
||||||
|
|
|
||||||
|
7 | @overload
|
||||||
|
8 | def ab(a: str): ...
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
info: Source
|
||||||
|
--> main.py:4:1
|
||||||
|
|
|
||||||
|
2 | from mymodule import ab
|
||||||
|
3 |
|
||||||
|
4 | ab("hello")
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
"#);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn goto_declaration_overload_arity_disambiguated1() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"main.py",
|
||||||
|
"
|
||||||
|
from mymodule import ab
|
||||||
|
|
||||||
|
a<CURSOR>b(1, 2)
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.py",
|
||||||
|
r#"
|
||||||
|
def ab(a, b = None):
|
||||||
|
"""the real implementation!"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.pyi",
|
||||||
|
r#"
|
||||||
|
from typing import overload
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int, b: int): ...
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int): ...
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assert_snapshot!(test.goto_declaration(), @r"
|
||||||
|
info[goto-declaration]: Declaration
|
||||||
|
--> mymodule.pyi:5:5
|
||||||
|
|
|
||||||
|
4 | @overload
|
||||||
|
5 | def ab(a: int, b: int): ...
|
||||||
|
| ^^
|
||||||
|
6 |
|
||||||
|
7 | @overload
|
||||||
|
|
|
||||||
|
info: Source
|
||||||
|
--> main.py:4:1
|
||||||
|
|
|
||||||
|
2 | from mymodule import ab
|
||||||
|
3 |
|
||||||
|
4 | ab(1, 2)
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
|
||||||
|
info[goto-declaration]: Declaration
|
||||||
|
--> mymodule.pyi:8:5
|
||||||
|
|
|
||||||
|
7 | @overload
|
||||||
|
8 | def ab(a: int): ...
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
info: Source
|
||||||
|
--> main.py:4:1
|
||||||
|
|
|
||||||
|
2 | from mymodule import ab
|
||||||
|
3 |
|
||||||
|
4 | ab(1, 2)
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn goto_declaration_overload_arity_disambiguated2() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"main.py",
|
||||||
|
"
|
||||||
|
from mymodule import ab
|
||||||
|
|
||||||
|
a<CURSOR>b(1)
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.py",
|
||||||
|
r#"
|
||||||
|
def ab(a, b = None):
|
||||||
|
"""the real implementation!"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.pyi",
|
||||||
|
r#"
|
||||||
|
from typing import overload
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int, b: int): ...
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int): ...
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assert_snapshot!(test.goto_declaration(), @r"
|
||||||
|
info[goto-declaration]: Declaration
|
||||||
|
--> mymodule.pyi:5:5
|
||||||
|
|
|
||||||
|
4 | @overload
|
||||||
|
5 | def ab(a: int, b: int): ...
|
||||||
|
| ^^
|
||||||
|
6 |
|
||||||
|
7 | @overload
|
||||||
|
|
|
||||||
|
info: Source
|
||||||
|
--> main.py:4:1
|
||||||
|
|
|
||||||
|
2 | from mymodule import ab
|
||||||
|
3 |
|
||||||
|
4 | ab(1)
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
|
||||||
|
info[goto-declaration]: Declaration
|
||||||
|
--> mymodule.pyi:8:5
|
||||||
|
|
|
||||||
|
7 | @overload
|
||||||
|
8 | def ab(a: int): ...
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
info: Source
|
||||||
|
--> main.py:4:1
|
||||||
|
|
|
||||||
|
2 | from mymodule import ab
|
||||||
|
3 |
|
||||||
|
4 | ab(1)
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn goto_declaration_overload_keyword_disambiguated1() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"main.py",
|
||||||
|
"
|
||||||
|
from mymodule import ab
|
||||||
|
|
||||||
|
a<CURSOR>b(1, b=2)
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.py",
|
||||||
|
r#"
|
||||||
|
def ab(a, *, b = None, c = None):
|
||||||
|
"""the real implementation!"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.pyi",
|
||||||
|
r#"
|
||||||
|
from typing import overload
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int): ...
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int, *, b: int): ...
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int, *, c: int): ...
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assert_snapshot!(test.goto_declaration(), @r"
|
||||||
|
info[goto-declaration]: Declaration
|
||||||
|
--> mymodule.pyi:5:5
|
||||||
|
|
|
||||||
|
4 | @overload
|
||||||
|
5 | def ab(a: int): ...
|
||||||
|
| ^^
|
||||||
|
6 |
|
||||||
|
7 | @overload
|
||||||
|
|
|
||||||
|
info: Source
|
||||||
|
--> main.py:4:1
|
||||||
|
|
|
||||||
|
2 | from mymodule import ab
|
||||||
|
3 |
|
||||||
|
4 | ab(1, b=2)
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
|
||||||
|
info[goto-declaration]: Declaration
|
||||||
|
--> mymodule.pyi:8:5
|
||||||
|
|
|
||||||
|
7 | @overload
|
||||||
|
8 | def ab(a: int, *, b: int): ...
|
||||||
|
| ^^
|
||||||
|
9 |
|
||||||
|
10 | @overload
|
||||||
|
|
|
||||||
|
info: Source
|
||||||
|
--> main.py:4:1
|
||||||
|
|
|
||||||
|
2 | from mymodule import ab
|
||||||
|
3 |
|
||||||
|
4 | ab(1, b=2)
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
|
||||||
|
info[goto-declaration]: Declaration
|
||||||
|
--> mymodule.pyi:11:5
|
||||||
|
|
|
||||||
|
10 | @overload
|
||||||
|
11 | def ab(a: int, *, c: int): ...
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
info: Source
|
||||||
|
--> main.py:4:1
|
||||||
|
|
|
||||||
|
2 | from mymodule import ab
|
||||||
|
3 |
|
||||||
|
4 | ab(1, b=2)
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn goto_declaration_overload_keyword_disambiguated2() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"main.py",
|
||||||
|
"
|
||||||
|
from mymodule import ab
|
||||||
|
|
||||||
|
a<CURSOR>b(1, c=2)
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.py",
|
||||||
|
r#"
|
||||||
|
def ab(a, *, b = None, c = None):
|
||||||
|
"""the real implementation!"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.pyi",
|
||||||
|
r#"
|
||||||
|
from typing import overload
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int): ...
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int, *, b: int): ...
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int, *, c: int): ...
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assert_snapshot!(test.goto_declaration(), @r"
|
||||||
|
info[goto-declaration]: Declaration
|
||||||
|
--> mymodule.pyi:5:5
|
||||||
|
|
|
||||||
|
4 | @overload
|
||||||
|
5 | def ab(a: int): ...
|
||||||
|
| ^^
|
||||||
|
6 |
|
||||||
|
7 | @overload
|
||||||
|
|
|
||||||
|
info: Source
|
||||||
|
--> main.py:4:1
|
||||||
|
|
|
||||||
|
2 | from mymodule import ab
|
||||||
|
3 |
|
||||||
|
4 | ab(1, c=2)
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
|
||||||
|
info[goto-declaration]: Declaration
|
||||||
|
--> mymodule.pyi:8:5
|
||||||
|
|
|
||||||
|
7 | @overload
|
||||||
|
8 | def ab(a: int, *, b: int): ...
|
||||||
|
| ^^
|
||||||
|
9 |
|
||||||
|
10 | @overload
|
||||||
|
|
|
||||||
|
info: Source
|
||||||
|
--> main.py:4:1
|
||||||
|
|
|
||||||
|
2 | from mymodule import ab
|
||||||
|
3 |
|
||||||
|
4 | ab(1, c=2)
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
|
||||||
|
info[goto-declaration]: Declaration
|
||||||
|
--> mymodule.pyi:11:5
|
||||||
|
|
|
||||||
|
10 | @overload
|
||||||
|
11 | def ab(a: int, *, c: int): ...
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
info: Source
|
||||||
|
--> main.py:4:1
|
||||||
|
|
|
||||||
|
2 | from mymodule import ab
|
||||||
|
3 |
|
||||||
|
4 | ab(1, c=2)
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
|
|
@ -802,6 +802,318 @@ my_func(my_other_func(a<CURSOR>b=5, y=2), 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn goto_definition_overload_type_disambiguated1() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"main.py",
|
||||||
|
"
|
||||||
|
from mymodule import ab
|
||||||
|
|
||||||
|
a<CURSOR>b(1)
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.py",
|
||||||
|
r#"
|
||||||
|
def ab(a):
|
||||||
|
"""the real implementation!"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.pyi",
|
||||||
|
r#"
|
||||||
|
from typing import overload
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int): ...
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: str): ...
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assert_snapshot!(test.goto_definition(), @r#"
|
||||||
|
info[goto-definition]: Definition
|
||||||
|
--> mymodule.py:2:5
|
||||||
|
|
|
||||||
|
2 | def ab(a):
|
||||||
|
| ^^
|
||||||
|
3 | """the real implementation!"""
|
||||||
|
|
|
||||||
|
info: Source
|
||||||
|
--> main.py:4:1
|
||||||
|
|
|
||||||
|
2 | from mymodule import ab
|
||||||
|
3 |
|
||||||
|
4 | ab(1)
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
"#);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn goto_definition_overload_type_disambiguated2() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"main.py",
|
||||||
|
r#"
|
||||||
|
from mymodule import ab
|
||||||
|
|
||||||
|
a<CURSOR>b("hello")
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.py",
|
||||||
|
r#"
|
||||||
|
def ab(a):
|
||||||
|
"""the real implementation!"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.pyi",
|
||||||
|
r#"
|
||||||
|
from typing import overload
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int): ...
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: str): ...
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assert_snapshot!(test.goto_definition(), @r#"
|
||||||
|
info[goto-definition]: Definition
|
||||||
|
--> mymodule.py:2:5
|
||||||
|
|
|
||||||
|
2 | def ab(a):
|
||||||
|
| ^^
|
||||||
|
3 | """the real implementation!"""
|
||||||
|
|
|
||||||
|
info: Source
|
||||||
|
--> main.py:4:1
|
||||||
|
|
|
||||||
|
2 | from mymodule import ab
|
||||||
|
3 |
|
||||||
|
4 | ab("hello")
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
"#);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn goto_definition_overload_arity_disambiguated1() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"main.py",
|
||||||
|
"
|
||||||
|
from mymodule import ab
|
||||||
|
|
||||||
|
a<CURSOR>b(1, 2)
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.py",
|
||||||
|
r#"
|
||||||
|
def ab(a, b = None):
|
||||||
|
"""the real implementation!"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.pyi",
|
||||||
|
r#"
|
||||||
|
from typing import overload
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int, b: int): ...
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int): ...
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assert_snapshot!(test.goto_definition(), @r#"
|
||||||
|
info[goto-definition]: Definition
|
||||||
|
--> mymodule.py:2:5
|
||||||
|
|
|
||||||
|
2 | def ab(a, b = None):
|
||||||
|
| ^^
|
||||||
|
3 | """the real implementation!"""
|
||||||
|
|
|
||||||
|
info: Source
|
||||||
|
--> main.py:4:1
|
||||||
|
|
|
||||||
|
2 | from mymodule import ab
|
||||||
|
3 |
|
||||||
|
4 | ab(1, 2)
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
"#);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn goto_definition_overload_arity_disambiguated2() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"main.py",
|
||||||
|
"
|
||||||
|
from mymodule import ab
|
||||||
|
|
||||||
|
a<CURSOR>b(1)
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.py",
|
||||||
|
r#"
|
||||||
|
def ab(a, b = None):
|
||||||
|
"""the real implementation!"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.pyi",
|
||||||
|
r#"
|
||||||
|
from typing import overload
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int, b: int): ...
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int): ...
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assert_snapshot!(test.goto_definition(), @r#"
|
||||||
|
info[goto-definition]: Definition
|
||||||
|
--> mymodule.py:2:5
|
||||||
|
|
|
||||||
|
2 | def ab(a, b = None):
|
||||||
|
| ^^
|
||||||
|
3 | """the real implementation!"""
|
||||||
|
|
|
||||||
|
info: Source
|
||||||
|
--> main.py:4:1
|
||||||
|
|
|
||||||
|
2 | from mymodule import ab
|
||||||
|
3 |
|
||||||
|
4 | ab(1)
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
"#);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn goto_definition_overload_keyword_disambiguated1() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"main.py",
|
||||||
|
"
|
||||||
|
from mymodule import ab
|
||||||
|
|
||||||
|
a<CURSOR>b(1, b=2)
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.py",
|
||||||
|
r#"
|
||||||
|
def ab(a, *, b = None, c = None):
|
||||||
|
"""the real implementation!"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.pyi",
|
||||||
|
r#"
|
||||||
|
from typing import overload
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int): ...
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int, *, b: int): ...
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int, *, c: int): ...
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assert_snapshot!(test.goto_definition(), @r#"
|
||||||
|
info[goto-definition]: Definition
|
||||||
|
--> mymodule.py:2:5
|
||||||
|
|
|
||||||
|
2 | def ab(a, *, b = None, c = None):
|
||||||
|
| ^^
|
||||||
|
3 | """the real implementation!"""
|
||||||
|
|
|
||||||
|
info: Source
|
||||||
|
--> main.py:4:1
|
||||||
|
|
|
||||||
|
2 | from mymodule import ab
|
||||||
|
3 |
|
||||||
|
4 | ab(1, b=2)
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
"#);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn goto_definition_overload_keyword_disambiguated2() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"main.py",
|
||||||
|
"
|
||||||
|
from mymodule import ab
|
||||||
|
|
||||||
|
a<CURSOR>b(1, c=2)
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.py",
|
||||||
|
r#"
|
||||||
|
def ab(a, *, b = None, c = None):
|
||||||
|
"""the real implementation!"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.pyi",
|
||||||
|
r#"
|
||||||
|
from typing import overload
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int): ...
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int, *, b: int): ...
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int, *, c: int): ...
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assert_snapshot!(test.goto_definition(), @r#"
|
||||||
|
info[goto-definition]: Definition
|
||||||
|
--> mymodule.py:2:5
|
||||||
|
|
|
||||||
|
2 | def ab(a, *, b = None, c = None):
|
||||||
|
| ^^
|
||||||
|
3 | """the real implementation!"""
|
||||||
|
|
|
||||||
|
info: Source
|
||||||
|
--> main.py:4:1
|
||||||
|
|
|
||||||
|
2 | from mymodule import ab
|
||||||
|
3 |
|
||||||
|
4 | ab(1, c=2)
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
"#);
|
||||||
|
}
|
||||||
|
|
||||||
struct GotoDefinitionDiagnostic {
|
struct GotoDefinitionDiagnostic {
|
||||||
source: FileRange,
|
source: FileRange,
|
||||||
target: FileRange,
|
target: FileRange,
|
||||||
|
|
|
@ -791,7 +791,453 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn hover_overload() {
|
fn hover_overload_type_disambiguated1() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"main.py",
|
||||||
|
"
|
||||||
|
from mymodule import ab
|
||||||
|
|
||||||
|
a<CURSOR>b(1)
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.py",
|
||||||
|
r#"
|
||||||
|
def ab(a):
|
||||||
|
"""the real implementation!"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.pyi",
|
||||||
|
r#"
|
||||||
|
from typing import overload
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int):
|
||||||
|
"""the int overload"""
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: str): ...
|
||||||
|
"""the str overload"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assert_snapshot!(test.hover(), @r"
|
||||||
|
(a: int) -> Unknown
|
||||||
|
(a: str) -> Unknown
|
||||||
|
---------------------------------------------
|
||||||
|
the int overload
|
||||||
|
|
||||||
|
---------------------------------------------
|
||||||
|
```python
|
||||||
|
(a: int) -> Unknown
|
||||||
|
(a: str) -> Unknown
|
||||||
|
```
|
||||||
|
---
|
||||||
|
```text
|
||||||
|
the int overload
|
||||||
|
|
||||||
|
```
|
||||||
|
---------------------------------------------
|
||||||
|
info[hover]: Hovered content is
|
||||||
|
--> main.py:4:1
|
||||||
|
|
|
||||||
|
2 | from mymodule import ab
|
||||||
|
3 |
|
||||||
|
4 | ab(1)
|
||||||
|
| ^-
|
||||||
|
| ||
|
||||||
|
| |Cursor offset
|
||||||
|
| source
|
||||||
|
|
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn hover_overload_type_disambiguated2() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"main.py",
|
||||||
|
r#"
|
||||||
|
from mymodule import ab
|
||||||
|
|
||||||
|
a<CURSOR>b("hello")
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.py",
|
||||||
|
r#"
|
||||||
|
def ab(a):
|
||||||
|
"""the real implementation!"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.pyi",
|
||||||
|
r#"
|
||||||
|
from typing import overload
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int):
|
||||||
|
"""the int overload"""
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: str):
|
||||||
|
"""the str overload"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assert_snapshot!(test.hover(), @r#"
|
||||||
|
(a: int) -> Unknown
|
||||||
|
(a: str) -> Unknown
|
||||||
|
---------------------------------------------
|
||||||
|
the int overload
|
||||||
|
|
||||||
|
---------------------------------------------
|
||||||
|
```python
|
||||||
|
(a: int) -> Unknown
|
||||||
|
(a: str) -> Unknown
|
||||||
|
```
|
||||||
|
---
|
||||||
|
```text
|
||||||
|
the int overload
|
||||||
|
|
||||||
|
```
|
||||||
|
---------------------------------------------
|
||||||
|
info[hover]: Hovered content is
|
||||||
|
--> main.py:4:1
|
||||||
|
|
|
||||||
|
2 | from mymodule import ab
|
||||||
|
3 |
|
||||||
|
4 | ab("hello")
|
||||||
|
| ^-
|
||||||
|
| ||
|
||||||
|
| |Cursor offset
|
||||||
|
| source
|
||||||
|
|
|
||||||
|
"#);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn hover_overload_arity_disambiguated1() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"main.py",
|
||||||
|
"
|
||||||
|
from mymodule import ab
|
||||||
|
|
||||||
|
a<CURSOR>b(1, 2)
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.py",
|
||||||
|
r#"
|
||||||
|
def ab(a, b = None):
|
||||||
|
"""the real implementation!"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.pyi",
|
||||||
|
r#"
|
||||||
|
from typing import overload
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int, b: int):
|
||||||
|
"""the two arg overload"""
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int):
|
||||||
|
"""the one arg overload"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assert_snapshot!(test.hover(), @r"
|
||||||
|
(
|
||||||
|
a: int,
|
||||||
|
b: int
|
||||||
|
) -> Unknown
|
||||||
|
(a: int) -> Unknown
|
||||||
|
---------------------------------------------
|
||||||
|
the two arg overload
|
||||||
|
|
||||||
|
---------------------------------------------
|
||||||
|
```python
|
||||||
|
(
|
||||||
|
a: int,
|
||||||
|
b: int
|
||||||
|
) -> Unknown
|
||||||
|
(a: int) -> Unknown
|
||||||
|
```
|
||||||
|
---
|
||||||
|
```text
|
||||||
|
the two arg overload
|
||||||
|
|
||||||
|
```
|
||||||
|
---------------------------------------------
|
||||||
|
info[hover]: Hovered content is
|
||||||
|
--> main.py:4:1
|
||||||
|
|
|
||||||
|
2 | from mymodule import ab
|
||||||
|
3 |
|
||||||
|
4 | ab(1, 2)
|
||||||
|
| ^-
|
||||||
|
| ||
|
||||||
|
| |Cursor offset
|
||||||
|
| source
|
||||||
|
|
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn hover_overload_arity_disambiguated2() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"main.py",
|
||||||
|
"
|
||||||
|
from mymodule import ab
|
||||||
|
|
||||||
|
a<CURSOR>b(1)
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.py",
|
||||||
|
r#"
|
||||||
|
def ab(a, b = None):
|
||||||
|
"""the real implementation!"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.pyi",
|
||||||
|
r#"
|
||||||
|
from typing import overload
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int, b: int):
|
||||||
|
"""the two arg overload"""
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int):
|
||||||
|
"""the one arg overload"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assert_snapshot!(test.hover(), @r"
|
||||||
|
(
|
||||||
|
a: int,
|
||||||
|
b: int
|
||||||
|
) -> Unknown
|
||||||
|
(a: int) -> Unknown
|
||||||
|
---------------------------------------------
|
||||||
|
the two arg overload
|
||||||
|
|
||||||
|
---------------------------------------------
|
||||||
|
```python
|
||||||
|
(
|
||||||
|
a: int,
|
||||||
|
b: int
|
||||||
|
) -> Unknown
|
||||||
|
(a: int) -> Unknown
|
||||||
|
```
|
||||||
|
---
|
||||||
|
```text
|
||||||
|
the two arg overload
|
||||||
|
|
||||||
|
```
|
||||||
|
---------------------------------------------
|
||||||
|
info[hover]: Hovered content is
|
||||||
|
--> main.py:4:1
|
||||||
|
|
|
||||||
|
2 | from mymodule import ab
|
||||||
|
3 |
|
||||||
|
4 | ab(1)
|
||||||
|
| ^-
|
||||||
|
| ||
|
||||||
|
| |Cursor offset
|
||||||
|
| source
|
||||||
|
|
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn hover_overload_keyword_disambiguated1() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"main.py",
|
||||||
|
"
|
||||||
|
from mymodule import ab
|
||||||
|
|
||||||
|
a<CURSOR>b(1, b=2)
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.py",
|
||||||
|
r#"
|
||||||
|
def ab(a, *, b = None, c = None):
|
||||||
|
"""the real implementation!"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.pyi",
|
||||||
|
r#"
|
||||||
|
from typing import overload
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int):
|
||||||
|
"""keywordless overload"""
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int, *, b: int):
|
||||||
|
"""b overload"""
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int, *, c: int):
|
||||||
|
"""c overload"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assert_snapshot!(test.hover(), @r"
|
||||||
|
(a: int) -> Unknown
|
||||||
|
(
|
||||||
|
a: int,
|
||||||
|
*,
|
||||||
|
b: int
|
||||||
|
) -> Unknown
|
||||||
|
(
|
||||||
|
a: int,
|
||||||
|
*,
|
||||||
|
c: int
|
||||||
|
) -> Unknown
|
||||||
|
---------------------------------------------
|
||||||
|
keywordless overload
|
||||||
|
|
||||||
|
---------------------------------------------
|
||||||
|
```python
|
||||||
|
(a: int) -> Unknown
|
||||||
|
(
|
||||||
|
a: int,
|
||||||
|
*,
|
||||||
|
b: int
|
||||||
|
) -> Unknown
|
||||||
|
(
|
||||||
|
a: int,
|
||||||
|
*,
|
||||||
|
c: int
|
||||||
|
) -> Unknown
|
||||||
|
```
|
||||||
|
---
|
||||||
|
```text
|
||||||
|
keywordless overload
|
||||||
|
|
||||||
|
```
|
||||||
|
---------------------------------------------
|
||||||
|
info[hover]: Hovered content is
|
||||||
|
--> main.py:4:1
|
||||||
|
|
|
||||||
|
2 | from mymodule import ab
|
||||||
|
3 |
|
||||||
|
4 | ab(1, b=2)
|
||||||
|
| ^-
|
||||||
|
| ||
|
||||||
|
| |Cursor offset
|
||||||
|
| source
|
||||||
|
|
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn hover_overload_keyword_disambiguated2() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"main.py",
|
||||||
|
"
|
||||||
|
from mymodule import ab
|
||||||
|
|
||||||
|
a<CURSOR>b(1, c=2)
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.py",
|
||||||
|
r#"
|
||||||
|
def ab(a, *, b = None, c = None):
|
||||||
|
"""the real implementation!"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.pyi",
|
||||||
|
r#"
|
||||||
|
from typing import overload
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int):
|
||||||
|
"""keywordless overload"""
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int, *, b: int):
|
||||||
|
"""b overload"""
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int, *, c: int):
|
||||||
|
"""c overload"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assert_snapshot!(test.hover(), @r"
|
||||||
|
(a: int) -> Unknown
|
||||||
|
(
|
||||||
|
a: int,
|
||||||
|
*,
|
||||||
|
b: int
|
||||||
|
) -> Unknown
|
||||||
|
(
|
||||||
|
a: int,
|
||||||
|
*,
|
||||||
|
c: int
|
||||||
|
) -> Unknown
|
||||||
|
---------------------------------------------
|
||||||
|
keywordless overload
|
||||||
|
|
||||||
|
---------------------------------------------
|
||||||
|
```python
|
||||||
|
(a: int) -> Unknown
|
||||||
|
(
|
||||||
|
a: int,
|
||||||
|
*,
|
||||||
|
b: int
|
||||||
|
) -> Unknown
|
||||||
|
(
|
||||||
|
a: int,
|
||||||
|
*,
|
||||||
|
c: int
|
||||||
|
) -> Unknown
|
||||||
|
```
|
||||||
|
---
|
||||||
|
```text
|
||||||
|
keywordless overload
|
||||||
|
|
||||||
|
```
|
||||||
|
---------------------------------------------
|
||||||
|
info[hover]: Hovered content is
|
||||||
|
--> main.py:4:1
|
||||||
|
|
|
||||||
|
2 | from mymodule import ab
|
||||||
|
3 |
|
||||||
|
4 | ab(1, c=2)
|
||||||
|
| ^-
|
||||||
|
| ||
|
||||||
|
| |Cursor offset
|
||||||
|
| source
|
||||||
|
|
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn hover_overload_ambiguous() {
|
||||||
let test = cursor_test(
|
let test = cursor_test(
|
||||||
r#"
|
r#"
|
||||||
from typing import overload
|
from typing import overload
|
||||||
|
@ -858,7 +1304,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn hover_overload_compact() {
|
fn hover_overload_ambiguous_compact() {
|
||||||
let test = cursor_test(
|
let test = cursor_test(
|
||||||
r#"
|
r#"
|
||||||
from typing import overload
|
from typing import overload
|
||||||
|
|
|
@ -258,6 +258,9 @@ fn create_parameters_from_offsets(
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use insta::assert_snapshot;
|
||||||
|
|
||||||
|
use crate::MarkupKind;
|
||||||
use crate::docstring::Docstring;
|
use crate::docstring::Docstring;
|
||||||
use crate::signature_help::SignatureHelpInfo;
|
use crate::signature_help::SignatureHelpInfo;
|
||||||
use crate::tests::{CursorTest, cursor_test};
|
use crate::tests::{CursorTest, cursor_test};
|
||||||
|
@ -470,6 +473,354 @@ mod tests {
|
||||||
assert_eq!(param2.name, "value");
|
assert_eq!(param2.name, "value");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn signature_help_overload_type_disambiguated1() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"main.py",
|
||||||
|
"
|
||||||
|
from mymodule import ab
|
||||||
|
|
||||||
|
ab(1<CURSOR>)
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.py",
|
||||||
|
r#"
|
||||||
|
def ab(a):
|
||||||
|
"""the real implementation!"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.pyi",
|
||||||
|
r#"
|
||||||
|
from typing import overload
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int):
|
||||||
|
"""the int overload"""
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: str): ...
|
||||||
|
"""the str overload"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assert_snapshot!(test.signature_help_render(), @r"
|
||||||
|
============== active signature =============
|
||||||
|
(a: int) -> Unknown
|
||||||
|
---------------------------------------------
|
||||||
|
the int overload
|
||||||
|
|
||||||
|
-------------- active parameter -------------
|
||||||
|
a: int
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
=============== other signature =============
|
||||||
|
(a: str) -> Unknown
|
||||||
|
---------------------------------------------
|
||||||
|
the real implementation!
|
||||||
|
|
||||||
|
-------------- active parameter -------------
|
||||||
|
a: str
|
||||||
|
---------------------------------------------
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn signature_help_overload_type_disambiguated2() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"main.py",
|
||||||
|
r#"
|
||||||
|
from mymodule import ab
|
||||||
|
|
||||||
|
ab("hello"<CURSOR>)
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.py",
|
||||||
|
r#"
|
||||||
|
def ab(a):
|
||||||
|
"""the real implementation!"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.pyi",
|
||||||
|
r#"
|
||||||
|
from typing import overload
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int):
|
||||||
|
"""the int overload"""
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: str):
|
||||||
|
"""the str overload"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assert_snapshot!(test.signature_help_render(), @r"
|
||||||
|
============== active signature =============
|
||||||
|
(a: int) -> Unknown
|
||||||
|
---------------------------------------------
|
||||||
|
the int overload
|
||||||
|
|
||||||
|
-------------- active parameter -------------
|
||||||
|
a: int
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
=============== other signature =============
|
||||||
|
(a: str) -> Unknown
|
||||||
|
---------------------------------------------
|
||||||
|
the str overload
|
||||||
|
|
||||||
|
-------------- active parameter -------------
|
||||||
|
a: str
|
||||||
|
---------------------------------------------
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn signature_help_overload_arity_disambiguated1() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"main.py",
|
||||||
|
"
|
||||||
|
from mymodule import ab
|
||||||
|
|
||||||
|
ab(1, 2<CURSOR>)
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.py",
|
||||||
|
r#"
|
||||||
|
def ab(a, b = None):
|
||||||
|
"""the real implementation!"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.pyi",
|
||||||
|
r#"
|
||||||
|
from typing import overload
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int, b: int):
|
||||||
|
"""the two arg overload"""
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int):
|
||||||
|
"""the one arg overload"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assert_snapshot!(test.signature_help_render(), @r"
|
||||||
|
============== active signature =============
|
||||||
|
(a: int, b: int) -> Unknown
|
||||||
|
---------------------------------------------
|
||||||
|
the two arg overload
|
||||||
|
|
||||||
|
-------------- active parameter -------------
|
||||||
|
b: int
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
=============== other signature =============
|
||||||
|
(a: int) -> Unknown
|
||||||
|
---------------------------------------------
|
||||||
|
the one arg overload
|
||||||
|
|
||||||
|
(no active parameter specified)
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn signature_help_overload_arity_disambiguated2() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"main.py",
|
||||||
|
"
|
||||||
|
from mymodule import ab
|
||||||
|
|
||||||
|
ab(1<CURSOR>)
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.py",
|
||||||
|
r#"
|
||||||
|
def ab(a, b = None):
|
||||||
|
"""the real implementation!"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.pyi",
|
||||||
|
r#"
|
||||||
|
from typing import overload
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int, b: int):
|
||||||
|
"""the two arg overload"""
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int):
|
||||||
|
"""the one arg overload"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assert_snapshot!(test.signature_help_render(), @r"
|
||||||
|
============== active signature =============
|
||||||
|
(a: int, b: int) -> Unknown
|
||||||
|
---------------------------------------------
|
||||||
|
the two arg overload
|
||||||
|
|
||||||
|
-------------- active parameter -------------
|
||||||
|
a: int
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
=============== other signature =============
|
||||||
|
(a: int) -> Unknown
|
||||||
|
---------------------------------------------
|
||||||
|
the one arg overload
|
||||||
|
|
||||||
|
-------------- active parameter -------------
|
||||||
|
a: int
|
||||||
|
---------------------------------------------
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn signature_help_overload_keyword_disambiguated1() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"main.py",
|
||||||
|
"
|
||||||
|
from mymodule import ab
|
||||||
|
|
||||||
|
ab(1, b=2<CURSOR>)
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.py",
|
||||||
|
r#"
|
||||||
|
def ab(a, *, b = None, c = None):
|
||||||
|
"""the real implementation!"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.pyi",
|
||||||
|
r#"
|
||||||
|
from typing import overload
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int):
|
||||||
|
"""keywordless overload"""
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int, *, b: int):
|
||||||
|
"""b overload"""
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int, *, c: int):
|
||||||
|
"""c overload"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assert_snapshot!(test.signature_help_render(), @r"
|
||||||
|
============== active signature =============
|
||||||
|
(a: int, *, b: int) -> Unknown
|
||||||
|
---------------------------------------------
|
||||||
|
b overload
|
||||||
|
|
||||||
|
-------------- active parameter -------------
|
||||||
|
b: int
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
=============== other signature =============
|
||||||
|
(a: int) -> Unknown
|
||||||
|
---------------------------------------------
|
||||||
|
keywordless overload
|
||||||
|
|
||||||
|
(no active parameter specified)
|
||||||
|
=============== other signature =============
|
||||||
|
(a: int, *, c: int) -> Unknown
|
||||||
|
---------------------------------------------
|
||||||
|
c overload
|
||||||
|
|
||||||
|
-------------- active parameter -------------
|
||||||
|
c: int
|
||||||
|
---------------------------------------------
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn signature_help_overload_keyword_disambiguated2() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"main.py",
|
||||||
|
"
|
||||||
|
from mymodule import ab
|
||||||
|
|
||||||
|
ab(1, c=2<CURSOR>)
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.py",
|
||||||
|
r#"
|
||||||
|
def ab(a, *, b = None, c = None):
|
||||||
|
"""the real implementation!"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"mymodule.pyi",
|
||||||
|
r#"
|
||||||
|
from typing import overload
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int):
|
||||||
|
"""keywordless overload"""
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int, *, b: int):
|
||||||
|
"""b overload"""
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def ab(a: int, *, c: int):
|
||||||
|
"""c overload"""
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assert_snapshot!(test.signature_help_render(), @r"
|
||||||
|
============== active signature =============
|
||||||
|
(a: int, *, c: int) -> Unknown
|
||||||
|
---------------------------------------------
|
||||||
|
c overload
|
||||||
|
|
||||||
|
-------------- active parameter -------------
|
||||||
|
c: int
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
=============== other signature =============
|
||||||
|
(a: int) -> Unknown
|
||||||
|
---------------------------------------------
|
||||||
|
keywordless overload
|
||||||
|
|
||||||
|
(no active parameter specified)
|
||||||
|
=============== other signature =============
|
||||||
|
(a: int, *, b: int) -> Unknown
|
||||||
|
---------------------------------------------
|
||||||
|
b overload
|
||||||
|
|
||||||
|
-------------- active parameter -------------
|
||||||
|
b: int
|
||||||
|
---------------------------------------------
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn signature_help_class_constructor() {
|
fn signature_help_class_constructor() {
|
||||||
let test = cursor_test(
|
let test = cursor_test(
|
||||||
|
@ -826,5 +1177,94 @@ mod tests {
|
||||||
fn signature_help(&self) -> Option<SignatureHelpInfo> {
|
fn signature_help(&self) -> Option<SignatureHelpInfo> {
|
||||||
crate::signature_help::signature_help(&self.db, self.cursor.file, self.cursor.offset)
|
crate::signature_help::signature_help(&self.db, self.cursor.file, self.cursor.offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn signature_help_render(&self) -> String {
|
||||||
|
use std::fmt::Write;
|
||||||
|
|
||||||
|
let Some(signature_help) = self.signature_help() else {
|
||||||
|
return "Signature help found no signatures".to_string();
|
||||||
|
};
|
||||||
|
let active_sig_heading = "\n============== active signature =============\n";
|
||||||
|
let second_sig_heading = "\n=============== other signature =============\n";
|
||||||
|
let active_arg_heading = "\n-------------- active parameter -------------\n";
|
||||||
|
|
||||||
|
let mut buf = String::new();
|
||||||
|
if let Some(active_signature) = signature_help.active_signature {
|
||||||
|
let signature = signature_help
|
||||||
|
.signatures
|
||||||
|
.get(active_signature)
|
||||||
|
.expect("failed to find active signature!");
|
||||||
|
write!(
|
||||||
|
&mut buf,
|
||||||
|
"{heading}{label}{line}{docs}",
|
||||||
|
heading = active_sig_heading,
|
||||||
|
label = signature.label,
|
||||||
|
line = MarkupKind::PlainText.horizontal_line(),
|
||||||
|
docs = signature
|
||||||
|
.documentation
|
||||||
|
.as_ref()
|
||||||
|
.map(Docstring::render_plaintext)
|
||||||
|
.unwrap_or_default(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
if let Some(active_parameter) = signature.active_parameter {
|
||||||
|
let parameter = signature
|
||||||
|
.parameters
|
||||||
|
.get(active_parameter)
|
||||||
|
.expect("failed to find active parameter!");
|
||||||
|
write!(
|
||||||
|
&mut buf,
|
||||||
|
"{heading}{label}{line}{docs}",
|
||||||
|
heading = active_arg_heading,
|
||||||
|
label = parameter.label,
|
||||||
|
line = MarkupKind::PlainText.horizontal_line(),
|
||||||
|
docs = parameter.documentation.as_deref().unwrap_or_default(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
} else {
|
||||||
|
writeln!(&mut buf, "\n(no active parameter specified)").unwrap();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
writeln!(&mut buf, "\n(no active signature specified)").unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (idx, signature) in signature_help.signatures.iter().enumerate() {
|
||||||
|
if Some(idx) == signature_help.active_signature {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
write!(
|
||||||
|
&mut buf,
|
||||||
|
"{heading}{label}{line}{docs}",
|
||||||
|
heading = second_sig_heading,
|
||||||
|
label = signature.label,
|
||||||
|
line = MarkupKind::PlainText.horizontal_line(),
|
||||||
|
docs = signature
|
||||||
|
.documentation
|
||||||
|
.as_ref()
|
||||||
|
.map(Docstring::render_plaintext)
|
||||||
|
.unwrap_or_default(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
if let Some(active_parameter) = signature.active_parameter {
|
||||||
|
let parameter = signature
|
||||||
|
.parameters
|
||||||
|
.get(active_parameter)
|
||||||
|
.expect("failed to find active parameter!");
|
||||||
|
write!(
|
||||||
|
&mut buf,
|
||||||
|
"{heading}{label}{line}{docs}",
|
||||||
|
heading = active_arg_heading,
|
||||||
|
label = parameter.label,
|
||||||
|
line = MarkupKind::PlainText.horizontal_line(),
|
||||||
|
docs = parameter.documentation.as_deref().unwrap_or_default(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
} else {
|
||||||
|
write!(&mut buf, "\n(no active parameter specified)").unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buf
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue