diff options
-rw-r--r-- | crates/ra_assists/src/handlers/inline_local_variable.rs | 29 | ||||
-rw-r--r-- | crates/ra_assists/src/marks.rs | 5 | ||||
-rw-r--r-- | crates/ra_hir/src/semantics.rs | 8 | ||||
-rw-r--r-- | crates/ra_hir/src/source_analyzer.rs | 35 |
4 files changed, 23 insertions, 54 deletions
diff --git a/crates/ra_assists/src/handlers/inline_local_variable.rs b/crates/ra_assists/src/handlers/inline_local_variable.rs index eb5112343..3bfcba8ff 100644 --- a/crates/ra_assists/src/handlers/inline_local_variable.rs +++ b/crates/ra_assists/src/handlers/inline_local_variable.rs | |||
@@ -1,3 +1,4 @@ | |||
1 | use ra_ide_db::defs::Definition; | ||
1 | use ra_syntax::{ | 2 | use ra_syntax::{ |
2 | ast::{self, AstNode, AstToken}, | 3 | ast::{self, AstNode, AstToken}, |
3 | TextRange, | 4 | TextRange, |
@@ -37,6 +38,15 @@ pub(crate) fn inline_local_variable(ctx: AssistCtx) -> Option<Assist> { | |||
37 | return None; | 38 | return None; |
38 | } | 39 | } |
39 | let initializer_expr = let_stmt.initializer()?; | 40 | let initializer_expr = let_stmt.initializer()?; |
41 | |||
42 | let def = ctx.sema.to_def(&bind_pat)?; | ||
43 | let def = Definition::Local(def); | ||
44 | let refs = def.find_usages(ctx.db, None); | ||
45 | if refs.is_empty() { | ||
46 | tested_by!(test_not_applicable_if_variable_unused); | ||
47 | return None; | ||
48 | }; | ||
49 | |||
40 | let delete_range = if let Some(whitespace) = let_stmt | 50 | let delete_range = if let Some(whitespace) = let_stmt |
41 | .syntax() | 51 | .syntax() |
42 | .next_sibling_or_token() | 52 | .next_sibling_or_token() |
@@ -49,16 +59,14 @@ pub(crate) fn inline_local_variable(ctx: AssistCtx) -> Option<Assist> { | |||
49 | } else { | 59 | } else { |
50 | let_stmt.syntax().text_range() | 60 | let_stmt.syntax().text_range() |
51 | }; | 61 | }; |
52 | let refs = ctx.sema.find_all_refs(&bind_pat); | ||
53 | if refs.is_empty() { | ||
54 | return None; | ||
55 | }; | ||
56 | 62 | ||
57 | let mut wrap_in_parens = vec![true; refs.len()]; | 63 | let mut wrap_in_parens = vec![true; refs.len()]; |
58 | 64 | ||
59 | for (i, desc) in refs.iter().enumerate() { | 65 | for (i, desc) in refs.iter().enumerate() { |
60 | let usage_node = | 66 | let usage_node = ctx |
61 | ctx.covering_node_for_range(desc.range).ancestors().find_map(ast::PathExpr::cast)?; | 67 | .covering_node_for_range(desc.file_range.range) |
68 | .ancestors() | ||
69 | .find_map(ast::PathExpr::cast)?; | ||
62 | let usage_parent_option = usage_node.syntax().parent().and_then(ast::Expr::cast); | 70 | let usage_parent_option = usage_node.syntax().parent().and_then(ast::Expr::cast); |
63 | let usage_parent = match usage_parent_option { | 71 | let usage_parent = match usage_parent_option { |
64 | Some(u) => u, | 72 | Some(u) => u, |
@@ -103,11 +111,9 @@ pub(crate) fn inline_local_variable(ctx: AssistCtx) -> Option<Assist> { | |||
103 | move |edit: &mut ActionBuilder| { | 111 | move |edit: &mut ActionBuilder| { |
104 | edit.delete(delete_range); | 112 | edit.delete(delete_range); |
105 | for (desc, should_wrap) in refs.iter().zip(wrap_in_parens) { | 113 | for (desc, should_wrap) in refs.iter().zip(wrap_in_parens) { |
106 | if should_wrap { | 114 | let replacement = |
107 | edit.replace(desc.range, init_in_paren.clone()) | 115 | if should_wrap { init_in_paren.clone() } else { init_str.clone() }; |
108 | } else { | 116 | edit.replace(desc.file_range.range, replacement) |
109 | edit.replace(desc.range, init_str.clone()) | ||
110 | } | ||
111 | } | 117 | } |
112 | edit.set_cursor(delete_range.start()) | 118 | edit.set_cursor(delete_range.start()) |
113 | }, | 119 | }, |
@@ -657,6 +663,7 @@ fn foo() { | |||
657 | 663 | ||
658 | #[test] | 664 | #[test] |
659 | fn test_not_applicable_if_variable_unused() { | 665 | fn test_not_applicable_if_variable_unused() { |
666 | covers!(test_not_applicable_if_variable_unused); | ||
660 | check_assist_not_applicable( | 667 | check_assist_not_applicable( |
661 | inline_local_variable, | 668 | inline_local_variable, |
662 | r" | 669 | r" |
diff --git a/crates/ra_assists/src/marks.rs b/crates/ra_assists/src/marks.rs index cef3df4e5..22404ee80 100644 --- a/crates/ra_assists/src/marks.rs +++ b/crates/ra_assists/src/marks.rs | |||
@@ -1,9 +1,10 @@ | |||
1 | //! See test_utils/src/marks.rs | 1 | //! See test_utils/src/marks.rs |
2 | 2 | ||
3 | test_utils::marks!( | 3 | test_utils::marks![ |
4 | introduce_var_in_comment_is_not_applicable | 4 | introduce_var_in_comment_is_not_applicable |
5 | test_introduce_var_expr_stmt | 5 | test_introduce_var_expr_stmt |
6 | test_introduce_var_last_expr | 6 | test_introduce_var_last_expr |
7 | not_applicable_outside_of_bind_pat | 7 | not_applicable_outside_of_bind_pat |
8 | test_not_inline_mut_variable | 8 | test_not_inline_mut_variable |
9 | ); | 9 | test_not_applicable_if_variable_unused |
10 | ]; | ||
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs index afc7f7ee7..7ce785791 100644 --- a/crates/ra_hir/src/semantics.rs +++ b/crates/ra_hir/src/semantics.rs | |||
@@ -19,7 +19,7 @@ use rustc_hash::{FxHashMap, FxHashSet}; | |||
19 | use crate::{ | 19 | use crate::{ |
20 | db::HirDatabase, | 20 | db::HirDatabase, |
21 | semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, | 21 | semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, |
22 | source_analyzer::{resolve_hir_path, ReferenceDescriptor, SourceAnalyzer}, | 22 | source_analyzer::{resolve_hir_path, SourceAnalyzer}, |
23 | Function, HirFileId, InFile, Local, MacroDef, Module, ModuleDef, Name, Origin, Path, | 23 | Function, HirFileId, InFile, Local, MacroDef, Module, ModuleDef, Name, Origin, Path, |
24 | PathResolution, ScopeDef, StructField, Trait, Type, TypeParam, VariantDef, | 24 | PathResolution, ScopeDef, StructField, Trait, Type, TypeParam, VariantDef, |
25 | }; | 25 | }; |
@@ -171,12 +171,6 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
171 | SemanticsScope { db: self.db, resolver } | 171 | SemanticsScope { db: self.db, resolver } |
172 | } | 172 | } |
173 | 173 | ||
174 | // FIXME: we only use this in `inline_local_variable` assist, ideally, we | ||
175 | // should switch to general reference search infra there. | ||
176 | pub fn find_all_refs(&self, pat: &ast::BindPat) -> Vec<ReferenceDescriptor> { | ||
177 | self.analyze(pat.syntax()).find_all_refs(pat) | ||
178 | } | ||
179 | |||
180 | fn analyze(&self, node: &SyntaxNode) -> SourceAnalyzer { | 174 | fn analyze(&self, node: &SyntaxNode) -> SourceAnalyzer { |
181 | let src = self.find_file(node.clone()); | 175 | let src = self.find_file(node.clone()); |
182 | self.analyze2(src.as_ref(), None) | 176 | self.analyze2(src.as_ref(), None) |
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs index 015389fb0..73cff17c9 100644 --- a/crates/ra_hir/src/source_analyzer.rs +++ b/crates/ra_hir/src/source_analyzer.rs | |||
@@ -7,7 +7,6 @@ | |||
7 | //! purely for "IDE needs". | 7 | //! purely for "IDE needs". |
8 | use std::{iter::once, sync::Arc}; | 8 | use std::{iter::once, sync::Arc}; |
9 | 9 | ||
10 | use either::Either; | ||
11 | use hir_def::{ | 10 | use hir_def::{ |
12 | body::{ | 11 | body::{ |
13 | scope::{ExprScopes, ScopeId}, | 12 | scope::{ExprScopes, ScopeId}, |
@@ -21,7 +20,7 @@ use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile}; | |||
21 | use hir_ty::{InEnvironment, InferenceResult, TraitEnvironment}; | 20 | use hir_ty::{InEnvironment, InferenceResult, TraitEnvironment}; |
22 | use ra_syntax::{ | 21 | use ra_syntax::{ |
23 | ast::{self, AstNode}, | 22 | ast::{self, AstNode}, |
24 | AstPtr, SyntaxNode, SyntaxNodePtr, TextRange, TextUnit, | 23 | SyntaxNode, SyntaxNodePtr, TextRange, TextUnit, |
25 | }; | 24 | }; |
26 | 25 | ||
27 | use crate::{ | 26 | use crate::{ |
@@ -251,38 +250,6 @@ impl SourceAnalyzer { | |||
251 | resolve_hir_path(db, &self.resolver, &hir_path) | 250 | resolve_hir_path(db, &self.resolver, &hir_path) |
252 | } | 251 | } |
253 | 252 | ||
254 | fn resolve_local_name( | ||
255 | &self, | ||
256 | name_ref: &ast::NameRef, | ||
257 | ) -> Option<Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>> { | ||
258 | let name = name_ref.as_name(); | ||
259 | let source_map = self.body_source_map.as_ref()?; | ||
260 | let scopes = self.scopes.as_ref()?; | ||
261 | let scope = scope_for(scopes, source_map, InFile::new(self.file_id, name_ref.syntax()))?; | ||
262 | let entry = scopes.resolve_name_in_scope(scope, &name)?; | ||
263 | Some(source_map.pat_syntax(entry.pat())?.value) | ||
264 | } | ||
265 | |||
266 | // FIXME: we only use this in `inline_local_variable` assist, ideally, we | ||
267 | // should switch to general reference search infra there. | ||
268 | pub(crate) fn find_all_refs(&self, pat: &ast::BindPat) -> Vec<ReferenceDescriptor> { | ||
269 | let fn_def = pat.syntax().ancestors().find_map(ast::FnDef::cast).unwrap(); | ||
270 | let ptr = Either::Left(AstPtr::new(&ast::Pat::from(pat.clone()))); | ||
271 | fn_def | ||
272 | .syntax() | ||
273 | .descendants() | ||
274 | .filter_map(ast::NameRef::cast) | ||
275 | .filter(|name_ref| match self.resolve_local_name(&name_ref) { | ||
276 | None => false, | ||
277 | Some(d_ptr) => d_ptr == ptr, | ||
278 | }) | ||
279 | .map(|name_ref| ReferenceDescriptor { | ||
280 | name: name_ref.text().to_string(), | ||
281 | range: name_ref.syntax().text_range(), | ||
282 | }) | ||
283 | .collect() | ||
284 | } | ||
285 | |||
286 | pub(crate) fn expand( | 253 | pub(crate) fn expand( |
287 | &self, | 254 | &self, |
288 | db: &impl HirDatabase, | 255 | db: &impl HirDatabase, |