mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-02-10 18:22:36 -05:00
Feature/peek def code gen (#215)
* Add codeGen for existing types * Modify code gen logic to match current code * Extend logic for new smo objects * Add logic to retrieve token type from QuickInfo * Remove duplicate types * Add tests for new types * Modify GetScript logic to use suggestions first * Add more tests * Modify codeGen to include quickInfo logic * Cake build changes to run CodeGen * CodeGen replace indentation * Refactor GetScript and add more tests * Refactor Resolver calls * Fix TestDriver test for Definition * Change quickInfo string case * Revert change sto .sln file * Fix typos in comments * change String to string * Rename test sql objects
This commit is contained in:
@@ -61,8 +61,8 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
|
||||
private ParseOptions defaultParseOptions = new ParseOptions(
|
||||
batchSeparator: LanguageService.DefaultBatchSeperator,
|
||||
isQuotedIdentifierSet: true,
|
||||
compatibilityLevel: DatabaseCompatibilityLevel.Current,
|
||||
isQuotedIdentifierSet: true,
|
||||
compatibilityLevel: DatabaseCompatibilityLevel.Current,
|
||||
transactSqlVersion: TransactSqlVersion.Current);
|
||||
|
||||
/// <summary>
|
||||
@@ -105,13 +105,13 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
|
||||
private static readonly Lazy<LanguageService> instance = new Lazy<LanguageService>(() => new LanguageService());
|
||||
|
||||
private Lazy<Dictionary<string, ScriptParseInfo>> scriptParseInfoMap
|
||||
private Lazy<Dictionary<string, ScriptParseInfo>> scriptParseInfoMap
|
||||
= new Lazy<Dictionary<string, ScriptParseInfo>>(() => new Dictionary<string, ScriptParseInfo>());
|
||||
|
||||
/// <summary>
|
||||
/// Gets a mapping dictionary for SQL file URIs to ScriptParseInfo objects
|
||||
/// </summary>
|
||||
internal Dictionary<string, ScriptParseInfo> ScriptParseInfoMap
|
||||
internal Dictionary<string, ScriptParseInfo> ScriptParseInfoMap
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -262,20 +262,20 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
}
|
||||
else
|
||||
{
|
||||
// get the current list of completion items and return to client
|
||||
// get the current list of completion items and return to client
|
||||
var scriptFile = LanguageService.WorkspaceServiceInstance.Workspace.GetFile(
|
||||
textDocumentPosition.TextDocument.Uri);
|
||||
|
||||
ConnectionInfo connInfo;
|
||||
LanguageService.ConnectionServiceInstance.TryFindConnection(
|
||||
scriptFile.ClientFilePath,
|
||||
scriptFile.ClientFilePath,
|
||||
out connInfo);
|
||||
|
||||
var completionItems = Instance.GetCompletionItems(
|
||||
textDocumentPosition, scriptFile, connInfo);
|
||||
|
||||
|
||||
await requestContext.SendResult(completionItems);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -322,7 +322,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
LanguageService.ConnectionServiceInstance.TryFindConnection(scriptFile.ClientFilePath, out connInfo);
|
||||
DefinitionResult definitionResult = LanguageService.Instance.GetDefinition(textDocumentPosition, scriptFile, connInfo);
|
||||
if (definitionResult != null)
|
||||
{
|
||||
{
|
||||
if (definitionResult.IsErrorResult)
|
||||
{
|
||||
await requestContext.SendError( new DefinitionError { message = definitionResult.Message });
|
||||
@@ -330,7 +330,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
else
|
||||
{
|
||||
await requestContext.SendResult(definitionResult.Locations);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
DocumentStatusHelper.SendStatusChange(requestContext, textDocumentPosition, DocumentStatusHelper.DefinitionRequestCompleted);
|
||||
@@ -382,10 +382,10 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
private static async Task HandleHoverRequest(
|
||||
TextDocumentPosition textDocumentPosition,
|
||||
RequestContext<Hover> requestContext)
|
||||
{
|
||||
{
|
||||
// check if Quick Info hover tooltips are enabled
|
||||
if (WorkspaceService<SqlToolsSettings>.Instance.CurrentSettings.IsQuickInfoEnabled)
|
||||
{
|
||||
{
|
||||
var scriptFile = WorkspaceService<SqlToolsSettings>.Instance.Workspace.GetFile(
|
||||
textDocumentPosition.TextDocument.Uri);
|
||||
|
||||
@@ -396,7 +396,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
}
|
||||
}
|
||||
|
||||
await requestContext.SendResult(new Hover());
|
||||
await requestContext.SendResult(new Hover());
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -404,42 +404,42 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
#region Handlers for Events from Other Services
|
||||
|
||||
/// <summary>
|
||||
/// Handle the file open notification
|
||||
/// Handle the file open notification
|
||||
/// </summary>
|
||||
/// <param name="scriptFile"></param>
|
||||
/// <param name="eventContext"></param>
|
||||
/// <returns></returns>
|
||||
public async Task HandleDidOpenTextDocumentNotification(
|
||||
ScriptFile scriptFile,
|
||||
ScriptFile scriptFile,
|
||||
EventContext eventContext)
|
||||
{
|
||||
// if not in the preview window and diagnostics are enabled then run diagnostics
|
||||
if (!IsPreviewWindow(scriptFile)
|
||||
&& WorkspaceService<SqlToolsSettings>.Instance.CurrentSettings.IsDiagnositicsEnabled)
|
||||
{
|
||||
await RunScriptDiagnostics(
|
||||
await RunScriptDiagnostics(
|
||||
new ScriptFile[] { scriptFile },
|
||||
eventContext);
|
||||
eventContext);
|
||||
}
|
||||
|
||||
await Task.FromResult(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles text document change events
|
||||
/// </summary>
|
||||
/// <param name="textChangeParams"></param>
|
||||
|
||||
/// <summary>
|
||||
/// Handles text document change events
|
||||
/// </summary>
|
||||
/// <param name="textChangeParams"></param>
|
||||
/// <param name="eventContext"></param>
|
||||
public async Task HandleDidChangeTextDocumentNotification(ScriptFile[] changedFiles, EventContext eventContext)
|
||||
{
|
||||
public async Task HandleDidChangeTextDocumentNotification(ScriptFile[] changedFiles, EventContext eventContext)
|
||||
{
|
||||
if (WorkspaceService<SqlToolsSettings>.Instance.CurrentSettings.IsDiagnositicsEnabled)
|
||||
{
|
||||
await this.RunScriptDiagnostics(
|
||||
changedFiles.ToArray(),
|
||||
eventContext);
|
||||
await this.RunScriptDiagnostics(
|
||||
changedFiles.ToArray(),
|
||||
eventContext);
|
||||
}
|
||||
|
||||
await Task.FromResult(true);
|
||||
await Task.FromResult(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -449,8 +449,8 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
/// <param name="oldSettings"></param>
|
||||
/// <param name="eventContext"></param>
|
||||
public async Task HandleDidChangeConfigurationNotification(
|
||||
SqlToolsSettings newSettings,
|
||||
SqlToolsSettings oldSettings,
|
||||
SqlToolsSettings newSettings,
|
||||
SqlToolsSettings oldSettings,
|
||||
EventContext eventContext)
|
||||
{
|
||||
bool oldEnableIntelliSense = oldSettings.SqlTools.IntelliSense.EnableIntellisense;
|
||||
@@ -480,7 +480,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -495,13 +495,13 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
{
|
||||
RemoveScriptParseInfo(ownerUri);
|
||||
|
||||
// currently this method is disabled, but we need to reimplement now that the
|
||||
// currently this method is disabled, but we need to reimplement now that the
|
||||
// implementation of the 'cache' has changed.
|
||||
await Task.FromResult(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses the SQL text and binds it to the SMO metadata provider if connected
|
||||
/// Parses the SQL text and binds it to the SMO metadata provider if connected
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
/// <param name="sqlText"></param>
|
||||
@@ -531,7 +531,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
key: parseInfo.ConnectionKey,
|
||||
bindingTimeout: LanguageService.BindingTimeout,
|
||||
bindOperation: (bindingContext, cancelToken) =>
|
||||
{
|
||||
{
|
||||
try
|
||||
{
|
||||
ParseResult parseResult = Parser.IncrementalParse(
|
||||
@@ -544,8 +544,8 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
List<ParseResult> parseResults = new List<ParseResult>();
|
||||
parseResults.Add(parseResult);
|
||||
bindingContext.Binder.Bind(
|
||||
parseResults,
|
||||
connInfo.ConnectionDetails.DatabaseName,
|
||||
parseResults,
|
||||
connInfo.ConnectionDetails.DatabaseName,
|
||||
BindMode.Batch);
|
||||
}
|
||||
catch (ConnectionException)
|
||||
@@ -562,9 +562,9 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
});
|
||||
|
||||
queueItem.ItemProcessed.WaitOne();
|
||||
queueItem.ItemProcessed.WaitOne();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -580,9 +580,9 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Write(LogLevel.Warning, "Binding metadata lock timeout in ParseAndBind");
|
||||
Logger.Write(LogLevel.Warning, "Binding metadata lock timeout in ParseAndBind");
|
||||
}
|
||||
|
||||
|
||||
return parseInfo.ParseResult;
|
||||
}
|
||||
|
||||
@@ -592,16 +592,16 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
/// <param name="info"></param>
|
||||
public async Task UpdateLanguageServiceOnConnection(ConnectionInfo info)
|
||||
{
|
||||
await Task.Run(() =>
|
||||
await Task.Run(() =>
|
||||
{
|
||||
ScriptParseInfo scriptInfo = GetScriptParseInfo(info.OwnerUri, createIfNotExists: true);
|
||||
if (Monitor.TryEnter(scriptInfo.BuildingMetadataLock, LanguageService.OnConnectionWaitTimeout))
|
||||
{
|
||||
try
|
||||
{
|
||||
{
|
||||
scriptInfo.ConnectionKey = this.BindingQueue.AddConnectionContext(info);
|
||||
scriptInfo.IsConnected = true;
|
||||
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -614,7 +614,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
// (Tell Language Service that I am ready with Metadata Provider Object)
|
||||
Monitor.Exit(scriptInfo.BuildingMetadataLock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AutoCompleteHelper.PrepopulateCommonMetadata(info, scriptInfo, this.BindingQueue);
|
||||
|
||||
@@ -658,7 +658,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
key: scriptParseInfo.ConnectionKey,
|
||||
bindingTimeout: LanguageService.BindingTimeout,
|
||||
bindOperation: (bindingContext, cancelToken) =>
|
||||
{
|
||||
{
|
||||
foreach (var suggestion in scriptParseInfo.CurrentSuggestions)
|
||||
{
|
||||
if (string.Equals(suggestion.Title, completionItem.Label))
|
||||
@@ -667,25 +667,25 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
completionItem.Documentation = suggestion.Description;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return completionItem;
|
||||
}
|
||||
return completionItem;
|
||||
});
|
||||
|
||||
queueItem.ItemProcessed.WaitOne();
|
||||
queueItem.ItemProcessed.WaitOne();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// if any exceptions are raised looking up extended completion metadata
|
||||
// if any exceptions are raised looking up extended completion metadata
|
||||
// then just return the original completion item
|
||||
Logger.Write(LogLevel.Error, "Exeception in ResolveCompletionItem " + ex.ToString());
|
||||
}
|
||||
Logger.Write(LogLevel.Error, "Exception in ResolveCompletionItem " + ex.ToString());
|
||||
}
|
||||
finally
|
||||
{
|
||||
Monitor.Exit(scriptParseInfo.BuildingMetadataLock);
|
||||
}
|
||||
Monitor.Exit(scriptParseInfo.BuildingMetadataLock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return completionItem;
|
||||
}
|
||||
@@ -725,25 +725,21 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
{
|
||||
try
|
||||
{
|
||||
// Queue the task with the binding queue
|
||||
// Queue the task with the binding queue
|
||||
QueueItem queueItem = this.BindingQueue.QueueBindingOperation(
|
||||
key: scriptParseInfo.ConnectionKey,
|
||||
bindingTimeout: LanguageService.PeekDefinitionTimeout,
|
||||
bindOperation: (bindingContext, cancelToken) =>
|
||||
{
|
||||
// Get suggestions for the token
|
||||
int parserLine = textDocumentPosition.Position.Line + 1;
|
||||
int parserColumn = textDocumentPosition.Position.Character + 1;
|
||||
IEnumerable<Declaration> declarationItems = Resolver.FindCompletions(
|
||||
scriptParseInfo.ParseResult,
|
||||
parserLine, parserColumn,
|
||||
bindingContext.MetadataDisplayInfoProvider);
|
||||
|
||||
// Match token with the suggestions(declaration items) returned
|
||||
|
||||
string schemaName = this.GetSchemaName(scriptParseInfo, textDocumentPosition.Position, scriptFile);
|
||||
// Script object using SMO
|
||||
PeekDefinition peekDefinition = new PeekDefinition(bindingContext.ServerConnection, connInfo);
|
||||
return peekDefinition.GetScript(declarationItems, tokenText, schemaName);
|
||||
return peekDefinition.GetScript(
|
||||
scriptParseInfo.ParseResult,
|
||||
textDocumentPosition.Position,
|
||||
bindingContext.MetadataDisplayInfoProvider,
|
||||
tokenText,
|
||||
schemaName);
|
||||
},
|
||||
timeoutOperation: (bindingContext) =>
|
||||
{
|
||||
@@ -813,7 +809,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
Token schemaToken = scriptParseInfo.ParseResult.Script.TokenManager.GetToken(schemaTokenIndex);
|
||||
return TextUtilities.RemoveSquareBracketSyntax(schemaToken.Text);
|
||||
}
|
||||
}
|
||||
}
|
||||
// if no schema name, returns null
|
||||
return null;
|
||||
}
|
||||
@@ -827,10 +823,10 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
{
|
||||
int startLine = textDocumentPosition.Position.Line;
|
||||
int startColumn = TextUtilities.PositionOfPrevDelimeter(
|
||||
scriptFile.Contents,
|
||||
scriptFile.Contents,
|
||||
textDocumentPosition.Position.Line,
|
||||
textDocumentPosition.Position.Character);
|
||||
int endColumn = textDocumentPosition.Position.Character;
|
||||
int endColumn = textDocumentPosition.Position.Character;
|
||||
|
||||
ScriptParseInfo scriptParseInfo = GetScriptParseInfo(textDocumentPosition.TextDocument.Uri);
|
||||
if (scriptParseInfo != null && scriptParseInfo.ParseResult != null)
|
||||
@@ -843,29 +839,29 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
key: scriptParseInfo.ConnectionKey,
|
||||
bindingTimeout: LanguageService.HoverTimeout,
|
||||
bindOperation: (bindingContext, cancelToken) =>
|
||||
{
|
||||
{
|
||||
// get the current quick info text
|
||||
Babel.CodeObjectQuickInfo quickInfo = Resolver.GetQuickInfo(
|
||||
scriptParseInfo.ParseResult,
|
||||
startLine + 1,
|
||||
endColumn + 1,
|
||||
scriptParseInfo.ParseResult,
|
||||
startLine + 1,
|
||||
endColumn + 1,
|
||||
bindingContext.MetadataDisplayInfoProvider);
|
||||
|
||||
|
||||
// convert from the parser format to the VS Code wire format
|
||||
return AutoCompleteHelper.ConvertQuickInfoToHover(
|
||||
quickInfo,
|
||||
quickInfo,
|
||||
startLine,
|
||||
startColumn,
|
||||
startColumn,
|
||||
endColumn);
|
||||
});
|
||||
|
||||
queueItem.ItemProcessed.WaitOne();
|
||||
return queueItem.GetResultAsT<Hover>();
|
||||
|
||||
queueItem.ItemProcessed.WaitOne();
|
||||
return queueItem.GetResultAsT<Hover>();
|
||||
}
|
||||
finally
|
||||
{
|
||||
Monitor.Exit(scriptParseInfo.BuildingMetadataLock);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -880,7 +876,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
{
|
||||
int startLine = textDocumentPosition.Position.Line;
|
||||
int startColumn = TextUtilities.PositionOfPrevDelimeter(
|
||||
scriptFile.Contents,
|
||||
scriptFile.Contents,
|
||||
textDocumentPosition.Position.Line,
|
||||
textDocumentPosition.Position.Character);
|
||||
int endColumn = textDocumentPosition.Position.Character;
|
||||
@@ -895,12 +891,12 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
|
||||
ConnectionInfo connInfo;
|
||||
LanguageService.ConnectionServiceInstance.TryFindConnection(
|
||||
scriptFile.ClientFilePath,
|
||||
scriptFile.ClientFilePath,
|
||||
out connInfo);
|
||||
|
||||
// reparse and bind the SQL statement if needed
|
||||
if (RequiresReparse(scriptParseInfo, scriptFile))
|
||||
{
|
||||
{
|
||||
ParseAndBind(scriptFile, connInfo);
|
||||
}
|
||||
|
||||
@@ -914,14 +910,14 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
key: scriptParseInfo.ConnectionKey,
|
||||
bindingTimeout: LanguageService.BindingTimeout,
|
||||
bindOperation: (bindingContext, cancelToken) =>
|
||||
{
|
||||
{
|
||||
// get the list of possible current methods for signature help
|
||||
var methods = Resolver.FindMethods(
|
||||
scriptParseInfo.ParseResult,
|
||||
startLine + 1,
|
||||
endColumn + 1,
|
||||
scriptParseInfo.ParseResult,
|
||||
startLine + 1,
|
||||
endColumn + 1,
|
||||
bindingContext.MetadataDisplayInfoProvider);
|
||||
|
||||
|
||||
// get positional information on the current method
|
||||
var methodLocations = Resolver.GetMethodNameAndParams(scriptParseInfo.ParseResult,
|
||||
startLine + 1,
|
||||
@@ -941,14 +937,14 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
queueItem.ItemProcessed.WaitOne();
|
||||
return queueItem.GetResultAsT<SignatureHelp>();
|
||||
|
||||
queueItem.ItemProcessed.WaitOne();
|
||||
return queueItem.GetResultAsT<SignatureHelp>();
|
||||
}
|
||||
finally
|
||||
{
|
||||
Monitor.Exit(scriptParseInfo.BuildingMetadataLock);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -974,14 +970,14 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
|
||||
// get the current script parse info object
|
||||
ScriptParseInfo scriptParseInfo = GetScriptParseInfo(textDocumentPosition.TextDocument.Uri);
|
||||
|
||||
|
||||
if (scriptParseInfo == null)
|
||||
{
|
||||
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))
|
||||
{
|
||||
@@ -1019,9 +1015,9 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
{
|
||||
ConnectionInfo connInfo;
|
||||
ConnectionService.Instance.TryFindConnection(
|
||||
scriptFile.ClientFilePath,
|
||||
scriptFile.ClientFilePath,
|
||||
out connInfo);
|
||||
|
||||
|
||||
var parseResult = ParseAndBind(scriptFile, connInfo);
|
||||
|
||||
// build a list of SQL script file markers from the errors
|
||||
@@ -1181,7 +1177,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
/// Internal for testing purposes only
|
||||
/// </summary>
|
||||
/// <param name="uri"></param>
|
||||
/// <param name="createIfNotExists">Creates a new instance if one doesn't exist</param>
|
||||
/// <param name="createIfNotExists">Creates a new instance if one doesn't exist</param>
|
||||
internal ScriptParseInfo GetScriptParseInfo(string uri, bool createIfNotExists = false)
|
||||
{
|
||||
lock (this.parseMapLock)
|
||||
@@ -1209,7 +1205,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
lock (this.parseMapLock)
|
||||
{
|
||||
if (this.ScriptParseInfoMap.ContainsKey(uri))
|
||||
{
|
||||
{
|
||||
return this.ScriptParseInfoMap.Remove(uri);
|
||||
}
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user