Skip to content

Commit 57d34e8

Browse files
committed
Shutdown
1 parent d569f3e commit 57d34e8

File tree

3 files changed

+83
-22
lines changed

3 files changed

+83
-22
lines changed

client/src/extension.ts

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* ------------------------------------------------------------------------------------------ */
55

66
import * as path from 'path';
7-
import { workspace, ExtensionContext, tasks, Task, ShellExecution } from 'vscode';
7+
import { workspace, ExtensionContext, tasks, Task, TaskScope, ShellExecution } from 'vscode';
88

99
import {
1010
LanguageClient,
@@ -16,40 +16,50 @@ import {
1616

1717
let client: LanguageClient;
1818

19-
// let taskProvider = tasks.registerTaskProvider('bsb', {
19+
// let taskProvider = tasks.registerTaskProvider('Run BuckleScript build', {
2020
// provideTasks: () => {
2121
// // if (!rakePromise) {
2222
// // rakePromise = getRakeTasks();
2323
// // }
2424
// // return rakePromise;
25+
26+
// // taskDefinition: TaskDefinition,
27+
// // scope: WorkspaceFolder | TaskScope.Global | TaskScope.Workspace,
28+
// // name: string,
29+
// // source: string,
30+
// // execution ?: ProcessExecution | ShellExecution | CustomExecution,
31+
// // problemMatchers ?: string | string[]
2532
// return [
2633
// new Task(
2734
// {
28-
// type: 'asd',
29-
// task: 'asd2',
35+
// type: 'bsb',
3036
// },
31-
// definition.task,
32-
// 'bsb run',
37+
// TaskScope.Workspace,
38+
// // definition.task,
39+
// 'build and watch',
40+
// 'bsb',
3341
// new ShellExecution(
34-
// `bsb run this`
42+
// // `./node_modules/.bin/bsb -make-world -w`
43+
// `pwd`
3544
// ),
45+
// "Hello"
3646
// )
3747
// ]
3848
// },
3949
// resolveTask(_task: Task): Task | undefined {
40-
// const task = _task.definition.task;
41-
// // A Rake task consists of a task and an optional file as specified in RakeTaskDefinition
42-
// // Make sure that this looks like a Rake task by checking that there is a task.
43-
// if (task) {
44-
// // resolveTask requires that the same definition object be used.
45-
// const definition: RakeTaskDefinition = <any>_task.definition;
46-
// return new Task(
47-
// definition,
48-
// definition.task,
49-
// 'rake',
50-
// new vscode.ShellExecution(`rake ${definition.task}`)
51-
// );
52-
// }
50+
// // const task = _task.definition.task;
51+
// // // A Rake task consists of a task and an optional file as specified in RakeTaskDefinition
52+
// // // Make sure that this looks like a Rake task by checking that there is a task.
53+
// // if (task) {
54+
// // // resolveTask requires that the same definition object be used.
55+
// // const definition: RakeTaskDefinition = <any>_task.definition;
56+
// // return new Task(
57+
// // definition,
58+
// // definition.task,
59+
// // 'rake',
60+
// // new vscode.ShellExecution(`rake ${definition.task}`)
61+
// // );
62+
// // }
5363
// return undefined;
5464
// }
5565
// });

package.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,20 @@
2222
],
2323
"main": "./client/out/extension",
2424
"contributes": {
25+
"taskDefinitions_unused": [
26+
{
27+
"type": "bsb",
28+
"required": [
29+
"task"
30+
],
31+
"properties": {
32+
"task": {
33+
"type": "string",
34+
"description": "The bsb task"
35+
}
36+
}
37+
}
38+
],
2539
"configuration": {
2640
"type": "object",
2741
"title": "Example configuration",

server/src/testserver.ts

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@ let bscPartialPath = path.join('node_modules', '.bin', 'bsc')
2020
// https://microsoft.github.io/language-server-protocol/specification#initialize
2121
// According to the spec, there could be requests before the 'initialize' request. Link in comment tells how to handle them.
2222
let initialized = false;
23+
// https://microsoft.github.io/language-server-protocol/specification#exit
24+
let shutdownRequestAlreadyReceived = false;
2325

2426
// congrats. A simple UI problem is now a distributed system problem
2527
let stupidFileContentCache: { [key: string]: string } = {
2628
}
2729

28-
let findDirOfFileNearFile = (fileToFind: p.DocumentUri, source: p.DocumentUri,) => {
30+
let findDirOfFileNearFile = (fileToFind: p.DocumentUri, source: p.DocumentUri) => {
2931
let dir = path.dirname(source)
3032
if (fs.existsSync(path.join(dir, fileToFind))) {
3133
return dir
@@ -68,13 +70,26 @@ let formatUsingValidBscPath = (code: string, bscPath: p.DocumentUri, isInterface
6870
}
6971
}
7072

73+
// let startWatchingBsbOutputFile = () => {
74+
// fs.watch()
75+
// }
76+
// let stopWatchingBsbOutputFile = () => {
77+
// fs.unwatchFile()
78+
// }
79+
7180
process.on('message', (a: (m.RequestMessage | m.NotificationMessage)) => {
7281
if ((a as m.RequestMessage).id == null) {
82+
// this is a notification message, aka client sent and forgot
7383
let aa = (a as m.NotificationMessage)
7484
if (!initialized && aa.method !== 'exit') {
7585
// From spec: "Notifications should be dropped, except for the exit notification. This will allow the exit of a server without an initialize request"
7686
} else if (aa.method === 'exit') {
77-
// nothing to do for now
87+
// The server should exit with success code 0 if the shutdown request has been received before; otherwise with error code 1
88+
if (shutdownRequestAlreadyReceived) {
89+
process.exit(0)
90+
} else {
91+
process.exit(1)
92+
}
7893
} else if (aa.method === DidOpenTextDocumentNotification.method) {
7994
let params = (aa.params as p.DidOpenTextDocumentParams);
8095
stupidFileContentCache[params.textDocument.uri] = params.textDocument.text;
@@ -92,6 +107,7 @@ process.on('message', (a: (m.RequestMessage | m.NotificationMessage)) => {
92107
delete stupidFileContentCache[params.textDocument.uri];
93108
}
94109
} else {
110+
// this is a request message, aka client sent request, waits for our reply
95111
let aa = (a as m.RequestMessage)
96112
if (!initialized && aa.method !== 'initialize') {
97113
let response: m.ResponseMessage = {
@@ -128,6 +144,27 @@ process.on('message', (a: (m.RequestMessage | m.NotificationMessage)) => {
128144
result: null,
129145
};
130146
(<any>process).send(response);
147+
} else if (aa.method === 'shutdown') {
148+
// https://microsoft.github.io/language-server-protocol/specification#shutdown
149+
if (shutdownRequestAlreadyReceived) {
150+
let response: m.ResponseMessage = {
151+
jsonrpc: jsonrpcVersion,
152+
id: aa.id,
153+
error: {
154+
code: m.ErrorCodes.InvalidRequest,
155+
message: `Language server already received the shutdown request`
156+
}
157+
};
158+
(<any>process).send(response);
159+
} else {
160+
shutdownRequestAlreadyReceived = true
161+
let response: m.ResponseMessage = {
162+
jsonrpc: jsonrpcVersion,
163+
id: aa.id,
164+
result: null,
165+
};
166+
(<any>process).send(response);
167+
}
131168
} else if (aa.method === p.DocumentFormattingRequest.method) {
132169
let params = (aa.params as p.DocumentFormattingParams)
133170
let filePath = params.textDocument.uri.replace('file:', '')

0 commit comments

Comments
 (0)