-
Notifications
You must be signed in to change notification settings - Fork 185
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
Add textEdits method to ScalafixPatch #1737
Conversation
Hi @LaurenceWarne! Thanks for putting this together, apologies for the (long) delay. First of all, I am not very knowledgeable about patch internals as I never got the chance to change anything in there, so take my words with a pinch of salt. I understand your idea is to let a user interactively review & apply patches, and that sounds like a cool feature! I see 4 options for the implementation:
My current thoughts:
Does this help? Let me know what you think. In any case, I'll be happy to help you with reviews (in a much more timely manner than this first one 😅), but not much more considering the limited bandwidth I have. |
Hi @bjaglin, no problem at all, thanks for the detailed response!
I think taking advantage of atomic patches might be enough for my use case actually. (you might have already guessed 🙂 ) I'm playing around with extending metals' scalafix integration to make it more fine-grained - and I realised I can use a workspace edit so multiple text edits can be applied at once (for a given code action) and they needn't overlap in any sense - we would only need to map a given atomic patch to a set of text edits if that makes sense. So we could return a nested collection of text edits, with each individual text edit set corresponding to one atomic patch without any need to resort to heuristics around combining overlapping token patches, etc. How does that sound? One problem with this method I found is that it relies on rule authors using I think the implementation is a lot easier as well, will push a commit 🙂 |
41260fa
to
cbeb5cc
Compare
Good - that's effectively what I was suggesting in (3).
As documented, rules must use One could argue that So I recommend that you open a PR to add |
Interestingly, it seems that |
cbeb5cc
to
a5564c9
Compare
Done! The test currently checks against how many edits are returned per patch, I can change this to the actual content of the edits f you think this would be better.
Yeah I saw that too, I can ask the question at least 🙂 - Xuwei's rules are one of the most popular repos I think, but I'll try and test with others. Do you maintain a curated list of community rules by any chance (I couldn't see mention of it on the microsite)? Another nice to have would be if |
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 test currently checks against how many edits are returned per patch, I can change this to the actual content of the edits f you think this would be better.
I think it would be good do check content, in order to guard the 0-based behavior of ranges.
Do you maintain a curated list of community rules by any chance (I couldn't see mention of it on the microsite)?
There is a list, but it hasn't been updated for a while.
Another nice to have would be if ScalafixPatches, had some kind of reference to their rule (I think RuleDiagnostics have this, but not patches?), but that's another issue slightly_smiling_face .
Agreed, let's keep that for another PR? For the record, I will cut a new minor release of Scalafix as soon as the new 2.12 and 2.13 patch releases are out (within a couple of weeks if I understand well, given that they depend on the release date of 3.3.0, for which RC5 seems final), so there is an opportunity to get this PR out very soon!
throw new UnsupportedOperationException("getTextEdits() is not implemented"); |
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.
For consistency with other interfaces
default ScalafixEdit[] getTextEdits() { | |
throw new UnsupportedOperationException("getTextEdits() is not implemented"); | |
default ScalafixEdit[] textEdits() { | |
throw new UnsupportedOperationException("textEdits() is not implemented"); |
@@ -0,0 +1,13 @@ | |||
package scalafix.interfaces; | |||
|
|||
public interface ScalafixEdit { |
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.
Even if a bit pedantic,
public interface ScalafixEdit { | |
public interface ScalafixTextEdit { |
would be more consistent
|
||
int endColumn(); | ||
|
||
String text(); |
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.
related to comment above, maybe
String text(); | |
String newText(); |
scalafix-tests/unit/src/test/scala/scalafix/tests/interfaces/ScalafixArgumentsSuite.scala
Show resolved
Hide resolved
int startLine(); | ||
|
||
int startColumn(); | ||
|
||
int endLine(); | ||
|
||
int endColumn(); |
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.
I initially thought that this was https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textEdit, however not only naming, but also the way the range is expressed differs.
Could we reuse ScalafixPosition
which is quite well documented?
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.
sure, sounds good to me.
// CommentFileNonAtomic produces two patches which in turn produce one | ||
// token patch each, whilst CommentFileAtomic produces one patch which | ||
// in turn produces two token patches |
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.
👍
Add textEdits method to ScalafixPatch as an alternative way of obtaining the results of a Scalafix evaluation. The results of applying a patch are exposed as a set of LSP style 'text edits', which consists of a start position, end position, and insert text.
a5564c9
to
285a014
Compare
Cool, I though I remembered one.
Yes, sorry that's what I meant, and nice! |
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.
Thanks @LaurenceWarne !
Sorry that it took longer than expected to cut the release with that! Somewhat related effort: https://contributors.scala-lang.org/t/roadmap-for-actionable-diagnostics/6172 |
No problem 🙂
Interesting, I hadn't seen this. Thanks for linking, I'll be sure to take a look. |
Hi! I'd like to be able to obtain (LSP style) text edit like information (essentially representing a diff as a start position, end position, and insert text) from the scalafix api (specifically a given
ScalafixFileEvaluation
) - AFAICS something like this is currently not exposed (?).I've created an implementation (the method is similar to
PatchInternals.tokenPatchApply
). Though I've found some rules don't give the greatest results, for example patches from theOptionWhenUnless
rule (from https://github.com/xuwei-k/scalafix-rules):Result in multiple overlapping text edits. Though I've had good results for many of the built in rules, for example a typical
LeakingImplicitVal
patch:results in a singular text edit.
Anyway, let me know if you are open to something like this, or if something like this is already implemented, thanks 🙂