diff --git a/src/Client/Clients/TextDocumentClient.Definition.cs b/src/Client/Clients/TextDocumentClient.Definition.cs
new file mode 100644
index 000000000..d113763d3
--- /dev/null
+++ b/src/Client/Clients/TextDocumentClient.Definition.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using OmniSharp.Extensions.LanguageServer.Client.Utilities;
+using OmniSharp.Extensions.LanguageServer.Protocol;
+using OmniSharp.Extensions.LanguageServer.Protocol.Models;
+
+namespace OmniSharp.Extensions.LanguageServer.Client.Clients
+{
+ ///
+ /// Client for the LSP Text Document API.
+ ///
+ public partial class TextDocumentClient
+ {
+ ///
+ /// Request definition at the specified document position.
+ ///
+ ///
+ /// The full file-system path of the text document.
+ ///
+ ///
+ /// The target line (0-based).
+ ///
+ ///
+ /// The target column (0-based).
+ ///
+ ///
+ /// An optional that can be used to cancel the request.
+ ///
+ ///
+ /// A that resolves to the completions or null if no definitions are available at the specified position.
+ ///
+ public Task Definition(string filePath, int line, int column, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ if (string.IsNullOrWhiteSpace(filePath))
+ throw new ArgumentException($"Argument cannot be null, empty, or entirely composed of whitespace: {nameof(filePath)}.", nameof(filePath));
+
+ var documentUri = DocumentUri.FromFileSystemPath(filePath);
+
+ return Definition(documentUri, line, column, cancellationToken);
+ }
+
+ ///
+ /// Request definition at the specified document position.
+ ///
+ ///
+ /// The document URI.
+ ///
+ ///
+ /// The target line (0-based).
+ ///
+ ///
+ /// The target column (0-based).
+ ///
+ ///
+ /// An optional that can be used to cancel the request.
+ ///
+ ///
+ /// A that resolves to the completions or null if no definitions are available at the specified position.
+ ///
+ public Task Definition(Uri documentUri, int line, int column, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return PositionalRequest(DocumentNames.Definition, documentUri, line, column, cancellationToken);
+ }
+ }
+}
diff --git a/src/Client/Clients/TextDocumentClient.DocumentHighlights.cs b/src/Client/Clients/TextDocumentClient.DocumentHighlights.cs
new file mode 100644
index 000000000..0b2ff9b45
--- /dev/null
+++ b/src/Client/Clients/TextDocumentClient.DocumentHighlights.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using OmniSharp.Extensions.LanguageServer.Client.Utilities;
+using OmniSharp.Extensions.LanguageServer.Protocol;
+using OmniSharp.Extensions.LanguageServer.Protocol.Models;
+
+namespace OmniSharp.Extensions.LanguageServer.Client.Clients
+{
+ ///
+ /// Client for the LSP Text Document API.
+ ///
+ public partial class TextDocumentClient
+ {
+ ///
+ /// Request document highlights at the specified document position.
+ ///
+ ///
+ /// The full file-system path of the text document.
+ ///
+ ///
+ /// The target line (0-based).
+ ///
+ ///
+ /// The target column (0-based).
+ ///
+ ///
+ /// An optional that can be used to cancel the request.
+ ///
+ ///
+ /// A that resolves to the completions or null if no document highlights are available at the specified position.
+ ///
+ public Task DocumentHighlights(string filePath, int line, int column, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ if (string.IsNullOrWhiteSpace(filePath))
+ throw new ArgumentException($"Argument cannot be null, empty, or entirely composed of whitespace: {nameof(filePath)}.", nameof(filePath));
+
+ var documentUri = DocumentUri.FromFileSystemPath(filePath);
+
+ return DocumentHighlights(documentUri, line, column, cancellationToken);
+ }
+
+ ///
+ /// Request document highlights at the specified document position.
+ ///
+ ///
+ /// The document URI.
+ ///
+ ///
+ /// The target line (0-based).
+ ///
+ ///
+ /// The target column (0-based).
+ ///
+ ///
+ /// An optional that can be used to cancel the request.
+ ///
+ ///
+ /// A that resolves to the completions or null if no document highlights are available at the specified position.
+ ///
+ public Task DocumentHighlights(Uri documentUri, int line, int column, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return PositionalRequest(DocumentNames.DocumentHighlight, documentUri, line, column, cancellationToken);
+ }
+ }
+}
diff --git a/src/Client/Clients/TextDocumentClient.FoldingRanges.cs b/src/Client/Clients/TextDocumentClient.FoldingRanges.cs
new file mode 100644
index 000000000..01433477c
--- /dev/null
+++ b/src/Client/Clients/TextDocumentClient.FoldingRanges.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using OmniSharp.Extensions.LanguageServer.Client.Utilities;
+using OmniSharp.Extensions.LanguageServer.Protocol;
+using OmniSharp.Extensions.LanguageServer.Protocol.Models;
+
+namespace OmniSharp.Extensions.LanguageServer.Client.Clients
+{
+ ///
+ /// Client for the LSP Text Document API.
+ ///
+ public partial class TextDocumentClient
+ {
+ ///
+ /// Request document folding ranges.
+ ///
+ ///
+ /// The full file-system path of the text document.
+ ///
+ ///
+ /// An optional that can be used to cancel the request.
+ ///
+ ///
+ /// A that resolves to the completions or null if no document highlights are available at the specified position.
+ ///
+ public Task> FoldingRanges(string filePath, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ if (string.IsNullOrWhiteSpace(filePath))
+ throw new ArgumentException($"Argument cannot be null, empty, or entirely composed of whitespace: {nameof(filePath)}.", nameof(filePath));
+
+ var documentUri = DocumentUri.FromFileSystemPath(filePath);
+
+ return FoldingRanges(documentUri, cancellationToken);
+ }
+
+ ///
+ /// Request document highlights at the specified document position.
+ ///
+ ///
+ /// The document URI.
+ ///
+ ///
+ /// The target line (0-based).
+ ///
+ ///
+ /// The target column (0-based).
+ ///
+ ///
+ /// An optional that can be used to cancel the request.
+ ///
+ ///
+ /// A that resolves to the completions or null if no document highlights are available at the specified position.
+ ///
+ public async Task> FoldingRanges(Uri documentUri, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ var request = new FoldingRangeRequestParam {
+ TextDocument = new TextDocumentItem {
+ Uri = documentUri
+ }
+ };
+
+ return await Client.SendRequest>(DocumentNames.FoldingRange, request, cancellationToken).ConfigureAwait(false);
+ }
+ }
+}
diff --git a/test/Client.Tests/ClientTests.cs b/test/Client.Tests/ClientTests.cs
index d14ea297d..4f2eb6afd 100644
--- a/test/Client.Tests/ClientTests.cs
+++ b/test/Client.Tests/ClientTests.cs
@@ -258,6 +258,162 @@ public async Task SignatureHelp_Success()
});
}
+ ///
+ /// Ensure that the language client can successfully request Definition.
+ ///
+ [Fact(DisplayName = "Language client can successfully request definition", Skip = "Periodic failures")]
+ public async Task Definition_Success()
+ {
+ await Connect();
+
+ const int line = 5;
+ const int column = 5;
+ var expectedDocumentPath = AbsoluteDocumentPath;
+ var expectedDocumentUri = DocumentUri.FromFileSystemPath(expectedDocumentPath);
+
+ var expectedDefinitions = new LocationOrLocationLinks(
+ new LocationOrLocationLink(new Location {
+ Uri = expectedDocumentUri,
+ Range = new Range {
+ Start = new Position {
+ Line = line,
+ Character = column
+ },
+ End = new Position {
+ Line = line,
+ Character = column
+ }
+ },
+ }));
+
+ ServerDispatcher.HandleRequest(DocumentNames.Definition, (request, cancellationToken) => {
+ Assert.NotNull(request.TextDocument);
+
+ Assert.Equal(expectedDocumentUri, request.TextDocument.Uri);
+
+ Assert.Equal(line, request.Position.Line);
+ Assert.Equal(column, request.Position.Character);
+
+ return Task.FromResult(expectedDefinitions);
+ });
+
+ var definitions = await LanguageClient.TextDocument.Definition(AbsoluteDocumentPath, line, column);
+
+ var actualDefinitions = definitions.ToArray();
+ Assert.Collection(actualDefinitions, actualDefinition => {
+ var expectedDefinition = expectedDefinitions.Single();
+
+ Assert.NotNull(actualDefinition.Location);
+ Assert.Equal(expectedDefinition.Location.Uri, actualDefinition.Location.Uri);
+
+ Assert.NotNull(actualDefinition.Location.Range);
+ Assert.NotNull(actualDefinition.Location.Range.Start);
+ Assert.NotNull(actualDefinition.Location.Range.End);
+ Assert.Equal(expectedDefinition.Location.Range.Start.Line, actualDefinition.Location.Range.Start.Line);
+ Assert.Equal(expectedDefinition.Location.Range.Start.Character, actualDefinition.Location.Range.Start.Character);
+ Assert.Equal(expectedDefinition.Location.Range.End.Line, actualDefinition.Location.Range.End.Line);
+ Assert.Equal(expectedDefinition.Location.Range.End.Character, actualDefinition.Location.Range.End.Character);
+ });
+ }
+
+ ///
+ /// Ensure that the language client can successfully request DocumentHighlight.
+ ///
+ [Fact(DisplayName = "Language client can successfully request document highlights", Skip = "Periodic failures")]
+ public async Task DocumentHighlights_Success()
+ {
+ await Connect();
+
+ const int line = 5;
+ const int column = 5;
+ var expectedDocumentPath = AbsoluteDocumentPath;
+ var expectedDocumentUri = DocumentUri.FromFileSystemPath(expectedDocumentPath);
+
+ var expectedHighlights = new DocumentHighlightContainer(
+ new DocumentHighlight {
+ Kind = DocumentHighlightKind.Write,
+ Range = new Range {
+ Start = new Position {
+ Line = line,
+ Character = column
+ },
+ End = new Position {
+ Line = line,
+ Character = column
+ }
+ },
+ });
+
+ ServerDispatcher.HandleRequest(DocumentNames.DocumentHighlight, (request, cancellationToken) => {
+ Assert.NotNull(request.TextDocument);
+
+ Assert.Equal(expectedDocumentUri, request.TextDocument.Uri);
+
+ Assert.Equal(line, request.Position.Line);
+ Assert.Equal(column, request.Position.Character);
+
+ return Task.FromResult(expectedHighlights);
+ });
+
+ var definitions = await LanguageClient.TextDocument.DocumentHighlights(AbsoluteDocumentPath, line, column);
+
+ var actualDefinitions = definitions.ToArray();
+ Assert.Collection(actualDefinitions, actualHighlight => {
+ var expectedHighlight = expectedHighlights.Single();
+
+ Assert.Equal(DocumentHighlightKind.Write, expectedHighlight.Kind);
+
+ Assert.NotNull(actualHighlight.Range);
+ Assert.NotNull(actualHighlight.Range.Start);
+ Assert.NotNull(actualHighlight.Range.End);
+ Assert.Equal(expectedHighlight.Range.Start.Line, actualHighlight.Range.Start.Line);
+ Assert.Equal(expectedHighlight.Range.Start.Character, actualHighlight.Range.Start.Character);
+ Assert.Equal(expectedHighlight.Range.End.Line, actualHighlight.Range.End.Line);
+ Assert.Equal(expectedHighlight.Range.End.Character, actualHighlight.Range.End.Character);
+ });
+ }
+
+ ///
+ /// Ensure that the language client can successfully request FoldingRanges.
+ ///
+ [Fact(DisplayName = "Language client can successfully request document folding ranges", Skip = "Periodic failures")]
+ public async Task FoldingRanges_Success()
+ {
+ await Connect();
+
+ var expectedDocumentPath = AbsoluteDocumentPath;
+ var expectedDocumentUri = DocumentUri.FromFileSystemPath(expectedDocumentPath);
+
+ var expectedFoldingRanges = new Container(
+ new FoldingRange {
+ Kind = FoldingRangeKind.Region,
+ StartLine = 5,
+ StartCharacter = 1,
+ EndLine = 7,
+ EndCharacter = 2,
+ });
+
+ ServerDispatcher.HandleRequest>(DocumentNames.FoldingRange, (request, cancellationToken) => {
+ Assert.NotNull(request.TextDocument);
+ Assert.Equal(expectedDocumentUri, request.TextDocument.Uri);
+ return Task.FromResult(expectedFoldingRanges);
+ });
+
+ var foldingRanges = await LanguageClient.TextDocument.FoldingRanges(AbsoluteDocumentPath);
+
+ var actualFoldingRanges = foldingRanges.ToArray();
+ Assert.Collection(actualFoldingRanges, actualFoldingRange => {
+ var expectedFoldingRange = expectedFoldingRanges.Single();
+
+ Assert.Equal(FoldingRangeKind.Region, expectedFoldingRange.Kind);
+
+ Assert.Equal(expectedFoldingRange.StartLine, actualFoldingRange.StartLine);
+ Assert.Equal(expectedFoldingRange.StartCharacter, actualFoldingRange.StartCharacter);
+ Assert.Equal(expectedFoldingRange.EndLine, actualFoldingRange.EndLine);
+ Assert.Equal(expectedFoldingRange.EndCharacter, actualFoldingRange.EndCharacter);
+ });
+ }
+
///
/// Ensure that the language client can successfully receive Diagnostics from the server.
///