SublimeDebugger icon indicating copy to clipboard operation
SublimeDebugger copied to clipboard

Java adapter

Open LDAP opened this issue 4 years ago • 29 comments

Connection to the debugger works. But I am getting a "missing mainClass..." error.

LDAP avatar Mar 08 '21 12:03 LDAP

Connection to the debugger works. But I am getting a "missing mainClass..." error.

Thats fixed by supplying:

"mainClass": "${file}",
"modulePaths": ["${folder}"]

Now the Debugger fails with:

jdtls: 08.03.2021, 15:28:47 [error response][launch]: Failed to launch debuggee in terminal. Reason: Failed to launch debuggee in terminal. Reason: java.util.concurrent.TimeoutException: timeout
Failed to launch debuggee in terminal. Reason: Failed to launch debuggee in terminal. Reason: java.util.concurrent.TimeoutException: timeout
com.microsoft.java.debug.core.DebugException: Failed to launch debuggee in terminal. Reason: Failed to launch debuggee in terminal. Reason: java.util.concurrent.TimeoutException: timeout
	at com.microsoft.java.debug.core.adapter.handler.LaunchWithDebuggingDelegate.lambda$launchInTerminal$0(LaunchWithDebuggingDelegate.java:157)
	at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:859)
	at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:837)
	at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:506)
	at java.base/java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:2152)
	at com.microsoft.java.debug.core.protocol.AbstractProtocolServer$1.run(AbstractProtocolServer.java:192)
	at java.base/java.util.TimerThread.mainLoop(Timer.java:556)
	at java.base/java.util.TimerThread.run(Timer.java:506)

Debugger does not reply to runInTerminal. Is this a known issue? (I am running Windows 10, ST 4098)

LDAP avatar Mar 08 '21 14:03 LDAP

Okey, I found the comment in terminal_process.py. Seems like ST4 does not support runInTerminal?

LDAP avatar Mar 08 '21 15:03 LDAP

Okey, I found the comment in terminal_process.py. Seems like ST4 does not support runInTerminal?

It relies on winpty and dependencies don't work on the 3.8 environment

daveleroy avatar Mar 08 '21 20:03 daveleroy

Okey, I found the comment in terminal_process.py. Seems like ST4 does not support runInTerminal?

@LDAP for now you can probably change your configuration to not use the integrated terminal.

"console": "internalConsole"

daveleroy avatar Mar 08 '21 20:03 daveleroy

"console": "internalConsole"

In this case the Server errors with:

jdtls: 08.03.2021, 23:12:44 Error parsing message: com.google.gson.JsonSyntaxException: Expected a com.google.gson.JsonObject but was com.google.gson.JsonNull
Expected a com.google.gson.JsonObject but was com.google.gson.JsonNull
com.google.gson.JsonSyntaxException: Expected a com.google.gson.JsonObject but was com.google.gson.JsonNull
	at com.google.gson.internal.bind.TypeAdapters$35$1.read(TypeAdapters.java:897)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:131)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:222)
	at com.google.gson.Gson.fromJson(Gson.java:932)
	at com.google.gson.Gson.fromJson(Gson.java:897)
	at com.google.gson.Gson.fromJson(Gson.java:846)
	at com.google.gson.Gson.fromJson(Gson.java:817)
	at com.microsoft.java.debug.core.protocol.JsonUtils.fromJson(JsonUtils.java:26)
	at com.microsoft.java.debug.core.protocol.AbstractProtocolServer.processData(AbstractProtocolServer.java:219)
	at com.microsoft.java.debug.core.protocol.AbstractProtocolServer.run(AbstractProtocolServer.java:98)
	at com.microsoft.java.debug.core.adapter.ProtocolServer.run(ProtocolServer.java:61)
	at com.microsoft.java.debug.plugin.internal.JavaDebugServer$2.run(JavaDebugServer.java:136)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
	at java.base/java.lang.Thread.run(Thread.java:832)

