mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-02-16 10:58:30 -05:00
Add try/catch blocks for request handlers (#408)
* Add try/catch for request handlers * Fix test break
This commit is contained in:
@@ -88,25 +88,32 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery
|
|||||||
DefaultDatabaseInfoParams optionsParams,
|
DefaultDatabaseInfoParams optionsParams,
|
||||||
RequestContext<BackupConfigInfoResponse> requestContext)
|
RequestContext<BackupConfigInfoResponse> requestContext)
|
||||||
{
|
{
|
||||||
var response = new BackupConfigInfoResponse();
|
try
|
||||||
ConnectionInfo connInfo;
|
|
||||||
DisasterRecoveryService.ConnectionServiceInstance.TryFindConnection(
|
|
||||||
optionsParams.OwnerUri,
|
|
||||||
out connInfo);
|
|
||||||
|
|
||||||
if (connInfo != null)
|
|
||||||
{
|
{
|
||||||
DatabaseTaskHelper helper = AdminService.CreateDatabaseTaskHelper(connInfo, databaseExists: true);
|
var response = new BackupConfigInfoResponse();
|
||||||
SqlConnection sqlConn = GetSqlConnection(connInfo);
|
ConnectionInfo connInfo;
|
||||||
if ((sqlConn != null) && !connInfo.IsSqlDW && !connInfo.IsAzure)
|
DisasterRecoveryService.ConnectionServiceInstance.TryFindConnection(
|
||||||
{
|
optionsParams.OwnerUri,
|
||||||
BackupConfigInfo backupConfigInfo = DisasterRecoveryService.Instance.GetBackupConfigInfo(helper.DataContainer, sqlConn, sqlConn.Database);
|
out connInfo);
|
||||||
backupConfigInfo.DatabaseInfo = AdminService.GetDatabaseInfo(connInfo);
|
|
||||||
response.BackupConfigInfo = backupConfigInfo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await requestContext.SendResult(response);
|
if (connInfo != null)
|
||||||
|
{
|
||||||
|
DatabaseTaskHelper helper = AdminService.CreateDatabaseTaskHelper(connInfo, databaseExists: true);
|
||||||
|
SqlConnection sqlConn = GetSqlConnection(connInfo);
|
||||||
|
if ((sqlConn != null) && !connInfo.IsSqlDW && !connInfo.IsAzure)
|
||||||
|
{
|
||||||
|
BackupConfigInfo backupConfigInfo = DisasterRecoveryService.Instance.GetBackupConfigInfo(helper.DataContainer, sqlConn, sqlConn.Database);
|
||||||
|
backupConfigInfo.DatabaseInfo = AdminService.GetDatabaseInfo(connInfo);
|
||||||
|
response.BackupConfigInfo = backupConfigInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await requestContext.SendResult(response);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await requestContext.SendError(ex.ToString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -116,22 +123,28 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery
|
|||||||
RestoreParams restoreParams,
|
RestoreParams restoreParams,
|
||||||
RequestContext<RestorePlanResponse> requestContext)
|
RequestContext<RestorePlanResponse> requestContext)
|
||||||
{
|
{
|
||||||
RestorePlanResponse response = new RestorePlanResponse();
|
try
|
||||||
ConnectionInfo connInfo;
|
|
||||||
bool supported = IsBackupRestoreOperationSupported(restoreParams, out connInfo);
|
|
||||||
|
|
||||||
if (supported && connInfo != null)
|
|
||||||
{
|
{
|
||||||
RestoreDatabaseTaskDataObject restoreDataObject = this.restoreDatabaseService.CreateRestoreDatabaseTaskDataObject(restoreParams);
|
RestorePlanResponse response = new RestorePlanResponse();
|
||||||
response = this.restoreDatabaseService.CreateRestorePlanResponse(restoreDataObject);
|
ConnectionInfo connInfo;
|
||||||
}
|
bool supported = IsBackupRestoreOperationSupported(restoreParams, out connInfo);
|
||||||
else
|
|
||||||
{
|
|
||||||
response.CanRestore = false;
|
|
||||||
response.ErrorMessage = SR.RestoreNotSupported;
|
|
||||||
}
|
|
||||||
await requestContext.SendResult(response);
|
|
||||||
|
|
||||||
|
if (supported && connInfo != null)
|
||||||
|
{
|
||||||
|
RestoreDatabaseTaskDataObject restoreDataObject = this.restoreDatabaseService.CreateRestoreDatabaseTaskDataObject(restoreParams);
|
||||||
|
response = this.restoreDatabaseService.CreateRestorePlanResponse(restoreDataObject);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
response.CanRestore = false;
|
||||||
|
response.ErrorMessage = SR.RestoreNotSupported;
|
||||||
|
}
|
||||||
|
await requestContext.SendResult(response);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await requestContext.SendError(ex.ToString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -141,46 +154,53 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery
|
|||||||
RestoreParams restoreParams,
|
RestoreParams restoreParams,
|
||||||
RequestContext<RestoreResponse> requestContext)
|
RequestContext<RestoreResponse> requestContext)
|
||||||
{
|
{
|
||||||
RestoreResponse response = new RestoreResponse();
|
try
|
||||||
ConnectionInfo connInfo;
|
|
||||||
bool supported = IsBackupRestoreOperationSupported(restoreParams, out connInfo);
|
|
||||||
|
|
||||||
if (supported && connInfo != null)
|
|
||||||
{
|
{
|
||||||
try
|
RestoreResponse response = new RestoreResponse();
|
||||||
|
ConnectionInfo connInfo;
|
||||||
|
bool supported = IsBackupRestoreOperationSupported(restoreParams, out connInfo);
|
||||||
|
|
||||||
|
if (supported && connInfo != null)
|
||||||
{
|
{
|
||||||
RestoreDatabaseTaskDataObject restoreDataObject = this.restoreDatabaseService.CreateRestoreDatabaseTaskDataObject(restoreParams);
|
try
|
||||||
|
|
||||||
if (restoreDataObject != null)
|
|
||||||
{
|
{
|
||||||
// create task metadata
|
RestoreDatabaseTaskDataObject restoreDataObject = this.restoreDatabaseService.CreateRestoreDatabaseTaskDataObject(restoreParams);
|
||||||
TaskMetadata metadata = new TaskMetadata();
|
|
||||||
metadata.ServerName = connInfo.ConnectionDetails.ServerName;
|
|
||||||
metadata.DatabaseName = connInfo.ConnectionDetails.DatabaseName;
|
|
||||||
metadata.Name = SR.RestoreTaskName;
|
|
||||||
metadata.IsCancelable = true;
|
|
||||||
metadata.Data = restoreDataObject;
|
|
||||||
|
|
||||||
// create restore task and perform
|
if (restoreDataObject != null)
|
||||||
SqlTask sqlTask = SqlTaskManager.Instance.CreateAndRun(metadata, this.restoreDatabaseService.RestoreTaskAsync, restoreDatabaseService.CancelTaskAsync);
|
{
|
||||||
response.TaskId = sqlTask.TaskId.ToString();
|
// create task metadata
|
||||||
|
TaskMetadata metadata = new TaskMetadata();
|
||||||
|
metadata.ServerName = connInfo.ConnectionDetails.ServerName;
|
||||||
|
metadata.DatabaseName = connInfo.ConnectionDetails.DatabaseName;
|
||||||
|
metadata.Name = SR.RestoreTaskName;
|
||||||
|
metadata.IsCancelable = true;
|
||||||
|
metadata.Data = restoreDataObject;
|
||||||
|
|
||||||
|
// create restore task and perform
|
||||||
|
SqlTask sqlTask = SqlTaskManager.Instance.CreateAndRun(metadata, this.restoreDatabaseService.RestoreTaskAsync, restoreDatabaseService.CancelTaskAsync);
|
||||||
|
response.TaskId = sqlTask.TaskId.ToString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
response.ErrorMessage = SR.RestorePlanFailed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
response.ErrorMessage = SR.RestorePlanFailed;
|
response.ErrorMessage = ex.Message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
else
|
||||||
{
|
{
|
||||||
response.ErrorMessage = ex.Message;
|
response.ErrorMessage = SR.RestoreNotSupported;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
response.ErrorMessage = SR.RestoreNotSupported;
|
|
||||||
}
|
|
||||||
|
|
||||||
await requestContext.SendResult(response);
|
await requestContext.SendResult(response);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await requestContext.SendError(ex.ToString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -189,35 +209,42 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery
|
|||||||
internal static async Task HandleBackupRequest(
|
internal static async Task HandleBackupRequest(
|
||||||
BackupParams backupParams,
|
BackupParams backupParams,
|
||||||
RequestContext<BackupResponse> requestContext)
|
RequestContext<BackupResponse> requestContext)
|
||||||
{
|
{
|
||||||
ConnectionInfo connInfo;
|
try
|
||||||
DisasterRecoveryService.ConnectionServiceInstance.TryFindConnection(
|
{
|
||||||
backupParams.OwnerUri,
|
ConnectionInfo connInfo;
|
||||||
out connInfo);
|
DisasterRecoveryService.ConnectionServiceInstance.TryFindConnection(
|
||||||
|
backupParams.OwnerUri,
|
||||||
|
out connInfo);
|
||||||
|
|
||||||
if (connInfo != null)
|
if (connInfo != null)
|
||||||
{
|
|
||||||
DatabaseTaskHelper helper = AdminService.CreateDatabaseTaskHelper(connInfo, databaseExists: true);
|
|
||||||
SqlConnection sqlConn = GetSqlConnection(connInfo);
|
|
||||||
if ((sqlConn != null) && !connInfo.IsSqlDW && !connInfo.IsAzure)
|
|
||||||
{
|
{
|
||||||
BackupOperation backupOperation = DisasterRecoveryService.Instance.SetBackupInput(helper.DataContainer, sqlConn, backupParams.BackupInfo);
|
DatabaseTaskHelper helper = AdminService.CreateDatabaseTaskHelper(connInfo, databaseExists: true);
|
||||||
|
SqlConnection sqlConn = GetSqlConnection(connInfo);
|
||||||
|
if ((sqlConn != null) && !connInfo.IsSqlDW && !connInfo.IsAzure)
|
||||||
|
{
|
||||||
|
BackupOperation backupOperation = DisasterRecoveryService.Instance.SetBackupInput(helper.DataContainer, sqlConn, backupParams.BackupInfo);
|
||||||
|
|
||||||
// create task metadata
|
// create task metadata
|
||||||
TaskMetadata metadata = new TaskMetadata();
|
TaskMetadata metadata = new TaskMetadata();
|
||||||
metadata.ServerName = connInfo.ConnectionDetails.ServerName;
|
metadata.ServerName = connInfo.ConnectionDetails.ServerName;
|
||||||
metadata.DatabaseName = connInfo.ConnectionDetails.DatabaseName;
|
metadata.DatabaseName = connInfo.ConnectionDetails.DatabaseName;
|
||||||
metadata.Name = SR.Backup_TaskName;
|
metadata.Name = SR.Backup_TaskName;
|
||||||
metadata.IsCancelable = true;
|
metadata.IsCancelable = true;
|
||||||
metadata.Data = backupOperation;
|
metadata.Data = backupOperation;
|
||||||
|
|
||||||
// create backup task and perform
|
// create backup task and perform
|
||||||
SqlTask sqlTask = SqlTaskManager.Instance.CreateTask(metadata, Instance.BackupTaskAsync);
|
SqlTask sqlTask = SqlTaskManager.Instance.CreateTask(metadata, Instance.BackupTaskAsync);
|
||||||
sqlTask.Run();
|
sqlTask.Run();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await requestContext.SendResult(new BackupResponse());
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await requestContext.SendError(ex.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
await requestContext.SendResult(new BackupResponse());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static SqlConnection GetSqlConnection(ConnectionInfo connInfo)
|
internal static SqlConnection GetSqlConnection(ConnectionInfo connInfo)
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Formatter
|
|||||||
EventContext eventContext)
|
EventContext eventContext)
|
||||||
{
|
{
|
||||||
// update the current settings to reflect any changes (assuming formatter settings exist)
|
// update the current settings to reflect any changes (assuming formatter settings exist)
|
||||||
settings = newSettings.SqlTools.Format ?? settings;
|
settings = newSettings?.SqlTools?.Format ?? settings;
|
||||||
return Task.FromResult(true);
|
return Task.FromResult(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -287,34 +287,41 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
|||||||
internal async Task HandleCompletionRequest(
|
internal async Task HandleCompletionRequest(
|
||||||
TextDocumentPosition textDocumentPosition,
|
TextDocumentPosition textDocumentPosition,
|
||||||
RequestContext<CompletionItem[]> requestContext)
|
RequestContext<CompletionItem[]> requestContext)
|
||||||
{
|
{
|
||||||
// check if Intellisense suggestions are enabled
|
try
|
||||||
if (ShouldSkipIntellisense(textDocumentPosition.TextDocument.Uri))
|
{
|
||||||
{
|
// check if Intellisense suggestions are enabled
|
||||||
await requestContext.SendResult(null);
|
if (ShouldSkipIntellisense(textDocumentPosition.TextDocument.Uri))
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// get the current list of completion items and return to client
|
|
||||||
var scriptFile = CurrentWorkspace.GetFile(
|
|
||||||
textDocumentPosition.TextDocument.Uri);
|
|
||||||
if (scriptFile == null)
|
|
||||||
{
|
{
|
||||||
await requestContext.SendResult(null);
|
await requestContext.SendResult(null);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// get the current list of completion items and return to client
|
||||||
|
var scriptFile = CurrentWorkspace.GetFile(
|
||||||
|
textDocumentPosition.TextDocument.Uri);
|
||||||
|
if (scriptFile == null)
|
||||||
|
{
|
||||||
|
await requestContext.SendResult(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ConnectionInfo connInfo;
|
ConnectionInfo connInfo;
|
||||||
ConnectionServiceInstance.TryFindConnection(
|
ConnectionServiceInstance.TryFindConnection(
|
||||||
scriptFile.ClientFilePath,
|
scriptFile.ClientFilePath,
|
||||||
out connInfo);
|
out connInfo);
|
||||||
|
|
||||||
var completionItems = GetCompletionItems(
|
var completionItems = GetCompletionItems(
|
||||||
textDocumentPosition, scriptFile, connInfo);
|
textDocumentPosition, scriptFile, connInfo);
|
||||||
|
|
||||||
await requestContext.SendResult(completionItems);
|
await requestContext.SendResult(completionItems);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await requestContext.SendError(ex.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle the resolve completion request event to provide additional
|
/// Handle the resolve completion request event to provide additional
|
||||||
@@ -327,59 +334,73 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
|||||||
CompletionItem completionItem,
|
CompletionItem completionItem,
|
||||||
RequestContext<CompletionItem> requestContext)
|
RequestContext<CompletionItem> requestContext)
|
||||||
{
|
{
|
||||||
// check if Intellisense suggestions are enabled
|
try
|
||||||
// Note: Do not know file, so no need to check for MSSQL flavor
|
|
||||||
if (!CurrentWorkspaceSettings.IsSuggestionsEnabled)
|
|
||||||
{
|
{
|
||||||
await requestContext.SendResult(completionItem);
|
// check if Intellisense suggestions are enabled
|
||||||
|
// Note: Do not know file, so no need to check for MSSQL flavor
|
||||||
|
if (!CurrentWorkspaceSettings.IsSuggestionsEnabled)
|
||||||
|
{
|
||||||
|
await requestContext.SendResult(completionItem);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
completionItem = ResolveCompletionItem(completionItem);
|
||||||
|
await requestContext.SendResult(completionItem);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
completionItem = ResolveCompletionItem(completionItem);
|
await requestContext.SendError(ex.ToString());
|
||||||
await requestContext.SendResult(completionItem);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal async Task HandleDefinitionRequest(TextDocumentPosition textDocumentPosition, RequestContext<Location[]> requestContext)
|
internal async Task HandleDefinitionRequest(TextDocumentPosition textDocumentPosition, RequestContext<Location[]> requestContext)
|
||||||
{
|
{
|
||||||
DocumentStatusHelper.SendStatusChange(requestContext, textDocumentPosition, DocumentStatusHelper.DefinitionRequested);
|
try
|
||||||
|
|
||||||
if (!ShouldSkipIntellisense(textDocumentPosition.TextDocument.Uri))
|
|
||||||
{
|
{
|
||||||
// Retrieve document and connection
|
DocumentStatusHelper.SendStatusChange(requestContext, textDocumentPosition, DocumentStatusHelper.DefinitionRequested);
|
||||||
ConnectionInfo connInfo;
|
|
||||||
var scriptFile = CurrentWorkspace.GetFile(textDocumentPosition.TextDocument.Uri);
|
if (!ShouldSkipIntellisense(textDocumentPosition.TextDocument.Uri))
|
||||||
bool isConnected = false;
|
|
||||||
bool succeeded = false;
|
|
||||||
DefinitionResult definitionResult = null;
|
|
||||||
if (scriptFile != null)
|
|
||||||
{
|
{
|
||||||
isConnected = ConnectionServiceInstance.TryFindConnection(scriptFile.ClientFilePath, out connInfo);
|
// Retrieve document and connection
|
||||||
definitionResult = GetDefinition(textDocumentPosition, scriptFile, connInfo);
|
ConnectionInfo connInfo;
|
||||||
}
|
var scriptFile = CurrentWorkspace.GetFile(textDocumentPosition.TextDocument.Uri);
|
||||||
|
bool isConnected = false;
|
||||||
if (definitionResult != null)
|
bool succeeded = false;
|
||||||
{
|
DefinitionResult definitionResult = null;
|
||||||
if (definitionResult.IsErrorResult)
|
if (scriptFile != null)
|
||||||
{
|
{
|
||||||
await requestContext.SendError(definitionResult.Message);
|
isConnected = ConnectionServiceInstance.TryFindConnection(scriptFile.ClientFilePath, out connInfo);
|
||||||
|
definitionResult = GetDefinition(textDocumentPosition, scriptFile, connInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (definitionResult != null)
|
||||||
|
{
|
||||||
|
if (definitionResult.IsErrorResult)
|
||||||
|
{
|
||||||
|
await requestContext.SendError(definitionResult.Message);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await requestContext.SendResult(definitionResult.Locations);
|
||||||
|
succeeded = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await requestContext.SendResult(definitionResult.Locations);
|
// Send an empty result so that processing does not hang
|
||||||
succeeded = true;
|
await requestContext.SendResult(Array.Empty<Location>());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
DocumentStatusHelper.SendTelemetryEvent(requestContext, CreatePeekTelemetryProps(succeeded, isConnected));
|
||||||
{
|
|
||||||
// Send an empty result so that processing does not hang
|
|
||||||
await requestContext.SendResult(Array.Empty<Location>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DocumentStatusHelper.SendTelemetryEvent(requestContext, CreatePeekTelemetryProps(succeeded, isConnected));
|
DocumentStatusHelper.SendStatusChange(requestContext, textDocumentPosition, DocumentStatusHelper.DefinitionRequestCompleted);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await requestContext.SendError(ex.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
DocumentStatusHelper.SendStatusChange(requestContext, textDocumentPosition, DocumentStatusHelper.DefinitionRequestCompleted);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TelemetryProperties CreatePeekTelemetryProps(bool succeeded, bool connected)
|
private static TelemetryProperties CreatePeekTelemetryProps(bool succeeded, bool connected)
|
||||||
@@ -416,54 +437,68 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
|||||||
TextDocumentPosition textDocumentPosition,
|
TextDocumentPosition textDocumentPosition,
|
||||||
RequestContext<SignatureHelp> requestContext)
|
RequestContext<SignatureHelp> requestContext)
|
||||||
{
|
{
|
||||||
// check if Intellisense suggestions are enabled
|
try
|
||||||
if (ShouldSkipNonMssqlFile(textDocumentPosition))
|
|
||||||
{
|
{
|
||||||
await requestContext.SendResult(null);
|
// check if Intellisense suggestions are enabled
|
||||||
}
|
if (ShouldSkipNonMssqlFile(textDocumentPosition))
|
||||||
else
|
|
||||||
{
|
|
||||||
ScriptFile scriptFile = CurrentWorkspace.GetFile(
|
|
||||||
textDocumentPosition.TextDocument.Uri);
|
|
||||||
SignatureHelp help = null;
|
|
||||||
if (scriptFile != null)
|
|
||||||
{
|
{
|
||||||
help = GetSignatureHelp(textDocumentPosition, scriptFile);
|
await requestContext.SendResult(null);
|
||||||
}
|
|
||||||
if (help != null)
|
|
||||||
{
|
|
||||||
await requestContext.SendResult(help);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await requestContext.SendResult(new SignatureHelp());
|
ScriptFile scriptFile = CurrentWorkspace.GetFile(
|
||||||
|
textDocumentPosition.TextDocument.Uri);
|
||||||
|
SignatureHelp help = null;
|
||||||
|
if (scriptFile != null)
|
||||||
|
{
|
||||||
|
help = GetSignatureHelp(textDocumentPosition, scriptFile);
|
||||||
|
}
|
||||||
|
if (help != null)
|
||||||
|
{
|
||||||
|
await requestContext.SendResult(help);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await requestContext.SendResult(new SignatureHelp());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await requestContext.SendError(ex.ToString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task HandleHoverRequest(
|
private async Task HandleHoverRequest(
|
||||||
TextDocumentPosition textDocumentPosition,
|
TextDocumentPosition textDocumentPosition,
|
||||||
RequestContext<Hover> requestContext)
|
RequestContext<Hover> requestContext)
|
||||||
{
|
{
|
||||||
// check if Quick Info hover tooltips are enabled
|
try
|
||||||
if (CurrentWorkspaceSettings.IsQuickInfoEnabled
|
|
||||||
&& !ShouldSkipNonMssqlFile(textDocumentPosition))
|
|
||||||
{
|
{
|
||||||
var scriptFile = CurrentWorkspace.GetFile(
|
// check if Quick Info hover tooltips are enabled
|
||||||
textDocumentPosition.TextDocument.Uri);
|
if (CurrentWorkspaceSettings.IsQuickInfoEnabled
|
||||||
|
&& !ShouldSkipNonMssqlFile(textDocumentPosition))
|
||||||
|
{
|
||||||
|
var scriptFile = CurrentWorkspace.GetFile(
|
||||||
|
textDocumentPosition.TextDocument.Uri);
|
||||||
|
|
||||||
Hover hover = null;
|
Hover hover = null;
|
||||||
if (scriptFile != null)
|
if (scriptFile != null)
|
||||||
{
|
{
|
||||||
hover = GetHoverItem(textDocumentPosition, scriptFile);
|
hover = GetHoverItem(textDocumentPosition, scriptFile);
|
||||||
}
|
}
|
||||||
if (hover != null)
|
if (hover != null)
|
||||||
{
|
{
|
||||||
await requestContext.SendResult(hover);
|
await requestContext.SendResult(hover);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await requestContext.SendResult(new Hover());
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await requestContext.SendError(ex.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
await requestContext.SendResult(new Hover());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -480,16 +515,24 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
|||||||
ScriptFile scriptFile,
|
ScriptFile scriptFile,
|
||||||
EventContext eventContext)
|
EventContext eventContext)
|
||||||
{
|
{
|
||||||
// if not in the preview window and diagnostics are enabled then run diagnostics
|
try
|
||||||
if (!IsPreviewWindow(scriptFile)
|
|
||||||
&& CurrentWorkspaceSettings.IsDiagnosticsEnabled)
|
|
||||||
{
|
{
|
||||||
await RunScriptDiagnostics(
|
// if not in the preview window and diagnostics are enabled then run diagnostics
|
||||||
new ScriptFile[] { scriptFile },
|
if (!IsPreviewWindow(scriptFile)
|
||||||
eventContext);
|
&& CurrentWorkspaceSettings.IsDiagnosticsEnabled)
|
||||||
}
|
{
|
||||||
|
await RunScriptDiagnostics(
|
||||||
|
new ScriptFile[] { scriptFile },
|
||||||
|
eventContext);
|
||||||
|
}
|
||||||
|
|
||||||
await Task.FromResult(true);
|
await Task.FromResult(true);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.Write(LogLevel.Error, "Unknown error " + ex.ToString());
|
||||||
|
// TODO: need mechanism return errors from event handlers
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -499,15 +542,23 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
|||||||
/// <param name="eventContext"></param>
|
/// <param name="eventContext"></param>
|
||||||
public async Task HandleDidChangeTextDocumentNotification(ScriptFile[] changedFiles, EventContext eventContext)
|
public async Task HandleDidChangeTextDocumentNotification(ScriptFile[] changedFiles, EventContext eventContext)
|
||||||
{
|
{
|
||||||
if (CurrentWorkspaceSettings.IsDiagnosticsEnabled)
|
try
|
||||||
{
|
{
|
||||||
// Only process files that are MSSQL flavor
|
if (CurrentWorkspaceSettings.IsDiagnosticsEnabled)
|
||||||
await this.RunScriptDiagnostics(
|
{
|
||||||
changedFiles.ToArray(),
|
// Only process files that are MSSQL flavor
|
||||||
eventContext);
|
await this.RunScriptDiagnostics(
|
||||||
}
|
changedFiles.ToArray(),
|
||||||
|
eventContext);
|
||||||
|
}
|
||||||
|
|
||||||
await Task.FromResult(true);
|
await Task.FromResult(true);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.Write(LogLevel.Error, "Unknown error " + ex.ToString());
|
||||||
|
// TODO: need mechanism return errors from event handlers
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -594,32 +645,78 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
|||||||
SqlToolsSettings oldSettings,
|
SqlToolsSettings oldSettings,
|
||||||
EventContext eventContext)
|
EventContext eventContext)
|
||||||
{
|
{
|
||||||
bool oldEnableIntelliSense = oldSettings.SqlTools.IntelliSense.EnableIntellisense;
|
try
|
||||||
bool? oldEnableDiagnostics = oldSettings.SqlTools.IntelliSense.EnableErrorChecking;
|
|
||||||
|
|
||||||
// update the current settings to reflect any changes
|
|
||||||
CurrentWorkspaceSettings.Update(newSettings);
|
|
||||||
|
|
||||||
// if script analysis settings have changed we need to clear the current diagnostic markers
|
|
||||||
if (oldEnableIntelliSense != newSettings.SqlTools.IntelliSense.EnableIntellisense
|
|
||||||
|| oldEnableDiagnostics != newSettings.SqlTools.IntelliSense.EnableErrorChecking)
|
|
||||||
{
|
{
|
||||||
// if the user just turned off diagnostics then send an event to clear the error markers
|
bool oldEnableIntelliSense = oldSettings.SqlTools.IntelliSense.EnableIntellisense;
|
||||||
if (!newSettings.IsDiagnosticsEnabled)
|
bool? oldEnableDiagnostics = oldSettings.SqlTools.IntelliSense.EnableErrorChecking;
|
||||||
{
|
|
||||||
ScriptFileMarker[] emptyAnalysisDiagnostics = new ScriptFileMarker[0];
|
|
||||||
|
|
||||||
foreach (var scriptFile in CurrentWorkspace.GetOpenedFiles())
|
// update the current settings to reflect any changes
|
||||||
|
CurrentWorkspaceSettings.Update(newSettings);
|
||||||
|
|
||||||
|
// if script analysis settings have changed we need to clear the current diagnostic markers
|
||||||
|
if (oldEnableIntelliSense != newSettings.SqlTools.IntelliSense.EnableIntellisense
|
||||||
|
|| oldEnableDiagnostics != newSettings.SqlTools.IntelliSense.EnableErrorChecking)
|
||||||
|
{
|
||||||
|
// if the user just turned off diagnostics then send an event to clear the error markers
|
||||||
|
if (!newSettings.IsDiagnosticsEnabled)
|
||||||
{
|
{
|
||||||
await DiagnosticsHelper.ClearScriptDiagnostics(scriptFile.ClientFilePath, eventContext);
|
ScriptFileMarker[] emptyAnalysisDiagnostics = new ScriptFileMarker[0];
|
||||||
|
|
||||||
|
foreach (var scriptFile in CurrentWorkspace.GetOpenedFiles())
|
||||||
|
{
|
||||||
|
await DiagnosticsHelper.ClearScriptDiagnostics(scriptFile.ClientFilePath, eventContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// otherwise rerun diagnostic analysis on all opened SQL files
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await this.RunScriptDiagnostics(CurrentWorkspace.GetOpenedFiles(), eventContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.Write(LogLevel.Error, "Unknown error " + ex.ToString());
|
||||||
|
// TODO: need mechanism return errors from event handlers
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles language flavor changes by disabling intellisense on a file if it does not match the specific
|
||||||
|
/// "MSSQL" language flavor returned by our service
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="info"></param>
|
||||||
|
public async Task HandleDidChangeLanguageFlavorNotification(
|
||||||
|
LanguageFlavorChangeParams changeParams,
|
||||||
|
EventContext eventContext)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Validate.IsNotNull(nameof(changeParams), changeParams);
|
||||||
|
Validate.IsNotNull(nameof(changeParams), changeParams.Uri);
|
||||||
|
bool shouldBlock = false;
|
||||||
|
if (SQL_LANG.Equals(changeParams.Language, StringComparison.OrdinalIgnoreCase)) {
|
||||||
|
shouldBlock = !ServiceHost.ProviderName.Equals(changeParams.Flavor, StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldBlock) {
|
||||||
|
this.nonMssqlUriMap.AddOrUpdate(changeParams.Uri, true, (k, oldValue) => true);
|
||||||
|
if (CurrentWorkspace.ContainsFile(changeParams.Uri))
|
||||||
|
{
|
||||||
|
await DiagnosticsHelper.ClearScriptDiagnostics(changeParams.Uri, eventContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// otherwise rerun diagnostic analysis on all opened SQL files
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await this.RunScriptDiagnostics(CurrentWorkspace.GetOpenedFiles(), eventContext);
|
bool value;
|
||||||
|
this.nonMssqlUriMap.TryRemove(changeParams.Uri, out value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.Write(LogLevel.Error, "Unknown error " + ex.ToString());
|
||||||
|
// TODO: need mechanism return errors from event handlers
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -852,36 +949,6 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Handles language flavor changes by disabling intellisense on a file if it does not match the specific
|
|
||||||
/// "MSSQL" language flavor returned by our service
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="info"></param>
|
|
||||||
public async Task HandleDidChangeLanguageFlavorNotification(
|
|
||||||
LanguageFlavorChangeParams changeParams,
|
|
||||||
EventContext eventContext)
|
|
||||||
{
|
|
||||||
Validate.IsNotNull(nameof(changeParams), changeParams);
|
|
||||||
Validate.IsNotNull(nameof(changeParams), changeParams.Uri);
|
|
||||||
bool shouldBlock = false;
|
|
||||||
if (SQL_LANG.Equals(changeParams.Language, StringComparison.OrdinalIgnoreCase)) {
|
|
||||||
shouldBlock = !ServiceHost.ProviderName.Equals(changeParams.Flavor, StringComparison.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shouldBlock) {
|
|
||||||
this.nonMssqlUriMap.AddOrUpdate(changeParams.Uri, true, (k, oldValue) => true);
|
|
||||||
if (CurrentWorkspace.ContainsFile(changeParams.Uri))
|
|
||||||
{
|
|
||||||
await DiagnosticsHelper.ClearScriptDiagnostics(changeParams.Uri, eventContext);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bool value;
|
|
||||||
this.nonMssqlUriMap.TryRemove(changeParams.Uri, out value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool ShouldSkipNonMssqlFile(TextDocumentPosition textDocPosition)
|
private bool ShouldSkipNonMssqlFile(TextDocumentPosition textDocPosition)
|
||||||
{
|
{
|
||||||
return ShouldSkipNonMssqlFile(textDocPosition.TextDocument.Uri);
|
return ShouldSkipNonMssqlFile(textDocPosition.TextDocument.Uri);
|
||||||
|
|||||||
@@ -134,31 +134,37 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
|
|||||||
EventContext eventContext)
|
EventContext eventContext)
|
||||||
{
|
{
|
||||||
// update the current settings to reflect any changes (assuming formatter settings exist)
|
// update the current settings to reflect any changes (assuming formatter settings exist)
|
||||||
settings = newSettings.SqlTools.ObjectExplorer ?? settings;
|
settings = newSettings?.SqlTools?.ObjectExplorer ?? settings;
|
||||||
return Task.FromResult(true);
|
return Task.FromResult(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal async Task HandleCreateSessionRequest(ConnectionDetails connectionDetails, RequestContext<CreateSessionResponse> context)
|
internal async Task HandleCreateSessionRequest(ConnectionDetails connectionDetails, RequestContext<CreateSessionResponse> context)
|
||||||
{
|
{
|
||||||
Logger.Write(LogLevel.Verbose, "HandleCreateSessionRequest");
|
try
|
||||||
|
|
||||||
Func<Task<CreateSessionResponse>> doCreateSession = async () =>
|
|
||||||
{
|
{
|
||||||
Validate.IsNotNull(nameof(connectionDetails), connectionDetails);
|
Logger.Write(LogLevel.Verbose, "HandleCreateSessionRequest");
|
||||||
Validate.IsNotNull(nameof(context), context);
|
Func<Task<CreateSessionResponse>> doCreateSession = async () =>
|
||||||
return await Task.Factory.StartNew(() =>
|
|
||||||
{
|
{
|
||||||
string uri = GenerateUri(connectionDetails);
|
Validate.IsNotNull(nameof(connectionDetails), connectionDetails);
|
||||||
|
Validate.IsNotNull(nameof(context), context);
|
||||||
|
return await Task.Factory.StartNew(() =>
|
||||||
|
{
|
||||||
|
string uri = GenerateUri(connectionDetails);
|
||||||
|
|
||||||
return new CreateSessionResponse { SessionId = uri };
|
return new CreateSessionResponse { SessionId = uri };
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
CreateSessionResponse response = await HandleRequestAsync(doCreateSession, context, "HandleCreateSessionRequest");
|
CreateSessionResponse response = await HandleRequestAsync(doCreateSession, context, "HandleCreateSessionRequest");
|
||||||
if (response != null)
|
if (response != null)
|
||||||
|
{
|
||||||
|
RunCreateSessionTask(connectionDetails, response.SessionId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
RunCreateSessionTask(connectionDetails, response.SessionId);
|
await context.SendError(ex.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -191,32 +197,39 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
await HandleRequestAsync(expandNode, context, "HandleExpandRequest");
|
await HandleRequestAsync(expandNode, context, "HandleExpandRequest");
|
||||||
}
|
}
|
||||||
|
|
||||||
internal async Task HandleRefreshRequest(RefreshParams refreshParams, RequestContext<bool> context)
|
internal async Task HandleRefreshRequest(RefreshParams refreshParams, RequestContext<bool> context)
|
||||||
{
|
{
|
||||||
Logger.Write(LogLevel.Verbose, "HandleRefreshRequest");
|
try
|
||||||
Validate.IsNotNull(nameof(refreshParams), refreshParams);
|
{
|
||||||
Validate.IsNotNull(nameof(context), context);
|
Logger.Write(LogLevel.Verbose, "HandleRefreshRequest");
|
||||||
|
Validate.IsNotNull(nameof(refreshParams), refreshParams);
|
||||||
|
Validate.IsNotNull(nameof(context), context);
|
||||||
|
|
||||||
string uri = refreshParams.SessionId;
|
string uri = refreshParams.SessionId;
|
||||||
ObjectExplorerSession session = null;
|
ObjectExplorerSession session = null;
|
||||||
if (!sessionMap.TryGetValue(uri, out session))
|
if (!sessionMap.TryGetValue(uri, out session))
|
||||||
{
|
|
||||||
Logger.Write(LogLevel.Verbose, $"Cannot expand object explorer node. Couldn't find session for uri. {uri} ");
|
|
||||||
await serviceHost.SendEvent(ExpandCompleteNotification.Type, new ExpandResponse
|
|
||||||
{
|
{
|
||||||
SessionId = refreshParams.SessionId,
|
Logger.Write(LogLevel.Verbose, $"Cannot expand object explorer node. Couldn't find session for uri. {uri} ");
|
||||||
NodePath = refreshParams.NodePath,
|
await serviceHost.SendEvent(ExpandCompleteNotification.Type, new ExpandResponse
|
||||||
ErrorMessage = $"Couldn't find session for session: {uri}"
|
{
|
||||||
});
|
SessionId = refreshParams.SessionId,
|
||||||
|
NodePath = refreshParams.NodePath,
|
||||||
|
ErrorMessage = $"Couldn't find session for session: {uri}"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RunExpandTask(session, refreshParams, true);
|
||||||
|
}
|
||||||
|
await context.SendResult(true);
|
||||||
}
|
}
|
||||||
else
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
RunExpandTask(session, refreshParams, true);
|
await context.SendError(ex.ToString());
|
||||||
}
|
}
|
||||||
await context.SendResult(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal async Task HandleCloseSessionRequest(CloseSessionParams closeSessionParams, RequestContext<CloseSessionResponse> context)
|
internal async Task HandleCloseSessionRequest(CloseSessionParams closeSessionParams, RequestContext<CloseSessionResponse> context)
|
||||||
|
|||||||
@@ -232,8 +232,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace
|
|||||||
var handlers = TextDocChangeCallbacks.Select(t => t(changedFiles.ToArray(), eventContext));
|
var handlers = TextDocChangeCallbacks.Select(t => t(changedFiles.ToArray(), eventContext));
|
||||||
return Task.WhenAll(handlers);
|
return Task.WhenAll(handlers);
|
||||||
}
|
}
|
||||||
catch
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
Logger.Write(LogLevel.Error, "Unknown error " + ex.ToString());
|
||||||
// Swallow exceptions here to prevent us from crashing
|
// Swallow exceptions here to prevent us from crashing
|
||||||
// TODO: this probably means the ScriptFile model is in a bad state or out of sync with the actual file; we should recover here
|
// TODO: this probably means the ScriptFile model is in a bad state or out of sync with the actual file; we should recover here
|
||||||
return Task.FromResult(true);
|
return Task.FromResult(true);
|
||||||
@@ -244,50 +245,70 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace
|
|||||||
DidOpenTextDocumentNotification openParams,
|
DidOpenTextDocumentNotification openParams,
|
||||||
EventContext eventContext)
|
EventContext eventContext)
|
||||||
{
|
{
|
||||||
Logger.Write(LogLevel.Verbose, "HandleDidOpenTextDocumentNotification");
|
try
|
||||||
|
|
||||||
if (IsScmEvent(openParams.TextDocument.Uri))
|
|
||||||
{
|
{
|
||||||
|
Logger.Write(LogLevel.Verbose, "HandleDidOpenTextDocumentNotification");
|
||||||
|
|
||||||
|
if (IsScmEvent(openParams.TextDocument.Uri))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read the SQL file contents into the ScriptFile
|
||||||
|
ScriptFile openedFile = Workspace.GetFileBuffer(openParams.TextDocument.Uri, openParams.TextDocument.Text);
|
||||||
|
if (openedFile == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Propagate the changes to the event handlers
|
||||||
|
var textDocOpenTasks = TextDocOpenCallbacks.Select(
|
||||||
|
t => t(openedFile, eventContext));
|
||||||
|
|
||||||
|
await Task.WhenAll(textDocOpenTasks);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.Write(LogLevel.Error, "Unknown error " + ex.ToString());
|
||||||
|
// Swallow exceptions here to prevent us from crashing
|
||||||
|
// TODO: this probably means the ScriptFile model is in a bad state or out of sync with the actual file; we should recover here
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// read the SQL file contents into the ScriptFile
|
|
||||||
ScriptFile openedFile = Workspace.GetFileBuffer(openParams.TextDocument.Uri, openParams.TextDocument.Text);
|
|
||||||
if (openedFile == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Propagate the changes to the event handlers
|
|
||||||
var textDocOpenTasks = TextDocOpenCallbacks.Select(
|
|
||||||
t => t(openedFile, eventContext));
|
|
||||||
|
|
||||||
await Task.WhenAll(textDocOpenTasks);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal async Task HandleDidCloseTextDocumentNotification(
|
internal async Task HandleDidCloseTextDocumentNotification(
|
||||||
DidCloseTextDocumentParams closeParams,
|
DidCloseTextDocumentParams closeParams,
|
||||||
EventContext eventContext)
|
EventContext eventContext)
|
||||||
{
|
{
|
||||||
Logger.Write(LogLevel.Verbose, "HandleDidCloseTextDocumentNotification");
|
try
|
||||||
|
|
||||||
if (IsScmEvent(closeParams.TextDocument.Uri))
|
|
||||||
{
|
{
|
||||||
|
Logger.Write(LogLevel.Verbose, "HandleDidCloseTextDocumentNotification");
|
||||||
|
|
||||||
|
if (IsScmEvent(closeParams.TextDocument.Uri))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip closing this file if the file doesn't exist
|
||||||
|
var closedFile = Workspace.GetFile(closeParams.TextDocument.Uri);
|
||||||
|
if (closedFile == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trash the existing document from our mapping
|
||||||
|
Workspace.CloseFile(closedFile);
|
||||||
|
|
||||||
|
// Send out a notification to other services that have subscribed to this event
|
||||||
|
var textDocClosedTasks = TextDocCloseCallbacks.Select(t => t(closedFile, eventContext));
|
||||||
|
await Task.WhenAll(textDocClosedTasks);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.Write(LogLevel.Error, "Unknown error " + ex.ToString());
|
||||||
|
// Swallow exceptions here to prevent us from crashing
|
||||||
|
// TODO: this probably means the ScriptFile model is in a bad state or out of sync with the actual file; we should recover here
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip closing this file if the file doesn't exist
|
|
||||||
var closedFile = Workspace.GetFile(closeParams.TextDocument.Uri);
|
|
||||||
if (closedFile == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Trash the existing document from our mapping
|
|
||||||
Workspace.CloseFile(closedFile);
|
|
||||||
|
|
||||||
// Send out a notification to other services that have subscribed to this event
|
|
||||||
var textDocClosedTasks = TextDocCloseCallbacks.Select(t => t(closedFile, eventContext));
|
|
||||||
await Task.WhenAll(textDocClosedTasks);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -297,12 +318,22 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace
|
|||||||
DidChangeConfigurationParams<TConfig> configChangeParams,
|
DidChangeConfigurationParams<TConfig> configChangeParams,
|
||||||
EventContext eventContext)
|
EventContext eventContext)
|
||||||
{
|
{
|
||||||
Logger.Write(LogLevel.Verbose, "HandleDidChangeConfigurationNotification");
|
try
|
||||||
|
{
|
||||||
|
Logger.Write(LogLevel.Verbose, "HandleDidChangeConfigurationNotification");
|
||||||
|
|
||||||
// Propagate the changes to the event handlers
|
// Propagate the changes to the event handlers
|
||||||
var configUpdateTasks = ConfigChangeCallbacks.Select(
|
var configUpdateTasks = ConfigChangeCallbacks.Select(
|
||||||
t => t(configChangeParams.Settings, CurrentSettings, eventContext));
|
t => t(configChangeParams.Settings, CurrentSettings, eventContext));
|
||||||
await Task.WhenAll(configUpdateTasks);
|
await Task.WhenAll(configUpdateTasks);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.Write(LogLevel.Error, "Unknown error " + ex.ToString());
|
||||||
|
// Swallow exceptions here to prevent us from crashing
|
||||||
|
// TODO: this probably means the ScriptFile model is in a bad state or out of sync with the actual file; we should recover here
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@@ -82,10 +82,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Workspace
|
|||||||
TextDocument = new TextDocumentItem {Uri = TestObjects.ScriptUri}
|
TextDocument = new TextDocumentItem {Uri = TestObjects.ScriptUri}
|
||||||
};
|
};
|
||||||
// Then:
|
// Then:
|
||||||
// ... There should be a file not found exception thrown
|
await workspaceService.HandleDidCloseTextDocumentNotification(requestParams, eventContext);
|
||||||
// TODO: This logic should be changed to not create the ScriptFile
|
|
||||||
await Assert.ThrowsAnyAsync<IOException>(
|
|
||||||
() => workspaceService.HandleDidCloseTextDocumentNotification(requestParams, eventContext));
|
|
||||||
|
|
||||||
// ... There should still be no open files
|
// ... There should still be no open files
|
||||||
// ... The callback should not have been called
|
// ... The callback should not have been called
|
||||||
|
|||||||
Reference in New Issue
Block a user