mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 04:44:57 +00:00
Adds sort for RecordLit comparison in SSR
This commit is contained in:
parent
1c2d4135db
commit
47e8f3c93b
1 changed files with 90 additions and 26 deletions
|
@ -5,7 +5,7 @@ use ra_db::{SourceDatabase, SourceDatabaseExt};
|
||||||
use ra_ide_db::symbol_index::SymbolsDatabase;
|
use ra_ide_db::symbol_index::SymbolsDatabase;
|
||||||
use ra_ide_db::RootDatabase;
|
use ra_ide_db::RootDatabase;
|
||||||
use ra_syntax::ast::make::try_expr_from_text;
|
use ra_syntax::ast::make::try_expr_from_text;
|
||||||
use ra_syntax::ast::{AstToken, Comment};
|
use ra_syntax::ast::{AstToken, Comment, RecordField, RecordLit};
|
||||||
use ra_syntax::{AstNode, SyntaxElement, SyntaxNode};
|
use ra_syntax::{AstNode, SyntaxElement, SyntaxNode};
|
||||||
use ra_text_edit::{TextEdit, TextEditBuilder};
|
use ra_text_edit::{TextEdit, TextEditBuilder};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
@ -186,47 +186,102 @@ fn create_name<'a>(name: &str, vars: &'a mut Vec<Var>) -> Result<&'a str, SsrErr
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find(pattern: &SsrPattern, code: &SyntaxNode) -> SsrMatches {
|
fn find(pattern: &SsrPattern, code: &SyntaxNode) -> SsrMatches {
|
||||||
|
fn check_record_lit(
|
||||||
|
pattern: RecordLit,
|
||||||
|
code: RecordLit,
|
||||||
|
placeholders: &[Var],
|
||||||
|
match_: Match,
|
||||||
|
) -> Option<Match> {
|
||||||
|
let match_ = check_opt_nodes(pattern.path(), code.path(), placeholders, match_)?;
|
||||||
|
|
||||||
|
let mut pattern_fields =
|
||||||
|
pattern.record_field_list().map(|x| x.fields().collect()).unwrap_or(vec![]);
|
||||||
|
let mut code_fields =
|
||||||
|
code.record_field_list().map(|x| x.fields().collect()).unwrap_or(vec![]);
|
||||||
|
|
||||||
|
if pattern_fields.len() != code_fields.len() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let by_name = |a: &RecordField, b: &RecordField| {
|
||||||
|
a.name_ref()
|
||||||
|
.map(|x| x.syntax().text().to_string())
|
||||||
|
.cmp(&b.name_ref().map(|x| x.syntax().text().to_string()))
|
||||||
|
};
|
||||||
|
pattern_fields.sort_by(by_name);
|
||||||
|
code_fields.sort_by(by_name);
|
||||||
|
|
||||||
|
pattern_fields.into_iter().zip(code_fields.into_iter()).fold(
|
||||||
|
Some(match_),
|
||||||
|
|accum, (a, b)| {
|
||||||
|
accum.and_then(|match_| check_opt_nodes(Some(a), Some(b), placeholders, match_))
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_opt_nodes(
|
||||||
|
pattern: Option<impl AstNode>,
|
||||||
|
code: Option<impl AstNode>,
|
||||||
|
placeholders: &[Var],
|
||||||
|
match_: Match,
|
||||||
|
) -> Option<Match> {
|
||||||
|
match (pattern, code) {
|
||||||
|
(Some(pattern), Some(code)) => check(
|
||||||
|
&SyntaxElement::from(pattern.syntax().clone()),
|
||||||
|
&SyntaxElement::from(code.syntax().clone()),
|
||||||
|
placeholders,
|
||||||
|
match_,
|
||||||
|
),
|
||||||
|
(None, None) => Some(match_),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn check(
|
fn check(
|
||||||
pattern: &SyntaxElement,
|
pattern: &SyntaxElement,
|
||||||
code: &SyntaxElement,
|
code: &SyntaxElement,
|
||||||
placeholders: &[Var],
|
placeholders: &[Var],
|
||||||
mut match_: Match,
|
mut match_: Match,
|
||||||
) -> Option<Match> {
|
) -> Option<Match> {
|
||||||
match (pattern, code) {
|
match (&pattern, &code) {
|
||||||
(SyntaxElement::Token(ref pattern), SyntaxElement::Token(ref code)) => {
|
(SyntaxElement::Token(pattern), SyntaxElement::Token(code)) => {
|
||||||
if pattern.text() == code.text() {
|
if pattern.text() == code.text() {
|
||||||
Some(match_)
|
Some(match_)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(SyntaxElement::Node(ref pattern), SyntaxElement::Node(ref code)) => {
|
(SyntaxElement::Node(pattern), SyntaxElement::Node(code)) => {
|
||||||
if placeholders.iter().any(|n| n.0.as_str() == pattern.text()) {
|
if placeholders.iter().any(|n| n.0.as_str() == pattern.text()) {
|
||||||
match_.binding.insert(Var(pattern.text().to_string()), code.clone());
|
match_.binding.insert(Var(pattern.text().to_string()), code.clone());
|
||||||
Some(match_)
|
Some(match_)
|
||||||
} else {
|
} else {
|
||||||
let mut pattern_children = pattern
|
if let (Some(pattern), Some(code)) =
|
||||||
.children_with_tokens()
|
(RecordLit::cast(pattern.clone()), RecordLit::cast(code.clone()))
|
||||||
.filter(|element| !element.kind().is_trivia());
|
{
|
||||||
let mut code_children =
|
check_record_lit(pattern, code, placeholders, match_)
|
||||||
code.children_with_tokens().filter(|element| !element.kind().is_trivia());
|
} else {
|
||||||
let new_ignored_comments = code.children_with_tokens().filter_map(|element| {
|
let mut pattern_children = pattern
|
||||||
element.as_token().and_then(|token| Comment::cast(token.clone()))
|
.children_with_tokens()
|
||||||
});
|
.filter(|element| !element.kind().is_trivia());
|
||||||
match_.ignored_comments.extend(new_ignored_comments);
|
let mut code_children = code
|
||||||
let match_from_children = pattern_children
|
.children_with_tokens()
|
||||||
.by_ref()
|
.filter(|element| !element.kind().is_trivia());
|
||||||
.zip(code_children.by_ref())
|
let new_ignored_comments =
|
||||||
.fold(Some(match_), |accum, (a, b)| {
|
code.children_with_tokens().filter_map(|element| {
|
||||||
accum.and_then(|match_| check(&a, &b, placeholders, match_))
|
element.as_token().and_then(|token| Comment::cast(token.clone()))
|
||||||
});
|
});
|
||||||
match_from_children.and_then(|match_| {
|
match_.ignored_comments.extend(new_ignored_comments);
|
||||||
if pattern_children.count() == 0 && code_children.count() == 0 {
|
pattern_children
|
||||||
Some(match_)
|
.by_ref()
|
||||||
} else {
|
.zip(code_children.by_ref())
|
||||||
None
|
.fold(Some(match_), |accum, (a, b)| {
|
||||||
}
|
accum.and_then(|match_| check(&a, &b, placeholders, match_))
|
||||||
})
|
})
|
||||||
|
.filter(|_| {
|
||||||
|
pattern_children.next().is_none() && code_children.next().is_none()
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -434,4 +489,13 @@ mod tests {
|
||||||
"fn main() { bar(5)/* using 5 */ }",
|
"fn main() { bar(5)/* using 5 */ }",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ssr_struct_lit() {
|
||||||
|
assert_ssr_transform(
|
||||||
|
"foo{a: $a:expr, b: $b:expr} ==>> foo::new($a, $b)",
|
||||||
|
"fn main() { foo{b:2, a:1} }",
|
||||||
|
"fn main() { foo::new(1, 2) }",
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue