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:
Sharon Ravindran
2017-01-19 13:24:58 -08:00
committed by GitHub
parent c055c459a0
commit 5464e4e63a
11 changed files with 1336 additions and 314 deletions

View File

@@ -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

View File

@@ -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
/// </summary>
internal class PeekDefinition
internal partial class PeekDefinition
{
private bool error;
private string errorMessage;
@@ -37,9 +41,14 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
private Dictionary<DeclarationType, ScriptGetter> sqlScriptGetters =
new Dictionary<DeclarationType, ScriptGetter>();
private Dictionary<string, ScriptGetter> sqlScriptGettersFromQuickInfo =
new Dictionary<string, ScriptGetter>();
// Dictionary that holds the object name (as appears on the TSQL create statement)
private Dictionary<DeclarationType, string> sqlObjectTypes = new Dictionary<DeclarationType, string>();
private Dictionary<string, string> sqlObjectTypesFromQuickInfo = new Dictionary<string, string>();
/// <summary>
/// Initialize a Peek Definition helper object
/// </summary>
@@ -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;
}
}
/// <summary>
/// Add getters for each sql object supported by peek definition
/// </summary>
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");
}
/// <summary>
/// Add the given type, scriptgetter and the typeName string to the respective dictionaries
/// </summary>
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);
}
/// <summary>
/// Convert a file to a location array containing a location object as expected by the extension
/// </summary>
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;
}
/// <summary>
/// Get line number for the create statement
/// </summary>
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;
}
/// <summary>
@@ -162,45 +116,77 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
/// <param name="tokenText"></param>
/// <param name="schemaName"></param>
/// <returns>Location object of the script file</returns>
internal DefinitionResult GetScript(IEnumerable<Declaration> 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<Declaration> 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);
}
/// <summary>
/// Script an object using the type extracted from quickInfo Text
/// </summary>
/// <param name="quickInfoText">the text from the quickInfo for the selected token</param>
/// <param name="tokenText">The text of the selected token</param>
/// <param name="schemaName">Schema name</param>
/// <returns></returns>
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
}
/// <summary>
/// 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
/// </summary>
/// <param name="fullObjectName"> The full database qualified name(database.schema.object)</param>
/// <param name="objectName"> Object name</param>
/// <returns>Schema name</returns>
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";
}
/// <summary>
/// Script a table using SMO
/// </summary>
/// <param name="tableName">Table name</param>
/// <param name="declarationItem">The Declarartion object that matched with the selected token</param>
/// <param name="tokenText">The text of the selected token</param>
/// <param name="schemaName">Schema name</param>
/// <returns>String collection of scripts</returns>
internal StringCollection GetTableScripts(string tableName, string schemaName)
/// <returns></returns>
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;
}
}
/// <summary>
/// Script a view using SMO
/// </summary>
/// <param name="viewName">View name</param>
/// <param name="schemaName">Schema name </param>
/// <returns>String collection of scripts</returns>
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;
}
}
/// <summary>
/// Script a stored procedure using SMO
/// </summary>
/// <param name="storedProcedureName">Stored Procedure name</param>
/// <param name="schemaName">Schema Name</param>
/// <returns>String collection of scripts</returns>
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);
}
/// <summary>
@@ -346,6 +276,71 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
}
}
#region Helper Methods
/// <summary>
/// Return schema name from the full name of the database. If schema is missing return dbo as schema name.
/// </summary>
/// <param name="fullObjectName"> The full database qualified name(database.schema.object)</param>
/// <param name="objectName"> Object name</param>
/// <returns>Schema name</returns>
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";
}
/// <summary>
/// Convert a file to a location array containing a location object as expected by the extension
/// </summary>
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;
}
/// <summary>
/// Get line number for the create statement
/// </summary>
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;
}
/// <summary>
/// Helper method to create definition error result object
/// </summary>
@@ -360,5 +355,75 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
Locations = null
};
}
/// <summary>
/// Return full object name(database.schema.objectName) from the quickInfo text("type database.schema.objectName")
/// </summary>
/// <param name="quickInfoText">QuickInfo Text for this token</param>
/// <param name="tokenText">Token Text</param>
/// <returns></returns>
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<string> tokenList = tokens.Where(el => el.Contains(tokenText)).ToList();
return (tokenList?.Count() > 0) ? tokenList[0] : null;
}
/// <summary>
/// Return token type from the quickInfo text("type database.schema.objectName")
/// </summary>
/// <param name="quickInfoText">QuickInfo Text for this token</param>
/// <param name="tokenText"Token Text></param>
/// <returns></returns>
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<int> 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;
}
/// <summary>
/// Wrapper method that calls Resolver.GetQuickInfo
/// </summary>
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;
}
/// <summary>
/// Wrapper method that calls Resolver.FindCompletions
/// </summary>
/// <param name="parseResult"></param>
/// <param name="parserLine"></param>
/// <param name="parserColumn"></param>
/// <param name="metadataDisplayInfoProvider"></param>
/// <returns></returns>
internal IEnumerable<Declaration> GetCompletionsForToken(ParseResult parseResult, int parserLine, int parserColumn, IMetadataDisplayInfoProvider metadataDisplayInfoProvider)
{
if (parseResult == null || metadataDisplayInfoProvider == null)
{
return null;
}
return Resolver.FindCompletions(
parseResult, parserLine, parserColumn, metadataDisplayInfoProvider);
}
#endregion
}
}

View File

