Skip to content

Commit 794dd86

Browse files
committed
In extract_module.rs, generate ast::Module instead of String
1 parent 8d75311 commit 794dd86

File tree

2 files changed

+48
-25
lines changed

2 files changed

+48
-25
lines changed

crates/ide-assists/src/handlers/extract_module.rs

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use std::iter;
22

3-
use either::Either;
43
use hir::{HasSource, ModuleSource};
54
use ide_db::{
65
FileId, FxHashMap, FxHashSet,
@@ -120,7 +119,8 @@ pub(crate) fn extract_module(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
120119
let import_paths_to_be_removed = module.resolve_imports(curr_parent_module, ctx);
121120
module.change_visibility(record_fields);
122121

123-
let module_def = generate_module_def(&impl_parent, &mut module, old_item_indent);
122+
let module_def =
123+
generate_module_def(&impl_parent, &mut module, old_item_indent).to_string();
124124

125125
let mut usages_to_be_processed_for_cur_file = vec![];
126126
for (file_id, usages) in usages_to_be_processed {
@@ -175,31 +175,36 @@ fn generate_module_def(
175175
parent_impl: &Option<ast::Impl>,
176176
module: &mut Module,
177177
old_indent: IndentLevel,
178-
) -> String {
179-
let (items_to_be_processed, new_item_indent) = if parent_impl.is_some() {
180-
(Either::Left(module.body_items.iter()), old_indent + 2)
178+
) -> ast::Module {
179+
let items = if let Some(self_ty) = parent_impl.as_ref().and_then(|imp| imp.self_ty()) {
180+
let assoc_items = module
181+
.body_items
182+
.iter()
183+
.filter_map(|item| match item {
184+
ast::Item::Const(it) => Some(ast::AssocItem::Const(it.clone())),
185+
ast::Item::Fn(it) => Some(ast::AssocItem::Fn(it.clone())),
186+
ast::Item::MacroCall(it) => Some(ast::AssocItem::MacroCall(it.clone())),
187+
ast::Item::TypeAlias(it) => Some(ast::AssocItem::TypeAlias(it.clone())),
188+
_ => None,
189+
})
190+
.map(|it| it.indent(IndentLevel(1)))
191+
.collect_vec();
192+
let assoc_item_list = make::assoc_item_list(Some(assoc_items));
193+
let impl_ = make::impl_(None, None, self_ty.clone(), None, Some(assoc_item_list));
194+
// Add the import for enum/struct corresponding to given impl block
195+
module.make_use_stmt_of_node_with_super(self_ty.syntax());
196+
let mut module_body_items = module.use_items.clone();
197+
module_body_items.push(ast::Item::Impl(impl_));
198+
module_body_items
181199
} else {
182-
(Either::Right(module.use_items.iter().chain(module.body_items.iter())), old_indent + 1)
200+
[module.use_items.clone(), module.body_items.clone()].concat()
183201
};
184202

185-
let mut body = items_to_be_processed
186-
.map(|item| item.indent(IndentLevel(1)))
187-
.map(|item| format!("{new_item_indent}{item}"))
188-
.join("\n\n");
189-
190-
if let Some(self_ty) = parent_impl.as_ref().and_then(|imp| imp.self_ty()) {
191-
let impl_indent = old_indent + 1;
192-
body = format!("{impl_indent}impl {self_ty} {{\n{body}\n{impl_indent}}}");
203+
let items = items.into_iter().map(|it| it.reset_indent().indent(IndentLevel(1))).collect_vec();
204+
let module_body = make::item_list(Some(items));
193205

194-
// Add the import for enum/struct corresponding to given impl block
195-
module.make_use_stmt_of_node_with_super(self_ty.syntax());
196-
for item in module.use_items.iter() {
197-
body = format!("{impl_indent}{item}\n\n{body}");
198-
}
199-
}
200-
201-
let module_name = module.name;
202-
format!("mod {module_name} {{\n{body}\n{old_indent}}}")
206+
let module_name = make::name(module.name);
207+
make::mod_(module_name, Some(module_body)).indent(old_indent)
203208
}
204209

205210
#[derive(Debug)]
@@ -1422,10 +1427,10 @@ $0fn foo(x: B) {}$0
14221427
struct B {}
14231428
14241429
mod modname {
1425-
use super::B;
1426-
14271430
use super::A;
14281431
1432+
use super::B;
1433+
14291434
impl A {
14301435
pub(crate) fn foo(x: B) {}
14311436
}

crates/syntax/src/ast/make.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,24 @@ pub fn ty_fn_ptr<I: Iterator<Item = Param>>(
229229
}
230230
}
231231

232+
pub fn item_list(body: Option<Vec<ast::Item>>) -> ast::ItemList {
233+
let is_break_braces = body.is_some();
234+
let body_newline = if is_break_braces { "\n".to_owned() } else { String::new() };
235+
let body_indent = if is_break_braces { " ".to_owned() } else { String::new() };
236+
237+
let body = match body {
238+
Some(bd) => bd.iter().map(|elem| elem.to_string()).join("\n\n "),
239+
None => String::new(),
240+
};
241+
ast_from_text(&format!("mod C {{{body_newline}{body_indent}{body}{body_newline}}}"))
242+
}
243+
244+
pub fn mod_(name: ast::Name, body: Option<ast::ItemList>) -> ast::Module {
245+
let name = name.to_string();
246+
let body = body.map_or(";".to_owned(), |body| format!(" {body}"));
247+
ast_from_text(&format!("mod {name}{body}"))
248+
}
249+
232250
pub fn assoc_item_list(body: Option<Vec<ast::AssocItem>>) -> ast::AssocItemList {
233251
let is_break_braces = body.is_some();
234252
let body_newline = if is_break_braces { "\n".to_owned() } else { String::new() };

0 commit comments

Comments
 (0)