Skip to content

Commit 4a6e27d

Browse files
authored
Merge pull request #294 from mnxn/go-to-declaration
Implement TextDocumentDeclaration
2 parents abbcae8 + d73095c commit 4a6e27d

File tree

8 files changed

+88
-4
lines changed

8 files changed

+88
-4
lines changed

CHANGES.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
- Add keyword completion
66

7+
- Add go to declaration functionality to jump to a value's specification in a
8+
.mli file (#294)
9+
710
## Fixes
811

912
- #245: correctly use mutexes on OpenBSD (#264)

ocaml-lsp-server/src/ocaml_lsp_server.ml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,10 @@ let initialize_info : InitializeResult.t =
4444
]
4545
in
4646
ServerCapabilities.create ~textDocumentSync ~hoverProvider:(`Bool true)
47-
~definitionProvider:(`Bool true) ~typeDefinitionProvider:(`Bool true)
48-
~completionProvider ~codeActionProvider ~codeLensProvider
49-
~referencesProvider:(`Bool true) ~documentHighlightProvider:(`Bool true)
47+
~declarationProvider:(`Bool true) ~definitionProvider:(`Bool true)
48+
~typeDefinitionProvider:(`Bool true) ~completionProvider
49+
~codeActionProvider ~codeLensProvider ~referencesProvider:(`Bool true)
50+
~documentHighlightProvider:(`Bool true)
5051
~documentFormattingProvider:(`Bool true)
5152
~selectionRangeProvider:(`Bool true) ~documentSymbolProvider:(`Bool true)
5253
~foldingRangeProvider:(`Bool true) ~experimental ~renameProvider ()
@@ -550,7 +551,10 @@ let ocaml_on_request :
550551
let open Fiber.O in
551552
let+ symbols = Document_symbol.run client_capabilities doc uri in
552553
Ok (Some symbols, state)
553-
| Client_request.TextDocumentDeclaration _ -> Fiber.return @@ Ok (None, state)
554+
| Client_request.TextDocumentDeclaration { textDocument = { uri }; position }
555+
->
556+
definition_query state uri position (fun pos ->
557+
Query_protocol.Locate (None, `MLI, pos))
554558
| Client_request.TextDocumentDefinition { textDocument = { uri }; position }
555559
->
556560
definition_query state uri position (fun pos ->
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
(library
2+
(name declaration_files))
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
(lang dune 2.5)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
let x = 1
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
val x : int
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
let y = Lib.x
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { promises as fs } from "fs";
2+
import * as path from "path";
3+
import * as child_process from "child_process";
4+
import * as LanguageServer from "./../src/LanguageServer";
5+
import * as Types from "vscode-languageserver-types";
6+
import { testUri, toEqualUri } from "./../src/LanguageServer";
7+
expect.extend({
8+
toEqualUri,
9+
});
10+
declare global {
11+
namespace jest {
12+
interface Matchers<R> {
13+
toEqualUri(uri: string): R;
14+
}
15+
}
16+
}
17+
18+
describe("textDocument/declaration", () => {
19+
let languageServer = null;
20+
21+
let testWorkspacePath = path.join(__dirname, "declaration_files/");
22+
23+
let createPathForFile = (filename: string) =>
24+
path.join(testWorkspacePath, filename);
25+
26+
beforeEach(async () => {
27+
languageServer = await LanguageServer.startAndInitialize();
28+
});
29+
30+
afterEach(async () => {
31+
await LanguageServer.exit(languageServer);
32+
languageServer = null;
33+
});
34+
35+
async function openDocument(filepath) {
36+
let source = await fs.readFile(filepath);
37+
await languageServer.sendNotification("textDocument/didOpen", {
38+
textDocument: Types.TextDocumentItem.create(
39+
testUri(filepath),
40+
"ocaml",
41+
0,
42+
source.toString(),
43+
),
44+
});
45+
}
46+
47+
async function queryDeclaration(filepath, position) {
48+
return await languageServer.sendRequest("textDocument/declaration", {
49+
textDocument: Types.TextDocumentIdentifier.create(testUri(filepath)),
50+
position,
51+
});
52+
}
53+
54+
it("returns location of a declaration", async () => {
55+
child_process.execSync("dune build", { cwd: testWorkspacePath });
56+
57+
await openDocument(createPathForFile("main.ml"));
58+
59+
let result = await queryDeclaration(
60+
createPathForFile("main.ml"),
61+
Types.Position.create(0, 13),
62+
);
63+
64+
expect(result.length).toBe(1);
65+
expect(result[0].range).toMatchObject({
66+
end: { character: 0, line: 0 },
67+
start: { character: 0, line: 0 },
68+
});
69+
expect(result[0].uri).toEqualUri(testUri(createPathForFile("lib.ml")));
70+
});
71+
});

0 commit comments

Comments
 (0)