mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-25 09:35:37 -05:00
fixed peek definition tokenizing (#281)
* fixed peek definition tokenizing * fixed signature help test * added new heuristic for PeekDefinition behaviour * added tests for new heuristic * fixed code according to Kevin's CR * fixed failing test due to shared connection * changed uri for procedure test
This commit is contained in:
@@ -774,6 +774,100 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
return completionItem;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Queue a task to the binding queue
|
||||
/// </summary>
|
||||
/// <param name="textDocumentPosition"></param>
|
||||
/// <param name="scriptParseInfo"></param>
|
||||
/// <param name="connectionInfo"></param>
|
||||
/// <param name="scriptFile"></param>
|
||||
/// <param name="tokenText"></param>
|
||||
/// <returns> Returns the result of the task as a DefinitionResult </returns>
|
||||
private DefinitionResult QueueTask(TextDocumentPosition textDocumentPosition, ScriptParseInfo scriptParseInfo,
|
||||
ConnectionInfo connInfo, ScriptFile scriptFile, string tokenText)
|
||||
{
|
||||
// Queue the task with the binding queue
|
||||
QueueItem queueItem = this.BindingQueue.QueueBindingOperation(
|
||||
key: scriptParseInfo.ConnectionKey,
|
||||
bindingTimeout: LanguageService.PeekDefinitionTimeout,
|
||||
bindOperation: (bindingContext, cancelToken) =>
|
||||
{
|
||||
string schemaName = this.GetSchemaName(scriptParseInfo, textDocumentPosition.Position, scriptFile);
|
||||
// Script object using SMO
|
||||
Scripter scripter = new Scripter(bindingContext.ServerConnection, connInfo);
|
||||
return scripter.GetScript(
|
||||
scriptParseInfo.ParseResult,
|
||||
textDocumentPosition.Position,
|
||||
bindingContext.MetadataDisplayInfoProvider,
|
||||
tokenText,
|
||||
schemaName);
|
||||
},
|
||||
timeoutOperation: (bindingContext) =>
|
||||
{
|
||||
// return error result
|
||||
return new DefinitionResult
|
||||
{
|
||||
IsErrorResult = true,
|
||||
Message = SR.PeekDefinitionTimedoutError,
|
||||
Locations = null
|
||||
};
|
||||
});
|
||||
|
||||
// wait for the queue item
|
||||
queueItem.ItemProcessed.WaitOne();
|
||||
var result = queueItem.GetResultAsT<DefinitionResult>();
|
||||
return result;
|
||||
}
|
||||
|
||||
private DefinitionResult GetDefinitionFromTokenList(TextDocumentPosition textDocumentPosition, List<Token> tokenList,
|
||||
ScriptParseInfo scriptParseInfo, ScriptFile scriptFile, ConnectionInfo connInfo)
|
||||
{
|
||||
|
||||
DefinitionResult lastResult = null;
|
||||
foreach (var token in tokenList)
|
||||
{
|
||||
|
||||
// Strip "[" and "]"(if present) from the token text to enable matching with the suggestions.
|
||||
// The suggestion title does not contain any sql punctuation
|
||||
string tokenText = TextUtilities.RemoveSquareBracketSyntax(token.Text);
|
||||
textDocumentPosition.Position.Line = token.StartLocation.LineNumber;
|
||||
textDocumentPosition.Position.Character = token.StartLocation.ColumnNumber;
|
||||
if (Monitor.TryEnter(scriptParseInfo.BuildingMetadataLock))
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = QueueTask(textDocumentPosition, scriptParseInfo, connInfo, scriptFile, tokenText);
|
||||
lastResult = result;
|
||||
if (!result.IsErrorResult)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// if any exceptions are raised return error result with message
|
||||
Logger.Write(LogLevel.Error, "Exception in GetDefinition " + ex.ToString());
|
||||
return new DefinitionResult
|
||||
{
|
||||
IsErrorResult = true,
|
||||
Message = SR.PeekDefinitionError(ex.Message),
|
||||
Locations = null
|
||||
};
|
||||
}
|
||||
finally
|
||||
{
|
||||
Monitor.Exit(scriptParseInfo.BuildingMetadataLock);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Write(LogLevel.Error, "Timeout waiting to query metadata from server");
|
||||
}
|
||||
}
|
||||
return (lastResult != null) ? lastResult : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get definition for a selected sql object using SMO Scripting
|
||||
/// </summary>
|
||||
@@ -796,76 +890,63 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
}
|
||||
|
||||
// Get token from selected text
|
||||
Token selectedToken = ScriptDocumentInfo.GetToken(scriptParseInfo, textDocumentPosition.Position.Line + 1, textDocumentPosition.Position.Character);
|
||||
Tuple<Stack<Token>, Queue<Token>> selectedToken = ScriptDocumentInfo.GetPeekDefinitionTokens(scriptParseInfo,
|
||||
textDocumentPosition.Position.Line + 1, textDocumentPosition.Position.Character + 1);
|
||||
|
||||
if (selectedToken == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
// Strip "[" and "]"(if present) from the token text to enable matching with the suggestions.
|
||||
// The suggestion title does not contain any sql punctuation
|
||||
string tokenText = TextUtilities.RemoveSquareBracketSyntax(selectedToken.Text);
|
||||
|
||||
if (scriptParseInfo.IsConnected && Monitor.TryEnter(scriptParseInfo.BuildingMetadataLock))
|
||||
{
|
||||
try
|
||||
{
|
||||
// Queue the task with the binding queue
|
||||
QueueItem queueItem = this.BindingQueue.QueueBindingOperation(
|
||||
key: scriptParseInfo.ConnectionKey,
|
||||
bindingTimeout: LanguageService.PeekDefinitionTimeout,
|
||||
bindOperation: (bindingContext, cancelToken) =>
|
||||
{
|
||||
string schemaName = this.GetSchemaName(scriptParseInfo, textDocumentPosition.Position, scriptFile);
|
||||
// Script object using SMO
|
||||
Scripter scripter = new Scripter(bindingContext.ServerConnection, connInfo);
|
||||
return scripter.GetScript(
|
||||
scriptParseInfo.ParseResult,
|
||||
textDocumentPosition.Position,
|
||||
bindingContext.MetadataDisplayInfoProvider,
|
||||
tokenText,
|
||||
schemaName);
|
||||
},
|
||||
timeoutOperation: (bindingContext) =>
|
||||
{
|
||||
// return error result
|
||||
return new DefinitionResult
|
||||
{
|
||||
IsErrorResult = true,
|
||||
Message = SR.PeekDefinitionTimedoutError,
|
||||
Locations = null
|
||||
};
|
||||
});
|
||||
|
||||
// wait for the queue item
|
||||
queueItem.ItemProcessed.WaitOne();
|
||||
return queueItem.GetResultAsT<DefinitionResult>();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// if any exceptions are raised return error result with message
|
||||
Logger.Write(LogLevel.Error, "Exception in GetDefinition " + ex.ToString());
|
||||
return new DefinitionResult
|
||||
{
|
||||
IsErrorResult = true,
|
||||
Message = SR.PeekDefinitionError(ex.Message),
|
||||
Locations = null
|
||||
};
|
||||
}
|
||||
finally
|
||||
{
|
||||
Monitor.Exit(scriptParseInfo.BuildingMetadataLock);
|
||||
}
|
||||
if (scriptParseInfo.IsConnected)
|
||||
{
|
||||
//try children tokens first
|
||||
Stack<Token> childrenTokens = selectedToken.Item1;
|
||||
List<Token> tokenList = childrenTokens.ToList();
|
||||
DefinitionResult childrenResult = GetDefinitionFromTokenList(textDocumentPosition, tokenList, scriptParseInfo, scriptFile, connInfo);
|
||||
|
||||
// if the children peak definition returned null then
|
||||
// try the parents
|
||||
if (childrenResult == null || childrenResult.IsErrorResult)
|
||||
{
|
||||
Queue<Token> parentTokens = selectedToken.Item2;
|
||||
tokenList = parentTokens.ToList();
|
||||
DefinitionResult parentResult = GetDefinitionFromTokenList(textDocumentPosition, tokenList, scriptParseInfo, scriptFile, connInfo);
|
||||
return (parentResult == null) ? null : parentResult;
|
||||
}
|
||||
else
|
||||
{
|
||||
return childrenResult;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// User is not connected.
|
||||
return new DefinitionResult
|
||||
{
|
||||
IsErrorResult = true,
|
||||
Message = SR.PeekDefinitionNotConnectedError,
|
||||
Locations = null
|
||||
};
|
||||
}
|
||||
else
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrapper around find token method
|
||||
/// </summary>
|
||||
/// <param name="scriptParseInfo"></param>
|
||||
/// <param name="startLine"></param>
|
||||
/// <param name="startColumn"></param>
|
||||
/// <returns> token index</returns>
|
||||
private int FindTokenWithCorrectOffset(ScriptParseInfo scriptParseInfo, int startLine, int startColumn)
|
||||
{
|
||||
var tokenIndex = scriptParseInfo.ParseResult.Script.TokenManager.FindToken(startLine, startColumn);
|
||||
var end = scriptParseInfo.ParseResult.Script.TokenManager.GetToken(tokenIndex).EndLocation;
|
||||
if (end.LineNumber == startLine && end.ColumnNumber == startColumn)
|
||||
{
|
||||
// User is not connected.
|
||||
return new DefinitionResult
|
||||
{
|
||||
IsErrorResult = true,
|
||||
Message = SR.PeekDefinitionNotConnectedError,
|
||||
Locations = null
|
||||
};
|
||||
return tokenIndex + 1;
|
||||
}
|
||||
return tokenIndex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -878,13 +959,13 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
private string GetSchemaName(ScriptParseInfo scriptParseInfo, Position position, ScriptFile scriptFile)
|
||||
{
|
||||
// Offset index by 1 for sql parser
|
||||
int startLine = position.Line + 1;
|
||||
int startColumn = position.Character + 1;
|
||||
int startLine = position.Line;
|
||||
int startColumn = position.Character;
|
||||
|
||||
// Get schema name
|
||||
if (scriptParseInfo != null && scriptParseInfo.ParseResult != null && scriptParseInfo.ParseResult.Script != null && scriptParseInfo.ParseResult.Script.Tokens != null)
|
||||
{
|
||||
var tokenIndex = scriptParseInfo.ParseResult.Script.TokenManager.FindToken(startLine, startColumn);
|
||||
var tokenIndex = FindTokenWithCorrectOffset(scriptParseInfo, startLine, startColumn);
|
||||
var prevTokenIndex = scriptParseInfo.ParseResult.Script.TokenManager.GetPreviousSignificantTokenIndex(tokenIndex);
|
||||
var prevTokenText = scriptParseInfo.ParseResult.Script.TokenManager.GetText(prevTokenIndex);
|
||||
if (prevTokenText != null && prevTokenText.Equals("."))
|
||||
|
||||
@@ -1,133 +1,192 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using Microsoft.SqlServer.Management.SqlParser.Parser;
|
||||
using Microsoft.SqlTools.Utility;
|
||||
using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.LanguageServices.Completion
|
||||
{
|
||||
/// <summary>
|
||||
/// A class to calculate the numbers used by SQL parser using the text positions and content
|
||||
/// </summary>
|
||||
internal class ScriptDocumentInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 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;
|
||||
StartColumn = TextUtilities.PositionOfPrevDelimeter(
|
||||
scriptFile.Contents,
|
||||
textDocumentPosition.Position.Line,
|
||||
textDocumentPosition.Position.Character);
|
||||
EndColumn = TextUtilities.PositionOfNextDelimeter(
|
||||
scriptFile.Contents,
|
||||
textDocumentPosition.Position.Line,
|
||||
textDocumentPosition.Position.Character);
|
||||
ParserColumn = textDocumentPosition.Position.Character + 1;
|
||||
Contents = scriptFile.Contents;
|
||||
}
|
||||
|
||||
/// <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>
|
||||
/// Gets a string containing the full contents of the file.
|
||||
/// </summary>
|
||||
public string Contents { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Script Parse Info Instance
|
||||
/// </summary>
|
||||
public ScriptParseInfo ScriptParseInfo { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Start Line
|
||||
/// </summary>
|
||||
public int StartLine { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Parser Line
|
||||
/// </summary>
|
||||
public int ParserLine { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Start Column
|
||||
/// </summary>
|
||||
public int StartColumn { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// end Column
|
||||
/// </summary>
|
||||
public int EndColumn { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Parser Column
|
||||
/// </summary>
|
||||
public int ParserColumn { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The token text in the file content used for completion list
|
||||
/// </summary>
|
||||
public virtual string TokenText
|
||||
{
|
||||
get
|
||||
{
|
||||
return Token != null ? Token.Text : null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The token in the file content used for completion list
|
||||
/// </summary>
|
||||
public Token Token { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the token that will be used by SQL parser for creating the completion list
|
||||
/// </summary>
|
||||
internal static Token GetToken(ScriptParseInfo scriptParseInfo, int startLine, int startColumn)
|
||||
{
|
||||
if (scriptParseInfo != null && scriptParseInfo.ParseResult != null && scriptParseInfo.ParseResult.Script != null && scriptParseInfo.ParseResult.Script.Tokens != null)
|
||||
{
|
||||
var tokenIndex = scriptParseInfo.ParseResult.Script.TokenManager.FindToken(startLine, startColumn);
|
||||
if (tokenIndex >= 0)
|
||||
{
|
||||
// return the current token
|
||||
int currentIndex = 0;
|
||||
foreach (var token in scriptParseInfo.ParseResult.Script.Tokens)
|
||||
{
|
||||
if (currentIndex == tokenIndex)
|
||||
{
|
||||
return token;
|
||||
}
|
||||
++currentIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
using Microsoft.SqlServer.Management.SqlParser.Parser;
|
||||
using Microsoft.SqlTools.Utility;
|
||||
using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.LanguageServices.Completion
|
||||
{
|
||||
/// <summary>
|
||||
/// A class to calculate the numbers used by SQL parser using the text positions and content
|
||||
/// </summary>
|
||||
internal class ScriptDocumentInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 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;
|
||||
StartColumn = TextUtilities.PositionOfPrevDelimeter(
|
||||
scriptFile.Contents,
|
||||
textDocumentPosition.Position.Line,
|
||||
textDocumentPosition.Position.Character);
|
||||
EndColumn = TextUtilities.PositionOfNextDelimeter(
|
||||
scriptFile.Contents,
|
||||
textDocumentPosition.Position.Line,
|
||||
textDocumentPosition.Position.Character);
|
||||
ParserColumn = textDocumentPosition.Position.Character + 1;
|
||||
Contents = scriptFile.Contents;
|
||||
}
|
||||
|
||||
/// <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>
|
||||
/// Gets a string containing the full contents of the file.
|
||||
/// </summary>
|
||||
public string Contents { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Script Parse Info Instance
|
||||
/// </summary>
|
||||
public ScriptParseInfo ScriptParseInfo { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Start Line
|
||||
/// </summary>
|
||||
public int StartLine { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Parser Line
|
||||
/// </summary>
|
||||
public int ParserLine { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Start Column
|
||||
/// </summary>
|
||||
public int StartColumn { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// end Column
|
||||
/// </summary>
|
||||
public int EndColumn { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Parser Column
|
||||
/// </summary>
|
||||
public int ParserColumn { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The token text in the file content used for completion list
|
||||
/// </summary>
|
||||
public virtual string TokenText
|
||||
{
|
||||
get
|
||||
{
|
||||
return Token != null ? Token.Text : null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The token in the file content used for completion list
|
||||
/// </summary>
|
||||
public Token Token { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the token that will be used by SQL parser for creating the completion list
|
||||
/// </summary>
|
||||
internal static Token GetToken(ScriptParseInfo scriptParseInfo, int startLine, int startColumn)
|
||||
{
|
||||
if (scriptParseInfo != null && scriptParseInfo.ParseResult != null && scriptParseInfo.ParseResult.Script != null && scriptParseInfo.ParseResult.Script.Tokens != null)
|
||||
{
|
||||
var tokenIndex = scriptParseInfo.ParseResult.Script.TokenManager.FindToken(startLine, startColumn);
|
||||
if (tokenIndex >= 0)
|
||||
{
|
||||
// return the current token
|
||||
int currentIndex = 0;
|
||||
foreach (var token in scriptParseInfo.ParseResult.Script.Tokens)
|
||||
{
|
||||
if (currentIndex == tokenIndex)
|
||||
{
|
||||
return token;
|
||||
}
|
||||
++currentIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the token that is used for Peek Definition objects
|
||||
/// </summary>
|
||||
internal static Tuple<Stack<Token>, Queue<Token>> GetPeekDefinitionTokens(ScriptParseInfo scriptParseInfo, int startLine, int startColumn)
|
||||
{
|
||||
Stack<Token> childrenTokens = new Stack<Token>();
|
||||
Queue<Token> parentTokens = new Queue<Token>();
|
||||
if (scriptParseInfo != null
|
||||
&& scriptParseInfo.ParseResult != null
|
||||
&& scriptParseInfo.ParseResult.Script != null
|
||||
&& scriptParseInfo.ParseResult.Script.Tokens != null)
|
||||
{
|
||||
var tokenIndex = scriptParseInfo.ParseResult.Script.TokenManager.FindToken(startLine, startColumn);
|
||||
if (tokenIndex >= 0)
|
||||
{
|
||||
// return the current token and the ones to its right
|
||||
// until we hit a whitespace token
|
||||
int currentIndex = 0;
|
||||
foreach (var token in scriptParseInfo.ParseResult.Script.Tokens)
|
||||
{
|
||||
if (currentIndex == tokenIndex)
|
||||
{
|
||||
// push all parent tokens until we hit whitespace
|
||||
int parentIndex = currentIndex;
|
||||
while (true)
|
||||
{
|
||||
if (scriptParseInfo.ParseResult.Script.TokenManager.GetToken(parentIndex).Type != "LEX_WHITE")
|
||||
{
|
||||
parentTokens.Enqueue(scriptParseInfo.ParseResult.Script.TokenManager.GetToken(parentIndex));
|
||||
parentIndex--;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (currentIndex > tokenIndex)
|
||||
{
|
||||
// push all children tokens until we hit whitespace
|
||||
if (scriptParseInfo.ParseResult.Script.TokenManager.GetToken(currentIndex).Type != "LEX_WHITE")
|
||||
{
|
||||
childrenTokens.Push(token);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
++currentIndex;
|
||||
}
|
||||
return Tuple.Create(childrenTokens, parentTokens);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,8 +133,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
||||
/// <returns>Location object of the script file</returns>
|
||||
internal DefinitionResult GetScript(ParseResult parseResult, Position position, IMetadataDisplayInfoProvider metadataDisplayInfoProvider, string tokenText, string schemaName)
|
||||
{
|
||||
int parserLine = position.Line + 1;
|
||||
int parserColumn = position.Character + 1;
|
||||
int parserLine = position.Line;
|
||||
int parserColumn = position.Character;
|
||||
// Get DeclarationItems from The Intellisense Resolver for the selected token. The type of the selected token is extracted from the declarationItem.
|
||||
IEnumerable<Declaration> declarationItems = GetCompletionsForToken(parseResult, parserLine, parserColumn, metadataDisplayInfoProvider);
|
||||
if (declarationItems != null && declarationItems.Count() > 0)
|
||||
|
||||
@@ -156,7 +156,36 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace.Contracts
|
||||
/// <summary>
|
||||
/// Gets or sets the zero-based column number.
|
||||
/// </summary>
|
||||
public int Character { get; set; }
|
||||
public int Character { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the base equality method
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj == null || (obj as Position == null))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Position p = (Position) obj;
|
||||
bool result = (Line == p.Line) && (Character == p.Character);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the base GetHashCode method
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
int hash = 17;
|
||||
hash = hash * 23 + Line.GetHashCode();
|
||||
hash = hash * 23 + Character.GetHashCode();
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
[DebuggerDisplay("Start = {Start.Line}:{Start.Character}, End = {End.Line}:{End.Character}")]
|
||||
@@ -171,6 +200,37 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace.Contracts
|
||||
/// Gets or sets the ending position of the range.
|
||||
/// </summary>
|
||||
public Position End { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the base equality method
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
|
||||
|
||||
if (obj == null || !(obj is Range))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Range range = (Range) obj;
|
||||
bool sameStart = range.Start.Equals(Start);
|
||||
bool sameEnd = range.End.Equals(End);
|
||||
return (sameStart && sameEnd);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the base GetHashCode method
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
int hash = 17;
|
||||
hash = hash * 23 + Start.GetHashCode();
|
||||
hash = hash * 23 + End.GetHashCode();
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
[DebuggerDisplay("Range = {Range.Start.Line}:{Range.Start.Character} - {Range.End.Line}:{Range.End.Character}, Uri = {Uri}")]
|
||||
@@ -185,6 +245,35 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace.Contracts
|
||||
/// Gets or sets the Range indicating the range in which location refers.
|
||||
/// </summary>
|
||||
public Range Range { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the base equality method
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj == null || (obj as Location == null))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Location loc = (Location)obj;
|
||||
bool sameUri = string.Equals(loc.Uri, Uri);
|
||||
bool sameRange = loc.Range.Equals(Range);
|
||||
return (sameUri && sameRange);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the base GetHashCode method
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
int hash = 17;
|
||||
hash = hash * 23 + Uri.GetHashCode();
|
||||
hash = hash * 23 + Range.GetHashCode();
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
public enum FileChangeType
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user