Implemented function signature help, and added tests (#153)

* Implemented function signature help, and added tests

* Incremental commit of changes from code review feedback

* Rename test

* Added check to make sure intellisense is enabled

* Use HoverTimeout instead of BindingTimeout
This commit is contained in:
Mitchell Sternke
2016-11-30 14:22:48 -08:00
committed by GitHub
parent 453ff9de15
commit c95933b7e1
3 changed files with 339 additions and 8 deletions

View File

@@ -3,6 +3,8 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts;
@@ -255,5 +257,172 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
await testHelper.Disconnect(queryTempFile.FilePath);
}
}
[Fact]
public async Task FunctionSignatureCompletionReturnsEmptySignatureHelpObjectWhenThereAreNoMatches()
{
string sqlText = "EXEC sys.fn_not_a_real_function ";
using (SelfCleaningTempFile tempFile = new SelfCleaningTempFile())
using (TestHelper testHelper = new TestHelper())
{
string ownerUri = tempFile.FilePath;
File.WriteAllText(ownerUri, sqlText);
// Connect
await testHelper.Connect(ownerUri, ConnectionTestUtils.LocalhostConnection);
// Wait for intellisense to be ready
var readyParams = await testHelper.Driver.WaitForEvent(IntelliSenseReadyNotification.Type, 30000);
Assert.NotNull(readyParams);
Assert.Equal(ownerUri, readyParams.OwnerUri);
// Send a function signature help Request
var position = new TextDocumentPosition()
{
TextDocument = new TextDocumentIdentifier()
{
Uri = ownerUri
},
Position = new Position()
{
Line = 0,
Character = sqlText.Length
}
};
var signatureHelp = await testHelper.Driver.SendRequest(SignatureHelpRequest.Type, position);
Assert.NotNull(signatureHelp);
Assert.False(signatureHelp.ActiveSignature.HasValue);
Assert.Null(signatureHelp.Signatures);
await testHelper.Disconnect(ownerUri);
}
}
[Fact]
public async Task FunctionSignatureCompletionReturnsCorrectFunction()
{
string sqlText = "EXEC sys.fn_isrolemember ";
using (SelfCleaningTempFile tempFile = new SelfCleaningTempFile())
using (TestHelper testHelper = new TestHelper())
{
string ownerUri = tempFile.FilePath;
File.WriteAllText(ownerUri, sqlText);
// Connect
await testHelper.Connect(ownerUri, ConnectionTestUtils.LocalhostConnection);
// Wait for intellisense to be ready
var readyParams = await testHelper.Driver.WaitForEvent(IntelliSenseReadyNotification.Type, 30000);
Assert.NotNull(readyParams);
Assert.Equal(ownerUri, readyParams.OwnerUri);
// Send a function signature help Request
var position = new TextDocumentPosition()
{
TextDocument = new TextDocumentIdentifier()
{
Uri = ownerUri
},
Position = new Position()
{
Line = 0,
Character = sqlText.Length
}
};
var signatureHelp = await testHelper.Driver.SendRequest(SignatureHelpRequest.Type, position);
Assert.NotNull(signatureHelp);
Assert.True(signatureHelp.ActiveSignature.HasValue);
Assert.NotEmpty(signatureHelp.Signatures);
var label = signatureHelp.Signatures[signatureHelp.ActiveSignature.Value].Label;
Assert.NotNull(label);
Assert.NotEmpty(label);
Assert.True(label.Contains("fn_isrolemember"));
await testHelper.Disconnect(ownerUri);
}
}
[Fact]
public async Task FunctionSignatureCompletionReturnsCorrectParametersAtEachPosition()
{
string sqlText = "EXEC sys.fn_isrolemember 1, 'testing', 2";
using (SelfCleaningTempFile tempFile = new SelfCleaningTempFile())
using (TestHelper testHelper = new TestHelper())
{
string ownerUri = tempFile.FilePath;
File.WriteAllText(ownerUri, sqlText);
// Connect
await testHelper.Connect(ownerUri, ConnectionTestUtils.LocalhostConnection);
// Wait for intellisense to be ready
var readyParams = await testHelper.Driver.WaitForEvent(IntelliSenseReadyNotification.Type, 30000);
Assert.NotNull(readyParams);
Assert.Equal(ownerUri, readyParams.OwnerUri);
// Verify all parameters when the cursor is inside of parameters and at separator boundaries (,)
await VerifyFunctionSignatureHelpParameter(testHelper, ownerUri, 25, "fn_isrolemember", 0, "@mode int");
await VerifyFunctionSignatureHelpParameter(testHelper, ownerUri, 26, "fn_isrolemember", 0, "@mode int");
await VerifyFunctionSignatureHelpParameter(testHelper, ownerUri, 27, "fn_isrolemember", 1, "@login sysname");
await VerifyFunctionSignatureHelpParameter(testHelper, ownerUri, 30, "fn_isrolemember", 1, "@login sysname");
await VerifyFunctionSignatureHelpParameter(testHelper, ownerUri, 37, "fn_isrolemember", 1, "@login sysname");
await VerifyFunctionSignatureHelpParameter(testHelper, ownerUri, 38, "fn_isrolemember", 2, "@tranpubid int");
await VerifyFunctionSignatureHelpParameter(testHelper, ownerUri, 39, "fn_isrolemember", 2, "@tranpubid int");
await testHelper.Disconnect(ownerUri);
}
}
public async Task VerifyFunctionSignatureHelpParameter(
TestHelper testHelper,
string ownerUri,
int character,
string expectedFunctionName,
int expectedParameterIndex,
string expectedParameterName)
{
var position = new TextDocumentPosition()
{
TextDocument = new TextDocumentIdentifier()
{
Uri = ownerUri
},
Position = new Position()
{
Line = 0,
Character = character
}
};
var signatureHelp = await testHelper.Driver.SendRequest(SignatureHelpRequest.Type, position);
Assert.NotNull(signatureHelp);
Assert.NotNull(signatureHelp.ActiveSignature);
Assert.True(signatureHelp.ActiveSignature.HasValue);
Assert.NotEmpty(signatureHelp.Signatures);
var activeSignature = signatureHelp.Signatures[signatureHelp.ActiveSignature.Value];
Assert.NotNull(activeSignature);
var label = activeSignature.Label;
Assert.NotNull(label);
Assert.NotEmpty(label);
Assert.True(label.Contains(expectedFunctionName));
Assert.NotNull(signatureHelp.ActiveParameter);
Assert.True(signatureHelp.ActiveParameter.HasValue);
Assert.Equal(expectedParameterIndex, signatureHelp.ActiveParameter.Value);
var parameter = activeSignature.Parameters[signatureHelp.ActiveParameter.Value];
Assert.NotNull(parameter);
Assert.NotNull(parameter.Label);
Assert.NotEmpty(parameter.Label);
Assert.Equal(expectedParameterName, parameter.Label);
}
}
}