/// <summary> /// Get quick info hover tooltips for the current position /// </summary> /// <param name="textDocumentPosition"></param> /// <param name="scriptFile"></param> internal Hover GetHoverItem(TextDocumentPosition textDocumentPosition, ScriptFile scriptFile) { int startLine = textDocumentPosition.Position.Line; int startColumn = TextUtilities.PositionOfPrevDelimeter( scriptFile.Contents, textDocumentPosition.Position.Line, textDocumentPosition.Position.Character); int endColumn = textDocumentPosition.Position.Character; ScriptParseInfo scriptParseInfo = GetScriptParseInfo(textDocumentPosition.TextDocument.Uri); if (scriptParseInfo != null && scriptParseInfo.ParseResult != null) { if (Monitor.TryEnter(scriptParseInfo.BuildingMetadataLock)) { try { QueueItem queueItem = this.BindingQueue.QueueBindingOperation( 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, bindingContext.MetadataDisplayInfoProvider); // convert from the parser format to the VS Code wire format return(AutoCompleteHelper.ConvertQuickInfoToHover( quickInfo, startLine, startColumn, endColumn)); }); queueItem.ItemProcessed.WaitOne(); return(queueItem.GetResultAsT <Hover>()); } finally { Monitor.Exit(scriptParseInfo.BuildingMetadataLock); } } } // return null if there isn't a tooltip for the current location return(null); }
/// <summary> /// Return the completion item list for the current text position. /// This method does not await cache builds since it expects to return quickly /// </summary> /// <param name="textDocumentPosition"></param> public CompletionItem[] GetCompletionItems( TextDocumentPosition textDocumentPosition, ScriptFile scriptFile, ConnectionInfo connInfo) { // initialize some state to parse and bind the current script file this.currentCompletionParseInfo = null; CompletionItem[] resultCompletionItems = null; string filePath = textDocumentPosition.TextDocument.Uri; int startLine = textDocumentPosition.Position.Line; int parserLine = textDocumentPosition.Position.Line + 1; int startColumn = TextUtilities.PositionOfPrevDelimeter( scriptFile.Contents, textDocumentPosition.Position.Line, textDocumentPosition.Position.Character); int endColumn = TextUtilities.PositionOfNextDelimeter( scriptFile.Contents, textDocumentPosition.Position.Line, textDocumentPosition.Position.Character); int parserColumn = textDocumentPosition.Position.Character + 1; bool useLowerCaseSuggestions = this.CurrentSettings.SqlTools.IntelliSense.LowerCaseSuggestions.Value; // get the current script parse info object ScriptParseInfo scriptParseInfo = GetScriptParseInfo(textDocumentPosition.TextDocument.Uri); if (scriptParseInfo == null) { return(AutoCompleteHelper.GetDefaultCompletionItems( startLine, startColumn, endColumn, useLowerCaseSuggestions)); } // reparse and bind the SQL statement if needed if (RequiresReparse(scriptParseInfo, scriptFile)) { ParseAndBind(scriptFile, connInfo); } // if the parse failed then return the default list if (scriptParseInfo.ParseResult == null) { return(AutoCompleteHelper.GetDefaultCompletionItems( startLine, startColumn, endColumn, useLowerCaseSuggestions)); } // need to adjust line & column for base-1 parser indices Token token = GetToken(scriptParseInfo, parserLine, parserColumn); string tokenText = token != null ? token.Text : null; // check if the file is connected and the file lock is available if (scriptParseInfo.IsConnected && Monitor.TryEnter(scriptParseInfo.BuildingMetadataLock)) { try { // queue the completion task with the binding queue QueueItem queueItem = this.BindingQueue.QueueBindingOperation( key: scriptParseInfo.ConnectionKey, bindingTimeout: LanguageService.BindingTimeout, bindOperation: (bindingContext, cancelToken) => { // get the completion list from SQL Parser scriptParseInfo.CurrentSuggestions = Resolver.FindCompletions( scriptParseInfo.ParseResult, parserLine, parserColumn, bindingContext.MetadataDisplayInfoProvider); // cache the current script parse info object to resolve completions later this.currentCompletionParseInfo = scriptParseInfo; // convert the suggestion list to the VS Code format return(AutoCompleteHelper.ConvertDeclarationsToCompletionItems( scriptParseInfo.CurrentSuggestions, startLine, startColumn, endColumn)); }, timeoutOperation: (bindingContext) => { // return the default list if the connected bind fails return(AutoCompleteHelper.GetDefaultCompletionItems( startLine, startColumn, endColumn, useLowerCaseSuggestions, tokenText)); }); // wait for the queue item queueItem.ItemProcessed.WaitOne(); var completionItems = queueItem.GetResultAsT <CompletionItem[]>(); if (completionItems != null && completionItems.Length > 0) { resultCompletionItems = completionItems; } else if (!ShouldShowCompletionList(token)) { resultCompletionItems = AutoCompleteHelper.EmptyCompletionList; } } finally { Monitor.Exit(scriptParseInfo.BuildingMetadataLock); } } // if there are no completions then provide the default list if (resultCompletionItems == null) { resultCompletionItems = AutoCompleteHelper.GetDefaultCompletionItems( startLine, startColumn, endColumn, useLowerCaseSuggestions, tokenText); } return(resultCompletionItems); }