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.rs163
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); }");
+ });
}
}