Skip to content

Commit ca6e9ee

Browse files
committed
add more tests for overloads in lsp functionality
1 parent 0959fd4 commit ca6e9ee

File tree

3 files changed

+540
-36
lines changed

3 files changed

+540
-36
lines changed

crates/ty_ide/src/goto.rs

Lines changed: 17 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use ty_python_semantic::HasDefinition;
1616
use ty_python_semantic::ImportAliasResolution;
1717
use ty_python_semantic::ResolvedDefinition;
1818
use ty_python_semantic::types::definitions_for_keyword_argument;
19-
use ty_python_semantic::types::{Type, call_signature_details, find_active_signature_from_details};
19+
use ty_python_semantic::types::{Type, call_signature_details};
2020
use ty_python_semantic::{
2121
HasType, SemanticModel, definitions_for_imported_symbol, definitions_for_name,
2222
};
@@ -437,24 +437,16 @@ impl GotoTarget<'_> {
437437
//
438438
// Prefer the function impl over the callable so that its docstrings win if defined.
439439
GotoTarget::Call { callable, call } => {
440-
let call_definitions = definitions_for_callable(db, file, call);
441-
let expr_definitions = definitions_for_expression(db, file, callable);
442-
443-
tracing::trace!(
444-
"GotoTarget::Call got {} call defs and {} expr defs",
445-
call_definitions.as_ref().map(Vec::len).unwrap_or_default(),
446-
expr_definitions.as_ref().map(Vec::len).unwrap_or_default(),
447-
);
448-
449-
let definitions = match (expr_definitions, call_definitions) {
450-
(Some(mut expr), Some(mut call)) => {
451-
call.append(&mut expr);
452-
call
453-
}
454-
(Some(defs), None) | (None, Some(defs)) => defs,
455-
(None, None) => return None,
456-
};
457-
Some(DefinitionsOrTargets::Definitions(definitions))
440+
let mut definitions = definitions_for_callable(db, file, call);
441+
let expr_definitions =
442+
definitions_for_expression(db, file, callable).unwrap_or_default();
443+
definitions.extend(expr_definitions);
444+
445+
if definitions.is_empty() {
446+
None
447+
} else {
448+
Some(DefinitionsOrTargets::Definitions(definitions))
449+
}
458450
}
459451

460452
_ => None,
@@ -801,22 +793,14 @@ fn definitions_for_callable<'db>(
801793
db: &'db dyn crate::Db,
802794
file: ruff_db::files::File,
803795
call: &ExprCall,
804-
) -> Option<Vec<ResolvedDefinition<'db>>> {
796+
) -> Vec<ResolvedDefinition<'db>> {
805797
let model = SemanticModel::new(db, file);
806798
// Attempt to refine to a specific call
807-
let mut signature_info = call_signature_details(db, &model, call);
808-
if let Some(active) = find_active_signature_from_details(&signature_info) {
809-
Some(vec![ResolvedDefinition::Definition(
810-
signature_info.remove(active).definition?,
811-
)])
812-
} else {
813-
Some(
814-
signature_info
815-
.into_iter()
816-
.filter_map(|signature| Some(ResolvedDefinition::Definition(signature.definition?)))
817-
.collect(),
818-
)
819-
}
799+
let signature_info = call_signature_details(db, &model, call);
800+
signature_info
801+
.into_iter()
802+
.filter_map(|signature| signature.definition.map(ResolvedDefinition::Definition))
803+
.collect()
820804
}
821805

822806
/// Shared helper to map and convert resolved definitions into navigation targets.

crates/ty_ide/src/goto_definition.rs

