-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Migrate introduce_named_generic
Assist to Use SyntaxFactory
#18483
base: master
Are you sure you want to change the base?
Migrate introduce_named_generic
Assist to Use SyntaxFactory
#18483
Conversation
Signed-off-by: Tarek <[email protected]>
Signed-off-by: Tarek <[email protected]>
Signed-off-by: Tarek <[email protected]>
Marking this as a draft for now since I’m running into a couple of errors with this assist
---- handlers::introduce_named_generic::tests::replace_two_impl_trait_with_generic_params stdout ----
Left:
fn foo<G, $0B: Bar>(foo: impl Foo, bar: B) {}
Right:
fn foo<$0G, B: Bar>(foo: impl Foo, bar: B) {}
Diff:
fn foo<$0G, $0B: Bar>(foo: impl Foo, bar: B) {}
thread 'handlers::introduce_named_generic::tests::replace_two_impl_trait_with_generic_params' panicked at crates/ide-assists/src/handlers/introduce_named_generic.rs:105:9:
text differs Here, only the cursor position appears to be off.
---- tests::generated::doctest_introduce_named_generic stdout ----
thread 'tests::generated::doctest_introduce_named_generic' panicked at /Users/tareknasser/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rowan-0.15.15/src/cursor.rs:810:9:
immutable tree: fn foo(bar: impl Bar) {} |
let target = fn_.syntax().text_range(); | ||
acc.add( | ||
AssistId("introduce_named_generic", AssistKind::RefactorRewrite), | ||
"Replace impl trait with generic", | ||
target, | ||
|edit| { | ||
let impl_trait_type = edit.make_mut(impl_trait_type); | ||
let fn_ = edit.make_mut(fn_); | ||
let mut editor = edit.make_editor(&parent_node); | ||
let fn_generic_param_list = fn_.get_or_create_generic_param_list(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This get_or_create_generic_param_list
mutates syntax tree if there is no generic params - as the function name shows 😄 - and causes immutable tree panics in rowan. (You can check this with RUST_BACKTRACE=full cargo test <panicking test name>
or $env:RUST_BACKTRACE="full"; cargo test <panicking test name>
if you are on Windows.)
This should be modified to copying existing generic params or making fresh new generic params rather than inserting into exsisting syntax tree.
#18385 might be a good reference working on SyntaxFactory
assist things
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason for panicking is because L35: let fn_ = edit.make_mut(fn_)
is being removed. Of course, it should be removed since we are migrating to SyntaxFactory
from mutable syntax tree and we should modify the L45
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the review
This
get_or_create_generic_param_list
mutates syntax tree if there is no generic params ... This should be modified to copying existing generic params
How can I ‘copy existing generic params’ if there are none to begin with?
or making fresh new generic params
How would I go about doing that? I looked into initializing a new GenericParamList
, and the only way I found was using make::generic_param_list
, which is actually what’s in place now (but fails).
I defined a new ast::Fn
method similar to get_or_create_generic_param_list()
that calls syntax_editor_create_generic_param_list
if there are no existing generic params. This uses SyntaxEditor
to initialize the list (since insert_raw()
isn’t available for SyntaxEditor
, I used insert
instead).
Unfortunately, I can’t fully test my updates due to a new error:
---- tests::generated::doctest_introduce_named_generic stdout ----
thread 'tests::generated::doctest_introduce_named_generic' panicked at crates/syntax/src/syntax_editor.rs:55:9:
assertion failed: is_ancestor_or_self(&position.parent(), &self.root)
After tracing, this seems to be related to my syntax_editor_add_generic_param
implementation, though it’s identical to add_generic_param
except it uses SyntaxEditor
instead of ted
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By the way, I know these new functions would ideally go into a separate file, but right now I’m just focused on getting them working first
let position = crate::syntax_editor::Position::after(last_param.syntax()); | ||
let elements = vec![ | ||
make::token(T![,]).into(), | ||
make::tokens::single_space().into(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should not use make::
in new assists but should create a corresponding method in impl SyntaxFactory
in here;
impl SyntaxFactory { |
make.token(..)
(See Bee's migration guide here)And I think that this function shouldn't be here since we are going to remove all mutable syntax tree things and "edit in place" is kinda mutation. We should "create new" rather than "modify existing".
About the cursor position errors, I noticed that the cursor is on the n - 1
indexed generic parameter element position when we are inserting n
indexed one as new. (and If we are inserting the 0 indexed one, the cursor is missing 🤔) I guess there might be some unexpected interaction between here and the SyntaxEditor::replace
but as this might be moved to somewhere, let's see if this still happens then.
Signed-off-by: Tarek <[email protected]>
This PR is part of #15710 and #18285.
Changes Made
SyntaxEditor
#18285 for migration.SyntaxFactory
method,type_param
.add_generic_param
(originally inGenericParamList
) with a new method,syntax_editor_add_generic_param
. This new method is similar but takes aSyntaxEditor
instance instead ofted
to avoid the “immutable tree” error.