jdtls: 08.03.2021, 23:12:44 Error parsing message: com.google.gson.JsonSyntaxException: Expected a com.google.gson.JsonObject but was com.google.gson.JsonNull
Expected a com.google.gson.JsonObject but was com.google.gson.JsonNull
com.google.gson.JsonSyntaxException: Expected a com.google.gson.JsonObject but was com.google.gson.JsonNull
	at com.google.gson.internal.bind.TypeAdapters$35$1.read(TypeAdapters.java:897)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:131)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:222)
	at com.google.gson.Gson.fromJson(Gson.java:932)
	at com.google.gson.Gson.fromJson(Gson.java:897)
	at com.google.gson.Gson.fromJson(Gson.java:846)
	at com.google.gson.Gson.fromJson(Gson.java:817)
	at com.microsoft.java.debug.core.protocol.JsonUtils.fromJson(JsonUtils.java:26)
	at com.microsoft.java.debug.core.protocol.AbstractProtocolServer.processData(AbstractProtocolServer.java:219)
	at com.microsoft.java.debug.core.protocol.AbstractProtocolServer.run(AbstractProtocolServer.java:98)
	at com.microsoft.java.debug.core.adapter.ProtocolServer.run(ProtocolServer.java:61)
	at com.microsoft.java.debug.plugin.internal.JavaDebugServer$2.run(JavaDebugServer.java:136)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
	at java.base/java.lang.Thread.run(Thread.java:832)

LDAP avatar Mar 08 '21 22:03 LDAP

What request is this failing on? If its the initialize request its likely there are additional required parameters in the configuration that get patched in.

https://github.com/microsoft/java-debug/blob/64d42435b9913ad39f49f8700e0c046abdc12dd5/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/protocol/Requests.java#L103

I would try adding "env":{}

daveleroy avatar Mar 08 '21 22:03 daveleroy

What request is this failing on? If its the initialize request its likely there are additional required parameters in the configuration that get patched in.

https://github.com/microsoft/java-debug/blob/64d42435b9913ad39f49f8700e0c046abdc12dd5/com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/protocol/Requests.java#L103

I would try adding "env":{}

Still erroring,

this is the Debugger Protocol:

⟸ process/started
⟸ request/initialize(1) :: {'clientID': 'sublime', 'clientName': 'Sublime Text', 'adapterID': 'java', 'pathFormat': 'path', 'linesStartAt1': True, 'columnsStartAt1': True, 'supportsVariableType': True, 'supportsVariablePaging': False, 'supportsRunInTerminalRequest': True, 'locale': 'en-us'}
⟹ response/initialize(1) :: {'supportsConfigurationDoneRequest': True, 'supportsHitConditionalBreakpoints': True, 'supportsConditionalBreakpoints': True, 'supportsEvaluateForHovers': True, 'supportsCompletionsRequest': True, 'supportsRestartFrame': True, 'supportsSetVariable': True, 'supportsRestartRequest': False, 'supportTerminateDebuggee': True, 'supportsDelayedStackTraceLoading': False, 'supportsLogPoints': True, 'supportsExceptionInfoRequest': True, 'exceptionBreakpointFilters': [{'label': 'Uncaught Exceptions', 'filter': 'uncaught'}, {'label': 'Caught Exceptions', 'filter': 'caught'}], 'supportsDataBreakpoints': True, 'supportsClipboardContext': True}
⟸ request/launch(2) :: {'console': 'internalConsole', 'cwd': 'D:\\Local_Repositories\\Development\\Java\\Projects\\TimeSheetGenerator', 'env': {}, 'mainClass': 'D:\\Local_Repositories\\Development\\Java\\Projects\\TimeSheetGenerator\\src\\main\\java\\main\\Main.java', 'modulePaths': ['D:\\Local_Repositories\\Development\\Java\\Projects\\TimeSheetGenerator'], 'name': 'Launch Current File', 'request': 'launch', 'stopOnEntry': False, 'type': 'java'}
⟹ event/initialized :: {'type': 'initialized'}
⟸ request/setDataBreakpoints(3) :: {'breakpoints': []}
⟸ request/setExceptionBreakpoints(4) :: {'filters': [], 'filterOptions': []}
⟸ request/setBreakpoints(5) :: {'source': {'path': 'D:\\Local_Repositories\\Development\\Java\\Projects\\TimeSheetGenerator\\src\\main\\java\\main\\Main.java'}, 'breakpoints': [{'line': 29}]}
⟹ response/launch(2) :: None
⟸ request/threads(6) :: None
⟹ response/setDataBreakpoints(3) :: {'breakpoints': []}
⟹ response/setExceptionBreakpoints(4) :: None
⟹ response/setBreakpoints(5) :: {'breakpoints': [{'id': 1, 'verified': False, 'line': 29, 'message': ''}]}
⟸ request/configurationDone(7) :: None

Config:

{
	"type": "java",
	"name": "Launch Current File",
	"request": "launch",
	"mainClass": "${file}",
	"modulePaths": ["${folder}"],
	"cwd": "${folder}",
	"console": "internalConsole",
	"env": {},
	"stopOnEntry": false
},

LDAP avatar Mar 09 '21 09:03 LDAP

Looks to be way past the initialize request. From the looks of it they are just not handling the configurationDone request correctly and treating the arguments as none optional.

https://github.com/daveleroy/sublime_debugger/blob/2b5f0a5860027a0f2ad9b9fcd791b41a3179da57/modules/dap/session.py#L672

Try changing await self.request('configurationDone', None) to await self.request('configurationDone', {})

daveleroy avatar Mar 09 '21 09:03 daveleroy

Looks to be way past the initialize request. From the looks of it they are just not handling the configurationDone request correctly and treating the arguments as none optional.

https://github.com/daveleroy/sublime_debugger/blob/2b5f0a5860027a0f2ad9b9fcd791b41a3179da57/modules/dap/session.py#L672

Try changing await self.request('configurationDone', None) to await self.request('configurationDone', {})

That did the trick. Now the command gets executed, but fails too...

LDAP avatar Mar 09 '21 09:03 LDAP

It's working now. Although I am still getting

Error parsing message: com.google.gson.JsonSyntaxException: Expected a com.google.gson.JsonObject but was com.google.gson.JsonNull

Settings:

{
	"type": "java",
	"name": "Launch",
	"request": "launch",
	"mainClass": "main.Main",
	"classPaths": ["${folder}/target/classes", "${folder}/target/lib/*"],
	"cwd": "${folder}",
	"console": "internalConsole",
},
(Its a Maven Project)

LDAP avatar Mar 09 '21 12:03 LDAP

Fixed that too. Since I changed the Protocol to {} instead of None, this may break other things?

LDAP avatar Mar 09 '21 12:03 LDAP

@daveleroy How would an adapter add/set configuration variables? I would like to fetch classpath, mainclass,... with the Language Server because for example classpath can get very complicated on a big maven Project.

LDAP avatar Mar 09 '21 14:03 LDAP

Fixed that too. Since I changed the Protocol to {} instead of None, this may break other things?

Unlikely to break anything and is probably what vscode does despite the threads request not having any arguments specified in the spec https://microsoft.github.io/debug-adapter-protocol/specification

daveleroy avatar Mar 09 '21 20:03 daveleroy

@daveleroy How would an adapter add/set configuration variables? I would like to fetch classpath, mainclass,... with the Language Server because for example classpath can get very complicated on a big maven Project.

You can adjust a configuration after the variables are expanded but before it is sent to the adapter using async def configuration_resolve(self, configuration). See https://github.com/daveleroy/sublime_debugger/blob/2b5f0a5860027a0f2ad9b9fcd791b41a3179da57/modules/adapters/go.py#L29

daveleroy avatar Mar 09 '21 20:03 daveleroy

If you are talking about adding custom variables that can't currently be done and would need support added for it

daveleroy avatar Mar 09 '21 20:03 daveleroy

@daveleroy How would an adapter add/set configuration variables? I would like to fetch classpath, mainclass,... with the Language Server because for example classpath can get very complicated on a big maven Project.

You can adjust a configuration after the variables are expanded but before it is sent to the adapter using async def configuration_resolve(self, configuration). See

https://github.com/daveleroy/sublime_debugger/blob/2b5f0a5860027a0f2ad9b9fcd791b41a3179da57/modules/adapters/go.py#L29

That should work :)

LDAP avatar Mar 09 '21 22:03 LDAP

Implemented auto-configuration of mainClass and classPaths allowing for a plug & play solution together with sublimelsp/LSP-jdtls#7

LDAP avatar Mar 10 '21 12:03 LDAP

@daveleroy I get errors in the client. Error:

