Skip to content

Commit c38a08c

Browse files
committed
Migrate Vue language server to 3.x
Signed-off-by: Dawid Pakuła <[email protected]>
1 parent dd90024 commit c38a08c

File tree

8 files changed

+157
-20
lines changed

8 files changed

+157
-20
lines changed

org.eclipse.wildwebdeveloper/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44
"astro-vscode" : "2.15.4",
55
"firefox-debugadapter": "2.15.0",
66
"typescript": "5.9.2",
7-
"typescript-language-server": "4.3.4",
7+
"typescript-language-server": "4.4.0",
88
"typescript-lit-html-plugin": "0.9.0",
99
"typescript-plugin-css-modules": "5.2.0",
1010
"yaml-language-server": "1.18.0",
1111
"vscode-css-languageservice": "6.3.7",
1212
"vscode-html-languageservice": "5.5.1",
1313
"vscode-json-languageservice": "5.6.1",
14-
"@vue/language-server" : "2.2.10",
15-
"@vue/typescript-plugin" : "2.2.10",
14+
"@vue/language-server" : "3.0.6",
15+
"@vue/typescript-plugin" : "3.0.6",
1616
"fsevents" : "2.3.3",
1717
"vscode-css-languageserver": "file:target/vscode-css-languageserver-1.0.0.tgz",
1818
"vscode-html-languageserver": "file:target/vscode-html-languageserver-1.0.0.tgz",