Lines changed: 305 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ pub fn goto_definition(
3131

3232
#[cfg(test)]
3333
mod test {
34-
use crate::tests::{CursorTest, IntoDiagnostic};
34+
use crate::tests::{CursorTest, IntoDiagnostic, cursor_test};
3535
use crate::{NavigationTarget, goto_definition};
3636
use insta::assert_snapshot;
3737
use ruff_db::diagnostic::{
@@ -798,6 +798,310 @@ my_func(my_other_func(a<CURSOR>b=5, y=2), 0)
798798
");
799799
}
800800

801+
#[test]
802+
fn goto_definition_overload_type_disambiguated1() {
803+
let test = cursor_test(
804+
r#"
805+
from typing import overload
806+
807+
@overload
808+
def ab(a: int):
809+
"""The first overload"""
810+
811+
@overload
812+
def ab(a: str):
813+
"""The second overload"""
814+
815+
def ab(a): ...
816+
817+
a<CURSOR>b(1)
818+
"#,
819+
);
820+
821+
assert_snapshot!(test.goto_definition(), @r#"
822+
info[goto-definition]: Definition
823+
--> main.py:5:5
824+
|
825+
4 | @overload
826+
5 | def ab(a: int):
827+
| ^^
828+
6 | """The first overload"""
829+
|
830+
info: Source
831+
--> main.py:14:1
832+
|
833+
12 | def ab(a): ...
834+
13 |
835+
14 | ab(1)
836+
| ^^
837+
|
838+
839+
info[goto-definition]: Definition
840+
--> main.py:9:5
841+
|
842+
8 | @overload
843+
9 | def ab(a: str):
844+
| ^^
845+
10 | """The second overload"""
846+
|
847+
info: Source
848+
--> main.py:14:1
849+
|
850+
12 | def ab(a): ...
851+
13 |
852+
14 | ab(1)
853+
| ^^
854+
|
855+
856+
info[goto-definition]: Definition
857+
--> main.py:12:5
858+
|
859+
10 | """The second overload"""
860+
11 |
861+
12 | def ab(a): ...
862+
| ^^
863+
13 |
864+
14 | ab(1)
865+
|
866+
info: Source
867+
--> main.py:14:1
868+
|
869+
12 | def ab(a): ...
870+
13 |
871+
14 | ab(1)
872+
| ^^
873+
|
874+
"#);
875+
}
876+
877+
#[test]
878+
fn goto_definition_overload_type_disambiguated2() {
879+
let test = cursor_test(
880+
r#"
881+
from typing import overload
882+
883+
@overload
884+
def ab(a: int):
885+
"""The first overload"""
886+
887+
@overload
888+
def ab(a: str):
889+
"""The second overload"""
890+
891+
def ab(a): ...
892+
893+
a<CURSOR>b("hello")
894+
"#,
895+
);
896+
897+
assert_snapshot!(test.goto_definition(), @r#"
898+
info[goto-definition]: Definition
899+
--> main.py:5:5
900+
|
901+
4 | @overload
902+
5 | def ab(a: int):
903+
| ^^
904+
6 | """The first overload"""
905+
|
906+
info: Source
907+
--> main.py:14:1
908+
|
909+
12 | def ab(a): ...
910+
13 |
911+
14 | ab("hello")
912+
| ^^
913+
|
914+
915+
info[goto-definition]: Definition
916+
--> main.py:9:5
917+
|
918+
8 | @overload
919+
9 | def ab(a: str):
920+
| ^^
921+
10 | """The second overload"""
922+
|
923+
info: Source
924+
--> main.py:14:1
925+
|
926+
12 | def ab(a): ...
927+
13 |
928+
14 | ab("hello")
929+
| ^^
930+
|
931+
932+
info[goto-definition]: Definition
933+
--> main.py:12:5
934+
|
935+
10 | """The second overload"""
936+
11 |
937+
12 | def ab(a): ...
938+
| ^^
939+
13 |
940+
14 | ab("hello")
941+
|
942+
info: Source
943+
--> main.py:14:1
944+
|
945+
12 | def ab(a): ...
946+
13 |
947+
14 | ab("hello")
948+
| ^^
949+
|
950+
"#);
951+
}
952+
953+
#[test]
954+
fn goto_definition_overload_arity_disambiguated1() {
955+
let test = cursor_test(
956+
r#"
957+
from typing import overload
958+
959+
@overload
960+
def ab(a: int, b: int):
961+
"""The first overload"""
962+
963+
@overload
964+
def ab(a: int):
965+
"""The second overload"""
966+
967+
def ab(a, b = None): ...
968+
969+
a<CURSOR>b(1, 2)
970+
"#,
971+
);
972+
973+
assert_snapshot!(test.goto_definition(), @r#"
974+
info[goto-definition]: Definition
975+
--> main.py:5:5
976+
|
977+
4 | @overload
978+
5 | def ab(a: int, b: int):
979+
| ^^
980+
6 | """The first overload"""
981+
|
982+
info: Source
983+
--> main.py:14:1
984+
|
985+
12 | def ab(a, b = None): ...
986+
13 |
987+
14 | ab(1, 2)
988+
| ^^
989+
|
990+
991+
info[goto-definition]: Definition
992+
--> main.py:9:5
993+
|
994+
8 | @overload
995+
9 | def ab(a: int):
996+
| ^^
997+
10 | """The second overload"""
998+
|
999+
info: Source
1000+
--> main.py:14:1
1001+
|
1002+
12 | def ab(a, b = None): ...
1003+
13 |
1004+
14 | ab(1, 2)
1005+
| ^^
1006+
|
1007+
1008+
info[goto-definition]: Definition
1009+
--> main.py:12:5
1010+
|
1011+
10 | """The second overload"""
1012+
11 |
1013+
12 | def ab(a, b = None): ...
1014+
| ^^
1015+
13 |
1016+
14 | ab(1, 2)
1017+
|
1018+
info: Source
1019+
--> main.py:14:1
1020+
|
1021+
12 | def ab(a, b = None): ...
1022+
13 |
1023+
14 | ab(1, 2)
1024+
| ^^
1025+
|
1026+
"#);
1027+
}
1028+
1029+
#[test]
1030+
fn goto_definition_overload_arity_disambiguated2() {
1031+
let test = cursor_test(
1032+
r#"
1033+
from typing import overload
1034+
1035+
@overload
1036+
def ab(a: int, b: int):
1037+
"""The first overload"""
1038+
1039+
@overload
1040+
def ab(a: int):
1041+
"""The second overload"""
1042+
1043+
def ab(a, b = None): ...
1044+
1045+
a<CURSOR>b(1)
1046+
"#,
1047+
);
1048+
1049+
assert_snapshot!(test.goto_definition(), @r#"
1050+
info[goto-definition]: Definition
1051+
--> main.py:5:5
1052+
|
1053+
4 | @overload
1054+
5 | def ab(a: int, b: int):
1055+
| ^^
1056+
6 | """The first overload"""
1057+
|
1058+
info: Source
1059+
--> main.py:14:1
1060+
|
1061+
12 | def ab(a, b = None): ...
1062+
13 |
1063+
14 | ab(1)
1064+
| ^^
1065+
|
1066+
1067+
info[goto-definition]: Definition
1068+
--> main.py:9:5
1069+
|
1070+
8 | @overload
1071+
9 | def ab(a: int):
1072+
| ^^
1073+
10 | """The second overload"""
1074+
|
1075+
info: Source
1076+
--> main.py:14:1
1077+
|
1078+
12 | def ab(a, b = None): ...
1079+
13 |
1080+
14 | ab(1)
1081+
| ^^
1082+
|
1083+
1084+
info[goto-definition]: Definition
1085+
--> main.py:12:5
1086+
|
1087+
10 | """The second overload"""
1088+
11 |
1089+
12 | def ab(a, b = None): ...
1090+
| ^^
1091+
13 |
1092+
14 | ab(1)
1093+
|
1094+
info: Source
1095+
--> main.py:14:1
1096+
|
1097+
12 | def ab(a, b = None): ...
1098+
13 |
1099+
14 | ab(1)
1100+
| ^^
1101+
|
1102+
"#);
1103+
}
1104+
8011105
impl CursorTest {
8021106
fn goto_definition(&self) -> String {
8031107
let Some(targets) = goto_definition(&self.db, self.cursor.file, self.cursor.offset)

0 commit comments

Comments
 (0)