mirror of
https://github.com/c-cube/linol.git
synced 2025-12-11 05:28:35 -05:00
187 lines
3.6 KiB
TypeScript
187 lines
3.6 KiB
TypeScript
import outdent from "outdent";
|
|
import * as Protocol from "vscode-languageserver-protocol";
|
|
import * as Types from "vscode-languageserver-types";
|
|
import { Position } from "vscode-languageserver-types";
|
|
import * as LanguageServer from "../src/LanguageServer";
|
|
|
|
describe("ocamllsp/wrappingAstNode", () => {
|
|
let languageServer: LanguageServer.LanguageServer;
|
|
|
|
function openDocument(source: string) {
|
|
languageServer.sendNotification(
|
|
Protocol.DidOpenTextDocumentNotification.type,
|
|
{
|
|
textDocument: Types.TextDocumentItem.create(
|
|
"file:///test.ml",
|
|
"ocaml",
|
|
0,
|
|
source,
|
|
),
|
|
},
|
|
);
|
|
}
|
|
|
|
async function sendWrappingAstNodeRequest({
|
|
line,
|
|
character,
|
|
}: {
|
|
line: number;
|
|
character: number;
|
|
}) {
|
|
return languageServer.sendRequest("ocamllsp/wrappingAstNode", {
|
|
uri: "file:///test.ml",
|
|
position: Position.create(line, character),
|
|
});
|
|
}
|
|
|
|
beforeEach(async () => {
|
|
languageServer = await LanguageServer.startAndInitialize();
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await LanguageServer.exit(languageServer);
|
|
});
|
|
|
|
it("empty document", async () => {
|
|
openDocument(
|
|
outdent`
|
|
`,
|
|
);
|
|
|
|
const r = await sendWrappingAstNodeRequest({ line: 0, character: 0 });
|
|
expect(r).toMatchInlineSnapshot("null");
|
|
});
|
|
|
|
const code_snippet_0 = outdent`
|
|
let k = 1
|
|
|
|
module M = struct
|
|
let a =
|
|
let b = 1 in
|
|
b + 1
|
|
|
|
let c = 2
|
|
end
|
|
`;
|
|
|
|
it("when on a toplevel let binding", async () => {
|
|
openDocument(code_snippet_0);
|
|
|
|
const r = await sendWrappingAstNodeRequest({ line: 0, character: 5 });
|
|
|
|
/* given range corresponds to:
|
|
let k = 1
|
|
*/
|
|
expect(r).toMatchInlineSnapshot(`
|
|
{
|
|
"end": {
|
|
"character": 9,
|
|
"line": 0,
|
|
},
|
|
"start": {
|
|
"character": 0,
|
|
"line": 0,
|
|
},
|
|
}
|
|
`);
|
|
});
|
|
|
|
it("in between toplevel bindings (let and module def)", async () => {
|
|
openDocument(code_snippet_0);
|
|
|
|
const r = await sendWrappingAstNodeRequest({ line: 1, character: 0 });
|
|
|
|
/* given range corresponds to:
|
|
whole `code_snippet_0`
|
|
*/
|
|
expect(r).toMatchInlineSnapshot(`
|
|
{
|
|
"end": {
|
|
"character": 3,
|
|
"line": 8,
|
|
},
|
|
"start": {
|
|
"character": 0,
|
|
"line": 0,
|
|
},
|
|
}
|
|
`);
|
|
});
|
|
|
|
it("on keyword struct", async () => {
|
|
openDocument(code_snippet_0);
|
|
|
|
const r = await sendWrappingAstNodeRequest({ line: 2, character: 14 });
|
|
|
|
/* given range corresponds to: the whole module definition M
|
|
module M = struct
|
|
let a =
|
|
let b = 1 in
|
|
b + 1
|
|
|
|
let c = 2
|
|
end
|
|
*/
|
|
expect(r).toMatchInlineSnapshot(`
|
|
{
|
|
"end": {
|
|
"character": 3,
|
|
"line": 8,
|
|
},
|
|
"start": {
|
|
"character": 0,
|
|
"line": 2,
|
|
},
|
|
}
|
|
`);
|
|
});
|
|
|
|
it("on `b`'s let-binding (nested let-binding in a module def)", async () => {
|
|
openDocument(code_snippet_0);
|
|
const r = await sendWrappingAstNodeRequest({ line: 4, character: 10 });
|
|
|
|
/* given range corresponds to:
|
|
let a =
|
|
let b = 1 in
|
|
b + 1
|
|
*/
|
|
expect(r).toMatchInlineSnapshot(`
|
|
{
|
|
"end": {
|
|
"character": 9,
|
|
"line": 5,
|
|
},
|
|
"start": {
|
|
"character": 2,
|
|
"line": 3,
|
|
},
|
|
}
|
|
`);
|
|
});
|
|
|
|
it("between `a`'s and `c`'s let-bindings in a module def", async () => {
|
|
openDocument(code_snippet_0);
|
|
|
|
const r = await sendWrappingAstNodeRequest({ line: 6, character: 0 });
|
|
|
|
/* given range corresponds to: values in M, but not module binding itself
|
|
let a =
|
|
let b = 1 in
|
|
b + 1
|
|
|
|
let c = 2
|
|
*/
|
|
expect(r).toMatchInlineSnapshot(`
|
|
{
|
|
"end": {
|
|
"character": 11,
|
|
"line": 7,
|
|
},
|
|
"start": {
|
|
"character": 2,
|
|
"line": 3,
|
|
},
|
|
}
|
|
`);
|
|
});
|
|
});
|