Skip to content
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

Using LSP's ErrorProvider & another attempt at CompletionCollector #7579

Merged
merged 2 commits into from
Jul 25, 2024

Conversation

jtulach
Copy link
Contributor

@jtulach jtulach commented Jul 15, 2024

Continuation of

Let's use ErrorProvider when available and display its hints in NetBeans.

Errors from Enso

The above picture shows errors provided by Enso IGV Plugin rev. 1.40.554 in NetBeans as proposed by enso-org/enso#10553

@jtulach jtulach requested review from dbalek, sdedic and lahodaj July 15, 2024 12:24
@jtulach jtulach self-assigned this Jul 15, 2024
@@ -1032,7 +1032,10 @@ public CompletableFuture<List<Either<Command, CodeAction>>> codeAction(CodeActio
continue;
}
}
Optional<Diagnostic> diag = diagnostics.stream().filter(d -> entry.getKey().equals(d.getCode().getLeft())).findFirst();
Optional<Diagnostic> diag = diagnostics.stream().filter(d -> {
String code = d.getCode() != null ? d.getCode().getLeft() : null;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unrelated to the core of this PR, but discovered at the same time. According to the LSP Spec code field is optional. Need to check for null.

@neilcsmith-net
Copy link
Member

What does continuation of #7505 mean? That was reverted in #7528

@jtulach
Copy link
Contributor Author

jtulach commented Jul 15, 2024

What does continuation of #7505 mean? That was reverted in #7528

Interesting. But I want the change in - new attempt 8356885 with additional fix in ea184f7. I tested the TypeScript editing on explorer.ts from java/java.lsp.server/vscode project. I am getting no NullPointerException (as reported by #7528). I can debug the TypeScript:

Debugging TypeScript

I can evaluate expressions while debugging and I see no AssertionErrors

@jtulach jtulach added LSP [ci] enable Language Server Protocol tests VSCode Extension [ci] enable VSCode Extension tests labels Jul 15, 2024
@mbien
Copy link
Member

mbien commented Jul 15, 2024

the slightly concerning aspect of the last revert was that it caused multiple issues in seemingly unrelated areas - and was only noticed during manual testing. It broke auto completion in the debug expression eval window, in a maven properties editor and @matthiasblaesing found also something in typescript (don't know the details). This indicates that there is a hole in the unit test coverage.

You can find the traces under the original PR #7505 (comment).

@mbien mbien added ci:all-tests [ci] enable all tests ci:dev-build [ci] produce a dev-build zip artifact (7 days expiration, see link on workflow summary page) labels Jul 15, 2024
@jtulach
Copy link
Contributor Author

jtulach commented Jul 15, 2024

the slightly concerning aspect of the last revert was that it caused multiple issues in seemingly unrelated areas - and was only noticed during manual testing. It broke auto completion in the debug expression eval window, in a maven properties editor and @matthiasblaesing found also something in typescript (don't know the details). This indicates that there is a hole in the unit test coverage.

Let's do more QA this time.

You can find the traces under the original PR #7505 (comment).

I believe ea184f7 eliminates the NPE. I never saw the AssertionError. If anyone sees it during QA, please give me steps to reproduce.

@jtulach
Copy link
Contributor Author

jtulach commented Jul 16, 2024

I see failure in Check PR labels, but I am not sure why? There are LSP and VSCode Extension labels on this PR.

@apache apache locked and limited conversation to collaborators Jul 16, 2024
@apache apache unlocked this conversation Jul 16, 2024
@jtulach
Copy link
Contributor Author

jtulach commented Jul 16, 2024

I see failure in Check PR labels, but I am not sure why? There are LSP and VSCode Extension labels on this PR.

Green CI

The CI checks are all green now, but I'd rather wait for Matthias to confirm the behavior is better when he edits TypeScript. On the other hand, I'd like these lsp.client changes to get into next version of NetBeans. My colleagues are eagerly waiting for Enso support in NetBeans/IGV and they don't build NetBeans from source.

@mbien
Copy link
Member

mbien commented Jul 16, 2024

I see failure in Check PR labels, but I am not sure why? There are LSP and VSCode Extension labels on this PR.

workflow runs are like container images. If you start one, the state doesn't change (restarts) until you build a new image. New ones are built when they are freshly triggered (e.g PR sync). This is also mentioned on the short reviewer guide we have on the wiki which is linked in the log when the label validation fails. So my guess is that this is what happened but I wasn't there to observe it. Neil forced a fresh workflow run and everything is green.

On the other hand, I'd like these lsp.client changes to get into next version of NetBeans.

you probably saw that I added the ci:dev-build [ci] produce a dev-build zip artifact (7 days expiration, see link on workflow summary page) label. This makes it easier to manually test this PR. As previously mentioned, the last time this caused problems and had to be reverted, it broke completion in seemingly unrelated areas + possibly more things without causing test failures. So I don't even know what features this can influence or what to look out for.

Copy link
Contributor

@matthiasblaesing matthiasblaesing left a comment

Choose a reason for hiding this comment

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

From a quick(!) look this should fix the NullPointerException problem as the use site is now guarded.

The second exception is still there. And indeed (quote from #7505 (comment))

Context: This happens when I call for code completion in "Evaluate expression", which is now broken.

can still be used to reproduce.

SEVERE [org.openide.util.RequestProcessor]: Error in RequestProcessor org.netbeans.spi.editor.completion.support.AsyncCompletionTask
java.lang.AssertionError: AsyncCompletionTask: query=org.netbeans.modules.lsp.client.bindings.LspCompletionProviderImpl$1@5804552c: query.query(): Result set not finished by resultSet.finish()
	at org.netbeans.spi.editor.completion.support.AsyncCompletionTask.run(AsyncCompletionTask.java:200)
	at org.openide.util.RequestProcessor$Task.run(RequestProcessor.java:1403)
	at org.netbeans.modules.openide.util.GlobalLookup.execute(GlobalLookup.java:45)
	at org.openide.util.lookup.Lookups.executeWith(Lookups.java:287)
[catch] at org.openide.util.RequestProcessor$Processor.run(RequestProcessor.java:2018)

More detailed steps to reproduce:

  1. Build from the branch backing this PR
  2. Create a new maven project
  3. Create a new class Dummy with this content:
import java.util.List;

public class Dummy {
  public static void main(String[] args) {
      List<String> list = List.of("X");
  }
}
  1. Place a break point inside main (line 5)
  2. Run "Debug file" on this
  3. Go to "Evaluate Expression"
  4. Enter "List."
  5. Call completion Ctrl+Space
  6. Observe problem

You are hitting the codepath in LspCompletionProviderImpl.java line 55.

Same file shows a new regression introduced by this. Before your change the unused variable "list" (line 5) is marked, but only slightly

image

now it is reported as a warning:

image

And I think the popup also shows, that the error is reported twice.

@jtulach
Copy link
Contributor Author

jtulach commented Jul 18, 2024

Thank you for the QA, Matthias.

Same file shows a new regression introduced by this. Before your change the unused variable "list" (line 5) is marked, but only slightly
now it is reported as a warning:
And I think the popup also shows, that the error is reported twice.

This one is particularly tricky. Unlike #7505 and #7483 - there is no declarative registration for "hints" (am I right @jlahoda). As such it is hard to find out whether there is a better alternative to JavaErrorManager or not. I can imagine various tricks to do such check (annotating ErrorProvider with some annotation, for example), but to keep the scope as small as possible I suggest just a simple isHeadless() check.

@jtulach jtulach force-pushed the UseLspErrorProvider branch from ab7bdc9 to 5366560 Compare July 18, 2024 13:17
@@ -94,7 +95,9 @@ public class JavaErrorProvider implements ErrorProvider {
@Override
public List<? extends Diagnostic> computeErrors(Context context) {
List<Diagnostic> result = new ArrayList<>();

if (!GraphicsEnvironment.isHeadless()) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The java.lsp.server project is using isHeadless() to detect whether the code is running in VSCode or in NetBeans IDE. Using it here to solve #7579 (comment) inquiry.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think I would rather suggest to drop the @MimeRegistration on this class, and register the class in nbcode. A similar pattern is already used for numerous services. Although in this case, it may be necessary/better to create the registration manually in layer.xml, for other services we do it by having a subclass in nbcode with an appropriate registration annotation.

Copy link
Contributor

Choose a reason for hiding this comment

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

This gives me bad vibes and is only a partial solution. I placed a breakpoint in ErrorProviderBridge#run and I see three ErrorProvider there:

  1. org.netbeans.modules.java.hints.infrastructure.JavaErrorProvider
  2. org.netbeans.modules.editor.hints.lsp.HintsDiagnosticsProvider
  3. org.netbeans.modules.micronaut.symbol.MicronautSymbolErrorProvider

(1) is now handled by checking GraphicsEnvironment#isHeadless, (2) ist explicitly filtered out by its name, (3) is retained.

This will become whac-a-mole because the interaction are not obvious. Would a different approach make sense where an autoloaded helper module, that depends on the modules, that provides the LSP implementation, provides the bridge only for that module? That way the interaction is easier to see and if necessary easy to drop.

I don't know the enso module name but assuming it is enso-lsp, a module enso-lsp.nb could be used to provide the integration limited to the enso type.

@jtulach
Copy link
Contributor Author

jtulach commented Jul 18, 2024

You are hitting the codepath in LspCompletionProviderImpl.java line 55.

Thanks for the hint. With such an error identification, it is easy to fix it: 87523ab. Now the debugging experience looks as expected (I'd say):

completion & hints while debugging Java

@jtulach jtulach requested a review from matthiasblaesing July 18, 2024 13:24
@jtulach jtulach changed the title Using LSP's ErrorProvider Using LSP's ErrorProvider & another attempt at CompletionCollector Jul 18, 2024
@neilcsmith-net neilcsmith-net removed their request for review July 19, 2024 17:39
*
* @author lahvac
*/
@MimeRegistration(mimeType="text/x-java", service=ErrorProvider.class)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

... drop the @MimeRegistration on this class, and register the class in nbcode.

Thanks @jlahoda. Done in 512ee11

@jtulach
Copy link
Contributor Author

jtulach commented Jul 20, 2024

freeze for NB23 was moved from 15th to the 26th (next Friday) so there is time to review/test this properly without rushing anything in https://lists.apache.org/thread/pr3dnjdkot8kny9g2htqlpcg1s9f9t45

Thanks for letting me know. I believe both NetBeans as well as VSCode are working fine with the current state of this PR:

  • TypeScript editing works and shows code completion and documentation
  • Matthias's debugging scenario works and there are no duplications
  • VSCode shows hints in Dummy.java file, can debug, offers code completion

I am confident things are OK this time. Unless I hear objections, I plan to integrate early next week.

I think the main discovery here remains that none of the existing tests picked any of the problems up. Would be good to check why that happened (is the module not loaded or something similar?). E.g regression tests for double occurrence of hint annotations might be something we could add (but I would be surprised if they weren't there yet).

Hints are certainly tested, but I think they are tested via "unit tests". Such kind of tests can detect missing functionality of own module, but cannot detect extra functionality of completely different module. Such an integration test would need NbModuleSuite with all enabled modules - I don't think NetBeans has such a test these days.

@jtulach jtulach requested a review from lahodaj July 20, 2024 06:18
Copy link
Contributor

@matthiasblaesing matthiasblaesing left a comment

Choose a reason for hiding this comment

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

This is still broken. The layer registration of JavaErrorProvider in java.lsp.server (added in 275ade6) restores the broken behavior, that should have been fixed by 512ee110f7865130c16a85d930a2217fcc4545a2. I.e. the invalid error markers are back again.

I also see MicronautSymbolErrorProvider in the java lookup and while currently there does not seem to be a provider that reports the same problems in NetBeans IDE, it might quickly turn up and cause similar problems as the JavaErrorManager.

@jtulach jtulach force-pushed the UseLspErrorProvider branch from 275ade6 to cba6ef2 Compare July 22, 2024 09:12
@jtulach
Copy link
Contributor Author

jtulach commented Jul 22, 2024

The best way to break things is to test everything and then make additional commit...

This is still broken. The layer registration of JavaErrorProvider in java.lsp.server (added in 275ade6) restores the broken behavior, that should have been fixed by 512ee110f7865130c16a85d930a2217fcc4545a2. I.e. the invalid error markers are back again.

Fixed by registering the provider only for tests, as was my intention to begin with. Please accept my apology for useless round of review.

@jtulach
Copy link
Contributor Author

jtulach commented Jul 22, 2024

I also see MicronautSymbolErrorProvider in the java lookup and while currently there does not seem to be a provider that reports the same problems in NetBeans IDE, it might quickly turn up and cause similar problems as the JavaErrorManager.

I can register MicronautSymbolErrorProvider in VSCode only just like I did for JavaErrorProvider. Or we can remove org.netbeans.modules.csl.api.HintsProvider implementation in micronaut module and let the bridge handle the error presentation. I let @dbalek decide.

Copy link
Contributor

@matthiasblaesing matthiasblaesing left a comment

Choose a reason for hiding this comment

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

I think my main pain points are fixed. I have two concerns remaining about the implementation, that make sense to me to fix before integration.

Comment on lines +63 to +64
computeHints(ErrorProvider.Kind.ERRORS, p, "lsp:errors");
computeHints(ErrorProvider.Kind.HINTS, p, "lsp:hints");
Copy link
Contributor

Choose a reason for hiding this comment

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

Do the runs with ErrorProvider.Kind.ERRORS and and ErrorProvider.Kind.HINTS yield disjunct sets of error sets? If not, what is the result for the user?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The Enso error provider is only computing ERRORS and returns empty array for HINTS request.

Copy link
Contributor

Choose a reason for hiding this comment

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

I would expect disjoint sets to be provided, which are then automatically merged, and the joint result is presented to the used. If a provider returns the same diagnostics from both queries, it will be duplicated for the user, I think.

The main purpose of this split is to show errors to the user quickly, and then take the time needed to compute the warnings.

@dbalek
Copy link
Contributor

dbalek commented Jul 24, 2024

I also see MicronautSymbolErrorProvider in the java lookup and while currently there does not seem to be a provider that reports the same problems in NetBeans IDE, it might quickly turn up and cause similar problems as the JavaErrorManager.

I can register MicronautSymbolErrorProvider in VSCode only just like I did for JavaErrorProvider. Or we can remove org.netbeans.modules.csl.api.HintsProvider implementation in micronaut module and let the bridge handle the error presentation. I let @dbalek decide.

In an ideal case, MicronautSymbolErrorProvider should provide the errors for both NetBeans IDE and VSCode.

@jtulach jtulach force-pushed the UseLspErrorProvider branch from 9ba53da to 993677e Compare July 24, 2024 08:37
@jtulach jtulach requested a review from matthiasblaesing July 24, 2024 13:41
@jtulach
Copy link
Contributor Author

jtulach commented Jul 24, 2024

I can register MicronautSymbolErrorProvider in VSCode only just like I did for JavaErrorProvider. Or we can remove org.netbeans.modules.csl.api.HintsProvider implementation in micronaut module and let the bridge handle the error presentation. I let @dbalek decide.

In an ideal case, MicronautSymbolErrorProvider should provide the errors for both NetBeans IDE and VSCode.

Looks like there are no doubled Micronaut warnings. Things look OK:

Micronaut

In such case I rather leave Micronaut support untouched for now.

@jtulach
Copy link
Contributor Author

jtulach commented Jul 24, 2024

Unless there are objections, I will merge tomorrow.

Copy link
Contributor

@matthiasblaesing matthiasblaesing left a comment

Choose a reason for hiding this comment

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

Looks sane to me. My concerns were addressed. Thank you.

One final request: Please squash the commits into logical unittests. We don't gain anything from intermediate states of the, if they are logically squashed, in the future have a change to understand the big picture not just one random fix.

@jtulach jtulach force-pushed the UseLspErrorProvider branch from 993677e to 557c823 Compare July 25, 2024 04:08
Comment on lines +63 to +64
computeHints(ErrorProvider.Kind.ERRORS, p, "lsp:errors");
computeHints(ErrorProvider.Kind.HINTS, p, "lsp:hints");
Copy link
Contributor

Choose a reason for hiding this comment

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

I would expect disjoint sets to be provided, which are then automatically merged, and the joint result is presented to the used. If a provider returns the same diagnostics from both queries, it will be duplicated for the user, I think.

The main purpose of this split is to show errors to the user quickly, and then take the time needed to compute the warnings.

@jtulach jtulach merged commit 536ddb9 into apache:master Jul 25, 2024
40 checks passed
@matthiasblaesing
Copy link
Contributor

@jtulach thanks for cleaning up and explaining one real example
@jlahoda thanks for chiming in and giving the overall perspective!

@matthiasblaesing
Copy link
Contributor

@jtulach a new regression was found introduced by this. See #7647

MartinBalin added a commit that referenced this pull request Sep 2, 2024
Revert PR #7579 ("Using LSP's ErrorProvider & another attempt at CompletionCollector")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ci:all-tests [ci] enable all tests ci:dev-build [ci] produce a dev-build zip artifact (7 days expiration, see link on workflow summary page) LSP [ci] enable Language Server Protocol tests VSCode Extension [ci] enable VSCode Extension tests
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants