mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-07-07 21:25:37 +00:00
Merge pull request #20137 from Hmikihiro/migrate-wrap_unwrap_cfg_attr-assist-to-syntaxeditor
Some checks are pending
metrics / build_metrics (push) Waiting to run
metrics / other_metrics (diesel-1.4.8) (push) Blocked by required conditions
metrics / other_metrics (hyper-0.14.18) (push) Blocked by required conditions
metrics / other_metrics (ripgrep-13.0.0) (push) Blocked by required conditions
metrics / other_metrics (self) (push) Blocked by required conditions
metrics / other_metrics (webrender-2022) (push) Blocked by required conditions
metrics / generate_final_metrics (push) Blocked by required conditions
rustdoc / rustdoc (push) Waiting to run
Some checks are pending
metrics / build_metrics (push) Waiting to run
metrics / other_metrics (diesel-1.4.8) (push) Blocked by required conditions
metrics / other_metrics (hyper-0.14.18) (push) Blocked by required conditions
metrics / other_metrics (ripgrep-13.0.0) (push) Blocked by required conditions
metrics / other_metrics (self) (push) Blocked by required conditions
metrics / other_metrics (webrender-2022) (push) Blocked by required conditions
metrics / generate_final_metrics (push) Blocked by required conditions
rustdoc / rustdoc (push) Waiting to run
Migrate `wrap_unwrap_cfg_attr` Assist to use `SyntaxEditor`
This commit is contained in:
commit
11d45c8813
2 changed files with 85 additions and 42 deletions
|
@ -2,8 +2,7 @@ use ide_db::source_change::SourceChangeBuilder;
|
|||
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 @@ fn wrap_derive(
|
|||
}
|
||||
}
|
||||
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 @@ fn wrap_cfg_attr(acc: &mut Assists, ctx: &AssistContext<'_>, attr: ast::Attr) ->
|
|||
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 @@ fn wrap_cfg_attr(acc: &mut Assists, ctx: &AssistContext<'_>, attr: ast::Attr) ->
|
|||
});
|
||||
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 @@ fn wrap_cfg_attr(acc: &mut Assists, ctx: &AssistContext<'_>, attr: ast::Attr) ->
|
|||
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"),
|
||||
|
|
|
@ -1212,6 +1212,43 @@ impl SyntaxFactory {
|
|||
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 @@ impl SyntaxFactory {
|
|||
pub fn whitespace(&self, text: &str) -> SyntaxToken {
|
||||
make::tokens::whitespace(text)
|
||||
}
|
||||
|
||||
pub fn ident(&self, text: &str) -> SyntaxToken {
|
||||
make::tokens::ident(text)
|
||||
}
|
||||
}
|
||||
|
||||
// `ext` constructors
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue