Skip to content

internal: migrate extract_module to SyntaxEditor#21868

Merged
Veykril merged 2 commits into
rust-lang:masterfrom
itang06:feature/US-18285-extract-module-syntax-editor
Jun 12, 2026
Merged

internal: migrate extract_module to SyntaxEditor#21868
Veykril merged 2 commits into
rust-lang:masterfrom
itang06:feature/US-18285-extract-module-syntax-editor

Conversation

@itang06

@itang06 itang06 commented Mar 25, 2026

Copy link
Copy Markdown
Contributor

Part of #18285

Migrates all ted:: calls in crates/ide-assists/src/handlers/extract_module.rs to the new SyntaxEditor/SyntaxFactory abstraction

Changes:

  • generate_module_def: replaced ted:: with SyntaxEditor/SyntaxFactory
  • expand_and_group_usages_file_wise: replaced ted::replace with SyntaxEditor
  • change_visibility: replaced ted::insert (via add_change_vis helper) with SyntaxEditor::insert_all; removes the add_change_vis function entirely

AI assistance was used for this contribution

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Mar 25, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please migrate remaining make::* usages to SyntaxFactory APIs

continue;
}

let mut editor = SyntaxEditor::new(body_item.syntax().clone());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this new SyntaxEditor instance and .finish() call on it necessary? Couldn't it be done by passing the mutable reference of existing one from the assist entrance function as a parameter of this function instead?

@itang06 itang06 Mar 29, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the items here are detached clone_subtree() nodes, so the editor from the entry point can't reach them. I can use SyntaxFactory::without_mappings() locally to get rid of the .clone_for_update() calls instead, does that work?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, yeah, I guess it could be still uplifted to the root SyntaxEditor but that would require more involved refactoring, so I think this is fine as is for now

})
.collect();
if !replacements.is_empty() {
let mut editor = SyntaxEditor::new(entry.syntax().clone());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, too

@@ -18,8 +18,10 @@ use syntax::{
self, HasVisibility,
edit::{AstNodeEdit, IndentLevel},
make,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kindly replace use of make with SyntaxFactory

let assoc_item_list = make::assoc_item_list(Some(assoc_items)).clone_for_update();
let impl_ = impl_.reset_indent();
ted::replace(impl_.get_or_create_assoc_item_list().syntax(), assoc_item_list.syntax());
let impl_detached = ast::Impl::cast(impl_.syntax().clone_subtree()).unwrap();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove unwraps

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?


let (mut replacements, record_field_parents, impls) =
get_replacements_for_visibility_change(&mut self.body_items, false);
get_replacements_for_visibility_change(&mut self.body_items, true);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this change?

@itang06 itang06 Mar 29, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this was a workaround because of the local SyntaxEditor approach, was an incorrect change


let mut editor = SyntaxEditor::new(body_item.syntax().clone());
for target in insert_targets {
let pub_crate_vis = make::visibility_pub_crate().clone_for_update();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be removed?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will fix, good catch

Some((
seg.syntax().parent()?,
make::path_from_text(&format!("{mod_name}::{seg}"))
.clone_for_update(),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i missed that this should use SyntaxFactory, will replace it

@ChayimFriedman2

Copy link
Copy Markdown
Contributor

@itang06 What's the status of this?

@itang06

itang06 commented Apr 9, 2026

Copy link
Copy Markdown
Contributor Author

@itang06 What's the status of this?

i addressed the unwrap issue. waiting for ShoyuVanilla's response to my question about using SyntaxFactory::without_mappings() locally in the helpers instead of passing the file-level editor since they operate on detached nodes

@itang06 itang06 force-pushed the feature/US-18285-extract-module-syntax-editor branch from 11ff3da to fbf2dfa Compare April 11, 2026 08:14
@rustbot

This comment has been minimized.

@rustbot

This comment has been minimized.

@itang06 itang06 force-pushed the feature/US-18285-extract-module-syntax-editor branch from fbf2dfa to a9d2246 Compare April 11, 2026 08:31
@rustbot

This comment has been minimized.

.entry(use_.syntax().text_range().start())
.or_insert_with(|| use_.clone_subtree().clone_for_update());
for seg in use_
.or_insert_with(|| use_.clone_subtree());

@Shourya742 Shourya742 Apr 11, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

View changes since the review

remove clone_subtree

let assoc_item_list = make::assoc_item_list(Some(assoc_items)).clone_for_update();
let impl_ = impl_.reset_indent();
ted::replace(impl_.get_or_create_assoc_item_list().syntax(), assoc_item_list.syntax());
let impl_detached = ast::Impl::cast(impl_.syntax().clone_subtree()).unwrap();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

],
);
}
*body_item = ast::Item::cast(editor.finish().new_root().clone_subtree()).unwrap();

@Shourya742 Shourya742 Apr 11, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

View changes since the review

Suggested change
*body_item = ast::Item::cast(editor.finish().new_root().clone_subtree()).unwrap();
*body_item = ast::Item::cast(editor.finish().new_root()).unwrap();

Comment on lines +435 to +437
for item in &mut self.body_items {
*item = ast::Item::cast(item.reset_indent().syntax().clone_subtree()).unwrap();
}

@Shourya742 Shourya742 Apr 11, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

View changes since the review

No need to call clone_subtree here anymore. SyntaxEditor manages this internally

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i tried removing the clone_subtree() calls but found that 3 of the 4 calls require using the detached root returned by SyntaxEditor::new() instead of just dropping clone_subtree(). i think the 4th at line 436 has to stay because replacements is collected from body_items immediately after. is there something i'm missing or is there a different approach you had in mind?

@ChayimFriedman2

Copy link
Copy Markdown
Contributor

@itang06 What's the status of this?

@itang06

itang06 commented Apr 26, 2026

Copy link
Copy Markdown
Contributor Author

@itang06 What's the status of this?

waiting on feedback from Shourya742 regarding the approach for removing clone_subtree() calls (see my comment above). all tests pass but i just need confirmation on the direction before committing

@Shourya742

Copy link
Copy Markdown
Member

Hey @itang06, can you rebase the changes onto the latest master? A lot of the semantics around syntaxEditor have changed. The clone_subtree issue can be resolved using a local editor.

@Shourya742

Copy link
Copy Markdown
Member

Can you also please squash the commits, seems like most are changing the same file.

@Shourya742

Copy link
Copy Markdown
Member

Hey @itang06 are you still working on this?

@itang06

itang06 commented May 10, 2026

Copy link
Copy Markdown
Contributor Author

Yes, still working on it. i'll have an update soon.

@Shourya742

Copy link
Copy Markdown
Member

Make sure to remove/update ted variant of get_or_create_assoc_item_list from edit-in-place .

@itang06 itang06 force-pushed the feature/US-18285-extract-module-syntax-editor branch from 74c1a1e to de6c326 Compare May 13, 2026 08:44
@rustbot

This comment has been minimized.

@rustbot

This comment has been minimized.

@itang06

itang06 commented May 13, 2026

Copy link
Copy Markdown
Contributor Author

@Shourya742 i found that after rebasing. removing the clone_subtree() calls causes is_ancestor_or_self_of_element to fail, since when SyntaxEditor::new() clones internally, the node references collected before the editor was created end up pointing to the wrong tree. would the fix be to collect targets from the editor's detached root instead?

@itang06 itang06 force-pushed the feature/US-18285-extract-module-syntax-editor branch from de6c326 to 7b0b9c7 Compare May 13, 2026 08:56
@Shourya742

Copy link
Copy Markdown
Member

@Shourya742 i found that after rebasing. removing the clone_subtree() calls causes is_ancestor_or_self_of_element to fail, since when SyntaxEditor::new() clones internally, the node references collected before the editor was created end up pointing to the wrong tree. would the fix be to collect targets from the editor's detached root instead?

Yes

@itang06 itang06 force-pushed the feature/US-18285-extract-module-syntax-editor branch 2 times, most recently from f828748 to 5b44119 Compare May 17, 2026 09:34
_ => true,
}
});
let make = SyntaxFactory::without_mappings();

@Shourya742 Shourya742 May 18, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need to initialize the without_mappining here, you can get it from the editor and have mapped changes stored in the factory.

View changes since the review

@itang06 itang06 May 22, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done, using editor.make() in a scoped block so it's dropped before editor.finish()

let (_, root) = SyntaxEditor::with_ast_node(&use_);
root
});
let make = SyntaxFactory::without_mappings();

@Shourya742 Shourya742 May 18, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need this

View changes since the review

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can use the make via the editor

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done, simplified to use_.clone()

@@ -741,7 +788,6 @@

fn get_replacements_for_visibility_change(
items: &mut [ast::Item],

@Shourya742 Shourya742 May 18, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we are not longer mutating it.

Suggested change
items: &mut [ast::Item],
items: &[ast::Item],

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


let (mut replacements, record_field_parents, impls) =
get_replacements_for_visibility_change(&mut self.body_items, false);
get_replacements_for_visibility_change(&mut self.body_items);

@Shourya742 Shourya742 May 18, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We dont need mut here now.

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


let (mut impl_item_replacements, _, _) =
get_replacements_for_visibility_change(&mut impl_items, true);
get_replacements_for_visibility_change(&mut impl_items);

@Shourya742 Shourya742 May 18, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need mut here now.

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Comment on lines +186 to +190
@@ -186,6 +187,7 @@
parent_impl: &Option<ast::Impl>,
Module { name, body_items, use_items }: &Module,
) -> ast::Module {
let make = SyntaxFactory::without_mappings();

@Shourya742 Shourya742 May 18, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can pass factory to generate_module_def method from extract_module

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done. also did the same for make_use_stmt_of_node_with_super and change_visibility which had the same issue

imports_to_remove
}

fn process_def_in_sel(

@Shourya742 Shourya742 May 18, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can pass factory to process_def_in_sel

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done, threaded it through resolve_imports

@itang06 itang06 force-pushed the feature/US-18285-extract-module-syntax-editor branch from 5b44119 to 563cdc6 Compare May 22, 2026 08:40
@Shourya742

Copy link
Copy Markdown
Member

Pinging @ChayimFriedman2, for a final look.

@Shourya742 Shourya742 mentioned this pull request Jun 3, 2026
@Shourya742

Copy link
Copy Markdown
Member

@itang06 Can you rebase the PR to current master?

@itang06 itang06 force-pushed the feature/US-18285-extract-module-syntax-editor branch from 563cdc6 to 774aeb2 Compare June 3, 2026 06:14
@rustbot

rustbot commented Jun 3, 2026

Copy link
Copy Markdown
Collaborator

This PR was rebased onto a different master commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@rustbot

rustbot commented Jun 3, 2026

Copy link
Copy Markdown
Collaborator

⚠️ Warning ⚠️

  • There are uncanonicalized issue links (such as #123) in the commit messages of the following commits.
    Please add the organization and repository before the issue number (like so rust-lang/rust#123) to avoid issues with subtree.

@itang06

itang06 commented Jun 3, 2026

Copy link
Copy Markdown
Contributor Author

@itang06 Can you rebase the PR to current master?

Rebased to current master

@Veykril Veykril added this pull request to the merge queue Jun 12, 2026
Merged via the queue into rust-lang:master with commit 1edcb12 Jun 12, 2026
18 checks passed
@rustbot rustbot removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jun 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants