mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-14 01:25:40 -05:00
Fixed null ref exception in GetSignatureHelp (#175)
- Fixed a few places where ScriptParseInfo was being used before it was verified to be non-null - Added 1 basic test for GetSignatureHelp scenario
This commit is contained in:
committed by
Kevin Cunnane
parent
431dfa4156
commit
40c1434745
@@ -847,6 +847,12 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
|
||||
ScriptParseInfo scriptParseInfo = GetScriptParseInfo(textDocumentPosition.TextDocument.Uri);
|
||||
|
||||
if (scriptParseInfo == null)
|
||||
{
|
||||
// Cache not set up yet - skip and wait until later
|
||||
return null;
|
||||
}
|
||||
|
||||
ConnectionInfo connInfo;
|
||||
LanguageService.ConnectionServiceInstance.TryFindConnection(
|
||||
scriptFile.ClientFilePath,
|
||||
@@ -858,7 +864,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
ParseAndBind(scriptFile, connInfo);
|
||||
}
|
||||
|
||||
if (scriptParseInfo != null && scriptParseInfo.ParseResult != null)
|
||||
if (scriptParseInfo.ParseResult != null)
|
||||
{
|
||||
if (Monitor.TryEnter(scriptParseInfo.BuildingMetadataLock))
|
||||
{
|
||||
@@ -928,13 +934,14 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
|
||||
// get the current script parse info object
|
||||
ScriptParseInfo scriptParseInfo = GetScriptParseInfo(textDocumentPosition.TextDocument.Uri);
|
||||
ScriptDocumentInfo scriptDocumentInfo = new ScriptDocumentInfo(textDocumentPosition, scriptFile, scriptParseInfo);
|
||||
|
||||
|
||||
if (scriptParseInfo == null)
|
||||
{
|
||||
return AutoCompleteHelper.GetDefaultCompletionItems(scriptDocumentInfo, useLowerCaseSuggestions);
|
||||
return AutoCompleteHelper.GetDefaultCompletionItems(ScriptDocumentInfo.CreateDefaultDocumentInfo(textDocumentPosition, scriptFile), useLowerCaseSuggestions);
|
||||
}
|
||||
|
||||
ScriptDocumentInfo scriptDocumentInfo = new ScriptDocumentInfo(textDocumentPosition, scriptFile, scriptParseInfo);
|
||||
|
||||
// reparse and bind the SQL statement if needed
|
||||
if (RequiresReparse(scriptParseInfo, scriptFile))
|
||||
{
|
||||
|
||||
@@ -18,6 +18,16 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices.Completion
|
||||
/// Create new instance
|
||||
/// </summary>
|
||||
public ScriptDocumentInfo(TextDocumentPosition textDocumentPosition, ScriptFile scriptFile, ScriptParseInfo scriptParseInfo)
|
||||
: this(textDocumentPosition, scriptFile)
|
||||
{
|
||||
Validate.IsNotNull(nameof(scriptParseInfo), scriptParseInfo);
|
||||
|
||||
ScriptParseInfo = scriptParseInfo;
|
||||
// need to adjust line & column for base-1 parser indices
|
||||
Token = GetToken(scriptParseInfo, ParserLine, ParserColumn);
|
||||
}
|
||||
|
||||
private ScriptDocumentInfo(TextDocumentPosition textDocumentPosition, ScriptFile scriptFile)
|
||||
{
|
||||
StartLine = textDocumentPosition.Position.Line;
|
||||
ParserLine = textDocumentPosition.Position.Line + 1;
|
||||
@@ -30,11 +40,18 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices.Completion
|
||||
textDocumentPosition.Position.Line,
|
||||
textDocumentPosition.Position.Character);
|
||||
ParserColumn = textDocumentPosition.Position.Character + 1;
|
||||
ScriptParseInfo = scriptParseInfo;
|
||||
Contents = scriptFile.Contents;
|
||||
}
|
||||
|
||||
// need to adjust line & column for base-1 parser indices
|
||||
Token = GetToken(scriptParseInfo, ParserLine, ParserColumn);
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="ScriptDocumentInfo"/> with no backing <see cref="ScriptParseInfo"/> defined
|
||||
/// </summary>
|
||||
/// <param name="textDocumentPosition">A <see cref="TextDocumentPosition"/></param>
|
||||
/// <param name="scriptFile">A <see cref="ScriptFile"/> to process</param>
|
||||
/// <returns></returns>
|
||||
public static ScriptDocumentInfo CreateDefaultDocumentInfo(TextDocumentPosition textDocumentPosition, ScriptFile scriptFile)
|
||||
{
|
||||
return new ScriptDocumentInfo(textDocumentPosition, scriptFile);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
using Microsoft.SqlTools.ServiceLayer.Connection;
|
||||
using Microsoft.SqlTools.ServiceLayer.LanguageServices;
|
||||
using Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts;
|
||||
using Microsoft.SqlTools.Test.Utility;
|
||||
using Xunit;
|
||||
@@ -125,6 +126,36 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServer
|
||||
Assert.Equal(10, fileMarkers[1].ScriptRegion.EndColumnNumber);
|
||||
Assert.Equal(3, fileMarkers[1].ScriptRegion.EndLineNumber);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetSignatureHelpReturnsNullIfParseInfoNotInitialized()
|
||||
{
|
||||
// Given service doesn't have parseinfo intialized for a document
|
||||
const string docContent = "SELECT * FROM sys.objects";
|
||||
LanguageService service = TestObjects.GetTestLanguageService();
|
||||
var scriptFile = new ScriptFile();
|
||||
scriptFile.SetFileContents(docContent);
|
||||
|
||||
// When requesting SignatureHelp
|
||||
SignatureHelp signatureHelp = service.GetSignatureHelp(CreateDummyDocPosition(), scriptFile);
|
||||
|
||||
// Then null is returned as no parse info can be used to find the signature
|
||||
Assert.Null(signatureHelp);
|
||||
}
|
||||
|
||||
private TextDocumentPosition CreateDummyDocPosition()
|
||||
{
|
||||
return new TextDocumentPosition
|
||||
{
|
||||
TextDocument = new TextDocumentIdentifier { Uri = TestObjects.ScriptUri },
|
||||
Position = new Position
|
||||
{
|
||||
Line = 0,
|
||||
Character = 0
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
Reference in New Issue
Block a user