Skip to content

Commit 8be606c

Browse files
fix(extension): Restart after changing path setting (#33)
1 parent 37e3a71 commit 8be606c

File tree

7 files changed

+120
-87
lines changed

7 files changed

+120
-87
lines changed

.vscode/settings.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,4 @@
55
"editor.codeActionsOnSave": {
66
"source.fixAll.eslint": "explicit"
77
},
8-
"rust-analyzer.trace.server": "verbose"
98
}

docs/content/development.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,10 +173,13 @@ See https://github.com/r-lib/tree-sitter-r/issues/166
173173

174174
### VS Code Extensions
175175

176-
* https://github.com/microsoft/vscode-extension-samples/tree/main/lsp-sample
177-
* https://github.com/semanticart/lsp-from-scratch
178-
* https://github.com/nix-community/vscode-nix-ide
179-
* https://github.com/ziglang/vscode-zig/
176+
* docs:
177+
* https://code.visualstudio.com/api/references/vscode-api
178+
* examples:
179+
* https://github.com/microsoft/vscode-extension-samples/tree/main/lsp-sample
180+
* https://github.com/semanticart/lsp-from-scratch
181+
* https://github.com/nix-community/vscode-nix-ide
182+
* https://github.com/ziglang/vscode-zig/
180183

181184
### Other Language Servers written in Rust
182185

editors/code/bun.lockb

-4.35 KB
Binary file not shown.

