Add try/catch blocks for request handlers (#408)

* Add try/catch for request handlers

* Fix test break
This commit is contained in:
Karl Burtram
2017-07-13 07:18:34 -07:00
committed by GitHub
parent 414949d129
commit 005fc9e4df
6 changed files with 441 additions and 306 deletions

View File

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

View File

@@ -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);
} }

View File

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

View File

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

View File

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

View File

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