use crate::goto::find_goto_target; use crate::{Db, NavigationTargets, RangedValue}; use ruff_db::files::{File, FileRange}; use ruff_db::parsed::parsed_module; use ruff_text_size::{Ranged, TextSize}; use ty_python_semantic::{ImportAliasResolution, SemanticModel}; /// Navigate to the declaration of a symbol. /// /// A "declaration" includes both formal declarations (class statements, def statements, /// and variable annotations) but also variable assignments. This expansive definition /// is needed because Python doesn't require formal declarations of variables like most languages do. pub fn goto_declaration( db: &dyn Db, file: File, offset: TextSize, ) -> Option> { let module = parsed_module(db, file).load(db); let model = SemanticModel::new(db, file); let goto_target = find_goto_target(&model, &module, offset)?; let declaration_targets = goto_target .get_definition_targets(&model, ImportAliasResolution::ResolveAliases)? .declaration_targets(db)?; Some(RangedValue { range: FileRange::new(file, goto_target.range()), value: declaration_targets, }) } #[cfg(test)] mod tests { use crate::goto_declaration; use crate::tests::{CursorTest, cursor_test}; use insta::assert_snapshot; #[test] fn goto_declaration_function_call_to_definition() { let test = cursor_test( " def my_function(x, y): return x + y result = my_function(1, 2) ", ); assert_snapshot!(test.goto_declaration(), @r" info[goto-declaration]: Go to declaration --> main.py:5:10 | 3 | return x + y 4 | 5 | result = my_function(1, 2) | ^^^^^^^^^^^ Clicking here | info: Found 1 declaration --> main.py:2:5 | 2 | def my_function(x, y): | ----------- 3 | return x + y | "); } #[test] fn goto_declaration_variable_assignment() { let test = cursor_test( " x = 42 y = x ", ); assert_snapshot!(test.goto_declaration(), @r" info[goto-declaration]: Go to declaration --> main.py:3:5 | 2 | x = 42 3 | y = x | ^ Clicking here | info: Found 1 declaration --> main.py:2:1 | 2 | x = 42 | - 3 | y = x | "); } #[test] fn goto_declaration_class_instantiation() { let test = cursor_test( " class MyClass: def __init__(self): pass instance = MyClass() ", ); assert_snapshot!(test.goto_declaration(), @r" info[goto-declaration]: Go to declaration --> main.py:6:12 | 4 | pass 5 | 6 | instance = MyClass() | ^^^^^^^ Clicking here | info: Found 2 declarations --> main.py:2:7 | 2 | class MyClass: | ------- 3 | def __init__(self): | -------- 4 | pass | "); } #[test] fn goto_declaration_parameter_usage() { let test = cursor_test( " def foo(param): return param * 2 ", ); assert_snapshot!(test.goto_declaration(), @r" info[goto-declaration]: Go to declaration --> main.py:3:12 | 2 | def foo(param): 3 | return param * 2 | ^^^^^ Clicking here | info: Found 1 declaration --> main.py:2:9 | 2 | def foo(param): | ----- 3 | return param * 2 | "); } #[test] fn goto_declaration_type_parameter() { let test = cursor_test( " def generic_func[T](value: T) -> T: v: T = value return v ", ); assert_snapshot!(test.goto_declaration(), @r" info[goto-declaration]: Go to declaration --> main.py:3:8 | 2 | def generic_func[T](value: T) -> T: 3 | v: T = value | ^ Clicking here 4 | return v | info: Found 1 declaration --> main.py:2:18 | 2 | def generic_func[T](value: T) -> T: | - 3 | v: T = value 4 | return v | "); } #[test] fn goto_declaration_type_parameter_class() { let test = cursor_test( " class GenericClass[T]: def __init__(self, value: T): self.value = value ", ); assert_snapshot!(test.goto_declaration(), @r" info[goto-declaration]: Go to declaration --> main.py:3:31 | 2 | class GenericClass[T]: 3 | def __init__(self, value: T): | ^ Clicking here 4 | self.value = value | info: Found 1 declaration --> main.py:2:20 | 2 | class GenericClass[T]: | - 3 | def __init__(self, value: T): 4 | self.value = value | "); } #[test] fn goto_declaration_nested_scope_variable() { let test = cursor_test( " x = \"outer\" def outer_func(): def inner_func(): return x # Should find outer x return inner_func ", ); assert_snapshot!(test.goto_declaration(), @r#" info[goto-declaration]: Go to declaration --> main.py:5:16 | 3 | def outer_func(): 4 | def inner_func(): 5 | return x # Should find outer x | ^ Clicking here 6 | return inner_func | info: Found 1 declaration --> main.py:2:1 | 2 | x = "outer" | - 3 | def outer_func(): 4 | def inner_func(): | "#); } #[test] fn goto_declaration_class_scope_skipped() { let test = cursor_test( r#" class A: x = 1 def method(self): def inner(): return x # Should NOT find class variable x return inner "#, ); // Should not find the class variable 'x' due to Python's scoping rules assert_snapshot!(test.goto_declaration(), @"No goto target found"); } #[test] fn goto_declaration_import_simple() { let test = CursorTest::builder() .source( "main.py", " import mymodule print(mymodule.function()) ", ) .source( "mymodule.py", r#" def function(): return "hello from mymodule" variable = 42 "#, ) .build(); assert_snapshot!(test.goto_declaration(), @r#" info[goto-declaration]: Go to declaration --> main.py:3:7 | 2 | import mymodule 3 | print(mymodule.function()) | ^^^^^^^^ Clicking here | info: Found 1 declaration --> mymodule.py:1:1 | 1 | | - 2 | def function(): 3 | return "hello from mymodule" | "#); } #[test] fn goto_declaration_import_from() { let test = CursorTest::builder() .source( "main.py", " from mymodule import my_function print(my_function()) ", ) .source( "mymodule.py", r#" def my_function(): return "hello" def other_function(): return "other" "#, ) .build(); assert_snapshot!(test.goto_declaration(), @r#" info[goto-declaration]: Go to declaration --> main.py:3:7 | 2 | from mymodule import my_function 3 | print(my_function()) | ^^^^^^^^^^^ Clicking here | info: Found 1 declaration --> mymodule.py:2:5 | 2 | def my_function(): | ----------- 3 | return "hello" | "#); } #[test] fn goto_declaration_import_as() { let test = CursorTest::builder() .source( "main.py", " import mymodule.submodule as sub print(sub.helper()) ", ) .source( "mymodule/__init__.py", " # Main module init ", ) .source( "mymodule/submodule.py", r#" FOO = 0 "#, ) .build(); // Should find the submodule file itself assert_snapshot!(test.goto_declaration(), @r" info[goto-declaration]: Go to declaration --> main.py:3:7 | 2 | import mymodule.submodule as sub 3 | print(sub.helper()) | ^^^ Clicking here | info: Found 1 declaration --> mymodule/submodule.py:1:1 | 1 | | - 2 | FOO = 0 | "); } #[test] fn goto_declaration_from_import_as() { let test = CursorTest::builder() .source( "main.py", r#" from utils import func as h print(h("test")) "#, ) .source( "utils.py", r#" def func(arg): return f"Processed: {arg}" "#, ) .build(); // Should resolve to the actual function definition, not the import statement assert_snapshot!(test.goto_declaration(), @r#" info[goto-declaration]: Go to declaration --> main.py:3:7 | 2 | from utils import func as h 3 | print(h("test")) | ^ Clicking here | info: Found 1 declaration --> utils.py:2:5 | 2 | def func(arg): | ---- 3 | return f"Processed: {arg}" | "#); } #[test] fn goto_declaration_from_import_chain() { let test = CursorTest::builder() .source( "main.py", r#" from intermediate import shared_function print(shared_function()) "#, ) .source( "intermediate.py", r#" # Re-export the function from the original module from original import shared_function "#, ) .source( "original.py", r#" def shared_function(): return "from original" "#, ) .build(); assert_snapshot!(test.goto_declaration(), @r#" info[goto-declaration]: Go to declaration --> main.py:3:7 | 2 | from intermediate import shared_function 3 | print(shared_function()) | ^^^^^^^^^^^^^^^ Clicking here | info: Found 1 declaration --> original.py:2:5 | 2 | def shared_function(): | --------------- 3 | return "from original" | "#); } #[test] fn goto_declaration_from_star_import() { let test = CursorTest::builder() .source( "main.py", r#" from math_utils import * result = add_numbers(5, 3) "#, ) .source( "math_utils.py", r#" def add_numbers(a, b): """Add two numbers together.""" return a + b def multiply_numbers(a, b): """Multiply two numbers together.""" return a * b "#, ) .build(); assert_snapshot!(test.goto_declaration(), @r#" info[goto-declaration]: Go to declaration --> main.py:3:10 | 2 | from math_utils import * 3 | result = add_numbers(5, 3) | ^^^^^^^^^^^ Clicking here | info: Found 1 declaration --> math_utils.py:2:5 | 2 | def add_numbers(a, b): | ----------- 3 | """Add two numbers together.""" 4 | return a + b | "#); } #[test] fn goto_declaration_relative_import() { let test = CursorTest::builder() .source( "package/main.py", r#" from .utils import helper_function result = helper_function("test") "#, ) .source( "package/__init__.py", r#" # Package init file "#, ) .source( "package/utils.py", r#" def helper_function(arg): """A helper function in utils module.""" return f"Processed: {arg}" def another_helper(): """Another helper function.""" pass "#, ) .build(); // Should resolve the relative import to find the actual function definition assert_snapshot!(test.goto_declaration(), @r#" info[goto-declaration]: Go to declaration --> package/main.py:3:10 | 2 | from .utils import helper_function 3 | result = helper_function("test") | ^^^^^^^^^^^^^^^ Clicking here | info: Found 1 declaration --> package/utils.py:2:5 | 2 | def helper_function(arg): | --------------- 3 | """A helper function in utils module.""" 4 | return f"Processed: {arg}" | "#); } #[test] fn goto_declaration_relative_star_import() { let test = CursorTest::builder() .source( "package/main.py", r#" from .utils import * result = helper_function("test") "#, ) .source( "package/__init__.py", r#" # Package init file "#, ) .source( "package/utils.py", r#" def helper_function(arg): """A helper function in utils module.""" return f"Processed: {arg}" def another_helper(): """Another helper function.""" pass "#, ) .build(); assert_snapshot!(test.goto_declaration(), @r#" info[goto-declaration]: Go to declaration --> package/main.py:3:10 | 2 | from .utils import * 3 | result = helper_function("test") | ^^^^^^^^^^^^^^^ Clicking here | info: Found 1 declaration --> package/utils.py:2:5 | 2 | def helper_function(arg): | --------------- 3 | """A helper function in utils module.""" 4 | return f"Processed: {arg}" | "#); } #[test] fn goto_declaration_import_as_alias_name() { let test = CursorTest::builder() .source( "main.py", " import mymodule.submodule as sub print(sub.helper()) ", ) .source( "mymodule/__init__.py", " # Main module init ", ) .source( "mymodule/submodule.py", r#" FOO = 0 "#, ) .build(); assert_snapshot!(test.goto_declaration(), @r" info[goto-declaration]: Go to declaration --> main.py:2:30 | 2 | import mymodule.submodule as sub | ^^^ Clicking here 3 | print(sub.helper()) | info: Found 1 declaration --> mymodule/submodule.py:1:1 | 1 | | - 2 | FOO = 0 | "); } #[test] fn goto_declaration_import_as_alias_name_on_module() { let test = CursorTest::builder() .source( "main.py", " import mymodule.submodule as sub print(sub.helper()) ", ) .source( "mymodule/__init__.py", " # Main module init ", ) .source( "mymodule/submodule.py", r#" FOO = 0 "#, ) .build(); assert_snapshot!(test.goto_declaration(), @r" info[goto-declaration]: Go to declaration --> main.py:2:17 | 2 | import mymodule.submodule as sub | ^^^^^^^^^ Clicking here 3 | print(sub.helper()) | info: Found 1 declaration --> mymodule/submodule.py:1:1 | 1 | | - 2 | FOO = 0 | "); } #[test] fn goto_declaration_from_import_symbol_original() { let test = CursorTest::builder() .source( "main.py", r#" from mypackage.utils import helper as h result = h("/a", "/b") "#, ) .source( "mypackage/__init__.py", r#" # Package init "#, ) .source( "mypackage/utils.py", r#" def helper(a, b): return a + "/" + b def another_helper(path): return "processed" "#, ) .build(); assert_snapshot!(test.goto_declaration(), @r#" info[goto-declaration]: Go to declaration --> main.py:2:29 | 2 | from mypackage.utils import helper as h | ^^^^^^ Clicking here 3 | result = h("/a", "/b") | info: Found 1 declaration --> mypackage/utils.py:2:5 | 2 | def helper(a, b): | ------ 3 | return a + "/" + b | "#); } #[test] fn goto_declaration_from_import_symbol_alias() { let test = CursorTest::builder() .source( "main.py", r#" from mypackage.utils import helper as h result = h("/a", "/b") "#, ) .source( "mypackage/__init__.py", r#" # Package init "#, ) .source( "mypackage/utils.py", r#" def helper(a, b): return a + "/" + b def another_helper(path): return "processed" "#, ) .build(); assert_snapshot!(test.goto_declaration(), @r#" info[goto-declaration]: Go to declaration --> main.py:2:39 | 2 | from mypackage.utils import helper as h | ^ Clicking here 3 | result = h("/a", "/b") | info: Found 1 declaration --> mypackage/utils.py:2:5 | 2 | def helper(a, b): | ------ 3 | return a + "/" + b | "#); } #[test] fn goto_declaration_from_import_module() { let test = CursorTest::builder() .source( "main.py", r#" from mypackage.utils import helper as h result = h("/a", "/b") "#, ) .source( "mypackage/__init__.py", r#" # Package init "#, ) .source( "mypackage/utils.py", r#" def helper(a, b): return a + "/" + b def another_helper(path): return "processed" "#, ) .build(); assert_snapshot!(test.goto_declaration(), @r#" info[goto-declaration]: Go to declaration --> main.py:2:16 | 2 | from mypackage.utils import helper as h | ^^^^^ Clicking here 3 | result = h("/a", "/b") | info: Found 1 declaration --> mypackage/utils.py:1:1 | 1 | | - 2 | def helper(a, b): 3 | return a + "/" + b | "#); } #[test] fn goto_declaration_instance_attribute() { let test = cursor_test( " class C: def __init__(self): self.x: int = 1 c = C() y = c.x ", ); assert_snapshot!(test.goto_declaration(), @r" info[goto-declaration]: Go to declaration --> main.py:7:7 | 6 | c = C() 7 | y = c.x | ^ Clicking here | info: Found 1 declaration --> main.py:4:9 | 2 | class C: 3 | def __init__(self): 4 | self.x: int = 1 | ------ 5 | 6 | c = C() | "); } #[test] fn goto_declaration_string_annotation1() { let test = cursor_test( r#" a: "MyClass" = 1 class MyClass: """some docs""" "#, ); assert_snapshot!(test.goto_declaration(), @r#" info[goto-declaration]: Go to declaration --> main.py:2:5 | 2 | a: "MyClass" = 1 | ^^^^^^^ Clicking here 3 | 4 | class MyClass: | info: Found 1 declaration --> main.py:4:7 | 2 | a: "MyClass" = 1 3 | 4 | class MyClass: | ------- 5 | """some docs""" | "#); } #[test] fn goto_declaration_string_annotation2() { let test = cursor_test( r#" a: "None | MyClass" = 1 class MyClass: """some docs""" "#, ); assert_snapshot!(test.goto_declaration(), @r#" info[goto-declaration]: Go to declaration --> main.py:2:12 | 2 | a: "None | MyClass" = 1 | ^^^^^^^ Clicking here 3 | 4 | class MyClass: | info: Found 1 declaration --> main.py:4:7 | 2 | a: "None | MyClass" = 1 3 | 4 | class MyClass: | ------- 5 | """some docs""" | "#); } #[test] fn goto_declaration_string_annotation3() { let test = cursor_test( r#" a: "None | MyClass" = 1 class MyClass: """some docs""" "#, ); assert_snapshot!(test.goto_declaration(), @"No goto target found"); } #[test] fn goto_declaration_string_annotation4() { let test = cursor_test( r#" a: "None | MyClass" = 1 class MyClass: """some docs""" "#, ); assert_snapshot!(test.goto_declaration(), @r#" info[goto-declaration]: Go to declaration --> main.py:2:12 | 2 | a: "None | MyClass" = 1 | ^^^^^^^ Clicking here 3 | 4 | class MyClass: | info: Found 1 declaration --> main.py:4:7 | 2 | a: "None | MyClass" = 1 3 | 4 | class MyClass: | ------- 5 | """some docs""" | "#); } #[test] fn goto_declaration_string_annotation5() { let test = cursor_test( r#" a: "None | MyClass" = 1 class MyClass: """some docs""" "#, ); assert_snapshot!(test.goto_declaration(), @"No goto target found"); } #[test] fn goto_declaration_string_annotation_dangling1() { let test = cursor_test( r#" a: "MyClass |" = 1 class MyClass: """some docs""" "#, ); assert_snapshot!(test.goto_declaration(), @"No goto target found"); } #[test] fn goto_declaration_string_annotation_dangling2() { let test = cursor_test( r#" a: "MyClass | No" = 1 class MyClass: """some docs""" "#, ); assert_snapshot!(test.goto_declaration(), @r#" info[goto-declaration]: Go to declaration --> main.py:2:5 | 2 | a: "MyClass | No" = 1 | ^^^^^^^ Clicking here 3 | 4 | class MyClass: | info: Found 1 declaration --> main.py:4:7 | 2 | a: "MyClass | No" = 1 3 | 4 | class MyClass: | ------- 5 | """some docs""" | "#); } #[test] fn goto_declaration_string_annotation_dangling3() { let test = cursor_test( r#" a: "MyClass | No" = 1 class MyClass: """some docs""" "#, ); assert_snapshot!(test.goto_declaration(), @"No goto target found"); } #[test] fn goto_declaration_string_annotation_recursive() { let test = cursor_test( r#" ab: "ab" "#, ); assert_snapshot!(test.goto_declaration(), @r#" info[goto-declaration]: Go to declaration --> main.py:2:6 | 2 | ab: "ab" | ^^ Clicking here | info: Found 1 declaration --> main.py:2:1 | 2 | ab: "ab" | -- | "#); } #[test] fn goto_declaration_string_annotation_unknown() { let test = cursor_test( r#" x: "foobar" "#, ); assert_snapshot!(test.goto_declaration(), @"No goto target found"); } #[test] fn goto_declaration_nested_instance_attribute() { let test = cursor_test( " class C: def __init__(self): self.x: int = 1 class D: def __init__(self): self.y: C = C() d = D() y = d.y.x ", ); assert_snapshot!(test.goto_declaration(), @r" info[goto-declaration]: Go to declaration --> main.py:11:9 | 10 | d = D() 11 | y = d.y.x | ^ Clicking here | info: Found 1 declaration --> main.py:4:9 | 2 | class C: 3 | def __init__(self): 4 | self.x: int = 1 | ------ 5 | 6 | class D: | "); } #[test] fn goto_declaration_instance_attribute_no_annotation() { let test = cursor_test( " class C: def __init__(self): self.x = 1 c = C() y = c.x ", ); assert_snapshot!(test.goto_declaration(), @r" info[goto-declaration]: Go to declaration --> main.py:7:7 | 6 | c = C() 7 | y = c.x | ^ Clicking here | info: Found 1 declaration --> main.py:4:9 | 2 | class C: 3 | def __init__(self): 4 | self.x = 1 | ------ 5 | 6 | c = C() | "); } #[test] fn goto_declaration_method_call_to_definition() { let test = cursor_test( " class C: def foo(self): return 42 c = C() res = c.foo() ", ); assert_snapshot!(test.goto_declaration(), @r" info[goto-declaration]: Go to declaration --> main.py:7:9 | 6 | c = C() 7 | res = c.foo() | ^^^ Clicking here | info: Found 1 declaration --> main.py:3:9 | 2 | class C: 3 | def foo(self): | --- 4 | return 42 | "); } #[test] fn goto_declaration_module_attribute() { let test = cursor_test( r#" x: int = 42 "#, ); // Test that we can navigate to builtin types, but don't snapshot the exact content // since typeshed stubs can change frequently let result = test.goto_declaration(); // Should not be "No goto target found" - we should find the builtin int type assert!( !result.contains("No goto target found"), "Should find builtin int type" ); assert!( !result.contains("No declarations found"), "Should find builtin int declarations" ); // Should navigate to a stdlib file containing the int class assert!( result.contains("builtins.pyi"), "Should navigate to builtins.pyi" ); assert!( result.contains("class int:"), "Should find the int class definition" ); assert!( result.contains("info[goto-declaration]: Go to declaration"), "Should be a goto-declaration result" ); } #[test] fn goto_declaration_nonlocal_binding() { let test = cursor_test( r#" def outer(): x = "outer_value" def inner(): nonlocal x x = "modified" return x # Should find the nonlocal x declaration in outer scope return inner "#, ); // Should find the variable declaration in the outer scope, not the nonlocal statement assert_snapshot!(test.goto_declaration(), @r#" info[goto-declaration]: Go to declaration --> main.py:8:16 | 6 | nonlocal x 7 | x = "modified" 8 | return x # Should find the nonlocal x declaration in outer scope | ^ Clicking here 9 | 10 | return inner | info: Found 1 declaration --> main.py:3:5 | 2 | def outer(): 3 | x = "outer_value" | - 4 | 5 | def inner(): | "#); } #[test] fn goto_declaration_nonlocal_stmt() { let test = cursor_test( r#" def outer(): xy = "outer_value" def inner(): nonlocal xy xy = "modified" return x # Should find the nonlocal x declaration in outer scope return inner "#, ); // Should find the variable declaration in the outer scope, not the nonlocal statement assert_snapshot!(test.goto_declaration(), @r#" info[goto-declaration]: Go to declaration --> main.py:6:18 | 5 | def inner(): 6 | nonlocal xy | ^^ Clicking here 7 | xy = "modified" 8 | return x # Should find the nonlocal x declaration in outer scope | info: Found 1 declaration --> main.py:3:5 | 2 | def outer(): 3 | xy = "outer_value" | -- 4 | 5 | def inner(): | "#); } #[test] fn goto_declaration_global_binding() { let test = cursor_test( r#" global_var = "global_value" def function(): global global_var global_var = "modified" return global_var # Should find the global variable declaration "#, ); // Should find the global variable declaration, not the global statement assert_snapshot!(test.goto_declaration(), @r#" info[goto-declaration]: Go to declaration --> main.py:7:12 | 5 | global global_var 6 | global_var = "modified" 7 | return global_var # Should find the global variable declaration | ^^^^^^^^^^ Clicking here | info: Found 1 declaration --> main.py:2:1 | 2 | global_var = "global_value" | ---------- 3 | 4 | def function(): | "#); } #[test] fn goto_declaration_global_stmt() { let test = cursor_test( r#" global_var = "global_value" def function(): global global_var global_var = "modified" return global_var # Should find the global variable declaration "#, ); // Should find the global variable declaration, not the global statement assert_snapshot!(test.goto_declaration(), @r#" info[goto-declaration]: Go to declaration --> main.py:5:12 | 4 | def function(): 5 | global global_var | ^^^^^^^^^^ Clicking here 6 | global_var = "modified" 7 | return global_var # Should find the global variable declaration | info: Found 1 declaration --> main.py:2:1 | 2 | global_var = "global_value" | ---------- 3 | 4 | def function(): | "#); } #[test] fn goto_declaration_inherited_attribute() { let test = cursor_test( " class A: x = 10 class B(A): pass b = B() y = b.x ", ); assert_snapshot!(test.goto_declaration(), @r" info[goto-declaration]: Go to declaration --> main.py:9:7 | 8 | b = B() 9 | y = b.x | ^ Clicking here | info: Found 1 declaration --> main.py:3:5 | 2 | class A: 3 | x = 10 | - 4 | 5 | class B(A): | "); } #[test] fn goto_declaration_match_name_stmt() { let test = cursor_test( r#" def my_func(command: str): match command.split(): case ["get", ab]: x = ab "#, ); assert_snapshot!(test.goto_declaration(), @r#" info[goto-declaration]: Go to declaration --> main.py:4:22 | 2 | def my_func(command: str): 3 | match command.split(): 4 | case ["get", ab]: | ^^ Clicking here 5 | x = ab | info: Found 1 declaration --> main.py:4:22 | 2 | def my_func(command: str): 3 | match command.split(): 4 | case ["get", ab]: | -- 5 | x = ab | "#); } #[test] fn goto_declaration_match_name_binding() { let test = cursor_test( r#" def my_func(command: str): match command.split(): case ["get", ab]: x = ab "#, ); assert_snapshot!(test.goto_declaration(), @r#" info[goto-declaration]: Go to declaration --> main.py:5:17 | 3 | match command.split(): 4 | case ["get", ab]: 5 | x = ab | ^^ Clicking here | info: Found 1 declaration --> main.py:4:22 | 2 | def my_func(command: str): 3 | match command.split(): 4 | case ["get", ab]: | -- 5 | x = ab | "#); } #[test] fn goto_declaration_match_rest_stmt() { let test = cursor_test( r#" def my_func(command: str): match command.split(): case ["get", *ab]: x = ab "#, ); assert_snapshot!(test.goto_declaration(), @r#" info[goto-declaration]: Go to declaration --> main.py:4:23 | 2 | def my_func(command: str): 3 | match command.split(): 4 | case ["get", *ab]: | ^^ Clicking here 5 | x = ab | info: Found 1 declaration --> main.py:4:23 | 2 | def my_func(command: str): 3 | match command.split(): 4 | case ["get", *ab]: | -- 5 | x = ab | "#); } #[test] fn goto_declaration_match_rest_binding() { let test = cursor_test( r#" def my_func(command: str): match command.split(): case ["get", *ab]: x = ab "#, ); assert_snapshot!(test.goto_declaration(), @r#" info[goto-declaration]: Go to declaration --> main.py:5:17 | 3 | match command.split(): 4 | case ["get", *ab]: 5 | x = ab | ^^ Clicking here | info: Found 1 declaration --> main.py:4:23 | 2 | def my_func(command: str): 3 | match command.split(): 4 | case ["get", *ab]: | -- 5 | x = ab | "#); } #[test] fn goto_declaration_match_as_stmt() { let test = cursor_test( r#" def my_func(command: str): match command.split(): case ["get", ("a" | "b") as ab]: x = ab "#, ); assert_snapshot!(test.goto_declaration(), @r#" info[goto-declaration]: Go to declaration --> main.py:4:37 | 2 | def my_func(command: str): 3 | match command.split(): 4 | case ["get", ("a" | "b") as ab]: | ^^ Clicking here 5 | x = ab | info: Found 1 declaration --> main.py:4:37 | 2 | def my_func(command: str): 3 | match command.split(): 4 | case ["get", ("a" | "b") as ab]: | -- 5 | x = ab | "#); } #[test] fn goto_declaration_match_as_binding() { let test = cursor_test( r#" def my_func(command: str): match command.split(): case ["get", ("a" | "b") as ab]: x = ab "#, ); assert_snapshot!(test.goto_declaration(), @r#" info[goto-declaration]: Go to declaration --> main.py:5:17 | 3 | match command.split(): 4 | case ["get", ("a" | "b") as ab]: 5 | x = ab | ^^ Clicking here | info: Found 1 declaration --> main.py:4:37 | 2 | def my_func(command: str): 3 | match command.split(): 4 | case ["get", ("a" | "b") as ab]: | -- 5 | x = ab | "#); } #[test] fn goto_declaration_match_keyword_stmt() { let test = cursor_test( r#" class Click: __match_args__ = ("position", "button") def __init__(self, pos, btn): self.position: int = pos self.button: str = btn def my_func(event: Click): match event: case Click(x, button=ab): x = ab "#, ); assert_snapshot!(test.goto_declaration(), @r" info[goto-declaration]: Go to declaration --> main.py:10:30 | 8 | def my_func(event: Click): 9 | match event: 10 | case Click(x, button=ab): | ^^ Clicking here 11 | x = ab | info: Found 1 declaration --> main.py:10:30 | 8 | def my_func(event: Click): 9 | match event: 10 | case Click(x, button=ab): | -- 11 | x = ab | "); } #[test] fn goto_declaration_match_keyword_binding() { let test = cursor_test( r#" class Click: __match_args__ = ("position", "button") def __init__(self, pos, btn): self.position: int = pos self.button: str = btn def my_func(event: Click): match event: case Click(x, button=ab): x = ab "#, ); assert_snapshot!(test.goto_declaration(), @r" info[goto-declaration]: Go to declaration --> main.py:11:17 | 9 | match event: 10 | case Click(x, button=ab): 11 | x = ab | ^^ Clicking here | info: Found 1 declaration --> main.py:10:30 | 8 | def my_func(event: Click): 9 | match event: 10 | case Click(x, button=ab): | -- 11 | x = ab | "); } #[test] fn goto_declaration_match_class_name() { let test = cursor_test( r#" class Click: __match_args__ = ("position", "button") def __init__(self, pos, btn): self.position: int = pos self.button: str = btn def my_func(event: Click): match event: case Click(x, button=ab): x = ab "#, ); assert_snapshot!(test.goto_declaration(), @r#" info[goto-declaration]: Go to declaration --> main.py:10:14 | 8 | def my_func(event: Click): 9 | match event: 10 | case Click(x, button=ab): | ^^^^^ Clicking here 11 | x = ab | info: Found 1 declaration --> main.py:2:7 | 2 | class Click: | ----- 3 | __match_args__ = ("position", "button") 4 | def __init__(self, pos, btn): | "#); } #[test] fn goto_declaration_match_class_field_name() { let test = cursor_test( r#" class Click: __match_args__ = ("position", "button") def __init__(self, pos, btn): self.position: int = pos self.button: str = btn def my_func(event: Click): match event: case Click(x, button=ab): x = ab "#, ); assert_snapshot!(test.goto_declaration(), @"No goto target found"); } #[test] fn goto_declaration_typevar_name_stmt() { let test = cursor_test( r#" type Alias1[AB: int = bool] = tuple[AB, list[AB]] "#, ); assert_snapshot!(test.goto_declaration(), @r" info[goto-declaration]: Go to declaration --> main.py:2:13 | 2 | type Alias1[AB: int = bool] = tuple[AB, list[AB]] | ^^ Clicking here | info: Found 1 declaration --> main.py:2:13 | 2 | type Alias1[AB: int = bool] = tuple[AB, list[AB]] | -- | "); } #[test] fn goto_declaration_typevar_name_binding() { let test = cursor_test( r#" type Alias1[AB: int = bool] = tuple[AB, list[AB]] "#, ); assert_snapshot!(test.goto_declaration(), @r" info[goto-declaration]: Go to declaration --> main.py:2:37 | 2 | type Alias1[AB: int = bool] = tuple[AB, list[AB]] | ^^ Clicking here | info: Found 1 declaration --> main.py:2:13 | 2 | type Alias1[AB: int = bool] = tuple[AB, list[AB]] | -- | "); } #[test] fn goto_declaration_typevar_spec_stmt() { let test = cursor_test( r#" from typing import Callable type Alias2[**AB = [int, str]] = Callable[AB, tuple[AB]] "#, ); assert_snapshot!(test.goto_declaration(), @r" info[goto-declaration]: Go to declaration --> main.py:3:15 | 2 | from typing import Callable 3 | type Alias2[**AB = [int, str]] = Callable[AB, tuple[AB]] | ^^ Clicking here | info: Found 1 declaration --> main.py:3:15 | 2 | from typing import Callable 3 | type Alias2[**AB = [int, str]] = Callable[AB, tuple[AB]] | -- | "); } #[test] fn goto_declaration_typevar_spec_binding() { let test = cursor_test( r#" from typing import Callable type Alias2[**AB = [int, str]] = Callable[AB, tuple[AB]] "#, ); assert_snapshot!(test.goto_declaration(), @r" info[goto-declaration]: Go to declaration --> main.py:3:43 | 2 | from typing import Callable 3 | type Alias2[**AB = [int, str]] = Callable[AB, tuple[AB]] | ^^ Clicking here | info: Found 1 declaration --> main.py:3:15 | 2 | from typing import Callable 3 | type Alias2[**AB = [int, str]] = Callable[AB, tuple[AB]] | -- | "); } #[test] fn goto_declaration_typevar_tuple_stmt() { let test = cursor_test( r#" type Alias3[*AB = ()] = tuple[tuple[*AB], tuple[*AB]] "#, ); assert_snapshot!(test.goto_declaration(), @r" info[goto-declaration]: Go to declaration --> main.py:2:14 | 2 | type Alias3[*AB = ()] = tuple[tuple[*AB], tuple[*AB]] | ^^ Clicking here | info: Found 1 declaration --> main.py:2:14 | 2 | type Alias3[*AB = ()] = tuple[tuple[*AB], tuple[*AB]] | -- | "); } #[test] fn goto_declaration_typevar_tuple_binding() { let test = cursor_test( r#" type Alias3[*AB = ()] = tuple[tuple[*AB], tuple[*AB]] "#, ); assert_snapshot!(test.goto_declaration(), @r" info[goto-declaration]: Go to declaration --> main.py:2:38 | 2 | type Alias3[*AB = ()] = tuple[tuple[*AB], tuple[*AB]] | ^^ Clicking here | info: Found 1 declaration --> main.py:2:14 | 2 | type Alias3[*AB = ()] = tuple[tuple[*AB], tuple[*AB]] | -- | "); } #[test] fn goto_declaration_property_getter_setter() { let test = cursor_test( " class C: def __init__(self): self._value = 0 @property def value(self): return self._value c = C() c.value = 42 ", ); assert_snapshot!(test.goto_declaration(), @r" info[goto-declaration]: Go to declaration --> main.py:11:3 | 10 | c = C() 11 | c.value = 42 | ^^^^^ Clicking here | info: Found 1 declaration --> main.py:7:9 | 6 | @property 7 | def value(self): | ----- 8 | return self._value | "); } #[test] fn goto_declaration_function_doc_attribute() { let test = cursor_test( r#" def my_function(): """This is a docstring.""" return 42 doc = my_function.__doc__ "#, ); // Should navigate to the __doc__ property in the FunctionType class in typeshed let result = test.goto_declaration(); assert!( !result.contains("No goto target found"), "Should find builtin __doc__ attribute" ); assert!( !result.contains("No declarations found"), "Should find builtin __doc__ declarations" ); // Should navigate to a typeshed file containing the __doc__ attribute assert!( result.contains("types.pyi") || result.contains("builtins.pyi"), "Should navigate to typeshed file with __doc__ definition" ); assert!( result.contains("__doc__"), "Should find the __doc__ attribute definition" ); assert!( result.contains("info[goto-declaration]: Go to declaration"), "Should be a goto-declaration result" ); } #[test] fn goto_declaration_protocol_instance_attribute() { let test = cursor_test( " from typing import Protocol class Drawable(Protocol): def draw(self) -> None: ... name: str def use_drawable(obj: Drawable): obj.name ", ); assert_snapshot!(test.goto_declaration(), @r" info[goto-declaration]: Go to declaration --> main.py:9:9 | 8 | def use_drawable(obj: Drawable): 9 | obj.name | ^^^^ Clicking here | info: Found 1 declaration --> main.py:6:5 | 4 | class Drawable(Protocol): 5 | def draw(self) -> None: ... 6 | name: str | ---- 7 | 8 | def use_drawable(obj: Drawable): | "); } #[test] fn goto_declaration_generic_method_class_type() { let test = cursor_test( r#" class MyClass: ClassType = int def generic_method[T](self, value: ClassType) -> T: return value "#, ); // Should find the ClassType defined in the class body, not fail to resolve assert_snapshot!(test.goto_declaration(), @r" info[goto-declaration]: Go to declaration --> main.py:5:40 | 3 | ClassType = int 4 | 5 | def generic_method[T](self, value: ClassType) -> T: | ^^^^^^^^^ Clicking here 6 | return value | info: Found 1 declaration --> main.py:3:5 | 2 | class MyClass: 3 | ClassType = int | --------- 4 | 5 | def generic_method[T](self, value: ClassType) -> T: | "); } #[test] fn goto_declaration_keyword_argument_simple() { let test = cursor_test( " def my_function(x, y, z=10): return x + y + z result = my_function(1, y=2, z=3) ", ); assert_snapshot!(test.goto_declaration(), @r" info[goto-declaration]: Go to declaration --> main.py:5:25 | 3 | return x + y + z 4 | 5 | result = my_function(1, y=2, z=3) | ^ Clicking here | info: Found 1 declaration --> main.py:2:20 | 2 | def my_function(x, y, z=10): | - 3 | return x + y + z | "); } #[test] fn goto_declaration_keyword_argument_overloaded() { let test = cursor_test( r#" from typing import overload @overload def process(data: str, format: str) -> str: ... @overload def process(data: int, format: int) -> int: ... def process(data, format): return data # Call the overloaded function result = process("hello", format="json") "#, ); // Should navigate to the parameter in both matching overloads assert_snapshot!(test.goto_declaration(), @r#" info[goto-declaration]: Go to declaration --> main.py:14:27 | 13 | # Call the overloaded function 14 | result = process("hello", format="json") | ^^^^^^ Clicking here | info: Found 2 declarations --> main.py:5:24 | 4 | @overload 5 | def process(data: str, format: str) -> str: ... | ------ 6 | 7 | @overload 8 | def process(data: int, format: int) -> int: ... | ------ 9 | 10 | def process(data, format): | "#); } #[test] fn goto_declaration_overload_type_disambiguated1() { let test = CursorTest::builder() .source( "main.py", " from mymodule import ab ab(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]: Go to declaration --> main.py:4:1 | 2 | from mymodule import ab 3 | 4 | ab(1) | ^^ Clicking here | info: Found 2 declarations --> mymodule.pyi:5:5 | 4 | @overload 5 | def ab(a: int): ... | -- 6 | 7 | @overload 8 | def ab(a: str): ... | -- | "); } #[test] fn goto_declaration_overload_type_disambiguated2() { let test = CursorTest::builder() .source( "main.py", r#" from mymodule import ab ab("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]: Go to declaration --> main.py:4:1 | 2 | from mymodule import ab 3 | 4 | ab("hello") | ^^ Clicking here | info: Found 2 declarations --> mymodule.pyi:5:5 | 4 | @overload 5 | def ab(a: int): ... | -- 6 | 7 | @overload 8 | def ab(a: str): ... | -- | "#); } #[test] fn goto_declaration_overload_arity_disambiguated1() { let test = CursorTest::builder() .source( "main.py", " from mymodule import ab ab(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]: Go to declaration --> main.py:4:1 | 2 | from mymodule import ab 3 | 4 | ab(1, 2) | ^^ Clicking here | info: Found 2 declarations --> mymodule.pyi:5:5 | 4 | @overload 5 | def ab(a: int, b: int): ... | -- 6 | 7 | @overload 8 | def ab(a: int): ... | -- | "); } #[test] fn goto_declaration_overload_arity_disambiguated2() { let test = CursorTest::builder() .source( "main.py", " from mymodule import ab ab(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]: Go to declaration --> main.py:4:1 | 2 | from mymodule import ab 3 | 4 | ab(1) | ^^ Clicking here | info: Found 2 declarations --> mymodule.pyi:5:5 | 4 | @overload 5 | def ab(a: int, b: int): ... | -- 6 | 7 | @overload 8 | def ab(a: int): ... | -- | "); } #[test] fn goto_declaration_overload_keyword_disambiguated1() { let test = CursorTest::builder() .source( "main.py", " from mymodule import ab ab(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]: Go to declaration --> main.py:4:1 | 2 | from mymodule import ab 3 | 4 | ab(1, b=2) | ^^ Clicking here | info: Found 3 declarations --> mymodule.pyi:5:5 | 4 | @overload 5 | def ab(a: int): ... | -- 6 | 7 | @overload 8 | def ab(a: int, *, b: int): ... | -- 9 | 10 | @overload 11 | def ab(a: int, *, c: int): ... | -- | "); } #[test] fn goto_declaration_overload_keyword_disambiguated2() { let test = CursorTest::builder() .source( "main.py", " from mymodule import ab ab(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]: Go to declaration --> main.py:4:1 | 2 | from mymodule import ab 3 | 4 | ab(1, c=2) | ^^ Clicking here | info: Found 3 declarations --> mymodule.pyi:5:5 | 4 | @overload 5 | def ab(a: int): ... | -- 6 | 7 | @overload 8 | def ab(a: int, *, b: int): ... | -- 9 | 10 | @overload 11 | 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 = subpkg "#, ) .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]: Go to declaration --> mypackage/__init__.py:4:5 | 2 | from .subpkg.submod import val 3 | 4 | x = subpkg | ^^^^^^ Clicking here | info: Found 1 declaration --> mypackage/__init__.py:2:1 | 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 .subpkg.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]: Go to declaration --> mypackage/__init__.py:2:7 | 2 | from .subpkg.submod import val | ^^^^^^ Clicking here 3 | 4 | x = subpkg | info: Found 1 declaration --> mypackage/subpkg/__init__.py:1:1 | | "); } #[test] fn goto_declaration_submodule_import_from_wrong_use() { let test = CursorTest::builder() .source( "mypackage/__init__.py", r#" from .subpkg.submod import val x = submod "#, ) .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.submod 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]: Go to declaration --> mypackage/__init__.py:2:14 | 2 | from .subpkg.submod import val | ^^^^^^ Clicking here 3 | 4 | x = submod | info: Found 1 declaration --> mypackage/subpkg/submod.py:1:1 | 1 | | - 2 | val: int = 0 | "); } #[test] fn goto_declaration_submodule_import_from_confusing_shadowed_def() { let test = CursorTest::builder() .source( "mypackage/__init__.py", r#" from .subpkg 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]: Go to declaration --> mypackage/__init__.py:2:7 | 2 | from .subpkg import subpkg | ^^^^^^ Clicking here 3 | 4 | x = subpkg | info: Found 1 declaration --> mypackage/subpkg/__init__.py:1:1 | 1 | | - 2 | subpkg: int = 10 | "); } #[test] fn goto_declaration_submodule_import_from_confusing_real_def() { let test = CursorTest::builder() .source( "mypackage/__init__.py", r#" from .subpkg import subpkg 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]: Go to declaration --> mypackage/__init__.py:2:21 | 2 | from .subpkg import subpkg | ^^^^^^ Clicking here 3 | 4 | x = subpkg | info: Found 1 declaration --> mypackage/subpkg/__init__.py:2:1 | 2 | subpkg: int = 10 | ------ | "); } #[test] fn goto_declaration_submodule_import_from_confusing_use() { let test = CursorTest::builder() .source( "mypackage/__init__.py", r#" from .subpkg import subpkg x = subpkg "#, ) .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]: Go to declaration --> mypackage/__init__.py:4:5 | 2 | from .subpkg import subpkg 3 | 4 | x = subpkg | ^^^^^^ Clicking here | info: Found 2 declarations --> mypackage/__init__.py:2:1 | 2 | from .subpkg import subpkg | -------------------------- 3 | 4 | x = subpkg | ::: mypackage/subpkg/__init__.py:2:1 | 2 | subpkg: int = 10 | ------ | "); } // TODO: Should only return `a: int` #[test] fn redeclarations() { let test = CursorTest::builder() .source( "main.py", r#" a: str = "test" a: int = 10 print(a) a: bool = True "#, ) .build(); assert_snapshot!(test.goto_declaration(), @r#" info[goto-declaration]: Go to declaration --> main.py:6:7 | 4 | a: int = 10 5 | 6 | print(a) | ^ Clicking here 7 | 8 | a: bool = True | info: Found 3 declarations --> main.py:2:1 | 2 | a: str = "test" | - 3 | 4 | a: int = 10 | - 5 | 6 | print(a) 7 | 8 | a: bool = True | - | "#); } impl CursorTest { fn goto_declaration(&self) -> String { let Some(targets) = salsa::attach(&self.db, || { goto_declaration(&self.db, self.cursor.file, self.cursor.offset) }) else { return "No goto target found".to_string(); }; if targets.is_empty() { return "No declarations found".to_string(); } self.render_diagnostics([crate::goto_definition::test::GotoDiagnostic::new( crate::goto_definition::test::GotoAction::Declaration, targets, )]) } } }