Skip to content

Categorize assists #5116

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

Merged
merged 5 commits into from
Jul 3, 2020
Merged

Categorize assists #5116

merged 5 commits into from
Jul 3, 2020

Conversation

kjeremy
Copy link
Contributor

@kjeremy kjeremy commented Jun 29, 2020

Categorize assists so that editors can use them. Follows the LSP spec pretty close (and some things may need adjustments) but this populates the Refactor menu in vscode and pushes quickfixes through again.

This is a prerequisite to filtering out assists that the client doesn't care about.

Fixes #4147

RefactorRewrite,
Source,
OrganizeImports,
}
Copy link
Member

Choose a reason for hiding this comment

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

Let' keep only those kinds which we actually use.

@@ -52,7 +52,7 @@ pub(crate) fn add_custom_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<
format!("Add custom impl `{}` for `{}`", trait_token.text().as_str(), annotated_name);

let target = attr.syntax().text_range();
acc.add(AssistId("add_custom_impl"), label, target, |builder| {
acc.add(AssistId("add_custom_impl"), AssistKind::Refactor, label, target, |builder| {
Copy link
Member

Choose a reason for hiding this comment

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

Wdyt, does it make sense to move AssistKind into AssistId struct? Kind is kind-of determined by ID.

Copy link
Member

Choose a reason for hiding this comment

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

On the other hand moving it into the AssistId struct makes it seem like AssistId("add_custom_impl", AssistKind::Refactor) and AssistId("add_custom_impl", AssistKind::RefactorExtract) are two separate assists.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@matklad I thought about this and almost made that change If that makes more sense I can do that.

@bjorn3 Aren't the id's supposed to be unique?

})
acc.add(
AssistId("add_function"),
AssistKind::RefactorExtract,
Copy link
Member

Choose a reason for hiding this comment

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

This is not extract though, but rather create from use. Ie, it doesn't wrap existing code into a function

.and_then(|impl_def| {
acc.add(
AssistId("add_new"),
AssistKind::Refactor,
Copy link
Member

Choose a reason for hiding this comment

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

Let's add AssistKind::Generate for things which generate new code (add constructor, add impl)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm now thinking that there's no reason to do this and we should just leave this kind as empty since there's no UI need to distinguish this case.

Copy link
Member

@matklad matklad Jul 2, 2020

Choose a reason for hiding this comment

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

Heh, my reason for suggesting this was that IntelliJ actually has a dedicated UI for generating stuff: https://www.jetbrains.com/help/idea/generating-code.html :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Definitely. I think if we get a menu to do that then we should re-categorize.

})
acc.add(
AssistId("fill_match_arms"),
AssistKind::RefactorRewrite,
Copy link
Member

Choose a reason for hiding this comment

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

Should probably be quick fix?

};
acc.add(
AssistId("move_guard_to_arm_body"),
AssistKind::RefactorExtract,
Copy link
Member

Choose a reason for hiding this comment

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

Rewrite

let ok_tuple = make::tuple_struct_pat(ok_path, iter::once(it)).into();
acc.add(
AssistId("replace_unwrap_with_match"),
AssistKind::RefactorRewrite,
Copy link
Member

Choose a reason for hiding this comment

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

Hm, let's introduce two kinds for:

  • assist that rewrite code to equivalent (apply de-morgan, replace if-let with match, etc)
  • assists that may change semantics of code

Not sure what are the best names for two things...

Copy link
Member

Choose a reason for hiding this comment

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

According to the lsp spec:

The set of kinds is open and client needs to announce the kinds it supports to the server during initialization.

This means that at least if you introduce new kinds, you would have to support a fallback when the client doesn't say it supports them.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This means that at least if you introduce new kinds, you would have to support a fallback when the client doesn't say it supports them.

It's the client job to handle unknown values:

  • The code action kind values the client supports. When this
  • property exists the client also guarantees that it will
  • handle values outside its set gracefully and falls back
  • to a default value when unknown.

@@ -28,7 +28,7 @@ pub(crate) fn split_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
}

let target = colon_colon.text_range();
acc.add(AssistId("split_import"), "Split import", target, |edit| {
acc.add(AssistId("split_import"), AssistKind::RefactorExtract, "Split import", target, |edit| {
Copy link
Member

Choose a reason for hiding this comment

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

Rewrite

@kjeremy
Copy link
Contributor Author

kjeremy commented Jun 29, 2020

We should also think about filtering: the LSP request can specify that it's only interested in certain assists and our infra makes it hard to avoid descending into the handlers based on this information.

@kjeremy
Copy link
Contributor Author

kjeremy commented Jun 29, 2020

@kjeremy kjeremy force-pushed the code-action-kind branch from 4dbf56a to 1d58e16 Compare July 2, 2020 21:14
@kjeremy
Copy link
Contributor Author

kjeremy commented Jul 2, 2020

I think this is ready for another round of review.

Copy link
Member

@matklad matklad left a comment

Choose a reason for hiding this comment

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

bors r+

@bors
Copy link
Contributor

bors bot commented Jul 3, 2020

@bors bors bot merged commit f51b0cf into rust-lang:master Jul 3, 2020
@kjeremy kjeremy deleted the code-action-kind branch July 6, 2020 17:55
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.

Add CodeActionKinds to assists and return them from server caps if the client supports it
3 participants