|
1 | 1 | use ide_db::source_change::SourceChangeBuilder; |
2 | | -use itertools::Itertools; |
3 | 2 | use syntax::{ |
4 | 3 | NodeOrToken, SyntaxToken, T, TextRange, algo, |
5 | | - ast::{self, AstNode, edit::AstNodeEdit, make}, |
| 4 | + ast::{self, AstNode, edit::AstNodeEdit}, |
6 | 5 | }; |
7 | 6 |
|
8 | 7 | use crate::{AssistContext, AssistId, Assists}; |
@@ -151,7 +150,7 @@ pub(crate) fn wrap_unwrap_cfg_attr(acc: &mut Assists, ctx: &AssistContext<'_>) - |
151 | 150 | if let [attr] = &attrs[..] |
152 | 151 | && let Some(ast::Meta::CfgAttrMeta(meta)) = attr.meta() |
153 | 152 | { |
154 | | - unwrap_cfg_attr(acc, meta) |
| 153 | + unwrap_cfg_attr(acc, ctx, meta) |
155 | 154 | } else { |
156 | 155 | wrap_cfg_attrs(acc, ctx, attrs) |
157 | 156 | } |
@@ -267,37 +266,41 @@ fn wrap_cfg_attrs(acc: &mut Assists, ctx: &AssistContext<'_>, attrs: Vec<ast::At |
267 | 266 | Some(()) |
268 | 267 | } |
269 | 268 |
|
270 | | -fn unwrap_cfg_attr(acc: &mut Assists, meta: ast::CfgAttrMeta) -> Option<()> { |
| 269 | +fn unwrap_cfg_attr( |
| 270 | + acc: &mut Assists, |
| 271 | + ctx: &AssistContext<'_>, |
| 272 | + meta: ast::CfgAttrMeta, |
| 273 | +) -> Option<()> { |
271 | 274 | let top_attr = ast::Meta::from(meta.clone()).parent_attr()?; |
272 | 275 | let range = top_attr.syntax().text_range(); |
273 | | - let inner_attrs = meta |
274 | | - .metas() |
275 | | - .map(|meta| { |
276 | | - if top_attr.excl_token().is_some() { |
277 | | - make::attr_inner(meta) |
278 | | - } else { |
279 | | - make::attr_outer(meta) |
280 | | - } |
281 | | - }) |
282 | | - .collect::<Vec<_>>(); |
283 | | - if inner_attrs.is_empty() { |
| 276 | + let inner_metas: Vec<ast::Meta> = meta.metas().collect(); |
| 277 | + if inner_metas.is_empty() { |
284 | 278 | return None; |
285 | 279 | } |
286 | | - let handle_source_change = |f: &mut SourceChangeBuilder| { |
287 | | - let inner_attrs = inner_attrs |
288 | | - .iter() |
289 | | - .map(|it| it.to_string()) |
290 | | - .join(&format!("\n{}", top_attr.indent_level())); |
291 | | - f.replace(range, inner_attrs); |
292 | | - }; |
| 280 | + let is_inner = top_attr.excl_token().is_some(); |
| 281 | + let indent = top_attr.indent_level(); |
293 | 282 | acc.add( |
294 | 283 | AssistId::refactor("wrap_unwrap_cfg_attr"), |
295 | 284 | "Extract Inner Attributes from `cfg_attr`", |
296 | 285 | range, |
297 | | - handle_source_change, |
| 286 | + |builder: &mut SourceChangeBuilder| { |
| 287 | + let editor = builder.make_editor(top_attr.syntax()); |
| 288 | + let make = editor.make(); |
| 289 | + let mut elements = vec![]; |
| 290 | + for (i, meta) in inner_metas.into_iter().enumerate() { |
| 291 | + if i > 0 { |
| 292 | + elements.push(make.whitespace(&format!("\n{indent}")).into()); |
| 293 | + } |
| 294 | + let attr = if is_inner { make.attr_inner(meta) } else { make.attr_outer(meta) }; |
| 295 | + elements.push(attr.syntax().clone().into()); |
| 296 | + } |
| 297 | + editor.replace_with_many(top_attr.syntax(), elements); |
| 298 | + builder.add_file_edits(ctx.vfs_file_id(), editor); |
| 299 | + }, |
298 | 300 | ); |
299 | 301 | Some(()) |
300 | 302 | } |
| 303 | + |
301 | 304 | #[cfg(test)] |
302 | 305 | mod tests { |
303 | 306 | use crate::tests::check_assist; |
|
0 commit comments