Skip to content

Commit e3d108f

Browse files
committed
Added Definition support to TextDocumentClient.
1 parent 3dd94c7 commit e3d108f

File tree

2 files changed

+124
-0
lines changed

2 files changed

+124
-0
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
using System;
2+
using System.Threading;
3+
using System.Threading.Tasks;
4+
using OmniSharp.Extensions.LanguageServer.Client.Utilities;
5+
using OmniSharp.Extensions.LanguageServer.Protocol;
6+
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
7+
8+
namespace OmniSharp.Extensions.LanguageServer.Client.Clients
9+
{
10+
/// <summary>
11+
/// Client for the LSP Text Document API.
12+
/// </summary>
13+
public partial class TextDocumentClient
14+
{
15+
/// <summary>
16+
/// Request definition at the specified document position.
17+
/// </summary>
18+
/// <param name="filePath">
19+
/// The full file-system path of the text document.
20+
/// </param>
21+
/// <param name="line">
22+
/// The target line (0-based).
23+
/// </param>
24+
/// <param name="column">
25+
/// The target column (0-based).
26+
/// </param>
27+
/// <param name="cancellationToken">
28+
/// An optional <see cref="CancellationToken"/> that can be used to cancel the request.
29+
/// </param>
30+
/// <returns>
31+
/// A <see cref="Task{TResult}"/> that resolves to the completions or <c>null</c> if no completions are available at the specified position.
32+
/// </returns>
33+
public Task<LocationOrLocationLinks> Definition(string filePath, int line, int column, CancellationToken cancellationToken = default(CancellationToken))
34+
{
35+
if (string.IsNullOrWhiteSpace(filePath))
36+
throw new ArgumentException($"Argument cannot be null, empty, or entirely composed of whitespace: {nameof(filePath)}.", nameof(filePath));
37+
38+
var documentUri = DocumentUri.FromFileSystemPath(filePath);
39+
40+
return Definition(documentUri, line, column, cancellationToken);
41+
}
42+
43+
/// <summary>
44+
/// Request definition at the specified document position.
45+
/// </summary>
46+
/// <param name="documentUri">
47+
/// The document URI.
48+
/// </param>
49+
/// <param name="line">
50+
/// The target line (0-based).
51+
/// </param>
52+
/// <param name="column">
53+
/// The target column (0-based).
54+
/// </param>
55+
/// <param name="cancellationToken">
56+
/// An optional <see cref="CancellationToken"/> that can be used to cancel the request.
57+
/// </param>
58+
/// <returns>
59+
/// A <see cref="Task{TResult}"/> that resolves to the completions or <c>null</c> if no completions are available at the specified position.
60+
/// </returns>
61+
public Task<LocationOrLocationLinks> Definition(Uri documentUri, int line, int column, CancellationToken cancellationToken = default(CancellationToken))
62+
{
63+
return PositionalRequest<LocationOrLocationLinks>(DocumentNames.Definition, documentUri, line, column, cancellationToken);
64+
}
65+
}
66+
}

test/Client.Tests/ClientTests.cs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,64 @@ public async Task SignatureHelp_Success()
258258
});
259259
}
260260

261+
/// <summary>
262+
/// Ensure that the language client can successfully request Definition.
263+
/// </summary>
264+
[Fact(DisplayName = "Language client can successfully request definition", Skip = "Periodic failures")]
265+
public async Task Definition_Success()
266+
{
267+
await Connect();
268+
269+
const int line = 5;
270+
const int column = 5;
271+
var expectedDocumentPath = AbsoluteDocumentPath;
272+
var expectedDocumentUri = DocumentUri.FromFileSystemPath(expectedDocumentPath);
273+
274+
var expectedDefinitions = new LocationOrLocationLinks(
275+
new LocationOrLocationLink(new Location {
276+
Uri = expectedDocumentUri,
277+
Range = new Range {
278+
Start = new Position {
279+
Line = line,
280+
Character = column
281+
},
282+
End = new Position {
283+
Line = line,
284+
Character = column
285+
}
286+
},
287+
}));
288+
289+
ServerDispatcher.HandleRequest<TextDocumentPositionParams, LocationOrLocationLinks>(DocumentNames.Definition, (request, cancellationToken) => {
290+
Assert.NotNull(request.TextDocument);
291+
292+
Assert.Equal(expectedDocumentUri, request.TextDocument.Uri);
293+
294+
Assert.Equal(line, request.Position.Line);
295+
Assert.Equal(column, request.Position.Character);
296+
297+
return Task.FromResult(expectedDefinitions);
298+
});
299+
300+
var definitions = await LanguageClient.TextDocument.Definition(AbsoluteDocumentPath, line, column);
301+
302+
var actualDefinitions = definitions.ToArray();
303+
Assert.Collection(actualDefinitions, actualDefinition => {
304+
var expectedDefinition = expectedDefinitions.First();
305+
306+
Assert.NotNull(actualDefinition.Location);
307+
Assert.Equal(expectedDefinition.Location.Uri, actualDefinition.Location.Uri);
308+
309+
Assert.NotNull(actualDefinition.Location.Range);
310+
Assert.NotNull(actualDefinition.Location.Range.Start);
311+
Assert.NotNull(actualDefinition.Location.Range.End);
312+
Assert.Equal(expectedDefinition.Location.Range.Start.Line, actualDefinition.Location.Range.Start.Line);
313+
Assert.Equal(expectedDefinition.Location.Range.Start.Character, actualDefinition.Location.Range.Start.Character);
314+
Assert.Equal(expectedDefinition.Location.Range.End.Line, actualDefinition.Location.Range.End.Line);
315+
Assert.Equal(expectedDefinition.Location.Range.End.Character, actualDefinition.Location.Range.End.Character);
316+
});
317+
}
318+
261319
/// <summary>
262320
/// Ensure that the language client can successfully receive Diagnostics from the server.
263321
/// </summary>

0 commit comments

Comments
 (0)