linol/thirdparty/lsp/ocaml-lsp-server/test/e2e/__tests__/ocamllsp-wrappingAstNode.test.ts

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,
},
}
`);
});
});