mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-21 01:25:42 -05:00
Clear and rebuild IntelliSense cache (#238)
* Stage changes to other machine * IntelliSense cache rebuild command * Move to other machine * Add a test for overwriting binding queue. * Move event handler into lanaguageservice.cs
This commit is contained in:
@@ -123,6 +123,28 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove the binding queue entry
|
||||
/// </summary>
|
||||
protected void RemoveBindingContext(string key)
|
||||
{
|
||||
lock (this.bindingContextLock)
|
||||
{
|
||||
if (this.BindingContextMap.ContainsKey(key))
|
||||
{
|
||||
// disconnect existing connection
|
||||
var bindingContext = this.BindingContextMap[key];
|
||||
if (bindingContext.ServerConnection != null && bindingContext.ServerConnection.IsOpen)
|
||||
{
|
||||
bindingContext.ServerConnection.Disconnect();
|
||||
}
|
||||
|
||||
// remove key from the map
|
||||
this.BindingContextMap.Remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool HasPendingQueueItems
|
||||
{
|
||||
get
|
||||
|
||||
@@ -51,8 +51,9 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
/// <summary>
|
||||
/// Use a ConnectionInfo item to create a connected binding context
|
||||
/// </summary>
|
||||
/// <param name="connInfo"></param>
|
||||
public virtual string AddConnectionContext(ConnectionInfo connInfo)
|
||||
/// <param name="connInfo">Connection info used to create binding context</param>
|
||||
/// <param name="overwrite">Overwrite existing context</param>
|
||||
public virtual string AddConnectionContext(ConnectionInfo connInfo, bool overwrite = false)
|
||||
{
|
||||
if (connInfo == null)
|
||||
{
|
||||
@@ -63,8 +64,15 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
string connectionKey = GetConnectionContextKey(connInfo);
|
||||
if (BindingContextExists(connectionKey))
|
||||
{
|
||||
// no need to populate the context again since the context already exists
|
||||
return connectionKey;
|
||||
if (overwrite)
|
||||
{
|
||||
RemoveBindingContext(connectionKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
// no need to populate the context again since the context already exists
|
||||
return connectionKey;
|
||||
}
|
||||
}
|
||||
IBindingContext bindingContext = this.GetOrCreateBindingContext(connectionKey);
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters to be sent back with a rebuild IntelliSense event
|
||||
/// </summary>
|
||||
public class RebuildIntelliSenseParams
|
||||
{
|
||||
/// <summary>
|
||||
/// URI identifying the file that should have its IntelliSense cache rebuilt
|
||||
/// </summary>
|
||||
public string OwnerUri { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// RebuildIntelliSenseNotification notification mapping entry
|
||||
/// </summary>
|
||||
public class RebuildIntelliSenseNotification
|
||||
{
|
||||
public static readonly
|
||||
EventType<RebuildIntelliSenseParams> Type =
|
||||
EventType<RebuildIntelliSenseParams>.Create("textDocument/rebuildIntelliSense");
|
||||
}
|
||||
}
|
||||
@@ -212,6 +212,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
serviceHost.SetRequestHandler(HoverRequest.Type, HandleHoverRequest);
|
||||
serviceHost.SetRequestHandler(CompletionRequest.Type, HandleCompletionRequest);
|
||||
serviceHost.SetRequestHandler(DefinitionRequest.Type, HandleDefinitionRequest);
|
||||
serviceHost.SetEventHandler(RebuildIntelliSenseNotification.Type, HandleRebuildIntelliSenseNotification);
|
||||
|
||||
// Register a no-op shutdown task for validation of the shutdown logic
|
||||
serviceHost.RegisterShutdownTask(async (shutdownParams, shutdownRequestContext) =>
|
||||
@@ -442,6 +443,62 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
await Task.FromResult(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle the rebuild IntelliSense cache notification
|
||||
/// </summary>
|
||||
public async Task HandleRebuildIntelliSenseNotification(
|
||||
RebuildIntelliSenseParams configChangeParams,
|
||||
EventContext eventContext)
|
||||
{
|
||||
Logger.Write(LogLevel.Verbose, "HandleRebuildIntelliSenseNotification");
|
||||
|
||||
// Skip closing this file if the file doesn't exist
|
||||
var scriptFile = this.CurrentWorkspace.GetFile(configChangeParams.OwnerUri);
|
||||
if (scriptFile == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ConnectionInfo connInfo;
|
||||
LanguageService.ConnectionServiceInstance.TryFindConnection(
|
||||
scriptFile.ClientFilePath,
|
||||
out connInfo);
|
||||
|
||||
await Task.Run(() =>
|
||||
{
|
||||
ScriptParseInfo scriptInfo = GetScriptParseInfo(connInfo.OwnerUri, createIfNotExists: false);
|
||||
if (scriptInfo != null && scriptInfo.IsConnected &&
|
||||
Monitor.TryEnter(scriptInfo.BuildingMetadataLock, LanguageService.OnConnectionWaitTimeout))
|
||||
{
|
||||
try
|
||||
{
|
||||
this.BindingQueue.AddConnectionContext(connInfo, overwrite: true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Write(LogLevel.Error, "Unknown error " + ex.ToString());
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Set Metadata Build event to Signal state.
|
||||
Monitor.Exit(scriptInfo.BuildingMetadataLock);
|
||||
}
|
||||
}
|
||||
|
||||
// if not in the preview window and diagnostics are enabled then run diagnostics
|
||||
if (!IsPreviewWindow(scriptFile)
|
||||
&& WorkspaceService<SqlToolsSettings>.Instance.CurrentSettings.IsDiagnositicsEnabled)
|
||||
{
|
||||
RunScriptDiagnostics(
|
||||
new ScriptFile[] { scriptFile },
|
||||
eventContext);
|
||||
}
|
||||
|
||||
// Send a notification to signal that autocomplete is ready
|
||||
ServiceHost.Instance.SendEvent(IntelliSenseReadyNotification.Type, new IntelliSenseReadyParams() {OwnerUri = connInfo.OwnerUri});
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle the file configuration change notification
|
||||
/// </summary>
|
||||
|
||||
@@ -112,6 +112,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace
|
||||
/// List of callbacks to call when a text document is closed
|
||||
/// </summary>
|
||||
private List<TextDocCloseCallback> TextDocCloseCallbacks { get; set; }
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -189,7 +190,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace
|
||||
public void RegisterTextDocOpenCallback(TextDocOpenCallback task)
|
||||
{
|
||||
TextDocOpenCallbacks.Add(task);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -287,7 +288,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace
|
||||
var configUpdateTasks = ConfigChangeCallbacks.Select(
|
||||
t => t(configChangeParams.Settings, CurrentSettings, eventContext));
|
||||
await Task.WhenAll(configUpdateTasks);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -135,5 +135,27 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServer
|
||||
SignatureHelp signatureHelp = service.GetSignatureHelp(textDocument, result.ScriptFile);
|
||||
Assert.NotNull(signatureHelp);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test overwriting the binding queue context
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void OverwriteBindingContext()
|
||||
{
|
||||
var result = TestObjects.InitLiveConnectionInfo();
|
||||
|
||||
// add a new connection context
|
||||
var connectionKey = LanguageService.Instance.BindingQueue.AddConnectionContext(result.ConnectionInfo, overwrite: true);
|
||||
Assert.True(LanguageService.Instance.BindingQueue.BindingContextMap.ContainsKey(connectionKey));
|
||||
|
||||
// cache the server connection
|
||||
var orgServerConnection = LanguageService.Instance.BindingQueue.BindingContextMap[connectionKey].ServerConnection;
|
||||
Assert.NotNull(orgServerConnection);
|
||||
|
||||
// add a new connection context
|
||||
connectionKey = LanguageService.Instance.BindingQueue.AddConnectionContext(result.ConnectionInfo, overwrite: true);
|
||||
Assert.True(LanguageService.Instance.BindingQueue.BindingContextMap.ContainsKey(connectionKey));
|
||||
Assert.False(object.ReferenceEquals(LanguageService.Instance.BindingQueue.BindingContextMap[connectionKey].ServerConnection, orgServerConnection));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices
|
||||
|
||||
// setup binding queue mock
|
||||
bindingQueue = new Mock<ConnectedBindingQueue>();
|
||||
bindingQueue.Setup(q => q.AddConnectionContext(It.IsAny<ConnectionInfo>()))
|
||||
bindingQueue.Setup(q => q.AddConnectionContext(It.IsAny<ConnectionInfo>(), It.IsAny<bool>()))
|
||||
.Returns(this.testConnectionKey);
|
||||
|
||||
// inject mock instances into the Language Service
|
||||
|
||||
@@ -82,7 +82,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices
|
||||
|
||||
// setup binding queue mock
|
||||
bindingQueue = new Mock<ConnectedBindingQueue>();
|
||||
bindingQueue.Setup(q => q.AddConnectionContext(It.IsAny<ConnectionInfo>()))
|
||||
bindingQueue.Setup(q => q.AddConnectionContext(It.IsAny<ConnectionInfo>(), It.IsAny<bool>()))
|
||||
.Returns(this.testConnectionKey);
|
||||
|
||||
// inject mock instances into the Language Service
|
||||
|
||||
Reference in New Issue
Block a user