Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-ssr/src/matching.rs')
| -rw-r--r-- | crates/ide-ssr/src/matching.rs | 163 |
1 files changed, 79 insertions, 84 deletions
diff --git a/crates/ide-ssr/src/matching.rs b/crates/ide-ssr/src/matching.rs index b350315ba5..264f0660d7 100644 --- a/crates/ide-ssr/src/matching.rs +++ b/crates/ide-ssr/src/matching.rs @@ -6,7 +6,7 @@ use crate::{ parsing::{Constraint, NodeKind, Placeholder, Var}, resolving::{ResolvedPattern, ResolvedRule, UfcsCallInfo}, }; -use hir::{FileRange, ImportPathConfig, Semantics}; +use hir::{FileRange, FindPathConfig, Semantics}; use ide_db::{FxHashMap, base_db::RootQueryDb}; use std::{cell::Cell, iter::Peekable}; use syntax::{ @@ -156,12 +156,11 @@ impl<'db, 'sema> Matcher<'db, 'sema> { /// processing a macro expansion and we want to fail the match if we're working with a node that /// didn't originate from the token tree of the macro call. fn validate_range(&self, range: &FileRange) -> Result<(), MatchFailed> { - if let Some(restrict_range) = &self.restrict_range { - if restrict_range.file_id != range.file_id - || !restrict_range.range.contains_range(range.range) - { - fail_match!("Node originated from a macro"); - } + if let Some(restrict_range) = &self.restrict_range + && (restrict_range.file_id != range.file_id + || !restrict_range.range.contains_range(range.range)) + { + fail_match!("Node originated from a macro"); } Ok(()) } @@ -404,30 +403,27 @@ impl<'db, 'sema> Matcher<'db, 'sema> { // Build a map keyed by field name. let mut fields_by_name: FxHashMap<SmolStr, SyntaxNode> = FxHashMap::default(); for child in code.children() { - if let Some(record) = ast::RecordExprField::cast(child.clone()) { - if let Some(name) = record.field_name() { - fields_by_name.insert(name.text().into(), child.clone()); - } + if let Some(record) = ast::RecordExprField::cast(child.clone()) + && let Some(name) = record.field_name() + { + fields_by_name.insert(name.text().into(), child.clone()); } } for p in pattern.children_with_tokens() { - if let SyntaxElement::Node(p) = p { - if let Some(name_element) = p.first_child_or_token() { - if self.get_placeholder(&name_element).is_some() { - // If the pattern is using placeholders for field names then order - // independence doesn't make sense. Fall back to regular ordered - // matching. - return self.attempt_match_node_children(phase, pattern, code); - } - if let Some(ident) = only_ident(name_element) { - let code_record = fields_by_name.remove(ident.text()).ok_or_else(|| { - match_error!( - "Placeholder has record field '{}', but code doesn't", - ident - ) - })?; - self.attempt_match_node(phase, &p, &code_record)?; - } + if let SyntaxElement::Node(p) = p + && let Some(name_element) = p.first_child_or_token() + { + if self.get_placeholder(&name_element).is_some() { + // If the pattern is using placeholders for field names then order + // independence doesn't make sense. Fall back to regular ordered + // matching. + return self.attempt_match_node_children(phase, pattern, code); + } + if let Some(ident) = only_ident(name_element) { + let code_record = fields_by_name.remove(ident.text()).ok_or_else(|| { + match_error!("Placeholder has record field '{}', but code doesn't", ident) + })?; + self.attempt_match_node(phase, &p, &code_record)?; } } } @@ -476,14 +472,13 @@ impl<'db, 'sema> Matcher<'db, 'sema> { } } SyntaxElement::Node(n) => { - if let Some(first_token) = n.first_token() { - if Some(first_token.text()) == next_pattern_token.as_deref() { - if let Some(SyntaxElement::Node(p)) = pattern.next() { - // We have a subtree that starts with the next token in our pattern. - self.attempt_match_token_tree(phase, &p, n)?; - break; - } - } + if let Some(first_token) = n.first_token() + && Some(first_token.text()) == next_pattern_token.as_deref() + && let Some(SyntaxElement::Node(p)) = pattern.next() + { + // We have a subtree that starts with the next token in our pattern. + self.attempt_match_token_tree(phase, &p, n)?; + break; } } }; @@ -562,23 +557,22 @@ impl<'db, 'sema> Matcher<'db, 'sema> { let deref_count = self.check_expr_type(pattern_type, expr)?; let pattern_receiver = pattern_args.next(); self.attempt_match_opt(phase, pattern_receiver.clone(), code.receiver())?; - if let Phase::Second(match_out) = phase { - if let Some(placeholder_value) = pattern_receiver + if let Phase::Second(match_out) = phase + && let Some(placeholder_value) = pattern_receiver .and_then(|n| self.get_placeholder_for_node(n.syntax())) .and_then(|placeholder| { match_out.placeholder_values.get_mut(&placeholder.ident) }) - { - placeholder_value.autoderef_count = deref_count; - placeholder_value.autoref_kind = self - .sema - .resolve_method_call_as_callable(code) - .and_then(|callable| { - let (self_param, _) = callable.receiver_param(self.sema.db)?; - Some(self.sema.source(self_param)?.value.kind()) - }) - .unwrap_or(ast::SelfParamKind::Owned); - } + { + placeholder_value.autoderef_count = deref_count; + placeholder_value.autoref_kind = self + .sema + .resolve_method_call_as_callable(code) + .and_then(|callable| { + let (self_param, _) = callable.receiver_param(self.sema.db)?; + Some(self.sema.source(self_param)?.value.kind()) + }) + .unwrap_or(ast::SelfParamKind::Owned); } } } else { @@ -667,7 +661,7 @@ impl Match { .module(); for (path, resolved_path) in &template.resolved_paths { if let hir::PathResolution::Def(module_def) = resolved_path.resolution { - let cfg = ImportPathConfig { + let cfg = FindPathConfig { prefer_no_std: false, prefer_prelude: true, prefer_absolute: false, @@ -698,12 +692,11 @@ impl Phase<'_> { } fn record_ignored_comments(&mut self, token: &SyntaxToken) { - if token.kind() == SyntaxKind::COMMENT { - if let Phase::Second(match_out) = self { - if let Some(comment) = ast::Comment::cast(token.clone()) { - match_out.ignored_comments.push(comment); - } - } + if token.kind() == SyntaxKind::COMMENT + && let Phase::Second(match_out) = self + && let Some(comment) = ast::Comment::cast(token.clone()) + { + match_out.ignored_comments.push(comment); } } } @@ -806,33 +799,35 @@ mod tests { let input = "fn foo() {} fn bar() {} fn main() { foo(1+2); }"; let (db, position, selections) = crate::tests::single_file(input); - let position = ide_db::FilePosition { - file_id: position.file_id.file_id(&db), - offset: position.offset, - }; - let mut match_finder = MatchFinder::in_context( - &db, - position, - selections - .into_iter() - .map(|frange| ide_db::FileRange { - file_id: frange.file_id.file_id(&db), - range: frange.range, - }) - .collect(), - ) - .unwrap(); - match_finder.add_rule(rule).unwrap(); - let matches = match_finder.matches(); - assert_eq!(matches.matches.len(), 1); - assert_eq!(matches.matches[0].matched_node.text(), "foo(1+2)"); - assert_eq!(matches.matches[0].placeholder_values.len(), 1); - - let edits = match_finder.edits(); - assert_eq!(edits.len(), 1); - let edit = &edits[&position.file_id]; - let mut after = input.to_owned(); - edit.apply(&mut after); - assert_eq!(after, "fn foo() {} fn bar() {} fn main() { bar(1+2); }"); + hir::attach_db(&db, || { + let position = ide_db::FilePosition { + file_id: position.file_id.file_id(&db), + offset: position.offset, + }; + let mut match_finder = MatchFinder::in_context( + &db, + position, + selections + .into_iter() + .map(|frange| ide_db::FileRange { + file_id: frange.file_id.file_id(&db), + range: frange.range, + }) + .collect(), + ) + .unwrap(); + match_finder.add_rule(rule).unwrap(); + let matches = match_finder.matches(); + assert_eq!(matches.matches.len(), 1); + assert_eq!(matches.matches[0].matched_node.text(), "foo(1+2)"); + assert_eq!(matches.matches[0].placeholder_values.len(), 1); + + let edits = match_finder.edits(); + assert_eq!(edits.len(), 1); + let edit = &edits[&position.file_id]; + let mut after = input.to_owned(); + edit.apply(&mut after); + assert_eq!(after, "fn foo() {} fn bar() {} fn main() { bar(1+2); }"); + }); } } |