mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-02-16 10:58:30 -05:00
Feature/sqlcmd : Enable running scripts with SQLCMD variables - Part 1 (#839)
* Part1 : Changes to make cmdcmd script to work with parameters in script * Stop SQL intellisense for SQLCMD * Adding test for Intellisense handling of SQLCMD page * Removing unintentional spacing changes caused by formatting * Updating with smaller CR comments. Will discuss regarding script vs other options in batch info * Removing unintentional change * Adding latest PR comments
This commit is contained in:
@@ -14,7 +14,7 @@ namespace Microsoft.SqlTools.Utility
|
|||||||
{
|
{
|
||||||
public GeneralRequestDetails()
|
public GeneralRequestDetails()
|
||||||
{
|
{
|
||||||
Options = new Dictionary<string, object>();
|
Options = new Dictionary<string, object>(StringComparer.InvariantCultureIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
public T GetOptionValue<T>(string name, T defaultValue = default(T))
|
public T GetOptionValue<T>(string name, T defaultValue = default(T))
|
||||||
@@ -112,3 +112,4 @@ namespace Microsoft.SqlTools.Utility
|
|||||||
public Dictionary<string, object> Options { get; set; }
|
public Dictionary<string, object> Options { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser
|
|||||||
int offset = offsets[0];
|
int offset = offsets[0];
|
||||||
int startColumn = batchInfos[0].startColumn;
|
int startColumn = batchInfos[0].startColumn;
|
||||||
int count = batchInfos.Count;
|
int count = batchInfos.Count;
|
||||||
string batchText = content.Substring(offset, batchInfos[0].length);
|
string batchText = batchInfos[0].batchText;
|
||||||
|
|
||||||
// if there's only one batch then the line difference is just startLine
|
// if there's only one batch then the line difference is just startLine
|
||||||
if (count > 1)
|
if (count > 1)
|
||||||
@@ -82,15 +82,15 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generate the rest batch definitions
|
// Generate the rest batch definitions
|
||||||
for (int index = 1; index < count - 1; index++)
|
for (int index = 1; index < count - 1 ; index++)
|
||||||
{
|
{
|
||||||
lineDifference = batchInfos[index + 1].startLine - batchInfos[index].startLine;
|
lineDifference = batchInfos[index + 1].startLine - batchInfos[index].startLine;
|
||||||
position = ReadLines(reader, lineDifference, endLine);
|
position = ReadLines(reader, lineDifference, endLine);
|
||||||
endLine = position.Item1;
|
endLine = position.Item1;
|
||||||
endColumn = position.Item2;
|
endColumn = position.Item2;
|
||||||
offset = offsets[index];
|
offset = offsets[index];
|
||||||
batchText = content.Substring(offset, batchInfos[index].length);
|
batchText = batchInfos[index].batchText;
|
||||||
startLine = batchInfos[index].startLine;
|
startLine = batchInfos[index].startLine + 1; //positions is 0 index based
|
||||||
startColumn = batchInfos[index].startColumn;
|
startColumn = batchInfos[index].startColumn;
|
||||||
|
|
||||||
// make a new batch definition for each batch
|
// make a new batch definition for each batch
|
||||||
@@ -109,7 +109,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser
|
|||||||
if (count > 1)
|
if (count > 1)
|
||||||
{
|
{
|
||||||
|
|
||||||
batchText = content.Substring(offsets[count-1], batchInfos[count - 1].length);
|
batchText = batchInfos[count - 1].batchText;
|
||||||
BatchDefinition lastBatchDef = GetLastBatchDefinition(reader, batchInfos[count - 1], batchText);
|
BatchDefinition lastBatchDef = GetLastBatchDefinition(reader, batchInfos[count - 1], batchText);
|
||||||
batchDefinitionList.Add(lastBatchDef);
|
batchDefinitionList.Add(lastBatchDef);
|
||||||
}
|
}
|
||||||
@@ -209,7 +209,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser
|
|||||||
private static BatchDefinition GetLastBatchDefinition(StringReader reader,
|
private static BatchDefinition GetLastBatchDefinition(StringReader reader,
|
||||||
BatchInfo batchInfo, string batchText)
|
BatchInfo batchInfo, string batchText)
|
||||||
{
|
{
|
||||||
int startLine = batchInfo.startLine;
|
int startLine = batchInfo.startLine + 1;
|
||||||
int startColumn = batchInfo.startColumn;
|
int startColumn = batchInfo.startColumn;
|
||||||
string prevLine = null;
|
string prevLine = null;
|
||||||
string line = reader.ReadLine();
|
string line = reader.ReadLine();
|
||||||
@@ -328,12 +328,12 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Takes in a query string and returns a list of BatchDefinitions
|
/// Takes in a query string and returns a list of BatchDefinitions
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<BatchDefinition> GetBatches(string sqlScript)
|
public List<BatchDefinition> GetBatches(string sqlScript, ExecutionEngineConditions conditions = null)
|
||||||
{
|
{
|
||||||
batchInfos = new List<BatchInfo>();
|
batchInfos = new List<BatchInfo>();
|
||||||
|
|
||||||
// execute the script - all communication / integration after here happen via event handlers
|
// execute the script - all communication / integration after here happen via event handlers
|
||||||
executionEngine.ParseScript(sqlScript, notificationHandler);
|
executionEngine.ParseScript(sqlScript, notificationHandler, conditions);
|
||||||
|
|
||||||
// retrieve a list of BatchDefinitions
|
// retrieve a list of BatchDefinitions
|
||||||
List<BatchDefinition> batchDefinitionList = ConvertToBatchDefinitionList(sqlScript, batchInfos);
|
List<BatchDefinition> batchDefinitionList = ConvertToBatchDefinitionList(sqlScript, batchInfos);
|
||||||
@@ -381,7 +381,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add the script info
|
// Add the script info
|
||||||
batchInfos.Add(new BatchInfo(args.Batch.TextSpan.iStartLine, args.Batch.TextSpan.iStartIndex, batchTextLength, args.Batch.ExpectedExecutionCount));
|
batchInfos.Add(new BatchInfo(args.Batch.TextSpan.iStartLine, args.Batch.TextSpan.iStartIndex, batchText, args.Batch.ExpectedExecutionCount));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (NotImplementedException)
|
catch (NotImplementedException)
|
||||||
@@ -474,17 +474,17 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser
|
|||||||
|
|
||||||
private class BatchInfo
|
private class BatchInfo
|
||||||
{
|
{
|
||||||
public BatchInfo(int startLine, int startColumn, int length, int repeatCount = 1)
|
public BatchInfo(int startLine, int startColumn, string batchText, int repeatCount = 1)
|
||||||
{
|
{
|
||||||
this.startLine = startLine;
|
this.startLine = startLine;
|
||||||
this.startColumn = startColumn;
|
this.startColumn = startColumn;
|
||||||
this.length = length;
|
|
||||||
this.executionCount = repeatCount;
|
this.executionCount = repeatCount;
|
||||||
|
this.batchText = batchText;
|
||||||
}
|
}
|
||||||
public int startLine;
|
public int startLine;
|
||||||
public int startColumn;
|
public int startColumn;
|
||||||
public int length;
|
|
||||||
public int executionCount;
|
public int executionCount;
|
||||||
|
public string batchText;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode
|
|||||||
batchParser.HaltParser = new BatchParser.HaltParserDelegate(OnHaltParser);
|
batchParser.HaltParser = new BatchParser.HaltParserDelegate(OnHaltParser);
|
||||||
batchParser.StartingLine = startingLine;
|
batchParser.StartingLine = startingLine;
|
||||||
|
|
||||||
if (isLocalParse)
|
if (isLocalParse && !sqlCmdMode)
|
||||||
{
|
{
|
||||||
batchParser.DisableVariableSubstitution();
|
batchParser.DisableVariableSubstitution();
|
||||||
}
|
}
|
||||||
@@ -1045,23 +1045,27 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode
|
|||||||
/// Parses the script locally
|
/// Parses the script locally
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="script">script to parse</param>
|
/// <param name="script">script to parse</param>
|
||||||
/// <param name="batchEventsHandler">batch handler</param>
|
/// <param name="batchEventsHandler">batch handler</param>
|
||||||
|
/// <param name="conditions">execution engine conditions if specified</param>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// The batch parser functionality is used in this case
|
/// The batch parser functionality is used in this case
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public void ParseScript(string script, IBatchEventsHandler batchEventsHandler)
|
public void ParseScript(string script, IBatchEventsHandler batchEventsHandler, ExecutionEngineConditions conditions = null)
|
||||||
{
|
{
|
||||||
Validate.IsNotNull(nameof(script), script);
|
Validate.IsNotNull(nameof(script), script);
|
||||||
Validate.IsNotNull(nameof(batchEventsHandler), batchEventsHandler);
|
Validate.IsNotNull(nameof(batchEventsHandler), batchEventsHandler);
|
||||||
|
|
||||||
|
if (conditions != null)
|
||||||
|
{
|
||||||
|
this.conditions = conditions;
|
||||||
|
}
|
||||||
this.script = script;
|
this.script = script;
|
||||||
batchEventHandlers = batchEventsHandler;
|
batchEventHandlers = batchEventsHandler;
|
||||||
isLocalParse = true;
|
isLocalParse = true;
|
||||||
|
|
||||||
DoExecute(/* isBatchParser */ true);
|
DoExecute(/* isBatchParser */ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Close the current connection
|
/// Close the current connection
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -58,12 +58,16 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Private / internal instance fields and constructor
|
#region Instance fields and constructor
|
||||||
private const int PrepopulateBindTimeout = 60000;
|
|
||||||
|
|
||||||
public const string SQL_LANG = "SQL";
|
public const string SQL_LANG = "SQL";
|
||||||
|
|
||||||
|
public const string SQL_CMD_LANG = "SQLCMD";
|
||||||
|
|
||||||
private const int OneSecond = 1000;
|
private const int OneSecond = 1000;
|
||||||
|
|
||||||
|
private const int PrepopulateBindTimeout = 60000;
|
||||||
|
|
||||||
internal const string DefaultBatchSeperator = "GO";
|
internal const string DefaultBatchSeperator = "GO";
|
||||||
|
|
||||||
internal const int DiagnosticParseDelay = 750;
|
internal const int DiagnosticParseDelay = 750;
|
||||||
@@ -80,6 +84,9 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
|||||||
|
|
||||||
internal const int CompletionExtTimeout = 200;
|
internal const int CompletionExtTimeout = 200;
|
||||||
|
|
||||||
|
// For testability only
|
||||||
|
internal Task DelayedDiagnosticsTask = null;
|
||||||
|
|
||||||
private ConnectionService connectionService = null;
|
private ConnectionService connectionService = null;
|
||||||
|
|
||||||
private WorkspaceService<SqlToolsSettings> workspaceServiceInstance;
|
private WorkspaceService<SqlToolsSettings> workspaceServiceInstance;
|
||||||
@@ -836,7 +843,10 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
|||||||
if (SQL_LANG.Equals(changeParams.Language, StringComparison.OrdinalIgnoreCase)) {
|
if (SQL_LANG.Equals(changeParams.Language, StringComparison.OrdinalIgnoreCase)) {
|
||||||
shouldBlock = !ServiceHost.ProviderName.Equals(changeParams.Flavor, StringComparison.OrdinalIgnoreCase);
|
shouldBlock = !ServiceHost.ProviderName.Equals(changeParams.Flavor, StringComparison.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
|
if (SQL_CMD_LANG.Equals(changeParams.Language, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
shouldBlock = true; // the provider will continue to be mssql
|
||||||
|
}
|
||||||
if (shouldBlock) {
|
if (shouldBlock) {
|
||||||
this.nonMssqlUriMap.AddOrUpdate(changeParams.Uri, true, (k, oldValue) => true);
|
this.nonMssqlUriMap.AddOrUpdate(changeParams.Uri, true, (k, oldValue) => true);
|
||||||
if (CurrentWorkspace.ContainsFile(changeParams.Uri))
|
if (CurrentWorkspace.ContainsFile(changeParams.Uri))
|
||||||
@@ -848,7 +858,10 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
|||||||
{
|
{
|
||||||
bool value;
|
bool value;
|
||||||
this.nonMssqlUriMap.TryRemove(changeParams.Uri, out value);
|
this.nonMssqlUriMap.TryRemove(changeParams.Uri, out value);
|
||||||
}
|
// should rebuild intellisense when re-considering as sql
|
||||||
|
RebuildIntelliSenseParams param = new RebuildIntelliSenseParams { OwnerUri = changeParams.Uri };
|
||||||
|
await HandleRebuildIntelliSenseNotification(param, eventContext);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -1733,7 +1746,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
|||||||
existingRequestCancellation = new CancellationTokenSource();
|
existingRequestCancellation = new CancellationTokenSource();
|
||||||
Task.Factory.StartNew(
|
Task.Factory.StartNew(
|
||||||
() =>
|
() =>
|
||||||
DelayThenInvokeDiagnostics(
|
this.DelayedDiagnosticsTask = DelayThenInvokeDiagnostics(
|
||||||
LanguageService.DiagnosticParseDelay,
|
LanguageService.DiagnosticParseDelay,
|
||||||
filesToAnalyze,
|
filesToAnalyze,
|
||||||
eventContext,
|
eventContext,
|
||||||
|
|||||||
@@ -116,7 +116,12 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
|||||||
|
|
||||||
// Process the query into batches
|
// Process the query into batches
|
||||||
BatchParserWrapper parser = new BatchParserWrapper();
|
BatchParserWrapper parser = new BatchParserWrapper();
|
||||||
List<BatchDefinition> parserResult = parser.GetBatches(queryText);
|
ExecutionEngineConditions conditions = null;
|
||||||
|
if (settings.IsSqlCmdMode)
|
||||||
|
{
|
||||||
|
conditions = new ExecutionEngineConditions() { IsSqlCmd = settings.IsSqlCmdMode };
|
||||||
|
}
|
||||||
|
List<BatchDefinition> parserResult = parser.GetBatches(queryText, conditions);
|
||||||
|
|
||||||
var batchSelection = parserResult
|
var batchSelection = parserResult
|
||||||
.Select((batchDefinition, index) =>
|
.Select((batchDefinition, index) =>
|
||||||
|
|||||||
@@ -163,6 +163,11 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlContext
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private const int DefaultQueryGovernorCostLimit = 0;
|
private const int DefaultQueryGovernorCostLimit = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default value for flag to run query in sqlcmd mode
|
||||||
|
/// </summary>
|
||||||
|
private bool DefaultSqlCmdMode = false;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Member Variables
|
#region Member Variables
|
||||||
@@ -633,6 +638,21 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlContext
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set sqlCmd Mode
|
||||||
|
/// </summary>
|
||||||
|
public bool IsSqlCmdMode
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return GetOptionValue<bool>("isSqlCmdMode", DefaultSqlCmdMode);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetOptionValue("isSqlCmdMode", value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public Methods
|
#region Public Methods
|
||||||
@@ -670,6 +690,7 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlContext
|
|||||||
AnsiPadding = newSettings.AnsiPadding;
|
AnsiPadding = newSettings.AnsiPadding;
|
||||||
AnsiWarnings = newSettings.AnsiWarnings;
|
AnsiWarnings = newSettings.AnsiWarnings;
|
||||||
AnsiNulls = newSettings.AnsiNulls;
|
AnsiNulls = newSettings.AnsiNulls;
|
||||||
|
IsSqlCmdMode = newSettings.IsSqlCmdMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@@ -338,6 +338,42 @@ namespace Microsoft.SqlTools.ManagedBatchParser.UnitTests.BatchParser
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Verify whether the batchParser execute SqlCmd successfully
|
||||||
|
/// </summary>
|
||||||
|
[Fact]
|
||||||
|
public void VerifyRunSqlCmd()
|
||||||
|
{
|
||||||
|
using (ExecutionEngine executionEngine = new ExecutionEngine())
|
||||||
|
{
|
||||||
|
const string sqlCmdQuery = @"
|
||||||
|
:setvar __var1 1
|
||||||
|
:setvar __var2 2
|
||||||
|
:setvar __IsSqlCmdEnabled " + "\"True\"" + @"
|
||||||
|
GO
|
||||||
|
IF N'$(__IsSqlCmdEnabled)' NOT LIKE N'True'
|
||||||
|
BEGIN
|
||||||
|
PRINT N'SQLCMD mode must be enabled to successfully execute this script.';
|
||||||
|
SET NOEXEC ON;
|
||||||
|
END
|
||||||
|
GO
|
||||||
|
select $(__var1) + $(__var2) as col
|
||||||
|
GO";
|
||||||
|
|
||||||
|
using (SqlConnection con = new SqlConnection(CONNECTION_STRING))
|
||||||
|
{
|
||||||
|
con.Open();
|
||||||
|
var condition = new ExecutionEngineConditions() { IsSqlCmd = true };
|
||||||
|
TestExecutor testExecutor = new TestExecutor(sqlCmdQuery, con, condition);
|
||||||
|
testExecutor.Run();
|
||||||
|
|
||||||
|
Assert.True(testExecutor.ResultCountQueue.Count >= 1);
|
||||||
|
Assert.True(testExecutor.ErrorMessageQueue.Count == 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Verify whether the executionEngine execute Batch
|
// Verify whether the executionEngine execute Batch
|
||||||
[Fact]
|
[Fact]
|
||||||
public void VerifyExecuteBatch()
|
public void VerifyExecuteBatch()
|
||||||
|
|||||||
@@ -231,6 +231,7 @@ namespace Microsoft.SqlTools.ManagedBatchParser.IntegrationTests.TSQLExecutionEn
|
|||||||
conditions.IsNoExec = exeCondition.IsNoExec;
|
conditions.IsNoExec = exeCondition.IsNoExec;
|
||||||
conditions.IsStatisticsIO = exeCondition.IsStatisticsIO;
|
conditions.IsStatisticsIO = exeCondition.IsStatisticsIO;
|
||||||
conditions.IsStatisticsTime = exeCondition.IsStatisticsTime;
|
conditions.IsStatisticsTime = exeCondition.IsStatisticsTime;
|
||||||
|
conditions.IsSqlCmd = exeCondition.IsSqlCmd;
|
||||||
|
|
||||||
_cancel = cancelExecution;
|
_cancel = cancelExecution;
|
||||||
connection = conn;
|
connection = conn;
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ using Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts;
|
|||||||
using Microsoft.SqlTools.ServiceLayer.Test.Common;
|
using Microsoft.SqlTools.ServiceLayer.Test.Common;
|
||||||
using Microsoft.SqlTools.ServiceLayer.UnitTests.ServiceHost;
|
using Microsoft.SqlTools.ServiceLayer.UnitTests.ServiceHost;
|
||||||
using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts;
|
using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts;
|
||||||
|
using Microsoft.SqlTools.ServiceLayer.Workspace;
|
||||||
|
using Microsoft.SqlTools.ServiceLayer.SqlContext;
|
||||||
|
using Microsoft.SqlTools.ServiceLayer.Connection;
|
||||||
|
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
@@ -329,5 +333,73 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServer
|
|||||||
testDb.Cleanup();
|
testDb.Cleanup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
// This test validates switching off editor intellisesnse for now.
|
||||||
|
// Will change to better handling once we have specific SQLCMD intellisense in Language Service
|
||||||
|
/// </summary>
|
||||||
|
[Fact]
|
||||||
|
public async Task HandleRequestToChangeToSqlcmdFile()
|
||||||
|
{
|
||||||
|
|
||||||
|
var scriptFile = new ScriptFile() { ClientFilePath = "HandleRequestToChangeToSqlcmdFile_" + DateTime.Now.ToLongDateString() + "_.sql" };
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Prepare a script file
|
||||||
|
scriptFile.SetFileContents("koko wants a bananas");
|
||||||
|
File.WriteAllText(scriptFile.ClientFilePath, scriptFile.Contents);
|
||||||
|
|
||||||
|
// Create a workspace and add file to it so that its found for intellense building
|
||||||
|
var workspace = new ServiceLayer.Workspace.Workspace();
|
||||||
|
var workspaceService = new WorkspaceService<SqlToolsSettings> { Workspace = workspace };
|
||||||
|
var langService = new LanguageService() { WorkspaceServiceInstance = workspaceService };
|
||||||
|
langService.CurrentWorkspace.GetFile(scriptFile.ClientFilePath);
|
||||||
|
langService.CurrentWorkspaceSettings.SqlTools.IntelliSense.EnableIntellisense = true;
|
||||||
|
|
||||||
|
// Add a connection to ensure the intellisense building works
|
||||||
|
ConnectionInfo connectionInfo = GetLiveAutoCompleteTestObjects().ConnectionInfo;
|
||||||
|
langService.ConnectionServiceInstance.OwnerToConnectionMap.Add(scriptFile.ClientFilePath, connectionInfo);
|
||||||
|
|
||||||
|
// Test SQL
|
||||||
|
int countOfValidationCalls = 0;
|
||||||
|
var eventContextSql = new Mock<SqlTools.Hosting.Protocol.EventContext>();
|
||||||
|
eventContextSql.Setup(x => x.SendEvent(PublishDiagnosticsNotification.Type, It.Is<PublishDiagnosticsNotification>((notif) => ValidateNotification(notif, 2, ref countOfValidationCalls)))).Returns(Task.FromResult(new object()));
|
||||||
|
await langService.HandleDidChangeLanguageFlavorNotification(new LanguageFlavorChangeParams
|
||||||
|
{
|
||||||
|
Uri = scriptFile.ClientFilePath,
|
||||||
|
Language = LanguageService.SQL_LANG.ToLower(),
|
||||||
|
Flavor = "MSSQL"
|
||||||
|
}, eventContextSql.Object);
|
||||||
|
await langService.DelayedDiagnosticsTask; // to ensure completion and validation before moveing to next step
|
||||||
|
|
||||||
|
// Test SQL CMD
|
||||||
|
var eventContextSqlCmd = new Mock<SqlTools.Hosting.Protocol.EventContext>();
|
||||||
|
eventContextSqlCmd.Setup(x => x.SendEvent(PublishDiagnosticsNotification.Type, It.Is<PublishDiagnosticsNotification>((notif) => ValidateNotification(notif, 0, ref countOfValidationCalls)))).Returns(Task.FromResult(new object()));
|
||||||
|
await langService.HandleDidChangeLanguageFlavorNotification(new LanguageFlavorChangeParams
|
||||||
|
{
|
||||||
|
Uri = scriptFile.ClientFilePath,
|
||||||
|
Language = LanguageService.SQL_CMD_LANG.ToLower(),
|
||||||
|
Flavor = "MSSQL"
|
||||||
|
}, eventContextSqlCmd.Object);
|
||||||
|
await langService.DelayedDiagnosticsTask;
|
||||||
|
|
||||||
|
Assert.True(countOfValidationCalls == 2, $"Validation should be called 2 time but is called {countOfValidationCalls} times");
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (File.Exists(scriptFile.ClientFilePath))
|
||||||
|
{
|
||||||
|
File.Delete(scriptFile.ClientFilePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ValidateNotification(PublishDiagnosticsNotification notif, int errors, ref int countOfValidationCalls)
|
||||||
|
{
|
||||||
|
countOfValidationCalls++;
|
||||||
|
Assert.True(notif.Diagnostics.Length == errors, $"Notification errors {notif.Diagnostics.Length} are not as expected {errors}");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user