Skip to content

Commit d93497a

Browse files
John Van Schultzmeta-codesync[bot]
authored andcommitted
Ensure that renaming a keyword argument also updates the names in function calls within the same file.
Summary: This builds upon the work in previous diffs and implements the local_keyword_argument_referneces_from_parameter_definition in local_references_from_local_definition. In the variable and VariableOrAttribute match arms, we do another check do see if the SymbolKind is either a parameter, variable, or None. If any of these cases are true, we will also include the keyword arguments in the collection that we return. {F1983467395} Reviewed By: kinto0 Differential Revision: D86888748 fbshipit-source-id: 2d51165b7d6df1afab8e3c360af332e65ecedd49
1 parent d3dafa6 commit d93497a

File tree

2 files changed

+103
-4
lines changed

2 files changed

+103
-4
lines changed

pyrefly/lib/state/lsp.rs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2007,14 +2007,15 @@ impl<'a> Transaction<'a> {
20072007
definition_name,
20082008
),
20092009
DefinitionMetadata::Module => Vec::new(),
2010-
DefinitionMetadata::Variable(_) => self
2010+
DefinitionMetadata::Variable(symbol_kind) => self
20112011
.local_variable_references_from_local_definition(
20122012
handle,
20132013
definition_range,
20142014
definition_name,
2015+
symbol_kind,
20152016
)
20162017
.unwrap_or_default(),
2017-
DefinitionMetadata::VariableOrAttribute(_) => [
2018+
DefinitionMetadata::VariableOrAttribute(symbol_kind) => [
20182019
self.local_attribute_references_from_local_definition(
20192020
handle,
20202021
definition_range,
@@ -2024,6 +2025,7 @@ impl<'a> Transaction<'a> {
20242025
handle,
20252026
definition_range,
20262027
definition_name,
2028+
symbol_kind,
20272029
)
20282030
.unwrap_or_default(),
20292031
]
@@ -2152,7 +2154,6 @@ impl<'a> Transaction<'a> {
21522154
results
21532155
}
21542156

2155-
#[allow(dead_code)]
21562157
pub(crate) fn local_keyword_argument_references_from_parameter_definition(
21572158
&self,
21582159
handle: &Handle,
@@ -2198,6 +2199,7 @@ impl<'a> Transaction<'a> {
21982199
handle: &Handle,
21992200
definition_range: TextRange,
22002201
expected_name: &Name,
2202+
symbol_kind: Option<SymbolKind>,
22012203
) -> Option<Vec<TextRange>> {
22022204
let mut references = Vec::new();
22032205
if let Some(mod_module) = self.get_ast(handle) {
@@ -2229,6 +2231,21 @@ impl<'a> Transaction<'a> {
22292231
}
22302232
mod_module.visit(&mut |x| f(x, &is_valid_use, &mut references));
22312233
}
2234+
2235+
if let Some(kind) = symbol_kind
2236+
&& (kind == SymbolKind::Parameter || kind == SymbolKind::Variable)
2237+
{
2238+
let kwarg_references = self
2239+
.local_keyword_argument_references_from_parameter_definition(
2240+
handle,
2241+
definition_range,
2242+
expected_name,
2243+
);
2244+
2245+
if let Some(refs) = kwarg_references {
2246+
references.extend(refs);
2247+
}
2248+
}
22322249
Some(references)
22332250
}
22342251

pyrefly/lib/test/lsp/rename.rs

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ fn get_test_report(state: &State, handle: &Handle, position: TextSize) -> String
2828
}
2929

3030
#[test]
31-
fn test_rename_parameter_does_not_update_keyword_arguments() {
31+
fn test_rename_parameter_updates_keyword_arguments() {
3232
let code = r#"
3333
def greet(name, message):
3434
"""Greet someone with a message."""
@@ -53,6 +53,88 @@ Rename locations:
5353
^^^^
5454
5 | return name
5555
^^^^
56+
8 | result = greet(name="Alice", message="Hello")
57+
^^^^
58+
"#
59+
.trim(),
60+
report.trim(),
61+
);
62+
}
63+
64+
#[test]
65+
fn test_rename_parameter_only_updates_correct_function() {
66+
let code = r#"
67+
def func1(name, message):
68+
"""First function with name parameter."""
69+
print(f"{message}, {name}!")
70+
return name
71+
72+
def func2(name, value):
73+
"""Second function with same name parameter."""
74+
print(f"Value: {value}, Name: {name}")
75+
return name
76+
77+
def caller():
78+
result1 = func1(name="Alice", message="Hello")
79+
# ^
80+
result2 = func2(name="Bob", value=42)
81+
return result1, result2
82+
"#;
83+
let report = get_batched_lsp_operations_report(&[("main", code)], get_test_report);
84+
assert_eq!(
85+
r#"
86+
# main.py
87+
13 | result1 = func1(name="Alice", message="Hello")
88+
^
89+
Rename locations:
90+
2 | def func1(name, message):
91+
^^^^
92+
4 | print(f"{message}, {name}!")
93+
^^^^
94+
5 | return name
95+
^^^^
96+
13 | result1 = func1(name="Alice", message="Hello")
97+
^^^^
98+
"#
99+
.trim(),
100+
report.trim(),
101+
);
102+
}
103+
104+
#[test]
105+
fn test_rename_function_parameter_updates_call_sites() {
106+
let code = r#"
107+
def greet(name, message):
108+
# ^
109+
"""Greet someone with a message."""
110+
print(f"{message}, {name}!")
111+
return name
112+
113+
def caller():
114+
result1 = greet(name="Alice", message="Hello")
115+
result2 = greet(message="Hi", name="Bob")
116+
result3 = greet(name="Charlie", message="Hey")
117+
return result1, result2, result3
118+
"#;
119+
let report = get_batched_lsp_operations_report(&[("main", code)], get_test_report);
120+
assert_eq!(
121+
r#"
122+
# main.py
123+
2 | def greet(name, message):
124+
^
125+
Rename locations:
126+
2 | def greet(name, message):
127+
^^^^
128+
5 | print(f"{message}, {name}!")
129+
^^^^
130+
6 | return name
131+
^^^^
132+
9 | result1 = greet(name="Alice", message="Hello")
133+
^^^^
134+
10 | result2 = greet(message="Hi", name="Bob")
135+
^^^^
136+
11 | result3 = greet(name="Charlie", message="Hey")
137+
^^^^
56138
"#
57139
.trim(),
58140
report.trim(),

0 commit comments

Comments
 (0)