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

Exception occurred after sending textDocument/completion request. #3116

Closed
TherCN opened this issue Mar 27, 2024 · 6 comments
Closed

Exception occurred after sending textDocument/completion request. #3116

TherCN opened this issue Mar 27, 2024 · 6 comments

Comments

@TherCN
Copy link

TherCN commented Mar 27, 2024

OS:Android 10
Java Version:17
Run Command:

export JDTLS_DIR=/sdcard/jdtls
java \
-Declipse.application=org.eclipse.jdt.ls.core.id1 \
-Dosgi.bundles.defaultStartLevel=4 \
-Declipse.product=org.eclipse.jdt.ls.core.product \
-Dosgi.checkConfiguration=true \
-Dosgi.sharedConfiguration.area=$JDTLS_DIR/config_linux \
-Dosgi.sharedConfiguration.area.readOnly=true \
-Dosgi.configuration.cascaded=true \
-Xms1G \
--add-modules=ALL-SYSTEM \
--add-opens \
java.base/java.util=ALL-UNNAMED \
--add-opens \
java.base/java.lang=ALL-UNNAMED \
-jar \
$JDTLS_DIR/plugins/org.eclipse.equinox.launcher_1.6.700.v20231214-2017.jar \
-data \
/storage/emulated/0/TestProject

The code to send the request is in: MainActivity.java

And I returned an exception when sending textDocument/completion, as down:

{
  "method": "window/logMessage",
  "jsonrpc": "2.0",
  "params": {
    "type": 1,
    "message": "Mar 25, 2024, 6:48:07 AM Problem with codeComplete for file:///storage/emulated/0/AppProjects/ADOFAI-Helper/src/main/java/thercn/adofai/helper/Main.java
Cannot invoke \"org.eclipse.lsp4j.CompletionCapabilities.getInsertTextMode()\" because the return value of \"org.eclipse.lsp4j.TextDocumentClientCapabilities.getCompletion()\" is null
java.lang.NullPointerException: Cannot invoke \"org.eclipse.lsp4j.CompletionCapabilities.getInsertTextMode()\" because the return value of \"org.eclipse.lsp4j.TextDocumentClientCapabilities.getCompletion()\" is null
	at org.eclipse.jdt.ls.core.internal.preferences.ClientPreferences.getCompletionItemInsertTextModeDefault(ClientPreferences.java:430)
	at org.eclipse.jdt.ls.core.internal.contentassist.CompletionProposalReplacementProvider.updateReplacement(CompletionProposalReplacementProvider.java:176)
	at org.eclipse.jdt.ls.core.internal.contentassist.CompletionProposalRequestor.initializeCompletionListItemDefaults(CompletionProposalRequestor.java:387)
	at org.eclipse.jdt.ls.core.internal.contentassist.CompletionProposalRequestor.getCompletionItems(CompletionProposalRequestor.java:283)
	at org.eclipse.jdt.ls.core.internal.contentassist.CompletionProposalRequestor.getCompletionItems(CompletionProposalRequestor.java:259)
	at org.eclipse.jdt.ls.core.internal.handlers.CompletionHandler.computeContentAssist(CompletionHandler.java:291)
	at org.eclipse.jdt.ls.core.internal.handlers.CompletionHandler.completion(CompletionHandler.java:121)
	at org.eclipse.jdt.ls.core.internal.handlers.JDTLanguageServer.completion(JDTLanguageServer.java:633)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.eclipse.lsp4j.jsonrpc.services.GenericEndpoint.lambda$recursiveFindRpcMethods$0(GenericEndpoint.java:65)
	at org.eclipse.lsp4j.jsonrpc.services.GenericEndpoint.notify(GenericEndpoint.java:152)
	at org.eclipse.lsp4j.jsonrpc.RemoteEndpoint.handleNotification(RemoteEndpoint.java:220)
	at org.eclipse.lsp4j.jsonrpc.RemoteEndpoint.consume(RemoteEndpoint.java:187)
	at org.eclipse.jdt.ls.core.internal.ParentProcessWatcher.lambda$1(ParentProcessWatcher.java:144)
	at org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer.handleMessage(StreamMessageProducer.java:194)
	at org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer.listen(StreamMessageProducer.java:94)
	at org.eclipse.lsp4j.jsonrpc.json.ConcurrentMessageProcessor.run(ConcurrentMessageProcessor.java:113)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
	at java.base/java.lang.Thread.run(Thread.java:833)
"
  }
}

I tried this problem in versions 1.32.0 and 1.33.0 and 1.34.0snapshot respectively. How can I solve it?

@rgrunber
Copy link
Contributor

I think this is actually a bug in our implementation that we should be fixing. According to the spec :

https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentClientCapabilities

