Skip to content

Commit d3b4f6c

Browse files
authored
feat: nextls (#20)
1 parent 1ed6e59 commit d3b4f6c

File tree

3 files changed

+159
-54
lines changed

3 files changed

+159
-54
lines changed

bin/nextls

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/usr/bin/env -S elixir --sname undefined
2+
3+
System.no_halt(true)
4+
5+
Logger.configure(level: :none)
6+
7+
Mix.start()
8+
Mix.shell(Mix.Shell.Process)
9+
10+
Mix.install([{:next_ls, System.get_env("NEXTLS_VERSION")}])
11+
12+
Logger.configure(level: :info)
13+
14+
Application.ensure_all_started(:next_ls)

package.json

+19
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,25 @@
5050
"type": "integer",
5151
"default": 9000,
5252
"description": "If adapter is `tcp`, use this port to connect."
53+
},
54+
"elixir-tools.nextls.enable": {
55+
"type": "boolean",
56+
"default": false,
57+
"description": "Whether to start NextLS."
58+
},
59+
"elixir-tools.nextls.adapter": {
60+
"type": "string",
61+
"enum": [
62+
"stdio",
63+
"tcp"
64+
],
65+
"default": "stdio",
66+
"description": "Which adapter to use when connecting to NextLS"
67+
},
68+
"elixir-tools.nextls.port": {
69+
"type": "integer",
70+
"default": 9000,
71+
"description": "If adapter is `tcp`, use this port to connect."
5372
}
5473
}
5574
},

src/extension.ts

+126-54
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@ import {
1010
} from "vscode-languageclient/node";
1111

1212
let credoClient: LanguageClient;
13+
let nextLSClient: LanguageClient;
1314

