linol/thirdparty/lsp/ocaml-lsp-server/test/e2e/__tests__/textDocument-signatureHelp.ts

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