<Future pending cb=[<TaskWakeupMethWrapper object at 0x000001C9BE368340>()]>
Debugger: error: adapter failed hover evaluation Evaluation failed because the thread is not suspended.
<Future pending cb=[<TaskWakeupMethWrapper object at 0x000001C9BE39DA90>()]>
Traceback (most recent call last):
  File "C:\Users\Lucas Alber\AppData\Roaming\Sublime Text 3\Packages\Debugger\modules\core\sublime_event_loop.py", line 105, in call_exception_handler
    raise context['exception']
  File "C:\Users\Lucas Alber\AppData\Roaming\Sublime Text 3\Packages\Debugger\modules\dap\session.py", line 739, in refresh_threads
    threads = array_from_json(dap.Thread.from_json, response['threads'])
KeyError: 'threads'

Protocol:

⟸ process/started
⟸ request/initialize(1) :: {'clientID': 'sublime', 'clientName': 'Sublime Text', 'adapterID': 'java', 'pathFormat': 'path', 'linesStartAt1': True, 'columnsStartAt1': True, 'supportsVariableType': True, 'supportsVariablePaging': False, 'supportsRunInTerminalRequest': True, 'locale': 'en-us'}
⟹ response/initialize(1) :: {'supportsConfigurationDoneRequest': True, 'supportsHitConditionalBreakpoints': True, 'supportsConditionalBreakpoints': True, 'supportsEvaluateForHovers': True, 'supportsCompletionsRequest': True, 'supportsRestartFrame': True, 'supportsSetVariable': True, 'supportsRestartRequest': False, 'supportTerminateDebuggee': True, 'supportsDelayedStackTraceLoading': False, 'supportsLogPoints': True, 'supportsExceptionInfoRequest': True, 'exceptionBreakpointFilters': [{'label': 'Uncaught Exceptions', 'filter': 'uncaught'}, {'label': 'Caught Exceptions', 'filter': 'caught'}], 'supportsDataBreakpoints': True, 'supportsClipboardContext': True}
⟸ request/launch(2) :: {'mainClass': 'org.lalber.tools.checkstyle.Main', 'name': 'Launch Java Program', 'request': 'launch', 'type': 'java', 'cwd': 'D:\\Local_Repositories\\Development\\Java\\Projects\\checkstylecompatibilitytest', 'classPaths': ['D:\\Local_Repositories\\Development\\Java\\Projects\\checkstylecompatibilitytest\\target\\classes', 'C:\\Users\\Lucas Alber\\.m2\\repository\\commons-io\\commons-io\\2.6\\commons-io-2.6.jar', 'C:\\Users\\Lucas Alber\\.m2\\repository\\org\\fusesource\\jansi\\jansi\\1.18\\jansi-1.18.jar', 'C:\\Users\\Lucas Alber\\.m2\\repository\\org\\antlr\\antlr4-runtime\\4.7.2\\antlr4-runtime-4.7.2.jar', 'C:\\Users\\Lucas Alber\\.m2\\repository\\net\\sf\\saxon\\Saxon-HE\\9.9.1-5\\Saxon-HE-9.9.1-5.jar', 'C:\\Users\\Lucas Alber\\.m2\\repository\\info\\picocli\\picocli\\4.1.1\\picocli-4.1.1.jar', 'C:\\Users\\Lucas Alber\\.m2\\repository\\commons-beanutils\\commons-beanutils\\1.9.4\\commons-beanutils-1.9.4.jar', 'C:\\Users\\Lucas Alber\\.m2\\repository\\commons-logging\\commons-logging\\1.2\\commons-logging-1.2.jar', 'C:\\Users\\Lucas Alber\\.m2\\repository\\commons-collections\\commons-collections\\3.2.2\\commons-collections-3.2.2.jar', 'C:\\Users\\Lucas Alber\\.m2\\repository\\com\\google\\guava\\guava\\28.1-jre\\guava-28.1-jre.jar', 'C:\\Users\\Lucas Alber\\.m2\\repository\\com\\google\\guava\\failureaccess\\1.0.1\\failureaccess-1.0.1.jar', 'C:\\Users\\Lucas Alber\\.m2\\repository\\com\\google\\guava\\listenablefuture\\9999.0-empty-to-avoid-conflict-with-guava\\listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar', 'C:\\Users\\Lucas Alber\\.m2\\repository\\com\\google\\code\\findbugs\\jsr305\\3.0.2\\jsr305-3.0.2.jar', 'C:\\Users\\Lucas Alber\\.m2\\repository\\org\\checkerframework\\checker-qual\\2.8.1\\checker-qual-2.8.1.jar', 'C:\\Users\\Lucas Alber\\.m2\\repository\\com\\google\\errorprone\\error_prone_annotations\\2.3.2\\error_prone_annotations-2.3.2.jar', 'C:\\Users\\Lucas Alber\\.m2\\repository\\com\\google\\j2objc\\j2objc-annotations\\1.3\\j2objc-annotations-1.3.jar', 'C:\\Users\\Lucas Alber\\.m2\\repository\\org\\codehaus\\mojo\\animal-sniffer-annotations\\1.18\\animal-sniffer-annotations-1.18.jar', 'C:\\Users\\Lucas Alber\\.m2\\repository\\antlr\\antlr\\2.7.7\\antlr-2.7.7.jar', 'C:\\Users\\Lucas Alber\\.m2\\repository\\org\\apache\\commons\\commons-lang3\\3.9\\commons-lang3-3.9.jar'], 'console': 'internalConsole'}
⟹ event/initialized :: {'type': 'initialized'}
⟹ response/launch(2) :: None
⟸ request/threads(3) :: {}
⟸ request/setBreakpoints(4) :: {'source': {'path': 'D:\\Local_Repositories\\Development\\Java\\Projects\\checkstylecompatibilitytest\\src\\main\\java\\org\\lalber\\tools\\checkstyle\\Main.java'}, 'breakpoints': [{'line': 40}]}
⟸ request/setExceptionBreakpoints(5) :: {'filters': [], 'filterOptions': []}
⟸ request/setDataBreakpoints(6) :: {'breakpoints': []}
⟹ response/threads(3) :: {'threads': [{'id': 1, 'name': 'Thread [main]'}, {'id': 2, 'name': 'Thread [Reference Handler]'}, {'id': 3, 'name': 'Thread [Finalizer]'}, {'id': 4, 'name': 'Thread [Signal Dispatcher]'}, {'id': 5, 'name': 'Thread [Attach Listener]'}]}
⟹ response/setBreakpoints(4) :: {'breakpoints': [{'id': 1, 'verified': True, 'line': 40, 'message': ''}]}
⟹ response/setExceptionBreakpoints(5) :: None
⟹ response/setDataBreakpoints(6) :: {'breakpoints': []}
⟸ request/configurationDone(7) :: {}
⟹ response/configurationDone(7) :: None
⟹ event/thread :: {'reason': 'started', 'threadId': 6, 'type': 'thread'}
⟹ event/thread :: {'reason': 'started', 'threadId': 1, 'type': 'thread'}
⟸ request/threads(8) :: {}
⟸ request/threads(9) :: {}
⟹ event/thread :: {'reason': 'started', 'threadId': 7, 'type': 'thread'}
⟸ request/threads(10) :: {}
⟹ response/threads(8) :: {'threads': [{'id': 1, 'name': 'Thread [main]'}, {'id': 2, 'name': 'Thread [Reference Handler]'}, {'id': 3, 'name': 'Thread [Finalizer]'}, {'id': 4, 'name': 'Thread [Signal Dispatcher]'}, {'id': 5, 'name': 'Thread [Attach Listener]'}, {'id': 6, 'name': 'Thread [Notification Thread]'}, {'id': 7, 'name': 'Thread [Common-Cleaner]'}]}
⟹ event/breakpoint :: {'reason': 'new', 'breakpoint': {'id': 1, 'verified': True, 'line': 40, 'message': ''}, 'type': 'breakpoint'}
⟹ response/threads(9) :: {'threads': [{'id': 1, 'name': 'Thread [main]'}, {'id': 2, 'name': 'Thread [Reference Handler]'}, {'id': 3, 'name': 'Thread [Finalizer]'}, {'id': 4, 'name': 'Thread [Signal Dispatcher]'}, {'id': 5, 'name': 'Thread [Attach Listener]'}, {'id': 6, 'name': 'Thread [Notification Thread]'}, {'id': 7, 'name': 'Thread [Common-Cleaner]'}]}
⟹ response/threads(10) :: {'threads': [{'id': 1, 'name': 'Thread [main]'}, {'id': 2, 'name': 'Thread [Reference Handler]'}, {'id': 3, 'name': 'Thread [Finalizer]'}, {'id': 4, 'name': 'Thread [Signal Dispatcher]'}, {'id': 5, 'name': 'Thread [Attach Listener]'}, {'id': 6, 'name': 'Thread [Notification Thread]'}, {'id': 7, 'name': 'Thread [Common-Cleaner]'}]}
⟹ event/stopped :: {'threadId': 1, 'reason': 'breakpoint', 'allThreadsStopped': False, 'type': 'stopped'}
⟹ event/output :: {'category': 'stdout', 'output': 'Checkstyle-Kompatibilitätstest, null', 'variablesReference': 0, 'line': 0, 'column': 0, 'type': 'output'}
⟹ event/output :: {'category': 'stdout', 'output': '.\r\n', 'variablesReference': 0, 'line': 0, 'column': 0, 'type': 'output'}
⟸ request/threads(11) :: {}
⟸ request/stackTrace(12) :: {'threadId': 1}
⟹ response/threads(11) :: {'threads': [{'id': 1, 'name': 'Thread [main]'}, {'id': 2, 'name': 'Thread [Reference Handler]'}, {'id': 3, 'name': 'Thread [Finalizer]'}, {'id': 4, 'name': 'Thread [Signal Dispatcher]'}, {'id': 5, 'name': 'Thread [Attach Listener]'}, {'id': 6, 'name': 'Thread [Notification Thread]'}, {'id': 7, 'name': 'Thread [Common-Cleaner]'}]}
⟹ response/stackTrace(12) :: {'stackFrames': [{'id': 1, 'source': {'name': 'Main.java', 'path': 'D:\\Local_Repositories\\Development\\Java\\Projects\\checkstylecompatibilitytest\\src\\main\\java\\org\\lalber\\tools\\checkstyle\\Main.java', 'sourceReference': 0}, 'line': 40, 'column': 1, 'name': 'Main.main(String[])'}], 'totalFrames': 1}
⟸ request/scopes(13) :: {'frameId': 1}
⟹ response/scopes(13) :: {'scopes': [{'name': 'Local', 'variablesReference': 2, 'expensive': False}]}
⟸ request/variables(14) :: {'variablesReference': 2}
⟹ response/variables(14) :: {'variables': [{'name': 'args', 'value': 'String[0]@9', 'type': 'String[]', 'variablesReference': 0, 'namedVariables': 0, 'indexedVariables': 0, 'evaluateName': 'args'}]}
⟸ request/next(15) :: {'threadId': 1}

