mirror of
https://github.com/c-cube/linol.git
synced 2025-12-09 20:55:43 -05:00
506 lines
9.6 KiB
TypeScript
506 lines
9.6 KiB
TypeScript
import outdent from "outdent";
|
|
import * as Protocol from "vscode-languageserver-protocol";
|
|
import * as Types from "vscode-languageserver-types";
|
|
import * as LanguageServer from "./../src/LanguageServer";
|
|
|
|
const describe_opt = LanguageServer.ocamlVersionGEq("4.08.0")
|
|
? describe
|
|
: xdescribe;
|
|
|
|
describe_opt("textDocument/completion", () => {
|
|
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 querySignatureHelp(position: Types.Position) {
|
|
return await languageServer.sendRequest(
|
|
Protocol.SignatureHelpRequest.type,
|
|
{
|
|
textDocument: Types.TextDocumentIdentifier.create("file:///test.ml"),
|
|
position,
|
|
},
|
|
);
|
|
}
|
|
|
|
beforeEach(async () => {
|
|
languageServer = await LanguageServer.startAndInitialize({
|
|
capabilities: {
|
|
textDocument: {
|
|
moniker: {},
|
|
signatureHelp: {
|
|
dynamicRegistration: true,
|
|
signatureInformation: {
|
|
documentationFormat: ["markdown", "plaintext"],
|
|
parameterInformation: {
|
|
labelOffsetSupport: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
});
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await LanguageServer.exit(languageServer);
|
|
});
|
|
|
|
it("can provide signature help after a function-type value", async () => {
|
|
openDocument(outdent`
|
|
let map = ListLabels.map
|
|
|
|
let _ = map
|
|
`);
|
|
|
|
const items = await querySignatureHelp(Types.Position.create(2, 11));
|
|
expect(items).toMatchInlineSnapshot(`
|
|
{
|
|
"activeParameter": 1,
|
|
"activeSignature": 0,
|
|
"signatures": [
|
|
{
|
|
"label": "map : f:('a -> 'b) -> 'a list -> 'b list",
|
|
"parameters": [
|
|
{
|
|
"label": [
|
|
6,
|
|
18,
|
|
],
|
|
},
|
|
{
|
|
"label": [
|
|
22,
|
|
29,
|
|
],
|
|
},
|
|
],
|
|
},
|
|
],
|
|
}
|
|
`);
|
|
});
|
|
|
|
it("can provide signature help for an operator", async () => {
|
|
openDocument(outdent`
|
|
let (+) = (+)
|
|
|
|
let _ = 1 + 2
|
|
`);
|
|
|
|
const items = await querySignatureHelp(Types.Position.create(2, 13));
|
|
expect(items).toMatchInlineSnapshot(`
|
|
{
|
|
"activeParameter": 1,
|
|
"activeSignature": 0,
|
|
"signatures": [
|
|
{
|
|
"label": "(+) : int -> int -> int",
|
|
"parameters": [
|
|
{
|
|
"label": [
|
|
6,
|
|
9,
|
|
],
|
|
},
|
|
{
|
|
"label": [
|
|
13,
|
|
16,
|
|
],
|
|
},
|
|
],
|
|
},
|
|
],
|
|
}
|
|
`);
|
|
});
|
|
|
|
it("can provide signature help for an anonymous function", async () => {
|
|
openDocument(outdent`
|
|
let _ = (fun x -> x + 1)
|
|
`);
|
|
|
|
const items = await querySignatureHelp(Types.Position.create(0, 26));
|
|
expect(items).toMatchInlineSnapshot(`
|
|
{
|
|
"activeParameter": 0,
|
|
"activeSignature": 0,
|
|
"signatures": [
|
|
{
|
|
"label": "_ : int -> int",
|
|
"parameters": [
|
|
{
|
|
"label": [
|
|
4,
|
|
7,
|
|
],
|
|
},
|
|
],
|
|
},
|
|
],
|
|
}
|
|
`);
|
|
});
|
|
|
|
it("can make the non-labelled parameter active", async () => {
|
|
openDocument(outdent`
|
|
let map = ListLabels.map
|
|
|
|
let _ = map []
|
|
`);
|
|
|
|
const items = await querySignatureHelp(Types.Position.create(2, 14));
|
|
expect(items).toMatchInlineSnapshot(`
|
|
{
|
|
"activeParameter": 1,
|
|
"activeSignature": 0,
|
|
"signatures": [
|
|
{
|
|
"label": "map : f:('a -> 'b) -> 'a list -> 'b list",
|
|
"parameters": [
|
|
{
|
|
"label": [
|
|
6,
|
|
18,
|
|
],
|
|
},
|
|
{
|
|
"label": [
|
|
22,
|
|
29,
|
|
],
|
|
},
|
|
],
|
|
},
|
|
],
|
|
}
|
|
`);
|
|
});
|
|
|
|
it("can make the labelled parameter active", async () => {
|
|
openDocument(outdent`
|
|
let map = ListLabels.map
|
|
|
|
let _ = map ~f:Int.abs
|
|
`);
|
|
|
|
const items = await querySignatureHelp(Types.Position.create(2, 22));
|
|
expect(items).toMatchInlineSnapshot(`
|
|
{
|
|
"activeParameter": 0,
|
|
"activeSignature": 0,
|
|
"signatures": [
|
|
{
|
|
"label": "map : f:(int -> int) -> int list -> int list",
|
|
"parameters": [
|
|
{
|
|
"label": [
|
|
6,
|
|
20,
|
|
],
|
|
},
|
|
{
|
|
"label": [
|
|
24,
|
|
32,
|
|
],
|
|
},
|
|
],
|
|
},
|
|
],
|
|
}
|
|
`);
|
|
});
|
|
|
|
it("can make a labelled parameter active by prefix", async () => {
|
|
openDocument(outdent`
|
|
let mem = ListLabels.mem
|
|
|
|
let _ = mem ~se
|
|
`);
|
|
|
|
const items = await querySignatureHelp(Types.Position.create(2, 15));
|
|
expect(items).toMatchInlineSnapshot(`
|
|
{
|
|
"activeParameter": 1,
|
|
"activeSignature": 0,
|
|
"signatures": [
|
|
{
|
|
"label": "mem : 'a -> set:'a list -> bool",
|
|
"parameters": [
|
|
{
|
|
"label": [
|
|
6,
|
|
8,
|
|
],
|
|
},
|
|
{
|
|
"label": [
|
|
12,
|
|
23,
|
|
],
|
|
},
|
|
],
|
|
},
|
|
],
|
|
}
|
|
`);
|
|
});
|
|
|
|
it("can make an optional parameter active by prefix", async () => {
|
|
openDocument(outdent`
|
|
let create = Hashtbl.create
|
|
|
|
let _ = create ?ra
|
|
`);
|
|
|
|
const items = await querySignatureHelp(Types.Position.create(2, 18));
|
|
expect(items).toMatchInlineSnapshot(`
|
|
{
|
|
"activeParameter": 0,
|
|
"activeSignature": 0,
|
|
"signatures": [
|
|
{
|
|
"label": "create : ?random:bool -> int -> ('a, 'b) Hashtbl.t",
|
|
"parameters": [
|
|
{
|
|
"label": [
|
|
9,
|
|
21,
|
|
],
|
|
},
|
|
{
|
|
"label": [
|
|
25,
|
|
28,
|
|
],
|
|
},
|
|
],
|
|
},
|
|
],
|
|
}
|
|
`);
|
|
});
|
|
|
|
it("can return documentation for the function being applied", async () => {
|
|
openDocument(
|
|
outdent`
|
|
(** This is an example of a docstring that demonstrates various ocamldoc syntax features.
|
|
|
|
{3 Sections and Labels}
|
|
|
|
We can create sections using {3 Section title} and labels using {3:label_name Section title with label}
|
|
|
|
{3 Links and Cross-references}
|
|
|
|
External links: {{:https://ocaml.org/} OCaml's official website}
|
|
|
|
Cross-references: {!List.length} {{!List.length} Replacement text}
|
|
|
|
{3 Inline Formatting}
|
|
|
|
{b Bold}, {i Italic}, {e Emphasize}, {^ Superscript}, {_ Subscript}, and [inline code]
|
|
|
|
{3 Text Alignment}
|
|
|
|
{C Centered text}
|
|
{L Left-aligned text}
|
|
{R Right-aligned text}
|
|
|
|
{3 Lists}
|
|
|
|
{ol
|
|
{- Ordered list item 1}
|
|
{- Ordered list item 2}
|
|
}
|
|
|
|
{ul
|
|
{- Unordered list item 1}
|
|
{- Unordered list item 2}
|
|
}
|
|
|
|
- Unordered list item 1
|
|
- Unordered list item 2
|
|
|
|
{3 Code Blocks}
|
|
|
|
{[
|
|
let square x = x * x
|
|
let result = square 3
|
|
]}
|
|
|
|
{@python[
|
|
def f():
|
|
return 0
|
|
]}
|
|
|
|
{3 Verbatim}
|
|
|
|
{v
|
|
This text will be displayed verbatim.
|
|
No formatting will be applied.
|
|
v}
|
|
|
|
{3 Module List}
|
|
|
|
{!modules: Array List String}
|
|
|
|
@param x dividend
|
|
@param divisor
|
|
|
|
@return {i quotient}, i.e. result of division
|
|
@raise Division_by_zero raised when divided by zero
|
|
|
|
@see <https://en.wikipedia.org/wiki/Arithmetic#Division_(%C3%B7,_or_/)> article
|
|
@see 'arithmetic.ml' for more context
|
|
|
|
@since 4.0.0
|
|
@before 4.4.0
|
|
|
|
@deprecated use [(/)]
|
|
|
|
@version 1.0.0
|
|
@author John Doe *)
|
|
let div x y =
|
|
x / y
|
|
|
|
let _ = div 1
|
|
`,
|
|
);
|
|
|
|
const items = await querySignatureHelp(Types.Position.create(80, 13));
|
|
expect(items).toMatchInlineSnapshot(`
|
|
{
|
|
"activeParameter": 0,
|
|
"activeSignature": 0,
|
|
"signatures": [
|
|
{
|
|
"documentation": {
|
|
"kind": "markdown",
|
|
"value": "This is an example of a docstring that demonstrates various ocamldoc syntax features.
|
|
|
|
#### Sections and Labels
|
|
|
|
We can create sections using
|
|
|
|
#### Section title
|
|
|
|
and labels using
|
|
|
|
#### Section title with label
|
|
|
|
#### Links and Cross-references
|
|
|
|
External links: [OCaml's official website](https://ocaml.org/)
|
|
|
|
Cross-references: \`List.length\` Replacement text
|
|
|
|
#### Inline Formatting
|
|
|
|
**Bold**, *Italic*, *Emphasize*, ^{Superscript}, \\_{Subscript}, and \`inline code\`
|
|
|
|
#### Text Alignment
|
|
|
|
Centered text
|
|
|
|
Left-aligned text
|
|
|
|
Right-aligned text
|
|
|
|
#### Lists
|
|
|
|
1. Ordered list item 1
|
|
2. Ordered list item 2
|
|
|
|
- Unordered list item 1
|
|
- Unordered list item 2
|
|
|
|
- Unordered list item 1
|
|
- Unordered list item 2
|
|
|
|
#### Code Blocks
|
|
|
|
\`\`\`ocaml
|
|
let square x = x * x
|
|
let result = square 3
|
|
\`\`\`
|
|
|
|
\`\`\`python
|
|
def f():
|
|
return 0
|
|
\`\`\`
|
|
|
|
#### Verbatim
|
|
|
|
\`\`\`verb
|
|
This text will be displayed verbatim.
|
|
No formatting will be applied.
|
|
\`\`\`
|
|
|
|
#### Module List
|
|
|
|
* Array
|
|
* List
|
|
* String
|
|
|
|
***@param*** \`x\`
|
|
dividend
|
|
|
|
***@param*** divisor
|
|
|
|
***@return***
|
|
*quotient*, i.e. result of division
|
|
|
|
***@raise*** \`Division_by_zero\`
|
|
raised when divided by zero
|
|
|
|
***@see*** [link](https://en.wikipedia.org/wiki/Arithmetic#Division_\\(%C3%B7,_or_/\\))
|
|
article
|
|
|
|
***@see*** \`arithmetic.ml\`
|
|
for more context
|
|
|
|
***@since*** \`4.0.0\`
|
|
|
|
***@before*** \`4.4.0\`
|
|
|
|
***@deprecated***
|
|
use \`(/)\`
|
|
|
|
***@version*** \`1.0.0\`
|
|
|
|
***@author*** John Doe",
|
|
},
|
|
"label": "div : int -> int -> int",
|
|
"parameters": [
|
|
{
|
|
"label": [
|
|
6,
|
|
9,
|
|
],
|
|
},
|
|
{
|
|
"label": [
|
|
13,
|
|
16,
|
|
],
|
|
},
|
|
],
|
|
},
|
|
],
|
|
}
|
|
`);
|
|
});
|
|
});
|