Get LSP test working for Python
This commit is contained in:
parent
e19d6a2c06
commit
6e92e506fc
|
@ -187,6 +187,7 @@ export class Session {
|
||||||
this.ws.send(JSON.stringify(msg));
|
this.ws.send(JSON.stringify(msg));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.log(`Failed to send websocket message: ${err}`);
|
this.log(`Failed to send websocket message: ${err}`);
|
||||||
|
console.log(err);
|
||||||
await this.teardown();
|
await this.teardown();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -39,7 +39,7 @@ export interface LangConfig {
|
||||||
init?: any;
|
init?: any;
|
||||||
config?: any;
|
config?: any;
|
||||||
lang?: string;
|
lang?: string;
|
||||||
code?: string;
|
code?: string; // FIXME
|
||||||
after?: string;
|
after?: string;
|
||||||
item?: string; // FIXME
|
item?: string; // FIXME
|
||||||
};
|
};
|
||||||
|
@ -1404,6 +1404,8 @@ main = do
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
code: "import func",
|
||||||
|
item: "functools",
|
||||||
},
|
},
|
||||||
template: `print("Hello, world!")
|
template: `print("Hello, world!")
|
||||||
`,
|
`,
|
||||||
|
|
|
@ -26,11 +26,7 @@ if (["-h", "-help", "--help", "help"].includes(args[0])) {
|
||||||
}
|
}
|
||||||
|
|
||||||
let cmdline;
|
let cmdline;
|
||||||
if (
|
if (args.length === 1 && langs[args[0]] && langs[args[0]].lsp) {
|
||||||
args.length === 1 &&
|
|
||||||
langs[args[0]] &&
|
|
||||||
typeof langs[args[0]].lsp === "string"
|
|
||||||
) {
|
|
||||||
cmdline = ["bash", "-c", langs[args[0]].lsp!.start];
|
cmdline = ["bash", "-c", langs[args[0]].lsp!.start];
|
||||||
} else {
|
} else {
|
||||||
cmdline = args;
|
cmdline = args;
|
||||||
|
|
|
@ -8,6 +8,13 @@ import { LangConfig, langs } from "./langs";
|
||||||
|
|
||||||
const TIMEOUT_MS = 3000;
|
const TIMEOUT_MS = 3000;
|
||||||
|
|
||||||
|
function findPosition(str: string, idx: number) {
|
||||||
|
const lines = str.substring(0, idx).split("\n");
|
||||||
|
const line = lines.length - 1;
|
||||||
|
const character = lines[lines.length - 1].length;
|
||||||
|
return { line, character };
|
||||||
|
}
|
||||||
|
|
||||||
class Test {
|
class Test {
|
||||||
lang: string;
|
lang: string;
|
||||||
type: string;
|
type: string;
|
||||||
|
@ -24,6 +31,8 @@ class Test {
|
||||||
|
|
||||||
send = (msg: any) => {
|
send = (msg: any) => {
|
||||||
this.ws.onMessage(JSON.stringify(msg));
|
this.ws.onMessage(JSON.stringify(msg));
|
||||||
|
this.messages.push(msg);
|
||||||
|
this.handledMessages += 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(lang: string, type: string) {
|
constructor(lang: string, type: string) {
|
||||||
|
@ -112,7 +121,7 @@ class Test {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
wait = async (handler: (msg: any) => boolean) => {
|
wait = async <T>(handler: (msg: any) => T) => {
|
||||||
return await new Promise((resolve, reject) => {
|
return await new Promise((resolve, reject) => {
|
||||||
this.handleUpdate = () => {
|
this.handleUpdate = () => {
|
||||||
if (this.timedOut) {
|
if (this.timedOut) {
|
||||||
|
@ -203,7 +212,320 @@ class Test {
|
||||||
throw new Error("formatted code did not match");
|
throw new Error("formatted code did not match");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
testLsp = async () => {};
|
testLsp = async () => {
|
||||||
|
const code = this.config.lsp!.code!; // FIXME
|
||||||
|
const after = this.config.lsp!.after;
|
||||||
|
const item = this.config.lsp!.item!; // FIXME
|
||||||
|
const root = await this.wait((msg: any) => {
|
||||||
|
if (msg.event === "lspStarted") {
|
||||||
|
return msg.root;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const idx = after
|
||||||
|
? this.config.template.indexOf(after)
|
||||||
|
: this.config.template.length;
|
||||||
|
const pos = findPosition(this.config.template, idx);
|
||||||
|
const newCode =
|
||||||
|
this.config.template.slice(0, idx) +
|
||||||
|
code +
|
||||||
|
this.config.template.slice(idx);
|
||||||
|
const newIdx = idx + code.length;
|
||||||
|
const newPos = findPosition(newCode, newIdx);
|
||||||
|
this.send({
|
||||||
|
event: "lspInput",
|
||||||
|
input: {
|
||||||
|
jsonrpc: "2.0",
|
||||||
|
id: "0d75333a-47d8-4da8-8030-c81d7bd9eed7",
|
||||||
|
method: "initialize",
|
||||||
|
params: {
|
||||||
|
processId: null,
|
||||||
|
clientInfo: { name: "vscode" },
|
||||||
|
rootPath: root,
|
||||||
|
rootUri: `file://${root}`,
|
||||||
|
capabilities: {
|
||||||
|
workspace: {
|
||||||
|
applyEdit: true,
|
||||||
|
workspaceEdit: {
|
||||||
|
documentChanges: true,
|
||||||
|
resourceOperations: ["create", "rename", "delete"],
|
||||||
|
failureHandling: "textOnlyTransactional",
|
||||||
|
},
|
||||||
|
didChangeConfiguration: { dynamicRegistration: true },
|
||||||
|
didChangeWatchedFiles: { dynamicRegistration: true },
|
||||||
|
symbol: {
|
||||||
|
dynamicRegistration: true,
|
||||||
|
symbolKind: {
|
||||||
|
valueSet: [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
6,
|
||||||
|
7,
|
||||||
|
8,
|
||||||
|
9,
|
||||||
|
10,
|
||||||
|
11,
|
||||||
|
12,
|
||||||
|
13,
|
||||||
|
14,
|
||||||
|
15,
|
||||||
|
16,
|
||||||
|
17,
|
||||||
|
18,
|
||||||
|
19,
|
||||||
|
20,
|
||||||
|
21,
|
||||||
|
22,
|
||||||
|
23,
|
||||||
|
24,
|
||||||
|
25,
|
||||||
|
26,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
executeCommand: { dynamicRegistration: true },
|
||||||
|
configuration: true,
|
||||||
|
workspaceFolders: true,
|
||||||
|
},
|
||||||
|
textDocument: {
|
||||||
|
publishDiagnostics: {
|
||||||
|
relatedInformation: true,
|
||||||
|
versionSupport: false,
|
||||||
|
tagSupport: { valueSet: [1, 2] },
|
||||||
|
},
|
||||||
|
synchronization: {
|
||||||
|
dynamicRegistration: true,
|
||||||
|
willSave: true,
|
||||||
|
willSaveWaitUntil: true,
|
||||||
|
didSave: true,
|
||||||
|
},
|
||||||
|
completion: {
|
||||||
|
dynamicRegistration: true,
|
||||||
|
contextSupport: true,
|
||||||
|
completionItem: {
|
||||||
|
snippetSupport: true,
|
||||||
|
commitCharactersSupport: true,
|
||||||
|
documentationFormat: ["markdown", "plaintext"],
|
||||||
|
deprecatedSupport: true,
|
||||||
|
preselectSupport: true,
|
||||||
|
tagSupport: { valueSet: [1] },
|
||||||
|
},
|
||||||
|
completionItemKind: {
|
||||||
|
valueSet: [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
6,
|
||||||
|
7,
|
||||||
|
8,
|
||||||
|
9,
|
||||||
|
10,
|
||||||
|
11,
|
||||||
|
12,
|
||||||
|
13,
|
||||||
|
14,
|
||||||
|
15,
|
||||||
|
16,
|
||||||
|
17,
|
||||||
|
18,
|
||||||
|
19,
|
||||||
|
20,
|
||||||
|
21,
|
||||||
|
22,
|
||||||
|
23,
|
||||||
|
24,
|
||||||
|
25,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
hover: {
|
||||||
|
dynamicRegistration: true,
|
||||||
|
contentFormat: ["markdown", "plaintext"],
|
||||||
|
},
|
||||||
|
signatureHelp: {
|
||||||
|
dynamicRegistration: true,
|
||||||
|
signatureInformation: {
|
||||||
|
documentationFormat: ["markdown", "plaintext"],
|
||||||
|
parameterInformation: { labelOffsetSupport: true },
|
||||||
|
},
|
||||||
|
contextSupport: true,
|
||||||
|
},
|
||||||
|
definition: { dynamicRegistration: true, linkSupport: true },
|
||||||
|
references: { dynamicRegistration: true },
|
||||||
|
documentHighlight: { dynamicRegistration: true },
|
||||||
|
documentSymbol: {
|
||||||
|
dynamicRegistration: true,
|
||||||
|
symbolKind: {
|
||||||
|
valueSet: [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
6,
|
||||||
|
7,
|
||||||
|
8,
|
||||||
|
9,
|
||||||
|
10,
|
||||||
|
11,
|
||||||
|
12,
|
||||||
|
13,
|
||||||
|
14,
|
||||||
|
15,
|
||||||
|
16,
|
||||||
|
17,
|
||||||
|
18,
|
||||||
|
19,
|
||||||
|
20,
|
||||||
|
21,
|
||||||
|
22,
|
||||||
|
23,
|
||||||
|
24,
|
||||||
|
25,
|
||||||
|
26,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
hierarchicalDocumentSymbolSupport: true,
|
||||||
|
},
|
||||||
|
codeAction: {
|
||||||
|
dynamicRegistration: true,
|
||||||
|
isPreferredSupport: true,
|
||||||
|
codeActionLiteralSupport: {
|
||||||
|
codeActionKind: {
|
||||||
|
valueSet: [
|
||||||
|
"",
|
||||||
|
"quickfix",
|
||||||
|
"refactor",
|
||||||
|
"refactor.extract",
|
||||||
|
"refactor.inline",
|
||||||
|
"refactor.rewrite",
|
||||||
|
"source",
|
||||||
|
"source.organizeImports",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
codeLens: { dynamicRegistration: true },
|
||||||
|
formatting: { dynamicRegistration: true },
|
||||||
|
rangeFormatting: { dynamicRegistration: true },
|
||||||
|
onTypeFormatting: { dynamicRegistration: true },
|
||||||
|
rename: { dynamicRegistration: true, prepareSupport: true },
|
||||||
|
documentLink: { dynamicRegistration: true, tooltipSupport: true },
|
||||||
|
typeDefinition: { dynamicRegistration: true, linkSupport: true },
|
||||||
|
implementation: { dynamicRegistration: true, linkSupport: true },
|
||||||
|
colorProvider: { dynamicRegistration: true },
|
||||||
|
foldingRange: {
|
||||||
|
dynamicRegistration: true,
|
||||||
|
rangeLimit: 5000,
|
||||||
|
lineFoldingOnly: true,
|
||||||
|
},
|
||||||
|
declaration: { dynamicRegistration: true, linkSupport: true },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
initializationOptions: this.config.lsp!.init || {},
|
||||||
|
trace: "off",
|
||||||
|
workspaceFolders: [
|
||||||
|
{
|
||||||
|
uri: `file://${root}`,
|
||||||
|
name: `file://${root}`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await this.wait((msg: any) => {
|
||||||
|
return (
|
||||||
|
msg.event === "lspOutput" &&
|
||||||
|
msg.output.id === "0d75333a-47d8-4da8-8030-c81d7bd9eed7"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
this.send({
|
||||||
|
event: "lspInput",
|
||||||
|
input: { jsonrpc: "2.0", method: "initialized", params: {} },
|
||||||
|
});
|
||||||
|
this.send({
|
||||||
|
event: "lspInput",
|
||||||
|
input: {
|
||||||
|
jsonrpc: "2.0",
|
||||||
|
method: "textDocument/didOpen",
|
||||||
|
params: {
|
||||||
|
textDocument: {
|
||||||
|
uri: `file://${root}/${this.config.main}`,
|
||||||
|
languageId: "python", // FIXME
|
||||||
|
version: 1,
|
||||||
|
text: `${this.config.template}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
this.send({
|
||||||
|
event: "lspInput",
|
||||||
|
input: {
|
||||||
|
jsonrpc: "2.0",
|
||||||
|
method: "textDocument/didChange",
|
||||||
|
params: {
|
||||||
|
textDocument: {
|
||||||
|
uri: `file://${root}/${this.config.main}`,
|
||||||
|
version: 3,
|
||||||
|
},
|
||||||
|
contentChanges: [
|
||||||
|
{
|
||||||
|
range: {
|
||||||
|
start: pos,
|
||||||
|
end: pos,
|
||||||
|
},
|
||||||
|
rangeLength: 0,
|
||||||
|
text: code,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
this.send({
|
||||||
|
event: "lspInput",
|
||||||
|
input: {
|
||||||
|
jsonrpc: "2.0",
|
||||||
|
id: "ecdb8a55-f755-4553-ae8e-91d6ebbc2045",
|
||||||
|
method: "textDocument/completion",
|
||||||
|
params: {
|
||||||
|
textDocument: {
|
||||||
|
uri: `file://${root}/${this.config.main}`,
|
||||||
|
},
|
||||||
|
position: newPos,
|
||||||
|
context: { triggerKind: 1 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const items: any = await this.wait((msg: any) => {
|
||||||
|
if (msg.event === "lspOutput") {
|
||||||
|
if (msg.output.method === "workspace/configuration") {
|
||||||
|
this.send({
|
||||||
|
event: "lspInput",
|
||||||
|
input: {
|
||||||
|
jsonrpc: "2.0",
|
||||||
|
id: msg.output.id,
|
||||||
|
result: Array(msg.output.params.items.length).fill(
|
||||||
|
this.config.lsp!.config !== undefined
|
||||||
|
? this.config.lsp!.config
|
||||||
|
: {}
|
||||||
|
),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else if (msg.output.id === "ecdb8a55-f755-4553-ae8e-91d6ebbc2045") {
|
||||||
|
return msg.output.result.items;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (
|
||||||
|
!(items && items.filter(({ label }: any) => label === item).length > 0)
|
||||||
|
) {
|
||||||
|
throw new Error("completion item did not appear");
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function lint(lang: string) {
|
function lint(lang: string) {
|
||||||
|
|
|
@ -25,11 +25,13 @@ interface RijuConfig {
|
||||||
id: string;
|
id: string;
|
||||||
monacoLang?: string;
|
monacoLang?: string;
|
||||||
main: string;
|
main: string;
|
||||||
format?: string;
|
format?: any;
|
||||||
lspDisableDynamicRegistration?: boolean;
|
lsp?: {
|
||||||
lspInit?: any;
|
disableDynamicRegistration?: boolean;
|
||||||
lspConfig?: any;
|
init?: any;
|
||||||
lspLang?: string;
|
config?: any;
|
||||||
|
lang?: string;
|
||||||
|
};
|
||||||
template: string;
|
template: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,13 +93,13 @@ class RijuMessageWriter extends AbstractMessageWriter {
|
||||||
switch ((msg as any).method) {
|
switch ((msg as any).method) {
|
||||||
case "initialize":
|
case "initialize":
|
||||||
(msg as any).params.processId = null;
|
(msg as any).params.processId = null;
|
||||||
if (config.lspDisableDynamicRegistration) {
|
if (config.lsp!.disableDynamicRegistration) {
|
||||||
this.disableDynamicRegistration(msg);
|
this.disableDynamicRegistration(msg);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "textDocument/didOpen":
|
case "textDocument/didOpen":
|
||||||
if (config.lspLang) {
|
if (config.lsp!.lang) {
|
||||||
(msg as any).params.textDocument.languageId = config.lspLang;
|
(msg as any).params.textDocument.languageId = config.lsp!.lang;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
|
@ -201,7 +203,7 @@ async function main() {
|
||||||
console.error("Unexpected message from server:", message);
|
console.error("Unexpected message from server:", message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const services = MonacoServices.create(editor, {
|
const services = MonacoServices.create(editor as any, {
|
||||||
rootUri: `file://${message.root}`,
|
rootUri: `file://${message.root}`,
|
||||||
});
|
});
|
||||||
servicesDisposable = Services.install(services);
|
servicesDisposable = Services.install(services);
|
||||||
|
@ -230,12 +232,12 @@ async function main() {
|
||||||
return Array(
|
return Array(
|
||||||
(configuration(params, token) as {}[]).length
|
(configuration(params, token) as {}[]).length
|
||||||
).fill(
|
).fill(
|
||||||
config.lspConfig !== undefined ? config.lspConfig : {}
|
config.lsp!.config !== undefined ? config.lsp!.config : {}
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
initializationOptions: config.lspInit || {},
|
initializationOptions: config.lsp!.init || {},
|
||||||
},
|
},
|
||||||
connectionProvider: {
|
connectionProvider: {
|
||||||
get: (errorHandler: any, closeHandler: any) =>
|
get: (errorHandler: any, closeHandler: any) =>
|
||||||
|
|
Loading…
Reference in New Issue