LDAP avatar Mar 10 '21 13:03 LDAP

@daveleroy The Java Language Server returns URIs like:

jdt://contents/java.base/java.lang/Integer.class?=jdt.ls-java-project/D:%5C/Local_Repositories%5C/windows-dev-tools%5C/bins%5C/jdk%5C/lib%5C/jrt-fs.jar%60java.base=/javadoc_location=/https:%5C/%5C/docs.oracle.com%5C/en%5C/java%5C/javase%5C/15%5C/docs%5C/api%5C/=/%3Cjava.lang(Integer.class

leading to an empty view. JDT.LS can actually provide the contents of the class file, does Debugger support that the server resolves the content itself?

LDAP avatar Mar 10 '21 17:03 LDAP

@daveleroy I get errors in the client.

This looks like another off spec thing. They are returning {} from the threads command when the response is supposed to be {'threads': [...]} and is not optional.

You can change threads = array_from_json(dap.Thread.from_json, response['threads']) to threads = array_from_json(dap.Thread.from_json, response.get('threads', [])) to handle their malformed response

daveleroy avatar Mar 10 '21 19:03 daveleroy

@daveleroy The Java Language Server returns URIs like:

jdt://contents/java.base/java.lang/Integer.class?=jdt.ls-java-project/D:%5C/Local_Repositories%5C/windows-dev-tools%5C/bins%5C/jdk%5C/lib%5C/jrt-fs.jar%60java.base=/javadoc_location=/https:%5C/%5C/docs.oracle.com%5C/en%5C/java%5C/javase%5C/15%5C/docs%5C/api%5C/=/%3Cjava.lang(Integer.class

leading to an empty view. JDT.LS can actually provide the contents of the class file, does Debugger support that the server resolves the content itself?

This seems like something they should probably change on their side. If the adapter is supposed to supply the contents of a source they should be adding a sourceReference not giving us a URI so that we can perform a SourceRequest for the contents.

https://microsoft.github.io/debug-adapter-protocol/specification#Types_Source

If they are not going to do that then we probably need to add an additional configuration function that lets you optionally return the contents of a path before we assume it should be opened in a view. That way the java adapter can ask jdt.ls for the contents.

daveleroy avatar Mar 10 '21 20:03 daveleroy

Ideally would be something like this sublimehq/sublime_text#3989. But yes until that is ready asking the LS for content is probably the easiest option.

LDAP avatar Mar 10 '21 20:03 LDAP

Ideally would be something like this sublimehq/sublime_text#3989. But yes until that is ready asking the LS for content is probably the easiest option.

Ideally java-debug would fix this because what they are doing does not conform to the protocol and makes integrating their adapter pretty convoluted. This issue appears to have been brought up already https://github.com/microsoft/java-debug/issues/259#issuecomment-695199086

daveleroy avatar Mar 10 '21 21:03 daveleroy

With version 1.5 of LSP, plugins can now define an on_open_uri_async callback.

https://github.com/sublimelsp/LSP/blob/97e138e8e3300e52140569f3ada95e05d5b8d9bc/plugin/core/sessions.py#L603-L614

The LSP-jdtls helper package can override this method and define what to do with jdt: schemes.

I guess we would still need a window command like lsp_open_uri that takes an URI and optionally a config name.

rwols avatar Jun 11 '21 21:06 rwols

@daveleroy does sublime_debugger expect anything special of a sublime View in particular to be able to attach to it or recognize it? the way this view with "virtual content" is made is:

https://github.com/sublimelsp/LSP/blob/97e138e8e3300e52140569f3ada95e05d5b8d9bc/plugin/core/sessions.py#L1106-L1113

rwols avatar Jun 11 '21 21:06 rwols

With version 1.5 of LSP, plugins can now define an on_open_uri_async callback.

https://github.com/sublimelsp/LSP/blob/97e138e8e3300e52140569f3ada95e05d5b8d9bc/plugin/core/sessions.py#L603-L614

The LSP-jdtls helper package can override this method and define what to do with jdt: schemes.

I guess we would still need a window command like lsp_open_uri that takes an URI and optionally a config name.

Nice! I'll look into this next week

LDAP avatar Jun 12 '21 08:06 LDAP

@daveleroy does sublime_debugger expect anything special of a sublime View in particular to be able to attach to it or recognize it? the way this view with "virtual content" is made is:

https://github.com/sublimelsp/LSP/blob/97e138e8e3300e52140569f3ada95e05d5b8d9bc/plugin/core/sessions.py#L1106-L1113

Not really no but currently breakpoints aren't supported in views that are not associated with a file (this includes generated views from the dap protocol which is probably an oversight).

This is where dap views are generated (when a source is not associated with an actual file) https://github.com/daveleroy/sublime_debugger/blob/ce44c963ac746e4ee1fc3b4fae66a7ba060a9a65/modules/source_navigation.py#L98

If breakpoints are supposed allowed in these views the view probably needs to have a uri setting or some way to check if a view is associated with a uri. It also seems like open_uri should return the generated view so that anyone who calls it can wait on the promise to resolve to get the view.

Somewhat Related: All the LSP packages seem to access the LSP api directly. I wonder if it makes sense to have debugger be the one that creates the 3.3 python bridge to interact with LSP/LSP-jdtls and add any command shims for LSP api's it needs to interact with (until/if LSP switches over to 3.8).

daveleroy avatar Jun 13 '21 16:06 daveleroy

until/if LSP switches over to 3.8

We're blocked on dependencies: https://github.com/sublimelsp/LSP/issues/1389 https://github.com/wbond/package_control/issues/1518

rwols avatar Jul 04 '21 11:07 rwols

I've enabled LSP-jdtls to understand jdt: URI schemes. But the actual opening of the URI should be done from the DAP side. See: https://github.com/sublimelsp/LSP-jdtls/pull/15#issuecomment-900191073

rwols avatar Aug 17 '21 10:08 rwols

The jar you are looking for is available at https://mvnrepository.com/artifact/com.microsoft.java/com.microsoft.java.debug.plugin and is exactly the same VSCode use to debug Java applications. image

davidsoles avatar Aug 20 '22 21:08 davidsoles