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> {
152152 . left_biased ( )
153153 . map ( |token| token. parent ( ) )
154154 . unwrap_or_else ( || file. syntax ( ) . clone ( ) ) ;
155+ let node = pick_node_for_resolution ( node) ;
155156 let scope = sema. scope ( & node) ;
156157 ResolutionScope {
157158 scope,
@@ -185,6 +186,33 @@ impl<'db> ResolutionScope<'db> {
185186 }
186187}
187188
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+
188216/// Returns whether `path` or any of its qualifiers contains type arguments.
189217fn path_contains_type_arguments ( path : Option < ast:: Path > ) -> bool {
190218 if let Some ( path) = path {
Original file line number Diff line number Diff line change @@ -885,3 +885,40 @@ fn ufcs_matches_method_call() {
885885 "# ] ] ,
886886 ) ;
887887}
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