diff --git a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/Contracts/StatusChangedNotification.cs b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/Contracts/StatusChangedNotification.cs new file mode 100644 index 00000000..4e5d1b92 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/Contracts/StatusChangedNotification.cs @@ -0,0 +1,35 @@ +// +// 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 +{ + /// + /// Parameters sent back with an status change event + /// + public class StatusChangeParams + { + /// + /// URI identifying the text document + /// + public string OwnerUri { get; set; } + + /// + /// The new status for the document + /// + public string Status { get; set; } + } + + /// + /// Event sent for language service status change notification + /// + public class StatusChangedNotification + { + public static readonly + EventType Type = + EventType.Create("textDocument/statusChanged"); + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/DocumentStatusHelper.cs b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/DocumentStatusHelper.cs new file mode 100644 index 00000000..8e580196 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/DocumentStatusHelper.cs @@ -0,0 +1,58 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System.Threading.Tasks; +using Microsoft.SqlTools.ServiceLayer.Hosting; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol; +using Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts; +using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts; + +namespace Microsoft.SqlTools.ServiceLayer.LanguageServices +{ + /// + /// Helper class to send events to the client + /// + public class DocumentStatusHelper + { + public const string DefinitionRequested = "DefinitionRequested"; + public const string DefinitionRequestCompleted = "DefinitionRequestCompleted"; + + /// + /// Sends an event for specific document using the existing request context + /// + public static void SendStatusChange(RequestContext requestContext, TextDocumentPosition textDocumentPosition, string status) + { + Task.Factory.StartNew(async () => + { + if (requestContext != null) + { + string ownerUri = textDocumentPosition != null && textDocumentPosition.TextDocument != null ? textDocumentPosition.TextDocument.Uri : ""; + await requestContext.SendEvent(StatusChangedNotification.Type, new StatusChangeParams() + { + OwnerUri = ownerUri, + Status = status + }); + } + }); + } + + /// + /// Sends a telemetry event for specific document using the existing request context + /// + public static void SendTelemetryEvent(RequestContext requestContext, string telemetryEvent) + { + Task.Factory.StartNew(async () => + { + await requestContext.SendEvent(TelemetryNotification.Type, new TelemetryParams() + { + Params = new TelemetryProperties + { + EventName = telemetryEvent + } + }); + }); + } + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/LanguageService.cs b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/LanguageService.cs index d87eab9a..7fb4bc69 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/LanguageService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/LanguageService.cs @@ -300,6 +300,17 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices internal static async Task HandleDefinitionRequest(TextDocumentPosition textDocumentPosition, RequestContext requestContext) { + // Send a notification to signal that definition is sent + await requestContext.SendEvent(TelemetryNotification.Type, new TelemetryParams() + { + Params = new TelemetryProperties + { + EventName = TelemetryEventNames.PeekDefinitionRequested + } + }); + DocumentStatusHelper.SendTelemetryEvent(requestContext, TelemetryEventNames.PeekDefinitionRequested); + DocumentStatusHelper.SendStatusChange(requestContext, textDocumentPosition, DocumentStatusHelper.DefinitionRequested); + if (WorkspaceService.Instance.CurrentSettings.IsIntelliSenseEnabled) { // Retrieve document and connection @@ -311,17 +322,9 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices if (locations != null) { await requestContext.SendResult(locations); - - // Send a notification to signal that definition is sent - await ServiceHost.Instance.SendEvent(TelemetryNotification.Type, new TelemetryParams() - { - Params = new TelemetryProperties - { - EventName = TelemetryEventNames.PeekDefinitionRequested - } - }); } } + DocumentStatusHelper.SendStatusChange(requestContext, textDocumentPosition, DocumentStatusHelper.DefinitionRequestCompleted); } // turn off this code until needed (10/28/2016) diff --git a/test/Microsoft.SqlTools.ServiceLayer.PerfTests/Tests/IntellisenseTests.cs b/test/Microsoft.SqlTools.ServiceLayer.PerfTests/Tests/IntellisenseTests.cs index 75d36e0b..3f84df16 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.PerfTests/Tests/IntellisenseTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.PerfTests/Tests/IntellisenseTests.cs @@ -122,7 +122,7 @@ namespace Microsoft.SqlTools.ServiceLayer.PerfTests TestServerType serverType = TestServerType.OnPrem; using (TestHelper testHelper = new TestHelper()) { - await VerifyBindingLoadScenario(testHelper, TestServerType.OnPrem, Scripts.TestDbSimpleSelectQuery, false); + await VerifyBindingLoadScenario(testHelper, serverType, Scripts.TestDbSimpleSelectQuery, false); } } @@ -170,10 +170,10 @@ namespace Microsoft.SqlTools.ServiceLayer.PerfTests [CreateTestDb(TestServerType.Azure)] public async Task BindingCacheColdOnPremComplexQuery() { - TestServerType serverType = TestServerType.Azure; + TestServerType serverType = TestServerType.OnPrem; using (TestHelper testHelper = new TestHelper()) { - await VerifyBindingLoadScenario(testHelper, TestServerType.OnPrem, Scripts.TestDbComplexSelectQueries, false); + await VerifyBindingLoadScenario(testHelper, serverType, Scripts.TestDbComplexSelectQueries, false); } } diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test/LanguageServer/PeekDefinitionTests.cs b/test/Microsoft.SqlTools.ServiceLayer.Test/LanguageServer/PeekDefinitionTests.cs index b70c6c54..9bb871b1 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.Test/LanguageServer/PeekDefinitionTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.Test/LanguageServer/PeekDefinitionTests.cs @@ -3,24 +3,26 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // using System; -using System.IO; using System.Collections.Generic; -using System.Threading.Tasks; +using System.IO; using System.Runtime.InteropServices; +using System.Threading.Tasks; using Microsoft.SqlServer.Management.SqlParser.Binder; using Microsoft.SqlServer.Management.SqlParser.MetadataProvider; using Microsoft.SqlServer.Management.SqlParser.Parser; using Microsoft.SqlTools.ServiceLayer.Connection; using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts; using Microsoft.SqlTools.ServiceLayer.LanguageServices; +using Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts; using Microsoft.SqlTools.ServiceLayer.SqlContext; using Microsoft.SqlTools.ServiceLayer.Test.QueryExecution; using Microsoft.SqlTools.ServiceLayer.Workspace; using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts; using Microsoft.SqlTools.Test.Utility; -using Location = Microsoft.SqlTools.ServiceLayer.Workspace.Contracts.Location; using Moq; using Xunit; +using Location = Microsoft.SqlTools.ServiceLayer.Workspace.Contracts.Location; namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices { @@ -89,6 +91,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices requestContext = new Mock>(); requestContext.Setup(rc => rc.SendResult(It.IsAny())) .Returns(Task.FromResult(0)); + requestContext.Setup(r => r.SendEvent(It.IsAny>(), It.IsAny())); + requestContext.Setup(r => r.SendEvent(It.IsAny>(), It.IsAny())); // setup the IBinder mock binder = new Mock(); @@ -114,13 +118,13 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices /// Tests the definition event handler. When called with no active connection, no definition is sent /// [Fact] - public void DefinitionsHandlerWithNoConnectionTest() + public async Task DefinitionsHandlerWithNoConnectionTest() { + TestObjects.InitializeTestServices(); InitializeTestObjects(); // request the completion list - Task handleCompletion = LanguageService.HandleDefinitionRequest(textDocument, requestContext.Object); - handleCompletion.Wait(TaskTimeout); - + await Task.WhenAny(LanguageService.HandleDefinitionRequest(textDocument, requestContext.Object), Task.Delay(TaskTimeout)); + // verify that send result was not called requestContext.Verify(m => m.SendResult(It.IsAny()), Times.Never()); }