File tree Expand file tree Collapse file tree 2 files changed +65
-0
lines changed Expand file tree Collapse file tree 2 files changed +65
-0
lines changed Original file line number Diff line number Diff line change @@ -152,6 +152,7 @@ impl<'db> ResolutionScope<'db> {
152
152
. left_biased ( )
153
153
. map ( |token| token. parent ( ) )
154
154
. unwrap_or_else ( || file. syntax ( ) . clone ( ) ) ;
155
+ let node = pick_node_for_resolution ( node) ;
155
156
let scope = sema. scope ( & node) ;
156
157
ResolutionScope {
157
158
scope,
@@ -185,6 +186,33 @@ impl<'db> ResolutionScope<'db> {
185
186
}
186
187
}
187
188
189
+ /// Returns a suitable node for resolving paths in the current scope. If we create a scope based on
190
+ /// a statement node, then we can't resolve local variables that were defined in the current scope
191
+ /// (only in parent scopes). So we find another node, ideally a child of the statement where local
192
+ /// variable resolution is permitted.
193
+ fn pick_node_for_resolution ( node : SyntaxNode ) -> SyntaxNode {
194
+ match node. kind ( ) {
195
+ SyntaxKind :: EXPR_STMT => {
196
+ if let Some ( n) = node. first_child ( ) {
197
+ mark:: hit!( cursor_after_semicolon) ;
198
+ return n;
199
+ }
200
+ }
201
+ SyntaxKind :: LET_STMT | SyntaxKind :: BIND_PAT => {
202
+ if let Some ( next) = node. next_sibling ( ) {
203
+ return pick_node_for_resolution ( next) ;
204
+ }
205
+ }
206
+ SyntaxKind :: NAME => {
207
+ if let Some ( parent) = node. parent ( ) {
208
+ return pick_node_for_resolution ( parent) ;
209
+ }
210
+ }
211
+ _ => { }
212
+ }
213
+ node
214
+ }
215
+
188
216
/// Returns whether `path` or any of its qualifiers contains type arguments.
189
217
fn path_contains_type_arguments ( path : Option < ast:: Path > ) -> bool {
190
218
if let Some ( path) = path {
Original file line number Diff line number Diff line change @@ -885,3 +885,40 @@ fn ufcs_matches_method_call() {
885
885
"# ] ] ,
886
886
) ;
887
887
}
888
+
889
+ #[ test]
890
+ fn replace_local_variable_reference ( ) {
891
+ // The pattern references a local variable `foo` in the block containing the cursor. We should
892
+ // only replace references to this variable `foo`, not other variables that just happen to have
893
+ // the same name.
894
+ mark:: check!( cursor_after_semicolon) ;
895
+ assert_ssr_transform (
896
+ "foo + $a ==>> $a - foo" ,
897
+ r#"
898
+ fn bar1() -> i32 {
899
+ let mut res = 0;
900
+ let foo = 5;
901
+ res += foo + 1;
902
+ let foo = 10;
903
+ res += foo + 2;<|>
904
+ res += foo + 3;
905
+ let foo = 15;
906
+ res += foo + 4;
907
+ res
908
+ }
909
+ "# ,
910
+ expect ! [ [ r#"
911
+ fn bar1() -> i32 {
912
+ let mut res = 0;
913
+ let foo = 5;
914
+ res += foo + 1;
915
+ let foo = 10;
916
+ res += 2 - foo;
917
+ res += 3 - foo;
918
+ let foo = 15;
919
+ res += foo + 4;
920
+ res
921
+ }
922
+ "# ] ] ,
923
+ )
924
+ }
You can’t perform that action at this time.
0 commit comments