[ty] Update goto range for attribute access to only target the attribute (#19848)

This commit is contained in:
Matthew Mckee 2025-08-11 15:24:14 +01:00 committed by GitHub
parent 6bc52f2855
commit 5063a73d7f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 75 additions and 34 deletions

View file

@ -557,7 +557,10 @@ impl GotoTarget<'_> {
impl Ranged for GotoTarget<'_> { impl Ranged for GotoTarget<'_> {
fn range(&self) -> TextRange { fn range(&self) -> TextRange {
match self { match self {
GotoTarget::Expression(expression) => expression.range(), GotoTarget::Expression(expression) => match expression {
ast::ExprRef::Attribute(attribute) => attribute.attr.range,
_ => expression.range(),
},
GotoTarget::FunctionDef(function) => function.name.range, GotoTarget::FunctionDef(function) => function.name.range,
GotoTarget::ClassDef(class) => class.name.range, GotoTarget::ClassDef(class) => class.name.range,
GotoTarget::Parameter(parameter) => parameter.name.range, GotoTarget::Parameter(parameter) => parameter.name.range,

View file

@ -865,15 +865,53 @@ def another_helper(path):
6 | c = C() 6 | c = C()
| |
info: Source info: Source
--> main.py:7:17 --> main.py:7:19
| |
6 | c = C() 6 | c = C()
7 | y = c.x 7 | y = c.x
| ^^^ | ^
| |
"); ");
} }
#[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<CURSOR>
",
);
assert_snapshot!(test.goto_declaration(), @r"
info[goto-declaration]: Declaration
--> main.py:4:21
|
2 | class C:
3 | def __init__(self):
4 | self.x: int = 1
| ^^^^^^
5 |
6 | class D:
|
info: Source
--> main.py:11:21
|
10 | d = D()
11 | y = d.y.x
| ^
|
");
}
#[test] #[test]
fn goto_declaration_instance_attribute_no_annotation() { fn goto_declaration_instance_attribute_no_annotation() {
let test = cursor_test( let test = cursor_test(
@ -899,11 +937,11 @@ def another_helper(path):
6 | c = C() 6 | c = C()
| |
info: Source info: Source
--> main.py:7:17 --> main.py:7:19
| |
6 | c = C() 6 | c = C()
7 | y = c.x 7 | y = c.x
| ^^^ | ^
| |
"); ");
} }
@ -931,11 +969,11 @@ def another_helper(path):
4 | return 42 4 | return 42
| |
info: Source info: Source
--> main.py:7:19 --> main.py:7:21
| |
6 | c = C() 6 | c = C()
7 | res = c.foo() 7 | res = c.foo()
| ^^^^^ | ^^^
| |
"); ");
} }
@ -1077,11 +1115,11 @@ def function():
5 | class B(A): 5 | class B(A):
| |
info: Source info: Source
--> main.py:9:17 --> main.py:9:19
| |
8 | b = B() 8 | b = B()
9 | y = b.x 9 | y = b.x
| ^^^ | ^
| |
"); ");
} }
@ -1113,11 +1151,11 @@ def function():
8 | return self._value 8 | return self._value
| |
info: Source info: Source
--> main.py:11:13 --> main.py:11:15
| |
10 | c = C() 10 | c = C()
11 | c.value = 42 11 | c.value = 42
| ^^^^^^^ | ^^^^^
| |
"); ");
} }
@ -1188,11 +1226,11 @@ def function():
8 | def use_drawable(obj: Drawable): 8 | def use_drawable(obj: Drawable):
| |
info: Source info: Source
--> main.py:9:17 --> main.py:9:21
| |
8 | def use_drawable(obj: Drawable): 8 | def use_drawable(obj: Drawable):
9 | obj.name 9 | obj.name
| ^^^^^^^^ | ^^^^
| |
"); ");
} }

View file

@ -439,12 +439,12 @@ class MyOtherClass:
6 | print(self.val) 6 | print(self.val)
| |
info: Source info: Source
--> main.py:4:1 --> main.py:4:3
| |
2 | from mymodule import MyClass 2 | from mymodule import MyClass
3 | x = MyClass(0) 3 | x = MyClass(0)
4 | x.action() 4 | x.action()
| ^^^^^^^^ | ^^^^^^
| |
"); ");
} }
@ -498,11 +498,11 @@ class MyOtherClass:
6 | print("hi!") 6 | print("hi!")
| |
info: Source info: Source
--> main.py:3:5 --> main.py:3:13
| |
2 | from mymodule import MyClass 2 | from mymodule import MyClass
3 | x = MyClass.action() 3 | x = MyClass.action()
| ^^^^^^^^^^^^^^ | ^^^^^^
| |
"#); "#);
} }

View file

@ -189,14 +189,14 @@ mod tests {
``` ```
--------------------------------------------- ---------------------------------------------
info[hover]: Hovered content is info[hover]: Hovered content is
--> main.py:10:9 --> main.py:10:13
| |
9 | foo = Foo() 9 | foo = Foo()
10 | foo.a 10 | foo.a
| ^^^^- | -
| | | | |
| | Cursor offset | source
| source | Cursor offset
| |
"); ");
} }
@ -517,14 +517,14 @@ mod tests {
``` ```
--------------------------------------------- ---------------------------------------------
info[hover]: Hovered content is info[hover]: Hovered content is
--> main.py:5:13 --> main.py:5:15
| |
3 | attr: int = 1 3 | attr: int = 1
4 | 4 |
5 | C.attr = 2 5 | C.attr = 2
| ^^^^^^- Cursor offset | ^^^^- Cursor offset
| | | |
| source | source
| |
"); ");
} }
@ -550,14 +550,14 @@ mod tests {
``` ```
--------------------------------------------- ---------------------------------------------
info[hover]: Hovered content is info[hover]: Hovered content is
--> main.py:5:13 --> main.py:5:15
| |
3 | attr = 1 3 | attr = 1
4 | 4 |
5 | C.attr += 2 5 | C.attr += 2
| ^^^^^^- Cursor offset | ^^^^- Cursor offset
| | | |
| source | source
| |
"); ");
} }
@ -636,14 +636,14 @@ mod tests {
``` ```
--------------------------------------------- ---------------------------------------------
info[hover]: Hovered content is info[hover]: Hovered content is
--> main.py:4:17 --> main.py:4:22
| |
2 | class Foo: 2 | class Foo:
3 | def __init__(self, a: int): 3 | def __init__(self, a: int):
4 | self.a: int = a 4 | self.a: int = a
| ^^^^^^- Cursor offset | ^- Cursor offset
| | | |
| source | source
| |
"); ");
} }