diff --git a/build.cake b/build.cake
index e3dbf3a8..595c7818 100644
--- a/build.cake
+++ b/build.cake
@@ -3,11 +3,13 @@
#load "scripts/runhelpers.cake"
#load "scripts/archiving.cake"
#load "scripts/artifacts.cake"
+#tool "nuget:?package=Mono.TextTransform"
using System.ComponentModel;
using System.Net;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
+using Cake.Common.IO
// Basic arguments
var target = Argument("target", "Default");
@@ -258,6 +260,7 @@ Task("TestCore")
Task("Test")
.IsDependentOn("Setup")
.IsDependentOn("SRGen")
+ .IsDependentOn("CodeGen")
.IsDependentOn("BuildTest")
.Does(() =>
{
@@ -306,6 +309,7 @@ Task("Test")
Task("OnlyPublish")
.IsDependentOn("Setup")
.IsDependentOn("SRGen")
+ .IsDependentOn("CodeGen")
.Does(() =>
{
var project = buildPlan.MainProject;
@@ -541,6 +545,20 @@ Task("SRGen")
}
});
+///
+/// Executes T4Template-based code generators
+///
+Task("CodeGen")
+ .Does(() =>
+{
+ var t4Files = GetFiles(sourceFolder + "/**/*.tt");
+ foreach(var t4Template in t4Files)
+ {
+ TransformTemplate(t4Template, new TextTransformSettings {});
+ }
+});
+
+
///
/// Default Task aliases to Local.
///
diff --git a/scripts/packages.config b/scripts/packages.config
index ccbbd827..fd0de851 100644
--- a/scripts/packages.config
+++ b/scripts/packages.config
@@ -1,6 +1,7 @@
-
+
-
+
+
\ No newline at end of file
diff --git a/sqltoolsservice.sln b/sqltoolsservice.sln
index b338c5d3..06934702 100644
--- a/sqltoolsservice.sln
+++ b/sqltoolsservice.sln
@@ -123,4 +123,4 @@ Global
{B6F4BECE-82EE-4AB6-99AC-108AEE466274} = {AB9CA2B8-6F70-431C-8A1D-67479D8A7BE4}
{E7CF630E-E084-4DA4-BF69-F61BF0A8F5BE} = {AB9CA2B8-6F70-431C-8A1D-67479D8A7BE4}
EndGlobalSection
-EndGlobal
+EndGlobal
\ No newline at end of file
diff --git a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/LanguageService.cs b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/LanguageService.cs
index 57096897..232bf217 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/LanguageService.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/LanguageService.cs
@@ -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);
///
@@ -105,13 +105,13 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
private static readonly Lazy instance = new Lazy(() => new LanguageService());
- private Lazy> scriptParseInfoMap
+ private Lazy> scriptParseInfoMap
= new Lazy>(() => new Dictionary());
///
/// Gets a mapping dictionary for SQL file URIs to ScriptParseInfo objects
///
- internal Dictionary ScriptParseInfoMap
+ internal Dictionary 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);
- }
+ }
}
///
@@ -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 requestContext)
- {
+ {
// check if Quick Info hover tooltips are enabled
if (WorkspaceService.Instance.CurrentSettings.IsQuickInfoEnabled)
- {
+ {
var scriptFile = WorkspaceService.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
///
- /// Handle the file open notification
+ /// Handle the file open notification
///
///
///
///
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.Instance.CurrentSettings.IsDiagnositicsEnabled)
{
- await RunScriptDiagnostics(
+ await RunScriptDiagnostics(
new ScriptFile[] { scriptFile },
- eventContext);
+ eventContext);
}
await Task.FromResult(true);
}
-
- ///
- /// Handles text document change events
- ///
- ///
+
+ ///
+ /// Handles text document change events
+ ///
+ ///
///
- public async Task HandleDidChangeTextDocumentNotification(ScriptFile[] changedFiles, EventContext eventContext)
- {
+ public async Task HandleDidChangeTextDocumentNotification(ScriptFile[] changedFiles, EventContext eventContext)
+ {
if (WorkspaceService.Instance.CurrentSettings.IsDiagnositicsEnabled)
{
- await this.RunScriptDiagnostics(
- changedFiles.ToArray(),
- eventContext);
+ await this.RunScriptDiagnostics(
+ changedFiles.ToArray(),
+ eventContext);
}
- await Task.FromResult(true);
+ await Task.FromResult(true);
}
///
@@ -449,8 +449,8 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
///
///
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);
}
///
- /// 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
///
///
///
@@ -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 parseResults = new List();
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
///
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 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();
+
+ queueItem.ItemProcessed.WaitOne();
+ return queueItem.GetResultAsT();
}
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();
+
+ queueItem.ItemProcessed.WaitOne();
+ return queueItem.GetResultAsT();
}
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
///
///
- /// Creates a new instance if one doesn't exist
+ /// Creates a new instance if one doesn't exist
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
diff --git a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/PeekDefinition.cs b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/PeekDefinition.cs
index d6456307..5c6d2e58 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/PeekDefinition.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/PeekDefinition.cs
@@ -4,17 +4,21 @@
//
using System;
using System.IO;
+using System.Linq;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Data.SqlClient;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.SqlParser.Intellisense;
+using Microsoft.SqlServer.Management.SqlParser.Parser;
+using Microsoft.SqlServer.Management.SqlParser.MetadataProvider;
using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.QueryExecution;
using Microsoft.SqlTools.ServiceLayer.Utility;
using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol;
using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts;
+using Location = Microsoft.SqlTools.ServiceLayer.Workspace.Contracts.Location;
namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
{
@@ -22,7 +26,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
/// Peek Definition/ Go to definition implementation
/// Script sql objects and write create scripts to file
///
- internal class PeekDefinition
+ internal partial class PeekDefinition
{
private bool error;
private string errorMessage;
@@ -37,9 +41,14 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
private Dictionary sqlScriptGetters =
new Dictionary();
+ private Dictionary sqlScriptGettersFromQuickInfo =
+ new Dictionary();
+
// Dictionary that holds the object name (as appears on the TSQL create statement)
private Dictionary sqlObjectTypes = new Dictionary();
+ private Dictionary sqlObjectTypesFromQuickInfo = new Dictionary();
+
///
/// Initialize a Peek Definition helper object
///
@@ -48,7 +57,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
{
this.serverConnection = serverConnection;
this.connectionInfo = connInfo;
- this.tempPath = FileUtils.GetPeekDefinitionTempFolder();
+ this.tempPath = FileUtils.GetPeekDefinitionTempFolder();
Initialize();
}
@@ -70,7 +79,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
{
Logger.Write(LogLevel.Error, "Exception at PeekDefinition Database.get() : " + cfe.Message);
this.error = true;
- this.errorMessage = (connectionInfo != null && connectionInfo.IsAzure)? SR.PeekDefinitionAzureError(cfe.Message) : SR.PeekDefinitionError(cfe.Message);
+ this.errorMessage = (connectionInfo != null && connectionInfo.IsAzure) ? SR.PeekDefinitionAzureError(cfe.Message) : SR.PeekDefinitionError(cfe.Message);
return null;
}
catch (Exception ex)
@@ -81,78 +90,23 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
return null;
}
}
-
}
return this.database;
}
}
- ///
- /// Add getters for each sql object supported by peek definition
- ///
- private void Initialize()
- {
- //Add script getters for each sql object
-
- //Add tables to supported types
- AddSupportedType(DeclarationType.Table, GetTableScripts, "Table");
-
- //Add views to supported types
- AddSupportedType(DeclarationType.View, GetViewScripts, "view");
-
- //Add stored procedures to supported types
- AddSupportedType(DeclarationType.StoredProcedure, GetStoredProcedureScripts, "Procedure");
- }
-
///
/// Add the given type, scriptgetter and the typeName string to the respective dictionaries
///
- private void AddSupportedType(DeclarationType type, ScriptGetter scriptGetter, string typeName)
+ private void AddSupportedType(DeclarationType type, ScriptGetter scriptGetter, string typeName, string quickInfoType)
{
sqlScriptGetters.Add(type, scriptGetter);
sqlObjectTypes.Add(type, typeName);
-
- }
-
- ///
- /// Convert a file to a location array containing a location object as expected by the extension
- ///
- internal Location[] GetLocationFromFile(string tempFileName, int lineNumber)
- {
- if (Path.DirectorySeparatorChar.Equals('/'))
+ if (!string.IsNullOrEmpty(quickInfoType))
{
- tempFileName = "file:" + tempFileName;
+ sqlScriptGettersFromQuickInfo.Add(quickInfoType.ToLowerInvariant(), scriptGetter);
+ sqlObjectTypesFromQuickInfo.Add(quickInfoType.ToLowerInvariant(), typeName);
}
- else
- {
- tempFileName = new Uri(tempFileName).AbsoluteUri;
- }
- Location[] locations = new[] {
- new Location {
- Uri = tempFileName,
- Range = new Range {
- Start = new Position { Line = lineNumber, Character = 1},
- End = new Position { Line = lineNumber + 1, Character = 1}
- }
- }
- };
- return locations;
- }
-
- ///
- /// Get line number for the create statement
- ///
- private int GetStartOfCreate(string script, string createString)
- {
- string[] lines = script.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
- for (int lineNumber = 0; lineNumber < lines.Length; lineNumber++)
- {
- if (lines[lineNumber].IndexOf(createString, StringComparison.OrdinalIgnoreCase) >= 0)
- {
- return lineNumber;
- }
- }
- return 0;
}
///
@@ -162,45 +116,77 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
///
///
/// Location object of the script file
- internal DefinitionResult GetScript(IEnumerable declarationItems, string tokenText, string schemaName)
+ internal DefinitionResult GetScript(ParseResult parseResult, Position position, IMetadataDisplayInfoProvider metadataDisplayInfoProvider, string tokenText, string schemaName)
{
- foreach (Declaration declarationItem in declarationItems)
+ int parserLine = position.Line + 1;
+ int parserColumn = position.Character + 1;
+ // Get DeclarationItems from The Intellisense Resolver for the selected token. The type of the selected token is extracted from the declarationItem.
+ IEnumerable declarationItems = GetCompletionsForToken(parseResult, parserLine, parserColumn, metadataDisplayInfoProvider);
+ if (declarationItems != null && declarationItems.Count() > 0)
{
- if (declarationItem.Title == null)
+ foreach (Declaration declarationItem in declarationItems)
{
- continue;
- }
-
- if (declarationItem.Title.Equals(tokenText))
- {
- // Script object using SMO based on type
- DeclarationType type = declarationItem.Type;
- if (sqlScriptGetters.ContainsKey(type) && sqlObjectTypes.ContainsKey(type))
+ if (declarationItem.Title == null)
{
- // On *nix and mac systems, the defaultSchema property throws an Exception when accessed.
- // This workaround ensures that a schema name is present by attempting
- // to get the schema name from the declaration item
- // If all fails, the default schema name is assumed to be "dbo"
- if ((connectionInfo != null && connectionInfo.ConnectionDetails.AuthenticationType.Equals(Constants.SqlLoginAuthenticationType)) && string.IsNullOrEmpty(schemaName))
- {
- string fullObjectName = declarationItem.DatabaseQualifiedName;
- schemaName = this.GetSchemaFromDatabaseQualifiedName(fullObjectName, tokenText);
- }
- Location[] locations = GetSqlObjectDefinition(
- sqlScriptGetters[type],
- tokenText,
- schemaName,
- sqlObjectTypes[type]
- );
- DefinitionResult result = new DefinitionResult
- {
- IsErrorResult = this.error,
- Message = this.errorMessage,
- Locations = locations
- };
- return result;
+ continue;
}
- // sql object type is currently not supported
+ // if declarartionItem matches the selected token, script SMO using that type
+ if (declarationItem.Title.Equals(tokenText))
+ {
+ return GetDefinitionUsingDeclarationType(declarationItem.Type, declarationItem.DatabaseQualifiedName, tokenText, schemaName);
+ }
+ }
+ }
+ else
+ {
+ // if no declarationItem matched the selected token, we try to find the type of the token using QuickInfo.Text
+ string quickInfoText = GetQuickInfoForToken(parseResult, parserLine, parserColumn, metadataDisplayInfoProvider);
+ return GetDefinitionUsingQuickInfoText(quickInfoText, tokenText, schemaName);
+ }
+ // no definition found
+ return GetDefinitionErrorResult(SR.PeekDefinitionNoResultsError);
+ }
+
+ ///
+ /// Script an object using the type extracted from quickInfo Text
+ ///
+ /// the text from the quickInfo for the selected token
+ /// The text of the selected token
+ /// Schema name
+ ///
+ internal DefinitionResult GetDefinitionUsingQuickInfoText(string quickInfoText, string tokenText, string schemaName)
+ {
+ string tokenType = GetTokenTypeFromQuickInfo(quickInfoText, tokenText);
+ if (tokenType != null)
+ {
+ if (sqlScriptGettersFromQuickInfo.ContainsKey(tokenType.ToLowerInvariant()))
+ {
+ // With SqlLogin authentication, the defaultSchema property throws an Exception when accessed.
+ // This workaround ensures that a schema name is present by attempting
+ // to get the schema name from the declaration item.
+ // If all fails, the default schema name is assumed to be "dbo"
+ if ((connectionInfo != null && connectionInfo.ConnectionDetails.AuthenticationType.Equals(Constants.SqlLoginAuthenticationType)) && string.IsNullOrEmpty(schemaName))
+ {
+ string fullObjectName = this.GetFullObjectNameFromQuickInfo(quickInfoText, tokenText);
+ schemaName = this.GetSchemaFromDatabaseQualifiedName(fullObjectName, tokenText);
+ }
+ Location[] locations = GetSqlObjectDefinition(
+ sqlScriptGettersFromQuickInfo[tokenType.ToLowerInvariant()],
+ tokenText,
+ schemaName,
+ sqlObjectTypesFromQuickInfo[tokenType.ToLowerInvariant()]
+ );
+ DefinitionResult result = new DefinitionResult
+ {
+ IsErrorResult = this.error,
+ Message = this.errorMessage,
+ Locations = locations
+ };
+ return result;
+ }
+ else
+ {
+ // If a type was found but is not in sqlScriptGettersFromQuickInfo, then the type is not supported
return GetDefinitionErrorResult(SR.PeekDefinitionTypeNotSupportedError);
}
}
@@ -209,97 +195,41 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
}
///
- /// Return schema name from the full name of the database. If schema is missing return dbo as schema name.
+ /// Script a object using the type extracted from declarationItem
///
- /// The full database qualified name(database.schema.object)
- /// Object name
- /// Schema name
- internal string GetSchemaFromDatabaseQualifiedName(string fullObjectName, string objectName)
- {
- string[] tokens = fullObjectName.Split('.');
- for (int i = tokens.Length - 1; i > 0; i--)
- {
- if (tokens[i].Equals(objectName))
- {
- return tokens[i - 1];
- }
- }
- return "dbo";
- }
-
- ///
- /// Script a table using SMO
- ///
- /// Table name
+ /// The Declarartion object that matched with the selected token
+ /// The text of the selected token
/// Schema name
- /// String collection of scripts
- internal StringCollection GetTableScripts(string tableName, string schemaName)
+ ///
+ internal DefinitionResult GetDefinitionUsingDeclarationType(DeclarationType type, string databaseQualifiedName, string tokenText, string schemaName)
{
- try
+ if (sqlScriptGetters.ContainsKey(type) && sqlObjectTypes.ContainsKey(type))
{
- Table table = string.IsNullOrEmpty(schemaName)
- ? new Table(this.Database, tableName)
- : new Table(this.Database, tableName, schemaName);
-
- table.Refresh();
-
- return table.Script();
- }
- catch (Exception ex)
- {
- Logger.Write(LogLevel.Error, "Exception at PeekDefinition GetTableScripts : " + ex.Message);
- return null;
- }
- }
-
- ///
- /// Script a view using SMO
- ///
- /// View name
- /// Schema name
- /// String collection of scripts
- internal StringCollection GetViewScripts(string viewName, string schemaName)
- {
- try
- {
- View view = string.IsNullOrEmpty(schemaName)
- ? new View(this.Database, viewName)
- : new View(this.Database, viewName, schemaName);
-
- view.Refresh();
-
- return view.Script();
- }
- catch (Exception ex)
- {
- Logger.Write(LogLevel.Error, "Exception at PeekDefinition GetViewScripts : " + ex.Message);
- return null;
- }
- }
-
- ///
- /// Script a stored procedure using SMO
- ///
- /// Stored Procedure name
- /// Schema Name
- /// String collection of scripts
- internal StringCollection GetStoredProcedureScripts(string sprocName, string schemaName)
- {
- try
- {
- StoredProcedure sproc = string.IsNullOrEmpty(schemaName)
- ? new StoredProcedure(this.Database, sprocName)
- : new StoredProcedure(this.Database, sprocName, schemaName);
-
- sproc.Refresh();
-
- return sproc.Script();
- }
- catch (Exception ex)
- {
- Logger.Write(LogLevel.Error, "Exception at PeekDefinition GetStoredProcedureScripts : " + ex.Message);
- return null;
+ // With SqlLogin authentication, the defaultSchema property throws an Exception when accessed.
+ // This workaround ensures that a schema name is present by attempting
+ // to get the schema name from the declaration item.
+ // If all fails, the default schema name is assumed to be "dbo"
+ if ((connectionInfo != null && connectionInfo.ConnectionDetails.AuthenticationType.Equals(Constants.SqlLoginAuthenticationType)) && string.IsNullOrEmpty(schemaName))
+ {
+ string fullObjectName = databaseQualifiedName;
+ schemaName = this.GetSchemaFromDatabaseQualifiedName(fullObjectName, tokenText);
+ }
+ Location[] locations = GetSqlObjectDefinition(
+ sqlScriptGetters[type],
+ tokenText,
+ schemaName,
+ sqlObjectTypes[type]
+ );
+ DefinitionResult result = new DefinitionResult
+ {
+ IsErrorResult = this.error,
+ Message = this.errorMessage,
+ Locations = locations
+ };
+ return result;
}
+ // If a type was found but is not in sqlScriptGetters, then the type is not supported
+ return GetDefinitionErrorResult(SR.PeekDefinitionTypeNotSupportedError);
}
///
@@ -346,6 +276,71 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
}
}
+ #region Helper Methods
+ ///
+ /// Return schema name from the full name of the database. If schema is missing return dbo as schema name.
+ ///
+ /// The full database qualified name(database.schema.object)
+ /// Object name
+ /// Schema name
+ internal string GetSchemaFromDatabaseQualifiedName(string fullObjectName, string objectName)
+ {
+ if(!string.IsNullOrEmpty(fullObjectName))
+ {
+ string[] tokens = fullObjectName.Split('.');
+ for (int i = tokens.Length - 1; i > 0; i--)
+ {
+ if (tokens[i].Equals(objectName))
+ {
+ return tokens[i - 1];
+ }
+ }
+ }
+ return "dbo";
+ }
+
+ ///
+ /// Convert a file to a location array containing a location object as expected by the extension
+ ///
+ internal Location[] GetLocationFromFile(string tempFileName, int lineNumber)
+ {
+ // Get absolute Uri based on uri format. This works around a dotnetcore URI bug for linux paths.
+ if (Path.DirectorySeparatorChar.Equals('/'))
+ {
+ tempFileName = "file:" + tempFileName;
+ }
+ else
+ {
+ tempFileName = new Uri(tempFileName).AbsoluteUri;
+ }
+ // Create a location array containing the tempFile Uri, as expected by VSCode.
+ Location[] locations = new[] {
+ new Location {
+ Uri = tempFileName,
+ Range = new Range {
+ Start = new Position { Line = lineNumber, Character = 1},
+ End = new Position { Line = lineNumber + 1, Character = 1}
+ }
+ }
+ };
+ return locations;
+ }
+
+ ///
+ /// Get line number for the create statement
+ ///
+ private int GetStartOfCreate(string script, string createString)
+ {
+ string[] lines = script.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
+ for (int lineNumber = 0; lineNumber < lines.Length; lineNumber++)
+ {
+ if (lines[lineNumber].IndexOf(createString, StringComparison.OrdinalIgnoreCase) >= 0)
+ {
+ return lineNumber;
+ }
+ }
+ return 0;
+ }
///
/// Helper method to create definition error result object
///
@@ -360,5 +355,75 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
Locations = null
};
}
+
+ ///
+ /// Return full object name(database.schema.objectName) from the quickInfo text("type database.schema.objectName")
+ ///
+ /// QuickInfo Text for this token
+ /// Token Text
+ ///
+ internal string GetFullObjectNameFromQuickInfo(string quickInfoText, string tokenText)
+ {
+ if (string.IsNullOrEmpty(quickInfoText) || string.IsNullOrEmpty(tokenText))
+ {
+ return null;
+ }
+ // extract full object name from quickInfo text
+ string[] tokens = quickInfoText.Split(' ');
+ List tokenList = tokens.Where(el => el.Contains(tokenText)).ToList();
+ return (tokenList?.Count() > 0) ? tokenList[0] : null;
+ }
+
+ ///
+ /// Return token type from the quickInfo text("type database.schema.objectName")
+ ///
+ /// QuickInfo Text for this token
+ ///
+ ///
+ internal string GetTokenTypeFromQuickInfo(string quickInfoText, string tokenText)
+ {
+ if (string.IsNullOrEmpty(quickInfoText) || string.IsNullOrEmpty(tokenText))
+ {
+ return null;
+ }
+ // extract string denoting the token type from quickInfo text
+ string[] tokens = quickInfoText.Split(' ');
+ List indexList = tokens.Select((s, i) => new { i, s }).Where(el => (el.s).Contains(tokenText)).Select(el => el.i).ToList();
+ return (indexList?.Count() > 0) ? String.Join(" ", tokens.Take(indexList[0])) : null;
+ }
+
+
+ ///
+ /// Wrapper method that calls Resolver.GetQuickInfo
+ ///
+ internal string GetQuickInfoForToken(ParseResult parseResult, int parserLine, int parserColumn, IMetadataDisplayInfoProvider metadataDisplayInfoProvider)
+ {
+ if (parseResult == null || metadataDisplayInfoProvider == null)
+ {
+ return null;
+ }
+ Babel.CodeObjectQuickInfo quickInfo = Resolver.GetQuickInfo(
+ parseResult, parserLine, parserColumn, metadataDisplayInfoProvider);
+ return quickInfo?.Text;
+ }
+
+ ///
+ /// Wrapper method that calls Resolver.FindCompletions
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ internal IEnumerable GetCompletionsForToken(ParseResult parseResult, int parserLine, int parserColumn, IMetadataDisplayInfoProvider metadataDisplayInfoProvider)
+ {
+ if (parseResult == null || metadataDisplayInfoProvider == null)
+ {
+ return null;
+ }
+ return Resolver.FindCompletions(
+ parseResult, parserLine, parserColumn, metadataDisplayInfoProvider);
+ }
+ #endregion
}
}
\ No newline at end of file
diff --git a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/PeekDefinitionScripts.cs b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/PeekDefinitionScripts.cs
new file mode 100644
index 00000000..ca20816d
--- /dev/null
+++ b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/PeekDefinitionScripts.cs
@@ -0,0 +1,199 @@
+//
+// 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 System.IO;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using Microsoft.SqlServer.Management.Smo;
+using Microsoft.SqlServer.Management.SqlParser.Intellisense;
+using Microsoft.SqlTools.ServiceLayer.Utility;
+namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
+{
+ internal partial class PeekDefinition
+ {
+
+ private void Initialize()
+ {
+ AddSupportedType(DeclarationType.Table, GetTableScripts, "Table", "table");
+ AddSupportedType(DeclarationType.View, GetViewScripts, "View", "view");
+ AddSupportedType(DeclarationType.StoredProcedure, GetStoredProcedureScripts, "Procedure", "stored procedure");
+ AddSupportedType(DeclarationType.UserDefinedDataType, GetUserDefinedDataTypeScripts, "Type", "user-defined data type");
+ AddSupportedType(DeclarationType.UserDefinedTableType, GetUserDefinedTableTypeScripts, "Type", "user-defined table type");
+ AddSupportedType(DeclarationType.Synonym, GetSynonymScripts, "Synonym", "");
+ AddSupportedType(DeclarationType.ScalarValuedFunction, GetScalarValuedFunctionScripts, "Function", "scalar-valued function");
+ AddSupportedType(DeclarationType.TableValuedFunction, GetTableValuedFunctionScripts, "Function", "table-valued function");
+ }
+
+ ///
+ /// Script a Table using SMO
+ ///
+ /// Table name
+ /// Schema name
+ /// String collection of scripts
+ internal StringCollection GetTableScripts(string objectName, string schemaName)
+ {
+ try
+ {
+ Table smoObject = string.IsNullOrEmpty(schemaName) ? new Table(this.Database, objectName) : new Table(this.Database, objectName, schemaName);
+ smoObject.Refresh();
+ return smoObject.Script();
+ }
+ catch (Exception ex)
+ {
+ Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetTableScripts : " + ex.Message);
+ return null;
+ }
+ }
+
+ ///
+ /// Script a View using SMO
+ ///
+ /// View name
+ /// Schema name
+ /// String collection of scripts
+ internal StringCollection GetViewScripts(string objectName, string schemaName)
+ {
+ try
+ {
+ View smoObject = string.IsNullOrEmpty(schemaName) ? new View(this.Database, objectName) : new View(this.Database, objectName, schemaName);
+ smoObject.Refresh();
+ return smoObject.Script();
+ }
+ catch (Exception ex)
+ {
+ Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetViewScripts : " + ex.Message);
+ return null;
+ }
+ }
+
+ ///
+ /// Script a StoredProcedure using SMO
+ ///
+ /// StoredProcedure name
+ /// Schema name
+ /// String collection of scripts
+ internal StringCollection GetStoredProcedureScripts(string objectName, string schemaName)
+ {
+ try
+ {
+ StoredProcedure smoObject = string.IsNullOrEmpty(schemaName) ? new StoredProcedure(this.Database, objectName) : new StoredProcedure(this.Database, objectName, schemaName);
+ smoObject.Refresh();
+ return smoObject.Script();
+ }
+ catch (Exception ex)
+ {
+ Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetStoredProcedureScripts : " + ex.Message);
+ return null;
+ }
+ }
+
+ ///
+ /// Script a UserDefinedDataType using SMO
+ ///
+ /// UserDefinedDataType name
+ /// Schema name
+ /// String collection of scripts
+ internal StringCollection GetUserDefinedDataTypeScripts(string objectName, string schemaName)
+ {
+ try
+ {
+ UserDefinedDataType smoObject = string.IsNullOrEmpty(schemaName) ? new UserDefinedDataType(this.Database, objectName) : new UserDefinedDataType(this.Database, objectName, schemaName);
+ smoObject.Refresh();
+ return smoObject.Script();
+ }
+ catch (Exception ex)
+ {
+ Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetUserDefinedDataTypeScripts : " + ex.Message);
+ return null;
+ }
+ }
+
+ ///
+ /// Script a UserDefinedTableType using SMO
+ ///
+ /// UserDefinedTableType name
+ /// Schema name
+ /// String collection of scripts
+ internal StringCollection GetUserDefinedTableTypeScripts(string objectName, string schemaName)
+ {
+ try
+ {
+ UserDefinedTableType smoObject = string.IsNullOrEmpty(schemaName) ? new UserDefinedTableType(this.Database, objectName) : new UserDefinedTableType(this.Database, objectName, schemaName);
+ smoObject.Refresh();
+ return smoObject.Script();
+ }
+ catch (Exception ex)
+ {
+ Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetUserDefinedTableTypeScripts : " + ex.Message);
+ return null;
+ }
+ }
+
+ ///
+ /// Script a Synonym using SMO
+ ///
+ /// Synonym name
+ /// Schema name
+ /// String collection of scripts
+ internal StringCollection GetSynonymScripts(string objectName, string schemaName)
+ {
+ try
+ {
+ Synonym smoObject = string.IsNullOrEmpty(schemaName) ? new Synonym(this.Database, objectName) : new Synonym(this.Database, objectName, schemaName);
+ smoObject.Refresh();
+ return smoObject.Script();
+ }
+ catch (Exception ex)
+ {
+ Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetSynonymScripts : " + ex.Message);
+ return null;
+ }
+ }
+
+ ///
+ /// Script a ScalarValuedFunction using SMO
+ ///
+ /// ScalarValuedFunction name
+ /// Schema name
+ /// String collection of scripts
+ internal StringCollection GetScalarValuedFunctionScripts(string objectName, string schemaName)
+ {
+ try
+ {
+ UserDefinedFunction smoObject = string.IsNullOrEmpty(schemaName) ? new UserDefinedFunction(this.Database, objectName) : new UserDefinedFunction(this.Database, objectName, schemaName);
+ smoObject.Refresh();
+ return smoObject.Script();
+ }
+ catch (Exception ex)
+ {
+ Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetScalarValuedFunctionScripts : " + ex.Message);
+ return null;
+ }
+ }
+
+ ///
+ /// Script a TableValuedFunction using SMO
+ ///
+ /// TableValuedFunction name
+ /// Schema name
+ /// String collection of scripts
+ internal StringCollection GetTableValuedFunctionScripts(string objectName, string schemaName)
+ {
+ try
+ {
+ UserDefinedFunction smoObject = string.IsNullOrEmpty(schemaName) ? new UserDefinedFunction(this.Database, objectName) : new UserDefinedFunction(this.Database, objectName, schemaName);
+ smoObject.Refresh();
+ return smoObject.Script();
+ }
+ catch (Exception ex)
+ {
+ Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetTableValuedFunctionScripts : " + ex.Message);
+ return null;
+ }
+ }
+
+ }
+}
+
\ No newline at end of file
diff --git a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/PeekDefinitionScripts.tt b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/PeekDefinitionScripts.tt
new file mode 100644
index 00000000..ac72a0b5
--- /dev/null
+++ b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/PeekDefinitionScripts.tt
@@ -0,0 +1,144 @@
+<#@ template debug="false" hostspecific="true" language="C#" #>
+<#@ output extension=".cs" #>
+<#@ assembly name="System.Xml.dll" #>
+<#@ import namespace="System" #>
+<#@ import namespace="System.Globalization" #>
+<#@ import namespace="System.Text" #>
+<#@ import namespace="System.Xml" #>
+<#@ import namespace="System.Collections.Generic" #>
+<#@ import namespace="System.IO" #>
+//
+// 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 System.IO;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using Microsoft.SqlServer.Management.Smo;
+using Microsoft.SqlServer.Management.SqlParser.Intellisense;
+using Microsoft.SqlTools.ServiceLayer.Utility;
+namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
+{
+ internal partial class PeekDefinition
+ {
+
+ <#
+ ///
+ /// Generate Initialize method
+ ///
+ var indent = " ";
+ var directory = Path.GetDirectoryName(Host.TemplateFile);
+ string xmlFile = Path.Combine(directory, "PeekDefinitionSupportedTypes.xml");
+ var supportedTypes = GetSupportedTypes(xmlFile);
+ if (supportedTypes != null && supportedTypes.Count > 0)
+ {
+ WriteLine("private void Initialize()");
+ PushIndent(indent);
+ PushIndent(indent);
+ WriteLine("{");
+ PushIndent(indent);
+ foreach(var typeProperty in supportedTypes)
+ {
+ string functionCall = string.Format("AddSupportedType(DeclarationType.{0}, Get{0}Scripts, \"{1}\", \"{2}\");", typeProperty["Name"], typeProperty["CreateSyntax"], typeProperty["QuickInfoType"]);
+ WriteLine(functionCall);
+ }
+ PopIndent();
+ WriteLine("}\n");
+
+ ///
+ /// Generate scriptGetters for each type
+ ///
+
+ foreach(var typeProperty in supportedTypes)
+ {
+ string statement;
+ // Write comments
+ WriteLine("/// ");
+ WriteLine(string.Format("/// Script a {0} using SMO", typeProperty["Name"]));
+ WriteLine("/// ");
+ WriteLine(string.Format("/// {0} name", typeProperty["Name"]));
+ WriteLine(string.Format("/// Schema name"));
+ WriteLine("/// String collection of scripts");
+
+ WriteLine(string.Format("internal StringCollection Get{0}Scripts(string objectName, string schemaName)", typeProperty["Name"]));
+ WriteLine("{");
+ PushIndent(indent);
+
+ // Write try block to retrieve object and return script
+ WriteLine("try");
+ WriteLine("{");
+ if(typeProperty["SupportsSchemaQuery"].IndexOf("true", StringComparison.OrdinalIgnoreCase) >= 0)
+ {
+ statement = string.Format("{0} smoObject = string.IsNullOrEmpty(schemaName) ? new {0}(this.Database, objectName) : new {0}(this.Database, objectName, schemaName);", typeProperty["AccessClass"]);
+ }
+ else
+ {
+ statement = string.Format("{0} smoObject = new {0}(this.Database, objectName);", typeProperty["Name"]);
+ }
+ PushIndent(indent);
+ WriteLine(statement);
+ WriteLine("smoObject.Refresh();");
+ WriteLine("return smoObject.Script();");
+ PopIndent();
+ WriteLine("}");
+
+ // Write catch block to catch and log exceptions
+ WriteLine("catch (Exception ex)");
+ WriteLine("{");
+ PushIndent(indent);
+ statement = string.Format("LogLevel.Error,\"Exception at PeekDefinition Get{0}Scripts : \" + ex.Message", typeProperty["Name"]);
+ WriteLine("Logger.Write(" + statement + ");");
+ WriteLine("return null;");
+ PopIndent();
+ WriteLine("}");
+ PopIndent();
+ WriteLine("}\n");
+ }
+ }
+ PopIndent();
+ PopIndent();
+ #>
+ }
+}
+ <#+
+ ///
+ /// Get the supported types from the xml file
+ ///
+ public static List> GetSupportedTypes(string xmlFile)
+ {
+ List> typeList = null;
+ XmlDocument doc = new XmlDocument();
+ doc.Load(xmlFile);
+ XmlNodeList supportedTypes = doc.SelectNodes("/SupportedTypes/Type");
+ if (supportedTypes != null)
+ {
+ typeList = new List>();
+ foreach (var type in supportedTypes)
+ {
+ XmlElement node = type as XmlElement;
+ if (node != null)
+ {
+ string typeName = (node["Name"] != null) ? node["Name"].InnerText : null;
+ string createSyntax = (node["CreateSyntax"] != null) ? node["CreateSyntax"].InnerText : null;
+ string accessClass = (node["AccessClass"] != null) ? node["AccessClass"].InnerText : null;
+ string supportsSchemaQuery = (node["SupportsSchemaQuery"] != null) ? node["SupportsSchemaQuery"].InnerText : null;
+ string quickInfoType = (node["QuickInfoType"] != null) ? node["QuickInfoType"].InnerText : null;
+ if (typeName != null && createSyntax != null && accessClass != null && supportsSchemaQuery!= null)
+ {
+ Dictionary typeProperties = new Dictionary();
+ typeProperties.Add("Name", typeName);
+ typeProperties.Add("CreateSyntax", createSyntax);
+ typeProperties.Add("AccessClass", accessClass);
+ typeProperties.Add("SupportsSchemaQuery", supportsSchemaQuery);
+ typeProperties.Add("QuickInfoType", quickInfoType);
+ typeList.Add(typeProperties);
+ }
+
+ }
+ }
+ }
+ return typeList;
+ }
+
+ #>
\ No newline at end of file
diff --git a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/PeekDefinitionSupportedTypes.xml b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/PeekDefinitionSupportedTypes.xml
new file mode 100644
index 00000000..b5325208
--- /dev/null
+++ b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/PeekDefinitionSupportedTypes.xml
@@ -0,0 +1,66 @@
+
+
+
+ Table
+ Table
+ Table
+ table
+ true
+
+
+ View
+ View
+ View
+ view
+ true
+
+
+ StoredProcedure
+ Procedure
+ StoredProcedure
+ stored procedure
+ true
+
+
+ UserDefinedDataType
+ Type
+ UserDefinedDataType
+ user-defined data type
+ true
+
+
+ UserDefinedTableType
+ Type
+ UserDefinedTableType
+ user-defined table type
+ true
+
+
+ Synonym
+ Synonym
+ Synonym
+
+ true
+
+
+ ScalarValuedFunction
+ Function
+ UserDefinedFunction
+ scalar-valued function
+ true
+
+
+ TableValuedFunction
+ Function
+ UserDefinedFunction
+ table-valued function
+ true
+
+
diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/LanguageServer/PeekDefinitionTests.cs b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/LanguageServer/PeekDefinitionTests.cs
index d3113b86..e619e657 100644
--- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/LanguageServer/PeekDefinitionTests.cs
+++ b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/LanguageServer/PeekDefinitionTests.cs
@@ -4,29 +4,23 @@
//
using System;
using System.IO;
-using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
-using System.Runtime.InteropServices;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.SqlParser.Binder;
-using Microsoft.SqlServer.Management.SqlParser.Intellisense;
-using Microsoft.SqlServer.Management.SqlParser.MetadataProvider;
-using Microsoft.SqlServer.Management.SqlParser.Parser;
using Microsoft.SqlTools.ServiceLayer.Connection;
+using Microsoft.SqlServer.Management.SqlParser.MetadataProvider;
using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol;
-using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts;
using Microsoft.SqlTools.ServiceLayer.LanguageServices;
-using Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts;
+using Microsoft.SqlTools.ServiceLayer.LanguageServices.Completion;
using Microsoft.SqlTools.ServiceLayer.SqlContext;
-using Microsoft.SqlTools.ServiceLayer.QueryExecution;
-using Microsoft.SqlTools.ServiceLayer.Test.QueryExecution;
using Microsoft.SqlTools.ServiceLayer.Workspace;
using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts;
using Microsoft.SqlTools.Test.Utility;
using Moq;
using Xunit;
using Location = Microsoft.SqlTools.ServiceLayer.Workspace.Contracts.Location;
+using Microsoft.SqlServer.Management.SqlParser.Intellisense;
namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServices
{
@@ -114,9 +108,10 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServices
{
Line = 0,
// test for 'dbo'
- Character = 16
+ Character = 15
}
};
+
TestConnectionResult connectionResult = await TestObjects.InitLiveConnectionInfo();
connectionResult.ScriptFile.Contents = "select * from dbo.func ()";
var languageService = new LanguageService();
@@ -142,15 +137,20 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServices
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
string objectName = "from";
-
- List declarations = new List();
- DefinitionResult result = peekDefinition.GetScript(declarations, objectName, null);
+ Position position = new Position()
+ {
+ Line = 1,
+ Character = 14
+ };
+ ScriptParseInfo scriptParseInfo = new ScriptParseInfo() { IsConnected = true };
+ Mock bindingContextMock = new Mock();
+ DefinitionResult result = peekDefinition.GetScript(scriptParseInfo.ParseResult, position, bindingContextMock.Object.MetadataDisplayInfoProvider, objectName, null);
Assert.NotNull(result);
Assert.True(result.IsErrorResult);
Assert.Equal(SR.PeekDefinitionNoResultsError, result.Message);
}
-
+
///
/// Test GetDefinition with a forced timeout. Expect a error result.
///
@@ -164,9 +164,9 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServices
ManualResetEvent mre = new ManualResetEvent(true); // Do not block
Mock itemMock = new Mock();
itemMock.Setup(i => i.ItemProcessed).Returns(mre);
-
+
DefinitionResult timeoutResult = null;
-
+
queueMock.Setup(q => q.QueueBindingOperation(
It.IsAny(),
It.IsAny>(),
@@ -174,7 +174,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServices
It.IsAny(),
It.IsAny()))
.Callback, Func, int?, int?>(
- (key, bindOperation, timeoutOperation, blah, blah2) =>
+ (key, bindOperation, timeoutOperation, t1, t2) =>
{
timeoutResult = (DefinitionResult) timeoutOperation((IBindingContext)null);
itemMock.Object.Result = timeoutResult;
@@ -306,6 +306,387 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServices
Cleanup(locations);
}
+ ///
+ /// Test get definition for a scalar valued function object with active connection and explicit schema name. Expect non-null locations
+ ///
+ [Fact]
+ public async Task GetScalarValuedFunctionDefinitionWithSchemaNameSuccessTest()
+ {
+ // Get live connectionInfo and serverConnection
+ ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition();
+ ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
+
+ PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
+ string objectName = "pd_addTwo";
+ string schemaName = "dbo";
+ string objectType = "FUNCTION";
+
+ Location[] locations = peekDefinition.GetSqlObjectDefinition(peekDefinition.GetScalarValuedFunctionScripts, objectName, schemaName, objectType);
+ Assert.NotNull(locations);
+ Cleanup(locations);
+ }
+
+ ///
+ /// Test get definition for a table valued function object with active connection and explicit schema name. Expect non-null locations
+ ///
+ [Fact]
+ public async Task GetTableValuedFunctionDefinitionWithSchemaNameSuccessTest()
+ {
+ // Get live connectionInfo and serverConnection
+ ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition();
+ ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
+
+ PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
+ string objectName = "pd_returnTable";
+ string schemaName = "dbo";
+ string objectType = "FUNCTION";
+
+ Location[] locations = peekDefinition.GetSqlObjectDefinition(peekDefinition.GetTableValuedFunctionScripts, objectName, schemaName, objectType);
+ Assert.NotNull(locations);
+ Cleanup(locations);
+ }
+
+ ///
+ /// Test get definition for a scalar valued function object that doesn't exist with active connection. Expect null locations
+ ///
+ [Fact]
+ public async Task GetScalarValuedFunctionDefinitionWithNonExistentFailureTest()
+ {
+ // Get live connectionInfo and serverConnection
+ ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition();
+ ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
+
+ PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
+ string objectName = "doesNotExist";
+ string schemaName = "dbo";
+ string objectType = "FUNCTION";
+
+ Location[] locations = peekDefinition.GetSqlObjectDefinition(peekDefinition.GetScalarValuedFunctionScripts, objectName, schemaName, objectType);
+ Assert.Null(locations);
+ }
+
+ ///
+ /// Test get definition for a table valued function object that doesn't exist with active connection. Expect null locations
+ ///
+ [Fact]
+ public async Task GetTableValuedFunctionDefinitionWithNonExistentObjectFailureTest()
+ {
+ // Get live connectionInfo and serverConnection
+ ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition();
+ ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
+
+ PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
+ string objectName = "doesNotExist";
+ string schemaName = "dbo";
+ string objectType = "FUNCTION";
+
+ Location[] locations = peekDefinition.GetSqlObjectDefinition(peekDefinition.GetTableValuedFunctionScripts, objectName, schemaName, objectType);
+ Assert.Null(locations);
+ }
+
+ ///
+ /// Test get definition for a scalar valued function object with active connection. Expect non-null locations
+ ///
+ [Fact]
+ public async Task GetScalarValuedFunctionDefinitionWithoutSchemaNameSuccessTest()
+ {
+ // Get live connectionInfo and serverConnection
+ ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition();
+ ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
+
+ PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
+ string objectName = "pd_addTwo";
+ string schemaName = null;
+ string objectType = "FUNCTION";
+
+ Location[] locations = peekDefinition.GetSqlObjectDefinition(peekDefinition.GetScalarValuedFunctionScripts, objectName, schemaName, objectType);
+ Assert.NotNull(locations);
+ Cleanup(locations);
+ }
+
+ ///
+ /// Test get definition for a table valued function object with active connection. Expect non-null locations
+ ///
+ [Fact]
+ public async Task GetTableValuedFunctionDefinitionWithoutSchemaNameSuccessTest()
+ {
+ // Get live connectionInfo and serverConnection
+ ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition();
+ ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
+
+ PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
+ string objectName = "pd_returnTable";
+ string schemaName = null;
+ string objectType = "FUNCTION";
+
+ Location[] locations = peekDefinition.GetSqlObjectDefinition(peekDefinition.GetTableValuedFunctionScripts, objectName, schemaName, objectType);
+ Assert.NotNull(locations);
+ Cleanup(locations);
+ }
+
+
+ ///
+ /// Test get definition for a user defined data type object with active connection and explicit schema name. Expect non-null locations
+ ///
+ [Fact]
+ public async Task GetUserDefinedDataTypeDefinitionWithSchemaNameSuccessTest()
+ {
+ // Get live connectionInfo and serverConnection
+ ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition();
+ ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
+
+ PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
+ string objectName = "pd_ssn";
+ string schemaName = "dbo";
+ string objectType = "Type";
+
+ Location[] locations = peekDefinition.GetSqlObjectDefinition(peekDefinition.GetUserDefinedDataTypeScripts, objectName, schemaName, objectType);
+ Assert.NotNull(locations);
+ Cleanup(locations);
+ }
+
+ ///
+ /// Test get definition for a user defined data type object with active connection. Expect non-null locations
+ ///
+ [Fact]
+ public async Task GetUserDefinedDataTypeDefinitionWithoutSchemaNameSuccessTest()
+ {
+ // Get live connectionInfo and serverConnection
+ ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition();
+ ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
+
+ PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
+ string objectName = "pd_ssn";
+ string schemaName = null;
+ string objectType = "Type";
+
+ Location[] locations = peekDefinition.GetSqlObjectDefinition(peekDefinition.GetUserDefinedDataTypeScripts, objectName, schemaName, objectType);
+ Assert.NotNull(locations);
+ Cleanup(locations);
+ }
+
+ ///
+ /// Test get definition for a user defined data type object that doesn't exist with active connection. Expect null locations
+ ///
+ [Fact]
+ public async Task GetUserDefinedDataTypeDefinitionWithNonExistentFailureTest()
+ {
+ // Get live connectionInfo and serverConnection
+ ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition();
+ ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
+
+ PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
+ string objectName = "doesNotExist";
+ string schemaName = "dbo";
+ string objectType = "Type";
+
+ Location[] locations = peekDefinition.GetSqlObjectDefinition(peekDefinition.GetUserDefinedDataTypeScripts, objectName, schemaName, objectType);
+ Assert.Null(locations);
+ }
+
+ ///
+ /// Test get definition for a user defined table type object with active connection and explicit schema name. Expect non-null locations
+ ///
+ [Fact]
+ public async Task GetUserDefinedTableTypeDefinitionWithSchemaNameSuccessTest()
+ {
+ // Get live connectionInfo and serverConnection
+ ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition();
+ ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
+
+ PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
+ string objectName = "pd_locationTableType";
+ string schemaName = "dbo";
+ string objectType = "Type";
+
+ Location[] locations = peekDefinition.GetSqlObjectDefinition(peekDefinition.GetUserDefinedTableTypeScripts, objectName, schemaName, objectType);
+ Assert.NotNull(locations);
+ Cleanup(locations);
+ }
+
+ ///
+ /// Test get definition for a user defined table type object with active connection. Expect non-null locations
+ ///
+ [Fact]
+ public async Task GetUserDefinedTableTypeDefinitionWithoutSchemaNameSuccessTest()
+ {
+ // Get live connectionInfo and serverConnection
+ ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition();
+ ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
+
+ PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
+ string objectName = "pd_locationTableType";
+ string schemaName = null;
+ string objectType = "Type";
+
+ Location[] locations = peekDefinition.GetSqlObjectDefinition(peekDefinition.GetUserDefinedTableTypeScripts, objectName, schemaName, objectType);
+ Assert.NotNull(locations);
+ Cleanup(locations);
+ }
+
+ ///
+ /// Test get definition for a user defined table type object that doesn't exist with active connection. Expect null locations
+ ///
+ [Fact]
+ public async Task GetUserDefinedTableTypeDefinitionWithNonExistentFailureTest()
+ {
+ // Get live connectionInfo and serverConnection
+ ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition();
+ ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
+
+ PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
+ string objectName = "doesNotExist";
+ string schemaName = "dbo";
+ string objectType = "Type";
+
+ Location[] locations = peekDefinition.GetSqlObjectDefinition(peekDefinition.GetUserDefinedTableTypeScripts, objectName, schemaName, objectType);
+ Assert.Null(locations);
+ }
+
+ ///
+ /// Test get definition for a synonym object with active connection and explicit schema name. Expect non-null locations
+ ///
+ [Fact]
+ public async Task GetSynonymDefinitionWithSchemaNameSuccessTest()
+ {
+ // Get live connectionInfo and serverConnection
+ ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition();
+ ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
+
+ PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
+ string objectName = "pd_testTable";
+ string schemaName = "dbo";
+ string objectType = "Synonym";
+
+ Location[] locations = peekDefinition.GetSqlObjectDefinition(peekDefinition.GetSynonymScripts, objectName, schemaName, objectType);
+ Assert.NotNull(locations);
+ Cleanup(locations);
+ }
+
+
+ ///
+ /// Test get definition for a Synonym object with active connection. Expect non-null locations
+ ///
+ [Fact]
+ public async Task GetSynonymDefinitionWithoutSchemaNameSuccessTest()
+ {
+ // Get live connectionInfo and serverConnection
+ ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition();
+ ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
+
+ PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
+ string objectName = "pd_testTable";
+ string schemaName = null;
+ string objectType = "Synonym";
+
+ Location[] locations = peekDefinition.GetSqlObjectDefinition(peekDefinition.GetSynonymScripts, objectName, schemaName, objectType);
+ Assert.NotNull(locations);
+ Cleanup(locations);
+ }
+
+ ///
+ /// Test get definition for a Synonym object that doesn't exist with active connection. Expect null locations
+ ///
+ [Fact]
+ public async Task GetSynonymDefinitionWithNonExistentFailureTest()
+ {
+ // Get live connectionInfo and serverConnection
+ ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition();
+ ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
+
+ PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
+ string objectName = "doesNotExist";
+ string schemaName = "dbo";
+ string objectType = "Synonym";
+
+ Location[] locations = peekDefinition.GetSqlObjectDefinition(peekDefinition.GetSynonymScripts, objectName, schemaName, objectType);
+ Assert.Null(locations);
+ }
+
+ ///
+ /// Test get definition using declaration type for a view object with active connection
+ /// Expect a non-null result with location
+ ///
+ [Fact]
+ public async Task GetDefinitionUsingDeclarationTypeWithValidObjectTest()
+ {
+ ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition();
+ ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
+
+ PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
+ string objectName = "objects";
+ string schemaName = "sys";
+
+ DefinitionResult result = peekDefinition.GetDefinitionUsingDeclarationType(DeclarationType.View, "master.sys.objects", objectName, schemaName);
+ Assert.NotNull(result);
+ Assert.NotNull(result.Locations);
+ Assert.False(result.IsErrorResult);
+ Cleanup(result.Locations);
+
+ }
+
+ ///
+ /// Test get definition using declaration type for a non existent view object with active connection
+ /// Expect a non-null result with location
+ ///
+ [Fact]
+ public async Task GetDefinitionUsingDeclarationTypeWithNonexistentObjectTest()
+ {
+ ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition();
+ ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
+
+ PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
+ string objectName = "doesNotExist";
+ string schemaName = "sys";
+
+ DefinitionResult result = peekDefinition.GetDefinitionUsingDeclarationType(DeclarationType.View, "master.sys.objects", objectName, schemaName);
+ Assert.NotNull(result);
+ Assert.True(result.IsErrorResult);
+ }
+
+ ///
+ /// Test get definition using quickInfo text for a view object with active connection
+ /// Expect a non-null result with location
+ ///
+ [Fact]
+ public async Task GetDefinitionUsingQuickInfoTextWithValidObjectTest()
+ {
+ ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition();
+ ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
+
+ PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
+ string objectName = "objects";
+ string schemaName = "sys";
+ string quickInfoText = "view master.sys.objects";
+
+ DefinitionResult result = peekDefinition.GetDefinitionUsingQuickInfoText(quickInfoText, objectName, schemaName);
+ Assert.NotNull(result);
+ Assert.NotNull(result.Locations);
+ Assert.False(result.IsErrorResult);
+ Cleanup(result.Locations);
+
+ }
+
+ ///
+ /// Test get definition using quickInfo text for a view object with active connection
+ /// Expect a non-null result with location
+ ///
+ [Fact]
+ public async Task GetDefinitionUsingQuickInfoTextWithNonexistentObjectTest()
+ {
+ ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition();
+ ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
+
+ PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
+ string objectName = "doesNotExist";
+ string schemaName = "sys";
+ string quickInfoText = "view master.sys.objects";
+
+ DefinitionResult result = peekDefinition.GetDefinitionUsingQuickInfoText(quickInfoText, objectName, schemaName);
+ Assert.NotNull(result);
+ Assert.True(result.IsErrorResult);
+ }
+
///
/// Helper method to clean up script files
///
diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test/LanguageServer/PeekDefinitionTests.cs b/test/Microsoft.SqlTools.ServiceLayer.Test/LanguageServer/PeekDefinitionTests.cs
index cc1d3e8e..a1d19476 100644
--- a/test/Microsoft.SqlTools.ServiceLayer.Test/LanguageServer/PeekDefinitionTests.cs
+++ b/test/Microsoft.SqlTools.ServiceLayer.Test/LanguageServer/PeekDefinitionTests.cs
@@ -220,7 +220,155 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices
FileUtils.SafeDirectoryDelete(FileUtils.PeekDefinitionTempFolder, true);
Assert.False(Directory.Exists(FileUtils.PeekDefinitionTempFolder));
// Expected not to throw any exception
- languageService.DeletePeekDefinitionScripts();
+ languageService.DeletePeekDefinitionScripts();
+ }
+
+ ///
+ /// Test Extracting the full object name from quickInfoText.
+ /// Given a valid object name string and a vaild quickInfo string containing the object name
+ /// Expect the full object name (database.schema.objectName)
+ ///
+ [Fact]
+ public void GetFullObjectNameFromQuickInfoWithValidStringsTest()
+ {
+ PeekDefinition peekDefinition = new PeekDefinition(null, null);
+ string objectName = "testTable";
+ string quickInfoText = "table master.dbo.testTable";
+ string result = peekDefinition.GetFullObjectNameFromQuickInfo(quickInfoText, objectName);
+ string expected = "master.dbo.testTable";
+ Assert.Equal(expected, result);
+ }
+
+ ///
+ /// Test Extracting the full object name from quickInfoText.
+ /// Given a null object name string and a vaild quickInfo string containing the object name( and vice versa)
+ /// Expect null
+ ///
+ [Fact]
+ public void GetFullObjectNameFromQuickInfoWithNullStringsTest()
+ {
+ PeekDefinition peekDefinition = new PeekDefinition(null, null);
+ string expected = null;
+
+ string objectName = null;
+ string quickInfoText = "table master.dbo.testTable";
+ string result = peekDefinition.GetFullObjectNameFromQuickInfo(quickInfoText, objectName);
+ Assert.Equal(expected, result);
+
+ quickInfoText = null;
+ objectName = "tableName";
+ result = peekDefinition.GetFullObjectNameFromQuickInfo(quickInfoText, objectName);
+ Assert.Equal(expected, result);
+
+ quickInfoText = null;
+ objectName = null;
+ result = peekDefinition.GetFullObjectNameFromQuickInfo(quickInfoText, objectName);
+ Assert.Equal(expected, result);
+ }
+
+ ///
+ /// Test Extracting the full object name from quickInfoText.
+ /// Given a valid object name string and a vaild quickInfo string that does not contain the object name
+ /// Expect null
+ ///
+ [Fact]
+ public void GetFullObjectNameFromQuickInfoWithIncorrectObjectNameTest()
+ {
+ PeekDefinition peekDefinition = new PeekDefinition(null, null);
+ string objectName = "test";
+ string quickInfoText = "table master.dbo.tableName";
+ string result = peekDefinition.GetFullObjectNameFromQuickInfo(quickInfoText, objectName);
+ string expected = null;
+ Assert.Equal(expected, result);
+ }
+
+ ///
+ /// Test Extracting the object type from quickInfoText.
+ /// Given a valid object name string and a vaild quickInfo string containing the object name
+ /// Expect correct object type
+ ///
+ [Fact]
+ public void GetTokenTypeFromQuickInfoWithValidStringsTest()
+ {
+ PeekDefinition peekDefinition = new PeekDefinition(null, null);
+ string objectName = "tableName";
+ string quickInfoText = "table master.dbo.tableName";
+ string result = peekDefinition.GetTokenTypeFromQuickInfo(quickInfoText, objectName);
+ string expected = "table";
+ Assert.Equal(expected, result);
+ }
+
+ ///
+ /// Test Extracting theobject type from quickInfoText.
+ /// Given a null object name string and a vaild quickInfo string containing the object name( and vice versa)
+ /// Expect null
+ ///
+ [Fact]
+ public void GetTokenTypeFromQuickInfoWithNullStringsTest()
+ {
+ PeekDefinition peekDefinition = new PeekDefinition(null, null);
+ string expected = null;
+
+ string objectName = null;
+ string quickInfoText = "table master.dbo.testTable";
+ string result = peekDefinition.GetTokenTypeFromQuickInfo(quickInfoText, objectName);
+ Assert.Equal(expected, result);
+
+ quickInfoText = null;
+ objectName = "tableName";
+ result = peekDefinition.GetTokenTypeFromQuickInfo(quickInfoText, objectName);
+ Assert.Equal(expected, result);
+
+ quickInfoText = null;
+ objectName = null;
+ result = peekDefinition.GetTokenTypeFromQuickInfo(quickInfoText, objectName);
+ Assert.Equal(expected, result);
+ }
+
+ ///
+ /// Test Extracting the object type from quickInfoText.
+ /// Given a valid object name string and a vaild quickInfo string that does not containthe object name
+ /// Expect null
+ ///
+ [Fact]
+ public void GetTokenTypeFromQuickInfoWithIncorrectObjectNameTest()
+ {
+ PeekDefinition peekDefinition = new PeekDefinition(null, null);
+ string objectName = "test";
+ string quickInfoText = "table master.dbo.tableName";
+ string result = peekDefinition.GetTokenTypeFromQuickInfo(quickInfoText, objectName);
+ string expected = null;
+ Assert.Equal(expected, result);
+ }
+
+ ///
+ /// test Getting definition using quickInfo text without a live connection
+ /// Expect an error result( because you cannot script without a live connection)
+ ///
+ [Fact]
+ public void GetDefinitionUsingQuickInfoWithoutConnectionTest()
+ {
+ PeekDefinition peekDefinition = new PeekDefinition(null, null);
+ string objectName = "tableName";
+ string quickInfoText = "table master.dbo.tableName";
+ DefinitionResult result = peekDefinition.GetDefinitionUsingQuickInfoText(quickInfoText, objectName, null);
+ Assert.NotNull(result);
+ Assert.True(result.IsErrorResult);
+ }
+
+ ///
+ /// test Getting definition using declarration Type without a live connection
+ /// Expect an error result( because you cannot script without a live connection)
+ ///
+ [Fact]
+ public void GetDefinitionUsingDeclarationItemWithoutConnectionTest()
+ {
+ PeekDefinition peekDefinition = new PeekDefinition(null, null);
+ string objectName = "tableName";
+ string fullObjectName = "master.dbo.tableName";
+ DefinitionResult result = peekDefinition.GetDefinitionUsingDeclarationType(DeclarationType.Table, fullObjectName, objectName, null);
+ Assert.NotNull(result);
+ Assert.True(result.IsErrorResult);
}
}
}
diff --git a/test/Microsoft.SqlTools.ServiceLayer.TestDriver.Tests/LanguageServiceTests.cs b/test/Microsoft.SqlTools.ServiceLayer.TestDriver.Tests/LanguageServiceTests.cs
index 007fc3e6..f7803176 100644
--- a/test/Microsoft.SqlTools.ServiceLayer.TestDriver.Tests/LanguageServiceTests.cs
+++ b/test/Microsoft.SqlTools.ServiceLayer.TestDriver.Tests/LanguageServiceTests.cs
@@ -45,7 +45,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
};
await testService.RequestOpenDocumentNotification(openParams);
-
+
Thread.Sleep(500);
bool connected = await testService.Connect(TestServerType.OnPrem, queryTempFile.FilePath);
@@ -86,7 +86,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
};
await testService.RequestOpenDocumentNotification(openParams);
-
+
Thread.Sleep(500);
bool connected = await testService.Connect(TestServerType.OnPrem, queryTempFile.FilePath);
@@ -136,7 +136,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
};
await testService.RequestOpenDocumentNotification(openParams);
-
+
Thread.Sleep(100);
var contentChanges = new TextDocumentChangeEvent[1];
@@ -172,7 +172,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
await testService.RequestChangeTextDocumentNotification(changeParams);
Thread.Sleep(100);
-
+
contentChanges[0] = new TextDocumentChangeEvent
{
Range = new Range
@@ -211,7 +211,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
}
///
- /// Peek Definition/ Go to definition
+ /// Peek Definition/ Go to definition
///
///
[Fact]
@@ -238,16 +238,20 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
};
await testService.RequestOpenDocumentNotification(openParams);
-
+
Thread.Sleep(500);
bool connected = await testService.Connect(TestServerType.OnPrem, queryTempFile.FilePath);
+
+ // Wait for intellisense to be ready
+ var readyParams = await testService.Driver.WaitForEvent(IntelliSenseReadyNotification.Type, 30000);
+ Assert.NotNull(readyParams);
Assert.True(connected, "Connection is successful");
- Thread.Sleep(10000);
+
// Request definition for "objects"
Location[] locations = await testService.RequestDefinition(queryTempFile.FilePath, query, lineNumber, position);
-
+
Assert.True(locations != null, "Location is not null and not empty");
await testService.Disconnect(queryTempFile.FilePath);
}
@@ -265,7 +269,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
bool connected = await testService.Connect(TestServerType.OnPrem, queryTempFile.FilePath);
Assert.True(connected, "Connection was not successful");
- Thread.Sleep(500);
+ Thread.Sleep(500);
var settings = new SqlToolsSettings();
settings.SqlTools.IntelliSense.EnableIntellisense = false;
@@ -422,10 +426,10 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
public async Task VerifyFunctionSignatureHelpParameter(
TestServiceDriverProvider TestService,
- string ownerUri,
- int character,
- string expectedFunctionName,
- int expectedParameterIndex,
+ string ownerUri,
+ int character,
+ string expectedFunctionName,
+ int expectedParameterIndex,
string expectedParameterName)
{
var position = new TextDocumentPosition()