diff --git a/src/Client/Clients/TextDocumentClient.SignatureHelp.cs b/src/Client/Clients/TextDocumentClient.SignatureHelp.cs new file mode 100644 index 000000000..cc799b237 --- /dev/null +++ b/src/Client/Clients/TextDocumentClient.SignatureHelp.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 signature help 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 completions are available at the specified position. + /// + public Task SignatureHelp(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 SignatureHelp(documentUri, line, column, cancellationToken); + } + + /// + /// Request signature help 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 completions are available at the specified position. + /// + public Task SignatureHelp(Uri documentUri, int line, int column, CancellationToken cancellationToken = default(CancellationToken)) + { + return PositionalRequest(DocumentNames.SignatureHelp, documentUri, line, column, cancellationToken); + } + } +} diff --git a/test/Client.Tests/ClientTests.cs b/test/Client.Tests/ClientTests.cs index 0f827d616..d14ea297d 100644 --- a/test/Client.Tests/ClientTests.cs +++ b/test/Client.Tests/ClientTests.cs @@ -191,6 +191,73 @@ public async Task Completions_Success() }); } + /// + /// Ensure that the language client can successfully request SignatureHelp. + /// + [Fact(DisplayName = "Language client can successfully request signature help", Skip = "Periodic failures")] + public async Task SignatureHelp_Success() + { + await Connect(); + + const int line = 5; + const int column = 5; + var expectedDocumentPath = AbsoluteDocumentPath; + var expectedDocumentUri = DocumentUri.FromFileSystemPath(expectedDocumentPath); + + var expectedSignatureHelp = new SignatureHelp { + ActiveParameter = 0, + ActiveSignature = 0, + Signatures = new[] { + new SignatureInformation { + Documentation = new StringOrMarkupContent("test documentation"), + Label = "TestSignature", + Parameters = new[] { + new ParameterInformation { + Documentation = "test parameter documentation", + Label = "parameter label" + } + } + } + } + }; + + ServerDispatcher.HandleRequest(DocumentNames.SignatureHelp, (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(expectedSignatureHelp); + }); + + var actualSignatureHelp = await LanguageClient.TextDocument.SignatureHelp(AbsoluteDocumentPath, line, column); + + Assert.Equal(expectedSignatureHelp.ActiveParameter, actualSignatureHelp.ActiveParameter); + Assert.Equal(expectedSignatureHelp.ActiveSignature, actualSignatureHelp.ActiveSignature); + + var actualSignatures = actualSignatureHelp.Signatures.ToArray(); + Assert.Collection(actualSignatures, actualSignature => { + var expectedSignature = expectedSignatureHelp.Signatures.ToArray()[0]; + + Assert.True(actualSignature.Documentation.HasString); + Assert.Equal(expectedSignature.Documentation.String, actualSignature.Documentation.String); + + Assert.Equal(expectedSignature.Label, actualSignature.Label); + + var expectedParameters = expectedSignature.Parameters.ToArray(); + var actualParameters = actualSignature.Parameters.ToArray(); + + Assert.Collection(actualParameters, actualParameter => { + var expectedParameter = expectedParameters[0]; + Assert.True(actualParameter.Documentation.HasString); + Assert.Equal(expectedParameter.Documentation.String, actualParameter.Documentation.String); + Assert.Equal(expectedParameter.Label, actualParameter.Label); + }); + }); + } + /// /// Ensure that the language client can successfully receive Diagnostics from the server. ///