editors/code/package.json

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,13 @@
3434
"vscode-languageclient": "^9.0.1"
3535
},
3636
"devDependencies": {
37-
"@eslint/js": "^9.29.0",
38-
"@stylistic/eslint-plugin": "^2.13.0",
39-
"@types/node": "^20.19.0",
40-
"@types/vscode": "^1.101.0",
37+
"@eslint/js": "^9.13.0",
38+
"@types/node": "^20",
39+
"@types/vscode": "^1.75.1",
4140
"@vscode/vsce": "^3.5.0",
4241
"eslint": "^9.29.0",
4342
"typescript": "^5.8.3",
44-
"typescript-eslint": "^8.34.0"
43+
"typescript-eslint": "^8.34.1"
4544
},
4645
"main": "./out/extension",
4746
"activationEvents": [

editors/code/src/extension.ts

Lines changed: 103 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import * as path from "path";
2-
import * as fs from 'fs';
1+
import * as fs from "fs"
2+
import * as path from "path"
33

44
import {
55
commands,
@@ -9,6 +9,7 @@ import {
99
ExtensionContext,
1010
MarkdownString,
1111
StatusBarAlignment,
12+
StatusBarItem,
1213
TextEditor,
1314
ThemeColor,
1415
} from 'vscode'
@@ -20,62 +21,21 @@ import {
2021
TransportKind,
2122
} from 'vscode-languageclient/node'
2223

23-
const logger = window.createOutputChannel("Roughly Extension", { log: true });
24+
const logger = window.createOutputChannel("Roughly Extension", { log: true })
25+
const outputChannel = window.createOutputChannel("Roughly")
2426

2527
const EXTENSION_ROOT_DIR = path.dirname(__dirname)
2628
const ROUGHLY_BINARY_NAME = process.platform === "win32" ? "roughly.exe" : "roughly"
2729
const BUNDLED_ROUGHLY_EXECUTABLE = path.join(EXTENSION_ROOT_DIR, "bin", ROUGHLY_BINARY_NAME)
2830

29-
let client: LanguageClient
30-
let statusBar
31+
let client: LanguageClient | null = null
32+
let statusBar: StatusBarItem
3133
let status = { health: "started" }
32-
let version
34+
let version: string | undefined
3335

34-
export function activate({ subscriptions, extension }: ExtensionContext) {
36+
export async function activate({ subscriptions, extension, }: ExtensionContext): Promise<void> {
3537
version = extension.packageJSON.version ?? "<unknown>"
3638

37-
const config = workspace.getConfiguration("roughly")
38-
39-
const command = process.env.SERVER_PATH
40-
?? config.get<string>("path")
41-
?? (
42-
fs.existsSync(BUNDLED_ROUGHLY_EXECUTABLE)
43-
? BUNDLED_ROUGHLY_EXECUTABLE
44-
: "roughly"
45-
)
46-
47-
const args = config.get<string[]>("args", ["server"])
48-
49-
logger.info("using server command:", [command, ...args].join(" "))
50-
51-
const outputChannel = window.createOutputChannel("Roughly");
52-
53-
client = (() => {
54-
const serverOptions: ServerOptions = {
55-
command,
56-
args,
57-
transport: TransportKind.stdio,
58-
options: {
59-
env: {
60-
...process.env,
61-
RUST_LOG: "debug",
62-
},
63-
},
64-
}
65-
66-
const clientOptions: LanguageClientOptions = {
67-
documentSelector: [{ scheme: "file", language: "r" }],
68-
outputChannel,
69-
}
70-
71-
return new LanguageClient(
72-
'roughly',
73-
'Roughly',
74-
serverOptions,
75-
clientOptions
76-
)
77-
})()
78-
7939
subscriptions.push(
8040
workspace.onDidChangeConfiguration(async (change) => {
8141
if (
@@ -85,43 +45,36 @@ export function activate({ subscriptions, extension }: ExtensionContext) {
8545
"Restart",
8646
)
8747
if (choice === "Restart") {
88-
await client.restart()
48+
await restartClient()
8949
setTimeout(() => {
90-
client.outputChannel.show()
50+
client?.outputChannel.show()
9151
}, 1500)
9252
}
9353
}
9454
}),
9555
commands.registerCommand(
9656
"roughly.restartServer",
9757
async () => {
98-
if (client.isRunning) {
99-
await client.restart()
100-
} else {
101-
await client.start()
102-
}
103-
setServerStatus({ health: "started" })
58+
await restartClient()
10459
}
10560
),
10661
commands.registerCommand(
10762
"roughly.startServer",
10863
async () => {
109-
await client.start()
110-
setServerStatus({ health: "started" })
64+
await restartClient()
11165
}
11266
),
11367
commands.registerCommand(
11468
"roughly.stopServer",
11569
async () => {
116-
await client.stop()
117-
setServerStatus({ health: "stopped" })
70+
await stopClient()
11871
}
11972
),
12073
commands.registerCommand(
12174
"roughly.openLogs",
12275
async () => {
123-
if (client.outputChannel) {
124-
client.outputChannel.show();
76+
if (client?.outputChannel) {
77+
client.outputChannel.show()
12578
}
12679
}
12780
)
@@ -133,16 +86,100 @@ export function activate({ subscriptions, extension }: ExtensionContext) {
13386
updateStatusBarVisibility(window.activeTextEditor)
13487
window.onDidChangeActiveTextEditor((editor) => updateStatusBarVisibility(editor))
13588

136-
client.start() // this also launches the server
89+
restartClient()
90+
}
91+
92+
export async function deactivate(): Promise<void> {
93+
await stopClient()
13794
}
13895

96+
//
97+
// SERVER
98+
//
99+
100+
async function restartClient(): Promise<void> {
101+
const newClient = createClient()
102+
try {
103+
await newClient.start()
104+
void stopClient()
105+
client = newClient
106+
setServerStatus({ health: "started" })
107+
} catch (reason) {
108+
void window.showWarningMessage("Failed to start Roughly language server.")
109+
setServerStatus({ health: "stopped" })
110+
}
111+
}
112+
113+
function createClient(): LanguageClient {
114+
const config = workspace.getConfiguration("roughly")
115+
116+
const command = process.env.SERVER_PATH
117+
?? config.get<string>("path")
118+
?? (
119+
fs.existsSync(BUNDLED_ROUGHLY_EXECUTABLE)
120+
? BUNDLED_ROUGHLY_EXECUTABLE
121+
: "roughly"
122+
)
123+
124+
const args = config.get<string[]>("args", ["server"])
125+
126+
logger.info("using server command:", [command, ...args].join(" "))
127+
128+
const serverOptions: ServerOptions = {
129+
command,
130+
args,
131+
transport: TransportKind.stdio,
132+
options: {
133+
env: {
134+
...process.env,
135+
RUST_LOG: "debug",
136+
},
137+
},
138+
}
139+
140+
const clientOptions: LanguageClientOptions = {
141+
documentSelector: [{ scheme: "file", language: "r" }],
142+
outputChannel,
143+
}
144+
145+
const client = new LanguageClient(
146+
'roughly',
147+
'Roughly',
148+
serverOptions,
149+
clientOptions
150+
)
151+
152+
return client
153+
}
154+
155+
156+
async function stopClient(): Promise<void> {
157+
if (!client) {
158+
return
159+
}
160+
161+
logger.info("stopping server ...")
162+
163+
const oldClient = client
164+
client = null
165+
166+
// The `stop` call will send the "shutdown" notification to the LSP
167+
await oldClient.stop()
168+
// The `dipose` call will send the "exit" request to the LSP which actually tells the child process to exit
169+
await oldClient.dispose()
170+
}
171+
172+
//
173+
// STATUS BAR
174+
//
175+
139176
type ServerStatus = {
140177
health: "started" | "stopped"
141178
}
142179

143180
function setServerStatus(newStatus: ServerStatus) {
144-
status = newStatus;
145-
updateStatusBarItem();
181+
status = newStatus
182+
updateStatusBarItem()
146183
}
147184

148185
function updateStatusBarVisibility(editor: TextEditor | undefined) {
@@ -188,11 +225,3 @@ function updateStatusBarItem() {
188225
// if (true) icon = "$(loading~spin) "
189226
statusBar.text = `${icon}Roughly`
190227
}
191-
192-
193-
export function deactivate(): Thenable<void> | undefined {
194-
if (!client) {
195-
return undefined
196-
}
197-
return client.stop()
198-
}

editors/code/tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"compilerOptions": {
3+
"strict": true,
34
"module": "commonjs",
45
"target": "es2020",
56
"lib": ["es2020"],

justfile

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,15 @@ snapshot *args:
2323
vsce *args:
2424
@bun --cwd=editors/code run vsce -- {{args}}
2525

26+
install-extension:
27+
mkdir -p release/dev
28+
just build-extension pre-release --out ../../release/dev/roughly.vsix
29+
code --install-extension release/dev/roughly.vsix
30+
2631
#
2732
# BUILD
2833
#
2934

30-
install-extension $path:
31-
code --install-extension {{path}}
32-
3335
build-linux:
3436
cargo build --release --target x86_64-unknown-linux-gnu
3537

0 commit comments

Comments
 (0)