14-
async function latestRelease(): Promise<string> {
15+
async function latestRelease(project: string): Promise<string> {
1516
return fetch(
16-
"https://api.github.com/repos/elixir-tools/credo-language-server/releases/latest",
17+
`https://api.github.com/repos/elixir-tools/${project}/releases/latest`,
1718
{
1819
headers: {
1920
["X-GitHub-Api-Version"]: "2022-11-28",
@@ -25,68 +26,139 @@ async function latestRelease(): Promise<string> {
2526
.then((x: any): string => x.tag_name.replace(/^v/, ""));
2627
}
2728

28-
export async function activate(context: vscode.ExtensionContext) {
29-
let files = await vscode.workspace.findFiles("mix.exs");
30-
29+
async function activateCredo(
30+
context: vscode.ExtensionContext,
31+
mixfile: vscode.Uri
32+
) {
3133
let config = vscode.workspace.getConfiguration("elixir-tools.credo");
34+
let text = await vscode.workspace.fs.readFile(mixfile);
3235

33-
if (files[0]) {
34-
let text = await vscode.workspace.fs.readFile(files[0]);
35-
36-
if (text.toString().includes("{:credo")) {
37-
if (config.get("enable")) {
38-
let serverOptions: ServerOptions;
39-
40-
switch (config.get("adapter")) {
41-
case "stdio":
42-
serverOptions = {
43-
options: {
44-
env: Object.assign({}, process.env, {
45-
["CREDO_LSP_VERSION"]: await latestRelease(),
46-
}),
47-
},
48-
command: context.asAbsolutePath("./bin/credo-language-server"),
49-
args: ["--stdio"],
50-
};
51-
break;
52-
case "tcp":
53-
serverOptions = () => {
54-
// Connect to language server via socket
55-
let socket = require("net").connect({
56-
host: "127.0.0.1",
57-
port: config.get("port"),
58-
});
59-
let result: StreamInfo = {
60-
writer: socket,
61-
reader: socket,
62-
};
63-
return Promise.resolve(result);
36+
if (text.toString().includes("{:credo")) {
37+
if (config.get("enable")) {
38+
let serverOptions: ServerOptions;
39+
40+
switch (config.get("adapter")) {
41+
case "stdio":
42+
serverOptions = {
43+
options: {
44+
env: Object.assign({}, process.env, {
45+
["CREDO_LSP_VERSION"]: await latestRelease(
46+
"credo-language-server"
47+
),
48+
}),
49+
},
50+
command: context.asAbsolutePath("./bin/credo-language-server"),
51+
args: ["--stdio"],
52+
};
53+
break;
54+
case "tcp":
55+
serverOptions = () => {
56+
// Connect to language server via socket
57+
let socket = require("net").connect({
58+
host: "127.0.0.1",
59+
port: config.get("port"),
60+
});
61+
let result: StreamInfo = {
62+
writer: socket,
63+
reader: socket,
6464
};
65-
break;
66-
default:
67-
throw new Error("boom");
68-
}
69-
const clientOptions: LanguageClientOptions = {
70-
documentSelector: [{ scheme: "file", language: "elixir" }],
71-
};
65+
return Promise.resolve(result);
66+
};
67+
break;
68+
default:
69+
throw new Error("boom");
70+
}
71+
const clientOptions: LanguageClientOptions = {
72+
documentSelector: [{ scheme: "file", language: "elixir" }],
73+
};
7274

73-
credoClient = new LanguageClient(
74-
"elixir-tools.credo",
75-
"Credo",
76-
serverOptions,
77-
clientOptions
78-
);
75+
credoClient = new LanguageClient(
76+
"elixir-tools.credo",
77+
"Credo",
78+
serverOptions,
79+
clientOptions
80+
);
7981

80-
// Start the credoClient. This will also launch the server
81-
credoClient.start();
82-
}
82+
// Start the credoClient. This will also launch the server
83+
credoClient.start();
84+
}
85+
}
86+
}
87+
88+
async function activateNextLS(
89+
context: vscode.ExtensionContext,
90+
_mixfile: vscode.Uri
91+
) {
92+
let config = vscode.workspace.getConfiguration("elixir-tools.nextls");
93+
94+
if (config.get("enable")) {
95+
let serverOptions: ServerOptions;
96+
97+
switch (config.get("adapter")) {
98+
case "stdio":
99+
serverOptions = {
100+
options: {
101+
env: Object.assign({}, process.env, {
102+
["NEXTLS_VERSION"]: await latestRelease("next-ls"),
103+
}),
104+
},
105+
command: context.asAbsolutePath("./bin/nextls"),
106+
args: ["--stdio"],
107+
};
108+
break;
109+
case "tcp":
110+
serverOptions = () => {
111+
// Connect to language server via socket
112+
let socket = require("net").connect({
113+
host: "127.0.0.1",
114+
port: config.get("port"),
115+
});
116+
let result: StreamInfo = {
117+
writer: socket,
118+
reader: socket,
119+
};
120+
return Promise.resolve(result);
121+
};
122+
break;
123+
default:
124+
throw new Error("boom");
83125
}
126+
const clientOptions: LanguageClientOptions = {
127+
documentSelector: [{ scheme: "file", language: "elixir" }],
128+
};
129+
130+
nextLSClient = new LanguageClient(
131+
"elixir-tools.nextls",
132+
"NextLS",
133+
serverOptions,
134+
clientOptions
135+
);
136+
137+
// Start the nextLSClient. This will also launch the server
138+
nextLSClient.start();
139+
}
140+
}
141+
142+
export async function activate(context: vscode.ExtensionContext) {
143+
let files = await vscode.workspace.findFiles("mix.exs");
144+
145+
if (files[0]) {
146+
await activateCredo(context, files[0]);
147+
await activateNextLS(context, files[0]);
84148
}
85149
}
86150

87151
export function deactivate() {
88-
if (!credoClient) {
152+
if (!credoClient && !nextLSClient) {
89153
return undefined;
90154
}
91-
return credoClient.stop();
155+
if (credoClient) {
156+
credoClient.stop();
157+
}
158+
159+
if (nextLSClient) {
160+
nextLSClient.stop();
161+
}
162+
163+
return true;
92164
}

0 commit comments

Comments
 (0)