/**
   * Capabilities specific to the `textDocument/completion` request.
 */
completion?: CompletionClientCapabilities;

That question mark indicates the value is optional and need not be defined.

However, we're clearly accessing it without checking whether it exists (line 430) :

public boolean isCompletionItemInsertTextModeSupport(InsertTextMode insertMode) {
return v3supported
&& capabilities.getTextDocument().getCompletion() != null
&& capabilities.getTextDocument().getCompletion().getCompletionItem() != null
&& capabilities.getTextDocument().getCompletion().getCompletionItem().getInsertTextModeSupport() != null
&& capabilities.getTextDocument().getCompletion().getCompletionItem().getInsertTextModeSupport().getValueSet().contains(insertMode);
}
public InsertTextMode getCompletionItemInsertTextModeDefault() {
return capabilities.getTextDocument().getCompletion().getInsertTextMode();
}

The lines immediately above show the right way to do it.

As a workaround, @TherCN , could you try setting defining :

JSONObject completionCapabilities = new JSONObject();
textCapabilities.put("completion", completionCapabilities);

at https://github.com/TherCN/LSPClient-Example/blob/main/app/src/main/java/com/example/MainActivity.java#L305 and see if that temporarily fixes it ?

@TherCN
Copy link
Author

TherCN commented Mar 28, 2024

我认为这实际上是我们实施中的一个错误,我们应该修复。根据规范:

https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specation/#textDocumentClientCapability

/**
   * Capabilities specific to the `textDocument/completion` request.
 */
completion?: CompletionClientCapabilities;

该问号表示该值是可选的,不需要定义。

然而,我们显然是在访问它而不检查它是否存在(第 430 行):

public boolean isCompletionItemInsertTextModeSupport(InsertTextMode insertMode) {
return v3supported
&& capabilities.getTextDocument().getCompletion() != null
&& capabilities.getTextDocument().getCompletion().getCompletionItem() != null
&& capabilities.getTextDocument().getCompletion().getCompletionItem().getInsertTextModeSupport() != null
&& capabilities.getTextDocument().getCompletion().getCompletionItem().getInsertTextModeSupport().getValueSet().contains(insertMode);
}
public InsertTextMode getCompletionItemInsertTextModeDefault() {
return capabilities.getTextDocument().getCompletion().getInsertTextMode();
}

上面的几行显示了正确的方法。

作为解决方法,@TherCN,你可以尝试设置定义:

JSONObject completionCapabilities = new JSONObject();
textCapabilities.put("completion", completionCapabilities);

https://github.com/TherCN/LSPClient-Example/blob/main/app/src/main/java/com/example/MainActivity.java#L305看看是否可以暂时修复它?

Thank you for your help. After I added the code, it didn't return an exception, but it didn't return a completion request either.

@rgrunber
Copy link
Contributor

Would you be able to attach a log of the client requests that are made to the server as well as how the server responds ? The client would need to at least call initialize, followed by didOpen (on the Java file URI) prior to calling completion.

@TherCN
Copy link
Author

TherCN commented Mar 28, 2024

Would you be able to attach a log of the client requests that are made to the server as well as how the server responds ? The client would need to at least call initialize, followed by didOpen (on the Java file URI) prior to calling completion.

LSPClient.log

@TherCN
Copy link
Author

TherCN commented Mar 29, 2024

Would you be able to attach a log of the client requests that are made to the server as well as how the server responds ? The client would need to at least call initialize, followed by didOpen (on the Java file URI) prior to calling completion.

I added the id when I sent the request, and the completion request has been successfully returned. I will close this issue soon.

@TherCN TherCN closed this as completed Mar 29, 2024
@rgrunber
Copy link
Contributor

rgrunber commented Apr 1, 2024

Good catch. Yeah according to https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#requestMessage , id is required.

In terms of debugging such issues in the future, you could start the language server to have it listening for a debugger, connect to it remotely so that you'd be able to see what's going wrong. I mention this in #2313 (comment) . This would have probably allowed you to debug where the id failure was occuring in https://github.com/eclipse-lsp4j/lsp4j/blob/32aac26422a93019c197f6f7d92349bee609f2d9/org.eclipse.lsp4j.jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/StreamMessageProducer.java#L80 .

To do this just make sure you add something like -agentlib:jdwp=transport=dt_socket,server=y,address=8000 to the virtual machine arguments of the language server startup. Since you're using the helper script, that, would be --jvm-arg="-agentlib:jdwp=transport=dt_socket,server=y,address=8000" . Then you can just connect to port 8000 as a remote Java debug session and as long you have JDT-LS and it's target platform in your workspace, it should be possible to debug.

@rgrunber rgrunber added this to the End March 2024 milestone Apr 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants