Skip to content
This repository was archived by the owner on May 4, 2022. It is now read-only.

Commit 1efebdb

Browse files
committed
Add the Java DAP implementation (+LSP uprev)
This change bundles a pre-built binary of the Java DAP with microsoft/java-debug#379 applied, so that we can specify what port it should bind to. In order for this to function correctly, it also needs to be running a more recent version of the Java LSP, so we will upgrade that too.
1 parent 0bb3692 commit 1efebdb

File tree

8 files changed

+140
-18
lines changed

8 files changed

+140
-18
lines changed

extra/java-dap

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
#!/usr/bin/env python3
2+
"""Small wrapper to correctly initialize the Java DAP."""
3+
4+
import json
5+
import logging
6+
import os
7+
import signal
8+
import subprocess
9+
import sys
10+
import time
11+
12+
from typing import Any, IO, Dict, List, Optional
13+
14+
_JAVA_DAP_BUNDLE = '/run_dir/com.microsoft.java.debug.plugin-0.32.0.jar'
15+
16+
17+
def _send_lsp_message(msg: Dict[str, Any], lsp: IO[bytes]) -> None:
18+
serialized_msg = json.dumps({
19+
'jsonrpc': '2.0',
20+
**msg,
21+
})
22+
payload = len(serialized_msg)
23+
lsp.write((f'Content-Length: {len(serialized_msg)}\r\n\r\n' +
24+
serialized_msg).encode('utf-8'))
25+
lsp.flush()
26+
27+
28+
def _receive_lsp_message(lsp: IO[bytes]) -> Optional[Dict[str, Any]]:
29+
headers = b''
30+
while not headers.endswith(b'\r\n\r\n'):
31+
byte = lsp.read(1)
32+
if len(byte) == 0:
33+
return None
34+
headers += byte
35+
content_length = 0
36+
for header in headers.strip().split(b'\r\n'):
37+
name, value = header.split(b':', maxsplit=2)
38+
if name.strip().lower() == b'content-length':
39+
content_length = int(value.strip())
40+
serialized = b''
41+
while content_length:
42+
chunk = lsp.read(content_length)
43+
if not chunk:
44+
raise Exception(f'short read: {serialized!r}')
45+
content_length -= len(chunk)
46+
serialized += chunk
47+
return json.loads(serialized)
48+
49+
50+
def _main() -> None:
51+
with subprocess.Popen(['/usr/bin/run-language-server', '-l', 'java'],
52+
stdout=subprocess.PIPE,
53+
stdin=subprocess.PIPE) as dap:
54+
try:
55+
_send_lsp_message(
56+
{
57+
'id': 1,
58+
'method': 'initialize',
59+
'params': {
60+
'processId': None,
61+
'initializationOptions': {
62+
'bundles': [
63+
_JAVA_DAP_BUNDLE,
64+
],
65+
},
66+
'trace': 'verbose',
67+
'capabilities': {},
68+
},
69+
}, dap.stdin)
70+
# Wait for the initialize message has been acknowledged.
71+
# This maximizes the probability of success.
72+
while True:
73+
message = _receive_lsp_message(dap.stdout)
74+
assert message
75+
if message.get('method') == 'window/logMessage':
76+
print(message.get('params', {}).get('message'),
77+
file=sys.stderr)
78+
if message.get('id') == 1:
79+
break
80+
_send_lsp_message(
81+
{
82+
'id': 2,
83+
'method': 'workspace/executeCommand',
84+
'params': {
85+
'command': 'vscode.java.startDebugSession',
86+
},
87+
}, dap.stdin)
88+
# Wait for the reply. If the request errored out, exit early to
89+
# send a clear signal to the caller.
90+
while True:
91+
message = _receive_lsp_message(dap.stdout)
92+
assert message
93+
if message.get('method') == 'window/logMessage':
94+
print(message.get('params', {}).get('message'),
95+
file=sys.stderr)
96+
if message.get('id') == 2:
97+
if 'error' in message:
98+
print(message['error'].get('message'), file=sys.stderr)
99+
return
100+
break
101+
# Keep reading to drain the queue.
102+
while True:
103+
message = _receive_lsp_message(dap.stdout)
104+
if not message:
105+
break
106+
if message.get('method') == 'window/logMessage':
107+
print(message.get('params', {}).get('message'),
108+
file=sys.stderr)
109+
except Exception:
110+
logging.exception('failed')
111+
finally:
112+
pgrp = os.getpgid(dap.pid)
113+
os.killpg(pgrp, signal.SIGINT)
114+
115+
116+
if __name__ == '__main__':
117+
_main()

gen/Dockerfile.ejs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ COPY ./run_dir /run_dir/
9595
RUN ln -sf /usr/lib/chromium-browser/chromedriver /usr/local/bin
9696

9797
COPY ./extra/apt-install /usr/bin/install-pkg
98+
COPY ./extra/java-dap /opt/dap/java/run
99+
RUN chmod +x /opt/dap/java/run
98100

99101
COPY ./extra/_test_runner.py /home/runner/_test_runner.py
100102
COPY ./extra/cquery11 /opt/homes/cpp11/.cquery

gen/run-language-server.ejs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ case "$LANGUAGE" in
2121
<% for ( let lang of languages ) { -%>
2222
<%- lang.names.map(x => `"${x}"`).join('|') %>)
2323
<% if ( lang.languageServer ) { -%>
24-
<%- c(lang.languageServer.command) %>
24+
exec <%- c(lang.languageServer.command) %>
2525
<% } else { -%>
2626
echo "No language server configured for <%= lang.name %>" >&2
2727
exit 1

languages/java.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ packages = [
88
"openjdk-11-jdk"
99
]
1010
setup = [
11-
"mkdir -p /config/language-server && cd /config/language-server && wget http://download.eclipse.org/jdtls/milestones/0.21.0/jdt-language-server-0.21.0-201806152234.tar.gz && tar -xzf jdt-language-server-0.21.0-201806152234.tar.gz && rm jdt-language-server-0.21.0-201806152234.tar.gz && chown runner:runner -R /config/language-server",
11+
"mkdir -p /config/language-server && cd /config/language-server && wget https://download.eclipse.org/jdtls/milestones/1.1.2/jdt-language-server-1.1.2-202105191944.tar.gz && tar -xzf jdt-language-server-1.1.2-202105191944.tar.gz && rm jdt-language-server-1.1.2-202105191944.tar.gz && chown runner:runner -R /config/language-server",
1212
"echo '<project> <modelVersion>4.0.0</modelVersion> <groupId>mygroupid</groupId> <artifactId>myartifactid</artifactId> <version>0.0-SNAPSHOT</version> <build><plugins> <plugin> <groupId>de.qaware.maven</groupId> <artifactId>go-offline-maven-plugin</artifactId> <version>1.2.5</version> <configuration> <dynamicDependencies> <DynamicDependency> <groupId>org.apache.maven.surefire</groupId> <artifactId>surefire-junit4</artifactId> <version>2.20.1</version> <repositoryType>PLUGIN</repositoryType> </DynamicDependency> <DynamicDependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-apt</artifactId> <version>4.2.1</version> <classifier>jpa</classifier> <repositoryType>MAIN</repositoryType> </DynamicDependency> </dynamicDependencies> </configuration> </plugin> </plugins></build> </project>' > /tmp/emptypom.xml",
1313
"mvn -f /tmp/emptypom.xml -Dmaven.repo.local=/home/runner/.m2/repository de.qaware.maven:go-offline-maven-plugin:resolve-dependencies dependency:copy-dependencies",
1414
"rm /tmp/emptypom.xml"
@@ -43,11 +43,12 @@ command = [
4343
"-Declipse.application=org.eclipse.jdt.ls.core.id1",
4444
"-Dosgi.bundles.defaultStartLevel=4",
4545
"-Declipse.product=org.eclipse.jdt.ls.core.product",
46+
"-Dcom.microsoft.java.debug.serverAddress=localhost:41010",
4647
"-noverify",
4748
"-Xmx256m",
4849
"-XX:+UseConcMarkSweepGC",
4950
"-jar",
50-
"/config/language-server/plugins/org.eclipse.equinox.launcher_1.5.0.v20180512-1130.jar",
51+
"/config/language-server/plugins/org.eclipse.equinox.launcher_1.6.100.v20201223-0822.jar",
5152
"-configuration",
5253
"/config/language-server/config_linux",
5354
"-data",

out/Dockerfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,8 @@ COPY ./run_dir /run_dir/
817817
RUN ln -sf /usr/lib/chromium-browser/chromedriver /usr/local/bin
818818

819819
COPY ./extra/apt-install /usr/bin/install-pkg
820+
COPY ./extra/java-dap /opt/dap/java/run
821+
RUN chmod +x /opt/dap/java/run
820822

821823
COPY ./extra/_test_runner.py /home/runner/_test_runner.py
822824
COPY ./extra/cquery11 /opt/homes/cpp11/.cquery

out/run-language-server

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ case "$LANGUAGE" in
2323
exit 1
2424
;;
2525
"java")
26-
java -Declipse.application=org.eclipse.jdt.ls.core.id1 -Dosgi.bundles.defaultStartLevel=4 -Declipse.product=org.eclipse.jdt.ls.core.product -noverify -Xmx256m -XX:+UseConcMarkSweepGC -jar /config/language-server/plugins/org.eclipse.equinox.launcher_1.5.0.v20180512-1130.jar -configuration /config/language-server/config_linux -data /home/runner
26+
exec java -Declipse.application=org.eclipse.jdt.ls.core.id1 -Dosgi.bundles.defaultStartLevel=4 -Declipse.product=org.eclipse.jdt.ls.core.product -Dcom.microsoft.java.debug.serverAddress=localhost:41010 -noverify -Xmx256m -XX:+UseConcMarkSweepGC -jar /config/language-server/plugins/org.eclipse.equinox.launcher_1.6.100.v20201223-0822.jar -configuration /config/language-server/config_linux -data /home/runner
2727
;;
2828
"ballerina")
2929
echo "No language server configured for ballerina" >&2
@@ -34,7 +34,7 @@ case "$LANGUAGE" in
3434
exit 1
3535
;;
3636
"c")
37-
cquery '--init={"progressReportFrequencyMs": -1,"cacheDirectory":"/tmp/cquery"}'
37+
exec cquery '--init={"progressReportFrequencyMs": -1,"cacheDirectory":"/tmp/cquery"}'
3838
;;
3939
"common lisp"|"clisp"|"lisp")
4040
echo "No language server configured for common lisp" >&2
@@ -45,10 +45,10 @@ case "$LANGUAGE" in
4545
exit 1
4646
;;
4747
"cpp"|"c++")
48-
cquery '--init={"progressReportFrequencyMs": -1,"cacheDirectory":"/tmp/cquery", "extraClangArguments": ["-std=c++17", "-pthread"]}'
48+
exec cquery '--init={"progressReportFrequencyMs": -1,"cacheDirectory":"/tmp/cquery", "extraClangArguments": ["-std=c++17", "-pthread"]}'
4949
;;
5050
"cpp11")
51-
cquery '--init={"progressReportFrequencyMs": -1,"cacheDirectory":"/tmp/cquery", "extraClangArguments": ["-std=c++11", "-pthread"]}'
51+
exec cquery '--init={"progressReportFrequencyMs": -1,"cacheDirectory":"/tmp/cquery", "extraClangArguments": ["-std=c++11", "-pthread"]}'
5252
;;
5353
"crystal")
5454
echo "No language server configured for crystal" >&2
@@ -63,10 +63,10 @@ case "$LANGUAGE" in
6363
exit 1
6464
;;
6565
"dart")
66-
/usr/lib/dart/bin/dart /usr/lib/dart/bin/snapshots/analysis_server.dart.snapshot --lsp
66+
exec /usr/lib/dart/bin/dart /usr/lib/dart/bin/snapshots/analysis_server.dart.snapshot --lsp
6767
;;
6868
"deno")
69-
deno lsp
69+
exec deno lsp
7070
;;
7171
"elisp")
7272
echo "No language server configured for elisp" >&2
@@ -93,7 +93,7 @@ case "$LANGUAGE" in
9393
exit 1
9494
;;
9595
"flow")
96-
flow-language-server --stdio
96+
exec flow-language-server --stdio
9797
;;
9898
"forth")
9999
echo "No language server configured for forth" >&2
@@ -112,7 +112,7 @@ case "$LANGUAGE" in
112112
exit 1
113113
;;
114114
"go"|"golang")
115-
/bin/bash -c /opt/homes/go/go/bin/bingo
115+
exec /bin/bash -c /opt/homes/go/go/bin/bingo
116116
;;
117117
"guile"|"scheme")
118118
echo "No language server configured for guile" >&2
@@ -123,7 +123,7 @@ case "$LANGUAGE" in
123123
exit 1
124124
;;
125125
"haxe")
126-
haxe --server-listen stdio
126+
exec haxe --server-listen stdio
127127
;;
128128
"jest")
129129
echo "No language server configured for jest" >&2
@@ -186,16 +186,16 @@ case "$LANGUAGE" in
186186
exit 1
187187
;;
188188
"python3")
189-
pyls -v
189+
exec pyls -v
190190
;;
191191
"pygame")
192-
pyls -v
192+
exec pyls -v
193193
;;
194194
"python")
195-
pyls -v
195+
exec pyls -v
196196
;;
197197
"pyxel")
198-
pyls -v
198+
exec pyls -v
199199
;;
200200
"quil")
201201
echo "No language server configured for quil" >&2
@@ -222,7 +222,7 @@ case "$LANGUAGE" in
222222
exit 1
223223
;;
224224
"ruby")
225-
solargraph stdio
225+
exec solargraph stdio
226226
;;
227227
"rust")
228228
echo "No language server configured for rust" >&2

out/share/polygott/phase2.d/java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ chown -R $(id -u):$(id -g) /home/runner
1010
echo 'Setup java'
1111
cd "${HOME}"
1212

13-
mkdir -p /config/language-server && cd /config/language-server && wget http://download.eclipse.org/jdtls/milestones/0.21.0/jdt-language-server-0.21.0-201806152234.tar.gz && tar -xzf jdt-language-server-0.21.0-201806152234.tar.gz && rm jdt-language-server-0.21.0-201806152234.tar.gz && chown runner:runner -R /config/language-server
13+
mkdir -p /config/language-server && cd /config/language-server && wget https://download.eclipse.org/jdtls/milestones/1.1.2/jdt-language-server-1.1.2-202105191944.tar.gz && tar -xzf jdt-language-server-1.1.2-202105191944.tar.gz && rm jdt-language-server-1.1.2-202105191944.tar.gz && chown runner:runner -R /config/language-server
1414
echo '<project> <modelVersion>4.0.0</modelVersion> <groupId>mygroupid</groupId> <artifactId>myartifactid</artifactId> <version>0.0-SNAPSHOT</version> <build><plugins> <plugin> <groupId>de.qaware.maven</groupId> <artifactId>go-offline-maven-plugin</artifactId> <version>1.2.5</version> <configuration> <dynamicDependencies> <DynamicDependency> <groupId>org.apache.maven.surefire</groupId> <artifactId>surefire-junit4</artifactId> <version>2.20.1</version> <repositoryType>PLUGIN</repositoryType> </DynamicDependency> <DynamicDependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-apt</artifactId> <version>4.2.1</version> <classifier>jpa</classifier> <repositoryType>MAIN</repositoryType> </DynamicDependency> </dynamicDependencies> </configuration> </plugin> </plugins></build> </project>' > /tmp/emptypom.xml
1515
mvn -f /tmp/emptypom.xml -Dmaven.repo.local=/home/runner/.m2/repository de.qaware.maven:go-offline-maven-plugin:resolve-dependencies dependency:copy-dependencies
1616
rm /tmp/emptypom.xml
Binary file not shown.

0 commit comments

Comments
 (0)