Merge pull request #20137 from Hmikihiro/migrate-wrap_unwrap_cfg_attr-assist-to-syntaxeditor
Migrate `wrap_unwrap_cfg_attr` Assist to use `SyntaxEditor`
diff --git a/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs b/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs
index e1b9467..5183566 100644
--- a/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs
+++ b/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs
@@ -2,8 +2,7 @@
use itertools::Itertools;
use syntax::{
NodeOrToken, SyntaxToken, T, TextRange, algo,
- ast::{self, AstNode, make},
- ted::{self, Position},
+ ast::{self, AstNode, make, syntax_factory::SyntaxFactory},
};
use crate::{AssistContext, AssistId, Assists};
@@ -173,40 +172,45 @@
}
}
let handle_source_change = |edit: &mut SourceChangeBuilder| {
- let new_derive = make::attr_outer(make::meta_token_tree(
- make::ext::ident_path("derive"),
- make::token_tree(T!['('], new_derive),
- ))
- .clone_for_update();
- let meta = make::meta_token_tree(
- make::ext::ident_path("cfg_attr"),
- make::token_tree(
+ let make = SyntaxFactory::with_mappings();
+ let mut editor = edit.make_editor(attr.syntax());
+ let new_derive = make.attr_outer(
+ make.meta_token_tree(make.ident_path("derive"), make.token_tree(T!['('], new_derive)),
+ );
+ let meta = make.meta_token_tree(
+ make.ident_path("cfg_attr"),
+ make.token_tree(
T!['('],
vec![
- NodeOrToken::Token(make::token(T![,])),
- NodeOrToken::Token(make::tokens::whitespace(" ")),
- NodeOrToken::Token(make::tokens::ident("derive")),
- NodeOrToken::Node(make::token_tree(T!['('], cfg_derive_tokens)),
+ NodeOrToken::Token(make.token(T![,])),
+ NodeOrToken::Token(make.whitespace(" ")),
+ NodeOrToken::Token(make.ident("derive")),
+ NodeOrToken::Node(make.token_tree(T!['('], cfg_derive_tokens)),
],
),
);
- // Remove the derive attribute
- let edit_attr = edit.make_syntax_mut(attr.syntax().clone());
- ted::replace(edit_attr, new_derive.syntax().clone());
- let cfg_attr = make::attr_outer(meta).clone_for_update();
-
- ted::insert_all_raw(
- Position::after(new_derive.syntax().clone()),
- vec![make::tokens::whitespace("\n").into(), cfg_attr.syntax().clone().into()],
+ let cfg_attr = make.attr_outer(meta);
+ editor.replace_with_many(
+ attr.syntax(),
+ vec![
+ new_derive.syntax().clone().into(),
+ make.whitespace("\n").into(),
+ cfg_attr.syntax().clone().into(),
+ ],
);
+
if let Some(snippet_cap) = ctx.config.snippet_cap {
if let Some(first_meta) =
cfg_attr.meta().and_then(|meta| meta.token_tree()).and_then(|tt| tt.l_paren_token())
{
- edit.add_tabstop_after_token(snippet_cap, first_meta)
+ let tabstop = edit.make_tabstop_after(snippet_cap);
+ editor.add_annotation(first_meta, tabstop);
}
}
+
+ editor.add_mappings(make.finish_with_mappings());
+ edit.add_file_edits(ctx.vfs_file_id(), editor);
};
acc.add(
@@ -221,10 +225,10 @@
let range = attr.syntax().text_range();
let path = attr.path()?;
let handle_source_change = |edit: &mut SourceChangeBuilder| {
- let mut raw_tokens = vec![
- NodeOrToken::Token(make::token(T![,])),
- NodeOrToken::Token(make::tokens::whitespace(" ")),
- ];
+ let make = SyntaxFactory::with_mappings();
+ let mut editor = edit.make_editor(attr.syntax());
+ let mut raw_tokens =
+ vec![NodeOrToken::Token(make.token(T![,])), NodeOrToken::Token(make.whitespace(" "))];
path.syntax().descendants_with_tokens().for_each(|it| {
if let NodeOrToken::Token(token) = it {
raw_tokens.push(NodeOrToken::Token(token));
@@ -232,9 +236,9 @@
});
if let Some(meta) = attr.meta() {
if let (Some(eq), Some(expr)) = (meta.eq_token(), meta.expr()) {
- raw_tokens.push(NodeOrToken::Token(make::tokens::whitespace(" ")));
+ raw_tokens.push(NodeOrToken::Token(make.whitespace(" ")));
raw_tokens.push(NodeOrToken::Token(eq));
- raw_tokens.push(NodeOrToken::Token(make::tokens::whitespace(" ")));
+ raw_tokens.push(NodeOrToken::Token(make.whitespace(" ")));
expr.syntax().descendants_with_tokens().for_each(|it| {
if let NodeOrToken::Token(token) = it {
@@ -245,26 +249,24 @@
raw_tokens.extend(tt.token_trees_and_tokens());
}
}
- let meta = make::meta_token_tree(
- make::ext::ident_path("cfg_attr"),
- make::token_tree(T!['('], raw_tokens),
- );
- let cfg_attr = if attr.excl_token().is_some() {
- make::attr_inner(meta)
- } else {
- make::attr_outer(meta)
- }
- .clone_for_update();
- let attr_syntax = edit.make_syntax_mut(attr.syntax().clone());
- ted::replace(attr_syntax, cfg_attr.syntax());
+ let meta =
+ make.meta_token_tree(make.ident_path("cfg_attr"), make.token_tree(T!['('], raw_tokens));
+ let cfg_attr =
+ if attr.excl_token().is_some() { make.attr_inner(meta) } else { make.attr_outer(meta) };
+
+ editor.replace(attr.syntax(), cfg_attr.syntax());
if let Some(snippet_cap) = ctx.config.snippet_cap {
if let Some(first_meta) =
cfg_attr.meta().and_then(|meta| meta.token_tree()).and_then(|tt| tt.l_paren_token())
{
- edit.add_tabstop_after_token(snippet_cap, first_meta)
+ let tabstop = edit.make_tabstop_after(snippet_cap);
+ editor.add_annotation(first_meta, tabstop);
}
}
+
+ editor.add_mappings(make.finish_with_mappings());
+ edit.add_file_edits(ctx.vfs_file_id(), editor);
};
acc.add(
AssistId::refactor("wrap_unwrap_cfg_attr"),
diff --git a/crates/syntax/src/ast/syntax_factory/constructors.rs b/crates/syntax/src/ast/syntax_factory/constructors.rs
index 429e51b..17cc5f9 100644
--- a/crates/syntax/src/ast/syntax_factory/constructors.rs
+++ b/crates/syntax/src/ast/syntax_factory/constructors.rs
@@ -1212,6 +1212,43 @@
ast
}
+ pub fn attr_outer(&self, meta: ast::Meta) -> ast::Attr {
+ let ast = make::attr_outer(meta.clone()).clone_for_update();
+
+ if let Some(mut mapping) = self.mappings() {
+ let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+ builder.map_node(meta.syntax().clone(), ast.meta().unwrap().syntax().clone());
+ builder.finish(&mut mapping);
+ }
+
+ ast
+ }
+
+ pub fn attr_inner(&self, meta: ast::Meta) -> ast::Attr {
+ let ast = make::attr_inner(meta.clone()).clone_for_update();
+
+ if let Some(mut mapping) = self.mappings() {
+ let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+ builder.map_node(meta.syntax().clone(), ast.meta().unwrap().syntax().clone());
+ builder.finish(&mut mapping);
+ }
+
+ ast
+ }
+
+ pub fn meta_token_tree(&self, path: ast::Path, tt: ast::TokenTree) -> ast::Meta {
+ let ast = make::meta_token_tree(path.clone(), tt.clone()).clone_for_update();
+
+ if let Some(mut mapping) = self.mappings() {
+ let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+ builder.map_node(path.syntax().clone(), ast.path().unwrap().syntax().clone());
+ builder.map_node(tt.syntax().clone(), ast.token_tree().unwrap().syntax().clone());
+ builder.finish(&mut mapping);
+ }
+
+ ast
+ }
+
pub fn token_tree(
&self,
delimiter: SyntaxKind,
@@ -1242,6 +1279,10 @@
pub fn whitespace(&self, text: &str) -> SyntaxToken {
make::tokens::whitespace(text)
}
+
+ pub fn ident(&self, text: &str) -> SyntaxToken {
+ make::tokens::ident(text)
+ }
}
// `ext` constructors