org.eclipse.wildwebdeveloper/plugin.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,7 @@
377377
<server
378378
class="org.eclipse.wildwebdeveloper.jsts.JSTSLanguageServer"
379379
clientImpl="org.eclipse.wildwebdeveloper.jsts.JSTSLanguageClientImpl"
380+
serverInterface="org.eclipse.wildwebdeveloper.jsts.JSTSLanguageServerAPI"
380381
id="org.eclipse.wildwebdeveloper.jsts"
381382
label="JavaScript-TypeScript Language Server">
382383
</server>
@@ -568,7 +569,6 @@
568569
clientImpl="org.eclipse.wildwebdeveloper.vue.VueClientImpl"
569570
serverInterface="org.eclipse.wildwebdeveloper.vue.VueLanguageServerAPI"
570571
id="org.eclipse.wildwebdeveloper.vue"
571-
singleton="true"
572572
label="VUE Language Server"/>
573573
<contentTypeMapping contentType="org.eclipse.wildwebdeveloper.vue" languageId="vue" id="org.eclipse.wildwebdeveloper.vue"/>
574574
</extension>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*******************************************************************************
2+
* Copyright (c) Dawid Pakuła and others.
3+
* This program and the accompanying materials are made
4+
* available under the terms of the Eclipse Public License 2.0
5+
* which is available at https://www.eclipse.org/legal/epl-2.0/
6+
*
7+
* SPDX-License-Identifier: EPL-2.0
8+
*
9+
* Contributors:
10+
* Dawid Pakuła <[email protected]> - initial implementation
11+
*******************************************************************************/
12+
package org.eclipse.wildwebdeveloper.jsts;
13+
14+
import org.eclipse.lsp4j.services.LanguageServer;
15+
16+
public interface JSTSLanguageServerAPI extends LanguageServer {
17+
18+
public final static String TS_REQUEST_COMMAND = "typescript.tsserverRequest";
19+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 Dawid Pakuła and others.
3+
* This program and the accompanying materials are made
4+
* available under the terms of the Eclipse Public License 2.0
5+
* which is available at https://www.eclipse.org/legal/epl-2.0/
6+
*
7+
* SPDX-License-Identifier: EPL-2.0
8+
*
9+
* Contributors:
10+
* Dawid Pakuła <[email protected]> - initial implementation
11+
*******************************************************************************/
12+
package org.eclipse.wildwebdeveloper.jsts.request;
13+
14+
public class ExecuteInfo {
15+
16+
private int executionTarget = 0;
17+
18+
private boolean expectsResult = true;
19+
20+
private boolean isAsync = false;
21+
22+
private boolean lowPriority = true;
23+
24+
public int getExecutionTarget() {
25+
return executionTarget;
26+
}
27+
28+
public void setExecutionTarget(int executionTarget) {
29+
this.executionTarget = executionTarget;
30+
}
31+
32+
public boolean isExpectsResult() {
33+
return expectsResult;
34+
}
35+
36+
public void setExpectsResult(boolean expectsResult) {
37+
this.expectsResult = expectsResult;
38+
}
39+
40+
public boolean isAsync() {
41+
return isAsync;
42+
}
43+
44+
public void setAsync(boolean isAsync) {
45+
this.isAsync = isAsync;
46+
}
47+
48+
public boolean isLowPriority() {
49+
return lowPriority;
50+
}
51+
52+
public void setLowPriority(boolean lowPriority) {
53+
this.lowPriority = lowPriority;
54+
}
55+
}

org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/vue/VueClientImpl.java

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,27 +14,35 @@
1414

1515
import java.util.Map;
1616

17-
import org.eclipse.lsp4e.LanguageClientImpl;
17+
import org.eclipse.lsp4e.client.DefaultLanguageClient;
1818
import org.eclipse.lsp4j.MessageParams;
1919
import org.eclipse.lsp4j.MessageType;
2020

21-
public class VueClientImpl extends LanguageClientImpl implements VueLanguageServerExtention {
21+
public class VueClientImpl extends DefaultLanguageClient implements VueLanguageServerExtention {
2222

2323
@Override
2424
public void projectLoadingFinish(Object object) {
2525
// TODO should this set some state because only now stuff will work like hover..
2626
// or maybe even after projectLanguageService "enabled" call
2727
logMessage(new MessageParams(MessageType.Info, "Vue project loading finished"));
2828
}
29-
29+
3030
@Override
3131
public void projectLoadingStart(Object object) {
3232
logMessage(new MessageParams(MessageType.Info, "Vue project loading started"));
3333
}
34-
34+
35+
@Override
36+
public void projectLanguageService(Map<String, Object> data) {
37+
logMessage(new MessageParams(MessageType.Info,
38+
"Language Service is "
39+
+ (((Boolean) data.get("languageServiceEnabled")).booleanValue() ? "" : "not yet ")
40+
+ "enabled for project " + data.get("projectName")));
41+
}
42+
3543
@Override
36-
public void projectLanguageService(Map<String,Object> data) {
37-
logMessage(new MessageParams(MessageType.Info, "Language Service is " + (((Boolean)data.get("languageServiceEnabled")).booleanValue()?"":"not yet ") + "enabled for project " + data.get("projectName")));
44+
public void tsserverRequest(Object[] params) {
45+
logMessage(new MessageParams(MessageType.Info, "Forward TS message " + params[0]));
3846
}
39-
47+
4048
}

org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/vue/VueLanguageServer.java

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,30 @@
1818
import java.net.URL;
1919
import java.nio.file.Paths;
2020
import java.util.ArrayList;
21+
import java.util.Arrays;
2122
import java.util.Collections;
2223
import java.util.HashMap;
2324
import java.util.List;
2425
import java.util.Map;
26+
import java.util.concurrent.CompletableFuture;
2527

2628
import org.eclipse.core.runtime.FileLocator;
2729
import org.eclipse.core.runtime.ILog;
30+
import org.eclipse.lsp4e.LSPEclipseUtils;
31+
import org.eclipse.lsp4e.LanguageServers;
2832
import org.eclipse.lsp4e.server.ProcessStreamConnectionProvider;
33+
import org.eclipse.lsp4j.ExecuteCommandParams;
34+
import org.eclipse.lsp4j.jsonrpc.messages.Message;
35+
import org.eclipse.lsp4j.jsonrpc.messages.NotificationMessage;
36+
import org.eclipse.lsp4j.services.LanguageServer;
2937
import org.eclipse.wildwebdeveloper.embedder.node.NodeJSManager;
38+
import org.eclipse.wildwebdeveloper.jsts.JSTSLanguageServerAPI;
39+
import org.eclipse.wildwebdeveloper.jsts.request.ExecuteInfo;
3040

3141
public class VueLanguageServer extends ProcessStreamConnectionProvider {
3242
private static String tsserverPath = null;
3343
private static String vuePath = null;
44+
private static String TS_REQUEST = "tsserver/request";
3445

3546
public VueLanguageServer() {
3647

@@ -53,7 +64,7 @@ private void resolvePaths() throws IOException {
5364
URL url = FileLocator
5465
.toFileURL(getClass().getResource("/node_modules/@vue/language-server/bin/vue-language-server.js"));
5566
vuePath = new File(url.getPath()).getAbsolutePath();
56-
67+
5768
url = FileLocator.toFileURL(getClass().getResource("/node_modules/typescript/lib"));
5869
tsserverPath = new File(url.getPath()).getAbsolutePath();
5970
}
@@ -69,21 +80,21 @@ protected ProcessBuilder createProcessBuilder() {
6980
public Object getInitializationOptions(URI rootUri) {
7081
Map<String, Object> options = new HashMap<>();
7182
setWorkingDirectory(Paths.get(rootUri).toString());
72-
83+
7384
options.put("typescript", Collections.singletonMap("tsdk", tsserverPath));
7485
options.put("diagnosticModel", 0);
7586
options.put("additionalExtensions", new String[] {});
76-
87+
7788
Map<String, Object> legend = new HashMap<>();
78-
legend.put("tokenTypes", new String[] {"component"} );
79-
legend.put("tokenModifiers", new String[] {} );
89+
legend.put("tokenTypes", new String[] { "component" });
90+
legend.put("tokenModifiers", new String[] {});
8091
options.put("semanticTokensLegend", legend);
81-
92+
8293
Map<String, Object> vue = new HashMap<>();
8394
vue.put("hybridMode", false);
84-
95+
8596
options.put("vue", vue);
86-
97+
8798
return options;
8899
}
89100

@@ -92,5 +103,40 @@ public String toString() {
92103
return "VUE Language Server: " + super.toString();
93104
}
94105

95-
106+
@Override
107+
public void handleMessage(Message message, LanguageServer languageServer, URI rootURI) {
108+
// System.out.println(message);
109+
if (message instanceof NotificationMessage) {
110+
NotificationMessage msg = (NotificationMessage) message;
111+
if (msg.getMethod().equals(TS_REQUEST)) {
112+
forwardTS((Object[]) msg.getParams(), (VueLanguageServerAPI) languageServer, rootURI);
113+
}
114+
}
115+
super.handleMessage(message, languageServer, rootURI);
116+
}
117+
118+
@SuppressWarnings("restriction")
119+
private void forwardTS(Object[] params, VueLanguageServerAPI languageServer, URI rootURI) {
120+
double requestId = (double) params[0];
121+
String commandId = (String) params[1];
122+
Object args = params.length > 2 ? params[2] : null;
123+
124+
LanguageServers.forProject(LSPEclipseUtils.findResourceFor(rootURI).getProject())
125+
.collectAll((w, ls) -> CompletableFuture.completedFuture(ls)).thenAccept((lss) -> {
126+
lss.stream().filter(JSTSLanguageServerAPI.class::isInstance).map(JSTSLanguageServerAPI.class::cast)
127+
.findAny().ifPresent(jsts -> {
128+
jsts.getWorkspaceService()
129+
.executeCommand(new ExecuteCommandParams(JSTSLanguageServerAPI.TS_REQUEST_COMMAND,
130+
Arrays.asList(new Object[] { commandId, args, new ExecuteInfo() })))
131+
.whenComplete((result, e) -> {
132+
Object body = null;
133+
if (result instanceof Map) {
134+
body = ((Map<?, ?>)result).get("body");
135+
}
136+
languageServer.tsserverResponse(new Object[] {requestId, body});
137+
});
138+
});
139+
});
140+
}
141+
96142
}

org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/vue/VueLanguageServerAPI.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import java.util.concurrent.CompletableFuture;
1616

1717
import org.eclipse.lsp4j.jsonrpc.messages.Either;
18+
import org.eclipse.lsp4j.jsonrpc.services.JsonNotification;
1819
import org.eclipse.lsp4j.jsonrpc.services.JsonRequest;
1920
import org.eclipse.lsp4j.services.LanguageServer;
2021
import org.eclipse.wildwebdeveloper.vue.autoinsert.AutoInsertParams;
@@ -38,5 +39,9 @@ public interface VueLanguageServerAPI extends LanguageServer {
3839
@JsonRequest("volar/client/autoInsert")
3940
CompletableFuture<Either<String, AutoInsertResponse>> autoInsert(AutoInsertParams params);
4041

42+
@JsonNotification("tsserver/response")
43+
void tsserverResponse(Object any);
44+
45+
4146

4247
}

org.eclipse.wildwebdeveloper/src/org/eclipse/wildwebdeveloper/vue/VueLanguageServerExtention.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,8 @@ public interface VueLanguageServerExtention {
2626

2727
@JsonNotification(value = "vue/projectLanguageService")
2828
public void projectLanguageService(Map<String,Object> data);
29+
30+
31+
@JsonNotification(value = "tsserver/request")
32+
public void tsserverRequest(Object[] params);
2933
}

0 commit comments

Comments
 (0)