@@ -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");
}
/// <summary>
/// Script a Table using SMO
/// </summary>
/// <param name="objectName">Table name</param>
/// <param name="schemaName">Schema name</param>
/// <returns>String collection of scripts</returns>
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;
}
}
/// <summary>
/// Script a View using SMO
/// </summary>
/// <param name="objectName">View name</param>
/// <param name="schemaName">Schema name</param>
/// <returns>String collection of scripts</returns>
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;
}
}
/// <summary>
/// Script a StoredProcedure using SMO
/// </summary>
/// <param name="objectName">StoredProcedure name</param>
/// <param name="schemaName">Schema name</param>
/// <returns>String collection of scripts</returns>
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;
}
}
/// <summary>
/// Script a UserDefinedDataType using SMO
/// </summary>
/// <param name="objectName">UserDefinedDataType name</param>
/// <param name="schemaName">Schema name</param>
/// <returns>String collection of scripts</returns>
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;
}
}
/// <summary>
/// Script a UserDefinedTableType using SMO
/// </summary>
/// <param name="objectName">UserDefinedTableType name</param>
/// <param name="schemaName">Schema name</param>
/// <returns>String collection of scripts</returns>
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;
}
}
/// <summary>
/// Script a Synonym using SMO
/// </summary>
/// <param name="objectName">Synonym name</param>
/// <param name="schemaName">Schema name</param>
/// <returns>String collection of scripts</returns>
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;
}
}
/// <summary>
/// Script a ScalarValuedFunction using SMO
/// </summary>
/// <param name="objectName">ScalarValuedFunction name</param>
/// <param name="schemaName">Schema name</param>
/// <returns>String collection of scripts</returns>
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;
}
}
/// <summary>
/// Script a TableValuedFunction using SMO
/// </summary>
/// <param name="objectName">TableValuedFunction name</param>
/// <param name="schemaName">Schema name</param>
/// <returns>String collection of scripts</returns>
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;
}
}
}
}

View File

@@ -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("/// <summary>");
WriteLine(string.Format("/// Script a {0} using SMO", typeProperty["Name"]));
WriteLine("/// </summary>");
WriteLine(string.Format("/// <param name=\"objectName\">{0} name</param>", typeProperty["Name"]));
WriteLine(string.Format("/// <param name=\"schemaName\">Schema name</param>"));
WriteLine("/// <returns>String collection of scripts</returns>");
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<Dictionary<string, string>> GetSupportedTypes(string xmlFile)
{
List<Dictionary<string, string>> typeList = null;
XmlDocument doc = new XmlDocument();
doc.Load(xmlFile);
XmlNodeList supportedTypes = doc.SelectNodes("/SupportedTypes/Type");
if (supportedTypes != null)
{
typeList = new List<Dictionary<string, string>>();
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<string, string> typeProperties = new Dictionary<string, string>();
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;
}
#>

View File

@@ -0,0 +1,66 @@
<!--
For each supported type
Name - As denoted in the Microsoft.SqlServer.Management.SqlParser.Intellisense.DeclarationType Enumeration for the object
Create Syntax - The keyword used in the create t-sql statement for the object - e.g create TABLE, create PROCEDURE etc.
AccessClass - The SMO class denoting the object e.g. Table, UserDefinedTableType etc.
QuickInfoType - The type of the object as displayed in the Babel.CodeObjectQuickInfo.Text string (optional)
SupportsSchemaQuery - Boolean denoting if the object can be queried/accessed using the schema name
-->
<SupportedTypes>
<Type>
<Name>Table</Name>
<CreateSyntax>Table</CreateSyntax>
<AccessClass>Table</AccessClass>
<QuickInfoType>table</QuickInfoType>
<SupportsSchemaQuery>true</SupportsSchemaQuery>
</Type>
<Type>
<Name>View</Name>
<CreateSyntax>View</CreateSyntax>
<AccessClass>View</AccessClass>
<QuickInfoType>view</QuickInfoType>
<SupportsSchemaQuery>true</SupportsSchemaQuery>
</Type>
<Type>
<Name>StoredProcedure</Name>
<CreateSyntax>Procedure</CreateSyntax>
<AccessClass>StoredProcedure</AccessClass>
<QuickInfoType>stored procedure</QuickInfoType>
<SupportsSchemaQuery>true</SupportsSchemaQuery>
</Type>
<Type>
<Name>UserDefinedDataType</Name>
<CreateSyntax>Type</CreateSyntax>
<AccessClass>UserDefinedDataType</AccessClass>
<QuickInfoType>user-defined data type</QuickInfoType>
<SupportsSchemaQuery>true</SupportsSchemaQuery>
</Type>
<Type>
<Name>UserDefinedTableType</Name>
<CreateSyntax>Type</CreateSyntax>
<AccessClass>UserDefinedTableType</AccessClass>
<QuickInfoType>user-defined table type</QuickInfoType>
<SupportsSchemaQuery>true</SupportsSchemaQuery>
</Type>
<Type>
<Name>Synonym</Name>
<CreateSyntax>Synonym</CreateSyntax>
<AccessClass>Synonym</AccessClass>
<QuickInfoType></QuickInfoType>
<SupportsSchemaQuery>true</SupportsSchemaQuery>
</Type>
<Type>
<Name>ScalarValuedFunction</Name>
<CreateSyntax>Function</CreateSyntax>
<AccessClass>UserDefinedFunction</AccessClass>
<QuickInfoType>scalar-valued function</QuickInfoType>
<SupportsSchemaQuery>true</SupportsSchemaQuery>
</Type>
<Type>
<Name>TableValuedFunction</Name>
<CreateSyntax>Function</CreateSyntax>
<AccessClass>UserDefinedFunction</AccessClass>
<QuickInfoType>table-valued function</QuickInfoType>
<SupportsSchemaQuery>true</SupportsSchemaQuery>
</Type>
</SupportedTypes>