diff --git a/src/ServiceHost/Connection/ConnectionMessages.cs b/src/ServiceHost/Connection/ConnectionMessages.cs index 814e55f0..a2b506aa 100644 --- a/src/ServiceHost/Connection/ConnectionMessages.cs +++ b/src/ServiceHost/Connection/ConnectionMessages.cs @@ -3,9 +3,9 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts; -namespace Microsoft.SqlTools.EditorServices.Connection +namespace Microsoft.SqlTools.ServiceLayer.Connection { /// /// Message format for the initial connection request diff --git a/src/ServiceHost/Connection/ConnectionService.cs b/src/ServiceHost/Connection/ConnectionService.cs index 8f0634a7..afbf4ab4 100644 --- a/src/ServiceHost/Connection/ConnectionService.cs +++ b/src/ServiceHost/Connection/ConnectionService.cs @@ -7,20 +7,47 @@ using System; using System.Collections.Generic; using System.Data.SqlClient; using System.Threading.Tasks; +using Microsoft.SqlTools.EditorServices.Utility; +using Microsoft.SqlTools.ServiceLayer.Hosting; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol; -namespace Microsoft.SqlTools.EditorServices.Connection +namespace Microsoft.SqlTools.ServiceLayer.Connection { /// /// Main class for the Connection Management services /// public class ConnectionService { + #region Singleton Instance Implementation + /// /// Singleton service instance /// private static Lazy instance = new Lazy(() => new ConnectionService()); + /// + /// Gets the singleton service instance + /// + public static ConnectionService Instance + { + get + { + return instance.Value; + } + } + + /// + /// Default constructor is private since it's a singleton class + /// + private ConnectionService() + { + } + + #endregion + + #region Properties + /// /// The SQL connection factory object /// @@ -60,17 +87,6 @@ namespace Microsoft.SqlTools.EditorServices.Connection } } - /// - /// Gets the singleton service instance - /// - public static ConnectionService Instance - { - get - { - return instance.Value; - } - } - /// /// Gets the SQL connection factory instance /// @@ -86,12 +102,7 @@ namespace Microsoft.SqlTools.EditorServices.Connection } } - /// - /// Default constructor is private since it's a singleton class - /// - private ConnectionService() - { - } + #endregion /// /// Test constructor that injects dependency interfaces @@ -102,6 +113,8 @@ namespace Microsoft.SqlTools.EditorServices.Connection this.connectionFactory = testFactory; } + #region Public Methods + /// /// Open a connection with the specified connection details /// @@ -133,6 +146,12 @@ namespace Microsoft.SqlTools.EditorServices.Connection }; } + public void Initialize(ServiceHost serviceHost) + { + // Register request and event handlers with the Service Host + serviceHost.SetRequestHandler(ConnectionRequest.Type, HandleConnectRequest); + } + /// /// Add a new method to be called when the onconnection request is submitted /// @@ -140,7 +159,33 @@ namespace Microsoft.SqlTools.EditorServices.Connection public void RegisterOnConnectionTask(OnConnectionHandler activity) { onConnectionActivities.Add(activity); - } + } + + #endregion + + #region Request Handlers + + /// + /// Handle new connection requests + /// + /// + /// + /// + protected async Task HandleConnectRequest( + ConnectionDetails connectionDetails, + RequestContext requestContext) + { + Logger.Write(LogLevel.Verbose, "HandleConnectRequest"); + + // open connection base on request details + ConnectionResult result = ConnectionService.Instance.Connect(connectionDetails); + + await requestContext.SendResult(result); + } + + #endregion + + #region Private Helpers /// /// Build a connection string from a connection details instance @@ -156,5 +201,7 @@ namespace Microsoft.SqlTools.EditorServices.Connection connectionBuilder["Initial Catalog"] = connectionDetails.DatabaseName; return connectionBuilder.ToString(); } + + #endregion } } diff --git a/src/ServiceHost/Connection/ISqlConnection.cs b/src/ServiceHost/Connection/ISqlConnection.cs index 4ef80c5e..3e5fbdfe 100644 --- a/src/ServiceHost/Connection/ISqlConnection.cs +++ b/src/ServiceHost/Connection/ISqlConnection.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; -namespace Microsoft.SqlTools.EditorServices.Connection +namespace Microsoft.SqlTools.ServiceLayer.Connection { /// /// Interface for the SQL Connection factory diff --git a/src/ServiceHost/Connection/SqlConnection.cs b/src/ServiceHost/Connection/SqlConnection.cs index 5bb92553..6ad90b39 100644 --- a/src/ServiceHost/Connection/SqlConnection.cs +++ b/src/ServiceHost/Connection/SqlConnection.cs @@ -7,7 +7,7 @@ using System.Collections.Generic; using System.Data; using System.Data.SqlClient; -namespace Microsoft.SqlTools.EditorServices.Connection +namespace Microsoft.SqlTools.ServiceLayer.Connection { /// /// Factory class to create SqlClientConnections diff --git a/src/ServiceHost/LanguageServer/ClientCapabilities.cs b/src/ServiceHost/Hosting/Contracts/ClientCapabilities.cs similarity index 85% rename from src/ServiceHost/LanguageServer/ClientCapabilities.cs rename to src/ServiceHost/Hosting/Contracts/ClientCapabilities.cs index 70e2d068..397deceb 100644 --- a/src/ServiceHost/LanguageServer/ClientCapabilities.cs +++ b/src/ServiceHost/Hosting/Contracts/ClientCapabilities.cs @@ -4,7 +4,7 @@ // -namespace Microsoft.SqlTools.EditorServices.Protocol.LanguageServer +namespace Microsoft.SqlTools.ServiceLayer.Hosting.Contracts { /// /// Defines a class that describes the capabilities of a language diff --git a/src/ServiceHost/LanguageServer/Initialize.cs b/src/ServiceHost/Hosting/Contracts/Initialize.cs similarity index 91% rename from src/ServiceHost/LanguageServer/Initialize.cs rename to src/ServiceHost/Hosting/Contracts/Initialize.cs index 7551835e..215edf87 100644 --- a/src/ServiceHost/LanguageServer/Initialize.cs +++ b/src/ServiceHost/Hosting/Contracts/Initialize.cs @@ -3,9 +3,9 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts; -namespace Microsoft.SqlTools.EditorServices.Protocol.LanguageServer +namespace Microsoft.SqlTools.ServiceLayer.Hosting.Contracts { public class InitializeRequest { diff --git a/src/ServiceHost/LanguageServer/ServerCapabilities.cs b/src/ServiceHost/Hosting/Contracts/ServerCapabilities.cs similarity index 96% rename from src/ServiceHost/LanguageServer/ServerCapabilities.cs rename to src/ServiceHost/Hosting/Contracts/ServerCapabilities.cs index 2f7404d9..32f0e736 100644 --- a/src/ServiceHost/LanguageServer/ServerCapabilities.cs +++ b/src/ServiceHost/Hosting/Contracts/ServerCapabilities.cs @@ -3,7 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -namespace Microsoft.SqlTools.EditorServices.Protocol.LanguageServer +namespace Microsoft.SqlTools.ServiceLayer.Hosting.Contracts { public class ServerCapabilities { diff --git a/src/ServiceHost/LanguageServer/Shutdown.cs b/src/ServiceHost/Hosting/Contracts/Shutdown.cs similarity index 86% rename from src/ServiceHost/LanguageServer/Shutdown.cs rename to src/ServiceHost/Hosting/Contracts/Shutdown.cs index f0a7bbd2..1ccb9cfc 100644 --- a/src/ServiceHost/LanguageServer/Shutdown.cs +++ b/src/ServiceHost/Hosting/Contracts/Shutdown.cs @@ -3,9 +3,9 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts; -namespace Microsoft.SqlTools.EditorServices.Protocol.LanguageServer +namespace Microsoft.SqlTools.ServiceLayer.Hosting.Contracts { /// /// Defines a message that is sent from the client to request diff --git a/src/ServiceHost/MessageProtocol/Channel/ChannelBase.cs b/src/ServiceHost/Hosting/Protocol/Channel/ChannelBase.cs similarity index 94% rename from src/ServiceHost/MessageProtocol/Channel/ChannelBase.cs rename to src/ServiceHost/Hosting/Protocol/Channel/ChannelBase.cs index 848da39f..48cd66aa 100644 --- a/src/ServiceHost/MessageProtocol/Channel/ChannelBase.cs +++ b/src/ServiceHost/Hosting/Protocol/Channel/ChannelBase.cs @@ -3,10 +3,10 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol.Serializers; using System.Threading.Tasks; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Serializers; -namespace Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol.Channel +namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Channel { /// /// Defines a base implementation for servers and their clients over a diff --git a/src/ServiceHost/MessageProtocol/Channel/StdioClientChannel.cs b/src/ServiceHost/Hosting/Protocol/Channel/StdioClientChannel.cs similarity index 96% rename from src/ServiceHost/MessageProtocol/Channel/StdioClientChannel.cs rename to src/ServiceHost/Hosting/Protocol/Channel/StdioClientChannel.cs index 5390f52d..02b79c6b 100644 --- a/src/ServiceHost/MessageProtocol/Channel/StdioClientChannel.cs +++ b/src/ServiceHost/Hosting/Protocol/Channel/StdioClientChannel.cs @@ -7,8 +7,9 @@ using System.Diagnostics; using System.IO; using System.Text; using System.Threading.Tasks; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Serializers; -namespace Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol.Channel +namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Channel { /// /// Provides a client implementation for the standard I/O channel. diff --git a/src/ServiceHost/MessageProtocol/Channel/StdioServerChannel.cs b/src/ServiceHost/Hosting/Protocol/Channel/StdioServerChannel.cs similarity index 93% rename from src/ServiceHost/MessageProtocol/Channel/StdioServerChannel.cs rename to src/ServiceHost/Hosting/Protocol/Channel/StdioServerChannel.cs index 0b9376d4..204a9908 100644 --- a/src/ServiceHost/MessageProtocol/Channel/StdioServerChannel.cs +++ b/src/ServiceHost/Hosting/Protocol/Channel/StdioServerChannel.cs @@ -6,8 +6,9 @@ using System.IO; using System.Text; using System.Threading.Tasks; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Serializers; -namespace Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol.Channel +namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Channel { /// /// Provides a server implementation for the standard I/O channel. diff --git a/src/ServiceHost/MessageProtocol/Constants.cs b/src/ServiceHost/Hosting/Protocol/Constants.cs similarity index 91% rename from src/ServiceHost/MessageProtocol/Constants.cs rename to src/ServiceHost/Hosting/Protocol/Constants.cs index 0fae5d8d..14f3d762 100644 --- a/src/ServiceHost/MessageProtocol/Constants.cs +++ b/src/ServiceHost/Hosting/Protocol/Constants.cs @@ -6,7 +6,7 @@ using Newtonsoft.Json; using Newtonsoft.Json.Serialization; -namespace Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol +namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol { public static class Constants { diff --git a/src/ServiceHost/MessageProtocol/EventType.cs b/src/ServiceHost/Hosting/Protocol/Contracts/EventType.cs similarity index 93% rename from src/ServiceHost/MessageProtocol/EventType.cs rename to src/ServiceHost/Hosting/Protocol/Contracts/EventType.cs index dd460817..4d9a251b 100644 --- a/src/ServiceHost/MessageProtocol/EventType.cs +++ b/src/ServiceHost/Hosting/Protocol/Contracts/EventType.cs @@ -3,7 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -namespace Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol +namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts { /// /// Defines an event type with a particular method name. diff --git a/src/ServiceHost/MessageProtocol/Message.cs b/src/ServiceHost/Hosting/Protocol/Contracts/Message.cs similarity index 98% rename from src/ServiceHost/MessageProtocol/Message.cs rename to src/ServiceHost/Hosting/Protocol/Contracts/Message.cs index 75dab5cd..6af6a101 100644 --- a/src/ServiceHost/MessageProtocol/Message.cs +++ b/src/ServiceHost/Hosting/Protocol/Contracts/Message.cs @@ -6,7 +6,7 @@ using System.Diagnostics; using Newtonsoft.Json.Linq; -namespace Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol +namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts { /// /// Defines all possible message types. diff --git a/src/ServiceHost/MessageProtocol/RequestType.cs b/src/ServiceHost/Hosting/Protocol/Contracts/RequestType.cs similarity index 89% rename from src/ServiceHost/MessageProtocol/RequestType.cs rename to src/ServiceHost/Hosting/Protocol/Contracts/RequestType.cs index 29fc11c5..67676259 100644 --- a/src/ServiceHost/MessageProtocol/RequestType.cs +++ b/src/ServiceHost/Hosting/Protocol/Contracts/RequestType.cs @@ -5,7 +5,7 @@ using System.Diagnostics; -namespace Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol +namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts { [DebuggerDisplay("RequestType MethodName = {MethodName}")] public class RequestType diff --git a/src/ServiceHost/MessageProtocol/EventContext.cs b/src/ServiceHost/Hosting/Protocol/EventContext.cs similarity index 86% rename from src/ServiceHost/MessageProtocol/EventContext.cs rename to src/ServiceHost/Hosting/Protocol/EventContext.cs index eb42ebbb..4a1bc40e 100644 --- a/src/ServiceHost/MessageProtocol/EventContext.cs +++ b/src/ServiceHost/Hosting/Protocol/EventContext.cs @@ -4,8 +4,9 @@ // using System.Threading.Tasks; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts; -namespace Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol +namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol { /// /// Provides context for a received event so that handlers diff --git a/src/ServiceHost/MessageProtocol/IMessageSender.cs b/src/ServiceHost/Hosting/Protocol/IMessageSender.cs similarity index 80% rename from src/ServiceHost/MessageProtocol/IMessageSender.cs rename to src/ServiceHost/Hosting/Protocol/IMessageSender.cs index 7f331eed..ba42d1b9 100644 --- a/src/ServiceHost/MessageProtocol/IMessageSender.cs +++ b/src/ServiceHost/Hosting/Protocol/IMessageSender.cs @@ -4,8 +4,9 @@ // using System.Threading.Tasks; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts; -namespace Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol +namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol { internal interface IMessageSender { diff --git a/src/ServiceHost/MessageProtocol/MessageDispatcher.cs b/src/ServiceHost/Hosting/Protocol/MessageDispatcher.cs similarity index 98% rename from src/ServiceHost/MessageProtocol/MessageDispatcher.cs rename to src/ServiceHost/Hosting/Protocol/MessageDispatcher.cs index 21c179e2..a18fa806 100644 --- a/src/ServiceHost/MessageProtocol/MessageDispatcher.cs +++ b/src/ServiceHost/Hosting/Protocol/MessageDispatcher.cs @@ -3,15 +3,16 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol.Channel; -using Microsoft.SqlTools.EditorServices.Utility; using System; using System.Collections.Generic; using System.IO; using System.Threading; using System.Threading.Tasks; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Channel; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts; +using Microsoft.SqlTools.EditorServices.Utility; -namespace Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol +namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol { public class MessageDispatcher { diff --git a/src/ServiceHost/MessageProtocol/MessageParseException.cs b/src/ServiceHost/Hosting/Protocol/MessageParseException.cs similarity index 89% rename from src/ServiceHost/MessageProtocol/MessageParseException.cs rename to src/ServiceHost/Hosting/Protocol/MessageParseException.cs index 98a17c20..b4ef94c2 100644 --- a/src/ServiceHost/MessageProtocol/MessageParseException.cs +++ b/src/ServiceHost/Hosting/Protocol/MessageParseException.cs @@ -5,7 +5,7 @@ using System; -namespace Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol +namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol { public class MessageParseException : Exception { diff --git a/src/ServiceHost/MessageProtocol/MessageProtocolType.cs b/src/ServiceHost/Hosting/Protocol/MessageProtocolType.cs similarity index 89% rename from src/ServiceHost/MessageProtocol/MessageProtocolType.cs rename to src/ServiceHost/Hosting/Protocol/MessageProtocolType.cs index 5484ae3c..480332fa 100644 --- a/src/ServiceHost/MessageProtocol/MessageProtocolType.cs +++ b/src/ServiceHost/Hosting/Protocol/MessageProtocolType.cs @@ -3,7 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -namespace Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol +namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol { /// /// Defines the possible message protocol types. diff --git a/src/ServiceHost/MessageProtocol/MessageReader.cs b/src/ServiceHost/Hosting/Protocol/MessageReader.cs similarity index 97% rename from src/ServiceHost/MessageProtocol/MessageReader.cs rename to src/ServiceHost/Hosting/Protocol/MessageReader.cs index a2df43ba..f3857710 100644 --- a/src/ServiceHost/MessageProtocol/MessageReader.cs +++ b/src/ServiceHost/Hosting/Protocol/MessageReader.cs @@ -3,16 +3,18 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using Microsoft.SqlTools.EditorServices.Utility; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.IO; using System.Text; using System.Threading.Tasks; +using Microsoft.SqlTools.EditorServices.Utility; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Serializers; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; -namespace Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol +namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol { public class MessageReader { diff --git a/src/ServiceHost/MessageProtocol/MessageWriter.cs b/src/ServiceHost/Hosting/Protocol/MessageWriter.cs similarity index 95% rename from src/ServiceHost/MessageProtocol/MessageWriter.cs rename to src/ServiceHost/Hosting/Protocol/MessageWriter.cs index 96e13bcd..b269f750 100644 --- a/src/ServiceHost/MessageProtocol/MessageWriter.cs +++ b/src/ServiceHost/Hosting/Protocol/MessageWriter.cs @@ -3,14 +3,16 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using Microsoft.SqlTools.EditorServices.Utility; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using System.IO; using System.Text; using System.Threading.Tasks; +using Microsoft.SqlTools.EditorServices.Utility; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Serializers; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; -namespace Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol +namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol { public class MessageWriter { diff --git a/src/ServiceHost/MessageProtocol/ProtocolEndpoint.cs b/src/ServiceHost/Hosting/Protocol/ProtocolEndpoint.cs similarity index 98% rename from src/ServiceHost/MessageProtocol/ProtocolEndpoint.cs rename to src/ServiceHost/Hosting/Protocol/ProtocolEndpoint.cs index daead186..2068f5c8 100644 --- a/src/ServiceHost/MessageProtocol/ProtocolEndpoint.cs +++ b/src/ServiceHost/Hosting/Protocol/ProtocolEndpoint.cs @@ -3,13 +3,14 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol.Channel; using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Channel; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts; -namespace Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol +namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol { /// /// Provides behavior for a client or server endpoint that diff --git a/src/ServiceHost/MessageProtocol/RequestContext.cs b/src/ServiceHost/Hosting/Protocol/RequestContext.cs similarity index 91% rename from src/ServiceHost/MessageProtocol/RequestContext.cs rename to src/ServiceHost/Hosting/Protocol/RequestContext.cs index a35bb136..153e46d6 100644 --- a/src/ServiceHost/MessageProtocol/RequestContext.cs +++ b/src/ServiceHost/Hosting/Protocol/RequestContext.cs @@ -3,10 +3,11 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using Newtonsoft.Json.Linq; using System.Threading.Tasks; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts; +using Newtonsoft.Json.Linq; -namespace Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol +namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol { public class RequestContext { diff --git a/src/ServiceHost/MessageProtocol/IMessageSerializer.cs b/src/ServiceHost/Hosting/Protocol/Serializers/IMessageSerializer.cs similarity index 87% rename from src/ServiceHost/MessageProtocol/IMessageSerializer.cs rename to src/ServiceHost/Hosting/Protocol/Serializers/IMessageSerializer.cs index 81b23fa6..6a1133ff 100644 --- a/src/ServiceHost/MessageProtocol/IMessageSerializer.cs +++ b/src/ServiceHost/Hosting/Protocol/Serializers/IMessageSerializer.cs @@ -3,9 +3,10 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts; using Newtonsoft.Json.Linq; -namespace Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol +namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Serializers { /// /// Defines a common interface for message serializers. diff --git a/src/ServiceHost/MessageProtocol/Serializers/JsonRpcMessageSerializer.cs b/src/ServiceHost/Hosting/Protocol/Serializers/JsonRpcMessageSerializer.cs similarity index 95% rename from src/ServiceHost/MessageProtocol/Serializers/JsonRpcMessageSerializer.cs rename to src/ServiceHost/Hosting/Protocol/Serializers/JsonRpcMessageSerializer.cs index fa1d1518..0ccca078 100644 --- a/src/ServiceHost/MessageProtocol/Serializers/JsonRpcMessageSerializer.cs +++ b/src/ServiceHost/Hosting/Protocol/Serializers/JsonRpcMessageSerializer.cs @@ -3,9 +3,10 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts; using Newtonsoft.Json.Linq; -namespace Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol.Serializers +namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Serializers { /// /// Serializes messages in the JSON RPC format. Used primarily diff --git a/src/ServiceHost/MessageProtocol/Serializers/V8MessageSerializer.cs b/src/ServiceHost/Hosting/Protocol/Serializers/V8MessageSerializer.cs similarity index 96% rename from src/ServiceHost/MessageProtocol/Serializers/V8MessageSerializer.cs rename to src/ServiceHost/Hosting/Protocol/Serializers/V8MessageSerializer.cs index 941e249a..f1385e00 100644 --- a/src/ServiceHost/MessageProtocol/Serializers/V8MessageSerializer.cs +++ b/src/ServiceHost/Hosting/Protocol/Serializers/V8MessageSerializer.cs @@ -5,8 +5,9 @@ using Newtonsoft.Json.Linq; using System; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts; -namespace Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol.Serializers +namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Serializers { /// /// Serializes messages in the V8 format. Used primarily for debug adapters. diff --git a/src/ServiceHost/Hosting/ServiceHost.cs b/src/ServiceHost/Hosting/ServiceHost.cs new file mode 100644 index 00000000..dbc561fe --- /dev/null +++ b/src/ServiceHost/Hosting/ServiceHost.cs @@ -0,0 +1,148 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; +using System.Linq; +using System.Threading.Tasks; +using System.Collections.Generic; +using Microsoft.SqlTools.EditorServices.Utility; +using Microsoft.SqlTools.ServiceLayer.Hosting.Contracts; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Channel; + +namespace Microsoft.SqlTools.ServiceLayer.Hosting +{ + /// + /// SQL Tools VS Code Language Server request handler. Provides the entire JSON RPC + /// implementation for sending/receiving JSON requests and dispatching the requests to + /// handlers that are registered prior to startup. + /// + public sealed class ServiceHost : ServiceHostBase + { + #region Singleton Instance Code + + /// + /// Singleton instance of the service host for internal storage + /// + private static readonly Lazy instance = new Lazy(() => new ServiceHost()); + + /// + /// Current instance of the ServiceHost + /// + public static ServiceHost Instance + { + get { return instance.Value; } + } + + /// + /// Constructs new instance of ServiceHost using the host and profile details provided. + /// Access is private to ensure only one instance exists at a time. + /// + private ServiceHost() : base(new StdioServerChannel()) + { + // Initialize the shutdown activities + shutdownCallbacks = new List(); + initializeCallbacks = new List(); + + // Register the requests that this service host will handle + this.SetRequestHandler(InitializeRequest.Type, this.HandleInitializeRequest); + this.SetRequestHandler(ShutdownRequest.Type, this.HandleShutdownRequest); + } + + #endregion + + #region Member Variables + + public delegate Task ShutdownCallback(object shutdownParams, RequestContext shutdownRequestContext); + + public delegate Task InitializeCallback(InitializeRequest startupParams, RequestContext requestContext); + + private readonly List shutdownCallbacks; + + private readonly List initializeCallbacks; + + #endregion + + #region Public Methods + + /// + /// Adds a new callback to be called when the shutdown request is submitted + /// + /// Callback to perform when a shutdown request is submitted + public void RegisterShutdownTask(ShutdownCallback callback) + { + shutdownCallbacks.Add(callback); + } + + /// + /// Add a new method to be called when the initialize request is submitted + /// + /// Callback to perform when an initialize request is submitted + public void RegisterInitializeTask(InitializeCallback callback) + { + initializeCallbacks.Add(callback); + } + + #endregion + + #region Request Handlers + + /// + /// Handles the shutdown event for the Language Server + /// + private async Task HandleShutdownRequest(object shutdownParams, RequestContext requestContext) + { + Logger.Write(LogLevel.Normal, "Service host is shutting down..."); + + // Call all the shutdown methods provided by the service components + Task[] shutdownTasks = shutdownCallbacks.Select(t => t(shutdownParams, requestContext)).ToArray(); + await Task.WhenAll(shutdownTasks); + } + + /// + /// Handles the initialization request + /// + /// + /// + /// + private async Task HandleInitializeRequest(InitializeRequest initializeParams, RequestContext requestContext) + { + Logger.Write(LogLevel.Verbose, "HandleInitializationRequest"); + + // Call all tasks that registered on the initialize request + var initializeTasks = initializeCallbacks.Select(t => t(initializeParams, requestContext)); + await Task.WhenAll(initializeTasks); + + // TODO: Figure out where this needs to go to be agnostic of the language + + // Send back what this server can do + await requestContext.SendResult( + new InitializeResult + { + Capabilities = new ServerCapabilities + { + TextDocumentSync = TextDocumentSyncKind.Incremental, + DefinitionProvider = true, + ReferencesProvider = true, + DocumentHighlightProvider = true, + DocumentSymbolProvider = true, + WorkspaceSymbolProvider = true, + HoverProvider = true, + CompletionProvider = new CompletionOptions + { + ResolveProvider = true, + TriggerCharacters = new string[] { ".", "-", ":", "\\" } + }, + SignatureHelpProvider = new SignatureHelpOptions + { + TriggerCharacters = new string[] { " " } // TODO: Other characters here? + } + } + }); + } + + #endregion + } +} diff --git a/src/ServiceHost/Hosting/ServiceHostBase.cs b/src/ServiceHost/Hosting/ServiceHostBase.cs new file mode 100644 index 00000000..8158822b --- /dev/null +++ b/src/ServiceHost/Hosting/ServiceHostBase.cs @@ -0,0 +1,47 @@ +// +// 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.Contracts; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Channel; + +namespace Microsoft.SqlTools.ServiceLayer.Hosting +{ + public abstract class ServiceHostBase : ProtocolEndpoint + { + private bool isStarted; + private TaskCompletionSource serverExitedTask; + + protected ServiceHostBase(ChannelBase serverChannel) : + base(serverChannel, MessageProtocolType.LanguageServer) + { + } + + protected override Task OnStart() + { + // Register handlers for server lifetime messages + + this.SetEventHandler(ExitNotification.Type, this.HandleExitNotification); + + return Task.FromResult(true); + } + + private async Task HandleExitNotification( + object exitParams, + EventContext eventContext) + { + // Stop the server channel + await this.Stop(); + + // Notify any waiter that the server has exited + if (this.serverExitedTask != null) + { + this.serverExitedTask.SetResult(true); + } + } + } +} + diff --git a/src/ServiceHost/Server/LanguageServerEditorOperations.cs b/src/ServiceHost/Hosting/ServiceHostEditorOperations.cs similarity index 100% rename from src/ServiceHost/Server/LanguageServerEditorOperations.cs rename to src/ServiceHost/Hosting/ServiceHostEditorOperations.cs diff --git a/src/ServiceHost/LanguageServices/AutoCompleteService.cs b/src/ServiceHost/LanguageServices/AutoCompleteService.cs new file mode 100644 index 00000000..67981ae5 --- /dev/null +++ b/src/ServiceHost/LanguageServices/AutoCompleteService.cs @@ -0,0 +1,123 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.SqlTools.ServiceLayer.Connection; +using Microsoft.SqlTools.ServiceLayer.Hosting; +using Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts; +using Microsoft.SqlTools.ServiceLayer.WorkspaceServices.Contracts; + +namespace Microsoft.SqlTools.ServiceLayer.LanguageServices +{ + /// + /// Main class for Autocomplete functionality + /// + public class AutoCompleteService + { + #region Singleton Instance Implementation + + /// + /// Singleton service instance + /// + private static Lazy instance + = new Lazy(() => new AutoCompleteService()); + + /// + /// Gets the singleton service instance + /// + public static AutoCompleteService Instance + { + get + { + return instance.Value; + } + } + + /// + /// Default, parameterless constructor. + /// TODO: Figure out how to make this truely singleton even with dependency injection for tests + /// + public AutoCompleteService() + { + } + + #endregion + + /// + /// Gets the current autocomplete candidate list + /// + public IEnumerable AutoCompleteList { get; private set; } + + public void InitializeService(ServiceHost serviceHost) + { + // Register a callback for when a connection is created + ConnectionService.Instance.RegisterOnConnectionTask(UpdateAutoCompleteCache); + } + + /// + /// Update the cached autocomplete candidate list when the user connects to a database + /// + /// + public async Task UpdateAutoCompleteCache(ISqlConnection connection) + { + AutoCompleteList = connection.GetServerObjects(); + await Task.FromResult(0); + } + + /// + /// Return the completion item list for the current text position + /// + /// + public CompletionItem[] GetCompletionItems(TextDocumentPosition textDocumentPosition) + { + var completions = new List(); + + int i = 0; + + // the completion list will be null is user not connected to server + if (this.AutoCompleteList != null) + { + foreach (var autoCompleteItem in this.AutoCompleteList) + { + // convert the completion item candidates into CompletionItems + completions.Add(new CompletionItem() + { + Label = autoCompleteItem, + Kind = CompletionItemKind.Keyword, + Detail = autoCompleteItem + " details", + Documentation = autoCompleteItem + " documentation", + TextEdit = new TextEdit + { + NewText = autoCompleteItem, + Range = new Range + { + Start = new Position + { + Line = textDocumentPosition.Position.Line, + Character = textDocumentPosition.Position.Character + }, + End = new Position + { + Line = textDocumentPosition.Position.Line, + Character = textDocumentPosition.Position.Character + 5 + } + } + } + }); + + // only show 50 items + if (++i == 50) + { + break; + } + } + } + return completions.ToArray(); + } + + } +} diff --git a/src/ServiceHost/LanguageServer/Completion.cs b/src/ServiceHost/LanguageServices/Contracts/Completion.cs similarity index 92% rename from src/ServiceHost/LanguageServer/Completion.cs rename to src/ServiceHost/LanguageServices/Contracts/Completion.cs index 5f26ea96..6dc41130 100644 --- a/src/ServiceHost/LanguageServer/Completion.cs +++ b/src/ServiceHost/LanguageServices/Contracts/Completion.cs @@ -4,9 +4,10 @@ // using System.Diagnostics; -using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts; +using Microsoft.SqlTools.ServiceLayer.WorkspaceServices.Contracts; -namespace Microsoft.SqlTools.EditorServices.Protocol.LanguageServer +namespace Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts { public class CompletionRequest { diff --git a/src/ServiceHost/LanguageServer/Definition.cs b/src/ServiceHost/LanguageServices/Contracts/Definition.cs similarity index 66% rename from src/ServiceHost/LanguageServer/Definition.cs rename to src/ServiceHost/LanguageServices/Contracts/Definition.cs index b18845c3..1c40996f 100644 --- a/src/ServiceHost/LanguageServer/Definition.cs +++ b/src/ServiceHost/LanguageServices/Contracts/Definition.cs @@ -3,9 +3,10 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts; +using Microsoft.SqlTools.ServiceLayer.WorkspaceServices.Contracts; -namespace Microsoft.SqlTools.EditorServices.Protocol.LanguageServer +namespace Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts { public class DefinitionRequest { diff --git a/src/ServiceHost/LanguageServer/Diagnostics.cs b/src/ServiceHost/LanguageServices/Contracts/Diagnostics.cs similarity index 90% rename from src/ServiceHost/LanguageServer/Diagnostics.cs rename to src/ServiceHost/LanguageServices/Contracts/Diagnostics.cs index a5472607..a591b925 100644 --- a/src/ServiceHost/LanguageServer/Diagnostics.cs +++ b/src/ServiceHost/LanguageServices/Contracts/Diagnostics.cs @@ -3,9 +3,10 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts; +using Microsoft.SqlTools.ServiceLayer.WorkspaceServices.Contracts; -namespace Microsoft.SqlTools.EditorServices.Protocol.LanguageServer +namespace Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts { public class PublishDiagnosticsNotification { diff --git a/src/ServiceHost/LanguageServer/DocumentHighlight.cs b/src/ServiceHost/LanguageServices/Contracts/DocumentHighlight.cs similarity index 77% rename from src/ServiceHost/LanguageServer/DocumentHighlight.cs rename to src/ServiceHost/LanguageServices/Contracts/DocumentHighlight.cs index 6849ddfb..f266801f 100644 --- a/src/ServiceHost/LanguageServer/DocumentHighlight.cs +++ b/src/ServiceHost/LanguageServices/Contracts/DocumentHighlight.cs @@ -3,9 +3,10 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts; +using Microsoft.SqlTools.ServiceLayer.WorkspaceServices.Contracts; -namespace Microsoft.SqlTools.EditorServices.Protocol.LanguageServer +namespace Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts { public enum DocumentHighlightKind { diff --git a/src/ServiceHost/LanguageServer/ExpandAliasRequest.cs b/src/ServiceHost/LanguageServices/Contracts/ExpandAliasRequest.cs similarity index 73% rename from src/ServiceHost/LanguageServer/ExpandAliasRequest.cs rename to src/ServiceHost/LanguageServices/Contracts/ExpandAliasRequest.cs index d7f9fde4..e758aa3d 100644 --- a/src/ServiceHost/LanguageServer/ExpandAliasRequest.cs +++ b/src/ServiceHost/LanguageServices/Contracts/ExpandAliasRequest.cs @@ -3,9 +3,9 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts; -namespace Microsoft.SqlTools.EditorServices.Protocol.LanguageServer +namespace Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts { public class ExpandAliasRequest { diff --git a/src/ServiceHost/LanguageServer/FindModuleRequest.cs b/src/ServiceHost/LanguageServices/Contracts/FindModuleRequest.cs similarity index 80% rename from src/ServiceHost/LanguageServer/FindModuleRequest.cs rename to src/ServiceHost/LanguageServices/Contracts/FindModuleRequest.cs index ab78a158..5de004d5 100644 --- a/src/ServiceHost/LanguageServer/FindModuleRequest.cs +++ b/src/ServiceHost/LanguageServices/Contracts/FindModuleRequest.cs @@ -3,10 +3,10 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol; using System.Collections.Generic; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts; -namespace Microsoft.SqlTools.EditorServices.Protocol.LanguageServer +namespace Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts { public class FindModuleRequest { diff --git a/src/ServiceHost/LanguageServer/Hover.cs b/src/ServiceHost/LanguageServices/Contracts/Hover.cs similarity index 76% rename from src/ServiceHost/LanguageServer/Hover.cs rename to src/ServiceHost/LanguageServices/Contracts/Hover.cs index 2e196fba..04c27d33 100644 --- a/src/ServiceHost/LanguageServer/Hover.cs +++ b/src/ServiceHost/LanguageServices/Contracts/Hover.cs @@ -3,9 +3,10 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts; +using Microsoft.SqlTools.ServiceLayer.WorkspaceServices.Contracts; -namespace Microsoft.SqlTools.EditorServices.Protocol.LanguageServer +namespace Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts { public class MarkedString { diff --git a/src/ServiceHost/LanguageServer/InstallModuleRequest.cs b/src/ServiceHost/LanguageServices/Contracts/InstallModuleRequest.cs similarity index 73% rename from src/ServiceHost/LanguageServer/InstallModuleRequest.cs rename to src/ServiceHost/LanguageServices/Contracts/InstallModuleRequest.cs index b03b8864..fc5bc289 100644 --- a/src/ServiceHost/LanguageServer/InstallModuleRequest.cs +++ b/src/ServiceHost/LanguageServices/Contracts/InstallModuleRequest.cs @@ -3,9 +3,9 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts; -namespace Microsoft.SqlTools.EditorServices.Protocol.LanguageServer +namespace Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts { class InstallModuleRequest { diff --git a/src/ServiceHost/LanguageServer/References.cs b/src/ServiceHost/LanguageServices/Contracts/References.cs similarity index 75% rename from src/ServiceHost/LanguageServer/References.cs rename to src/ServiceHost/LanguageServices/Contracts/References.cs index 25a92b12..ad2f23bd 100644 --- a/src/ServiceHost/LanguageServer/References.cs +++ b/src/ServiceHost/LanguageServices/Contracts/References.cs @@ -3,9 +3,10 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts; +using Microsoft.SqlTools.ServiceLayer.WorkspaceServices.Contracts; -namespace Microsoft.SqlTools.EditorServices.Protocol.LanguageServer +namespace Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts { public class ReferencesRequest { diff --git a/src/ServiceHost/LanguageServer/ShowOnlineHelpRequest.cs b/src/ServiceHost/LanguageServices/Contracts/ShowOnlineHelpRequest.cs similarity index 73% rename from src/ServiceHost/LanguageServer/ShowOnlineHelpRequest.cs rename to src/ServiceHost/LanguageServices/Contracts/ShowOnlineHelpRequest.cs index 8f21fb1b..d8cf3f48 100644 --- a/src/ServiceHost/LanguageServer/ShowOnlineHelpRequest.cs +++ b/src/ServiceHost/LanguageServices/Contracts/ShowOnlineHelpRequest.cs @@ -3,9 +3,9 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts; -namespace Microsoft.SqlTools.EditorServices.Protocol.LanguageServer +namespace Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts { public class ShowOnlineHelpRequest { diff --git a/src/ServiceHost/LanguageServer/SignatureHelp.cs b/src/ServiceHost/LanguageServices/Contracts/SignatureHelp.cs similarity index 82% rename from src/ServiceHost/LanguageServer/SignatureHelp.cs rename to src/ServiceHost/LanguageServices/Contracts/SignatureHelp.cs index 5d4233e3..bd1103c9 100644 --- a/src/ServiceHost/LanguageServer/SignatureHelp.cs +++ b/src/ServiceHost/LanguageServices/Contracts/SignatureHelp.cs @@ -3,9 +3,10 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts; +using Microsoft.SqlTools.ServiceLayer.WorkspaceServices.Contracts; -namespace Microsoft.SqlTools.EditorServices.Protocol.LanguageServer +namespace Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts { public class SignatureHelpRequest { diff --git a/src/ServiceHost/LanguageServices/LanguageService.cs b/src/ServiceHost/LanguageServices/LanguageService.cs new file mode 100644 index 00000000..d40aa5fc --- /dev/null +++ b/src/ServiceHost/LanguageServices/LanguageService.cs @@ -0,0 +1,442 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.SqlTools.EditorServices.Utility; +using Microsoft.SqlTools.ServiceLayer.Hosting; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol; +using Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts; +using Microsoft.SqlTools.ServiceLayer.SqlContext; +using Microsoft.SqlTools.ServiceLayer.WorkspaceServices; +using Microsoft.SqlTools.ServiceLayer.WorkspaceServices.Contracts; +using System.Linq; +using Microsoft.SqlServer.Management.SqlParser.Parser; +using Location = Microsoft.SqlTools.ServiceLayer.WorkspaceServices.Contracts.Location; + +namespace Microsoft.SqlTools.ServiceLayer.LanguageServices +{ + /// + /// Main class for Language Service functionality including anything that reqires knowledge of + /// the language to perfom, such as definitions, intellisense, etc. + /// + public sealed class LanguageService + { + + #region Singleton Instance Implementation + + private static readonly Lazy instance = new Lazy(() => new LanguageService()); + + public static LanguageService Instance + { + get { return instance.Value; } + } + + /// + /// Default, parameterless constructor. + /// TODO: Figure out how to make this truely singleton even with dependency injection for tests + /// + public LanguageService() + { + } + + #endregion + + #region Properties + + private static CancellationTokenSource ExistingRequestCancellation { get; set; } + + private SqlToolsSettings CurrentSettings + { + get { return WorkspaceService.Instance.CurrentSettings; } + } + + private Workspace CurrentWorkspace + { + get { return WorkspaceService.Instance.Workspace; } + } + + /// + /// Gets or sets the current SQL Tools context + /// + /// + private SqlToolsContext Context { get; set; } + + /// + /// The cached parse result from previous incremental parse + /// + private ParseResult prevParseResult; + + #endregion + + #region Public Methods + + public void InitializeService(ServiceHost serviceHost, SqlToolsContext context) + { + // Register the requests that this service will handle + serviceHost.SetRequestHandler(DefinitionRequest.Type, HandleDefinitionRequest); + serviceHost.SetRequestHandler(ReferencesRequest.Type, HandleReferencesRequest); + serviceHost.SetRequestHandler(CompletionRequest.Type, HandleCompletionRequest); + serviceHost.SetRequestHandler(CompletionResolveRequest.Type, HandleCompletionResolveRequest); + serviceHost.SetRequestHandler(SignatureHelpRequest.Type, HandleSignatureHelpRequest); + serviceHost.SetRequestHandler(DocumentHighlightRequest.Type, HandleDocumentHighlightRequest); + serviceHost.SetRequestHandler(HoverRequest.Type, HandleHoverRequest); + serviceHost.SetRequestHandler(DocumentSymbolRequest.Type, HandleDocumentSymbolRequest); + serviceHost.SetRequestHandler(WorkspaceSymbolRequest.Type, HandleWorkspaceSymbolRequest); + + // Register a no-op shutdown task for validation of the shutdown logic + serviceHost.RegisterShutdownTask(async (shutdownParams, shutdownRequestContext) => + { + Logger.Write(LogLevel.Verbose, "Shutting down language service"); + await Task.FromResult(0); + }); + + // Register the configuration update handler + WorkspaceService.Instance.RegisterConfigChangeCallback(HandleDidChangeConfigurationNotification); + + // Store the SqlToolsContext for future use + Context = context; + } + + /// + /// Gets a list of semantic diagnostic marks for the provided script file + /// + /// + public ScriptFileMarker[] GetSemanticMarkers(ScriptFile scriptFile) + { + // parse current SQL file contents to retrieve a list of errors + ParseOptions parseOptions = new ParseOptions(); + ParseResult parseResult = Parser.IncrementalParse( + scriptFile.Contents, + prevParseResult, + parseOptions); + + // save previous result for next incremental parse + this.prevParseResult = parseResult; + + // build a list of SQL script file markers from the errors + List markers = new List(); + foreach (var error in parseResult.Errors) + { + markers.Add(new ScriptFileMarker() + { + Message = error.Message, + Level = ScriptFileMarkerLevel.Error, + ScriptRegion = new ScriptRegion() + { + File = scriptFile.FilePath, + StartLineNumber = error.Start.LineNumber, + StartColumnNumber = error.Start.ColumnNumber, + StartOffset = 0, + EndLineNumber = error.End.LineNumber, + EndColumnNumber = error.End.ColumnNumber, + EndOffset = 0 + } + }); + } + + return markers.ToArray(); + } + + #endregion + + #region Request Handlers + + private static async Task HandleDefinitionRequest( + TextDocumentPosition textDocumentPosition, + RequestContext requestContext) + { + Logger.Write(LogLevel.Verbose, "HandleDefinitionRequest"); + await Task.FromResult(true); + } + + private static async Task HandleReferencesRequest( + ReferencesParams referencesParams, + RequestContext requestContext) + { + Logger.Write(LogLevel.Verbose, "HandleReferencesRequest"); + await Task.FromResult(true); + } + + private static async Task HandleCompletionRequest( + TextDocumentPosition textDocumentPosition, + RequestContext requestContext) + { + Logger.Write(LogLevel.Verbose, "HandleCompletionRequest"); + await Task.FromResult(true); + } + + private static async Task HandleCompletionResolveRequest( + CompletionItem completionItem, + RequestContext requestContext) + { + Logger.Write(LogLevel.Verbose, "HandleCompletionResolveRequest"); + await Task.FromResult(true); + } + + private static async Task HandleSignatureHelpRequest( + TextDocumentPosition textDocumentPosition, + RequestContext requestContext) + { + Logger.Write(LogLevel.Verbose, "HandleSignatureHelpRequest"); + await Task.FromResult(true); + } + + private static async Task HandleDocumentHighlightRequest( + TextDocumentPosition textDocumentPosition, + RequestContext requestContext) + { + Logger.Write(LogLevel.Verbose, "HandleDocumentHighlightRequest"); + await Task.FromResult(true); + } + + private static async Task HandleHoverRequest( + TextDocumentPosition textDocumentPosition, + RequestContext requestContext) + { + Logger.Write(LogLevel.Verbose, "HandleHoverRequest"); + await Task.FromResult(true); + } + + private static async Task HandleDocumentSymbolRequest( + TextDocumentIdentifier textDocumentIdentifier, + RequestContext requestContext) + { + Logger.Write(LogLevel.Verbose, "HandleDocumentSymbolRequest"); + await Task.FromResult(true); + } + + private static async Task HandleWorkspaceSymbolRequest( + WorkspaceSymbolParams workspaceSymbolParams, + RequestContext requestContext) + { + Logger.Write(LogLevel.Verbose, "HandleWorkspaceSymbolRequest"); + await Task.FromResult(true); + } + + #endregion + + #region Handlers for Events from Other Services + + public async Task HandleDidChangeConfigurationNotification( + SqlToolsSettings newSettings, + SqlToolsSettings oldSettings, + EventContext eventContext) + { + // If script analysis settings have changed we need to clear & possibly update the current diagnostic records. + bool oldScriptAnalysisEnabled = oldSettings.ScriptAnalysis.Enable.HasValue; + if ((oldScriptAnalysisEnabled != newSettings.ScriptAnalysis.Enable)) + { + // If the user just turned off script analysis or changed the settings path, send a diagnostics + // event to clear the analysis markers that they already have. + if (!newSettings.ScriptAnalysis.Enable.Value) + { + ScriptFileMarker[] emptyAnalysisDiagnostics = new ScriptFileMarker[0]; + + foreach (var scriptFile in WorkspaceService.Instance.Workspace.GetOpenedFiles()) + { + await PublishScriptDiagnostics(scriptFile, emptyAnalysisDiagnostics, eventContext); + } + } + else + { + await this.RunScriptDiagnostics(CurrentWorkspace.GetOpenedFiles(), eventContext); + } + } + + // Update the settings in the current + CurrentSettings.EnableProfileLoading = newSettings.EnableProfileLoading; + CurrentSettings.ScriptAnalysis.Update(newSettings.ScriptAnalysis, CurrentWorkspace.WorkspacePath); + } + + #endregion + + #region Private Helpers + + /// + /// Runs script diagnostics on changed files + /// + /// + /// + private Task RunScriptDiagnostics(ScriptFile[] filesToAnalyze, EventContext eventContext) + { + if (!CurrentSettings.ScriptAnalysis.Enable.Value) + { + // If the user has disabled script analysis, skip it entirely + return Task.FromResult(true); + } + + // If there's an existing task, attempt to cancel it + try + { + if (ExistingRequestCancellation != null) + { + // Try to cancel the request + ExistingRequestCancellation.Cancel(); + + // If cancellation didn't throw an exception, + // clean up the existing token + ExistingRequestCancellation.Dispose(); + ExistingRequestCancellation = null; + } + } + catch (Exception e) + { + Logger.Write( + LogLevel.Error, + String.Format( + "Exception while cancelling analysis task:\n\n{0}", + e.ToString())); + + TaskCompletionSource cancelTask = new TaskCompletionSource(); + cancelTask.SetCanceled(); + return cancelTask.Task; + } + + // Create a fresh cancellation token and then start the task. + // We create this on a different TaskScheduler so that we + // don't block the main message loop thread. + ExistingRequestCancellation = new CancellationTokenSource(); + Task.Factory.StartNew( + () => + DelayThenInvokeDiagnostics( + 750, + filesToAnalyze, + eventContext, + ExistingRequestCancellation.Token), + CancellationToken.None, + TaskCreationOptions.None, + TaskScheduler.Default); + + return Task.FromResult(true); + } + + /// + /// Actually run the script diagnostics after waiting for some small delay + /// + /// + /// + /// + /// + private async Task DelayThenInvokeDiagnostics( + int delayMilliseconds, + ScriptFile[] filesToAnalyze, + EventContext eventContext, + CancellationToken cancellationToken) + { + // First of all, wait for the desired delay period before + // analyzing the provided list of files + try + { + await Task.Delay(delayMilliseconds, cancellationToken); + } + catch (TaskCanceledException) + { + // If the task is cancelled, exit directly + return; + } + + // If we've made it past the delay period then we don't care + // about the cancellation token anymore. This could happen + // when the user stops typing for long enough that the delay + // period ends but then starts typing while analysis is going + // on. It makes sense to send back the results from the first + // delay period while the second one is ticking away. + + // Get the requested files + foreach (ScriptFile scriptFile in filesToAnalyze) + { + Logger.Write(LogLevel.Verbose, "Analyzing script file: " + scriptFile.FilePath); + ScriptFileMarker[] semanticMarkers = GetSemanticMarkers(scriptFile); + Logger.Write(LogLevel.Verbose, "Analysis complete."); + + await PublishScriptDiagnostics(scriptFile, semanticMarkers, eventContext); + } + } + + /// + /// Send the diagnostic results back to the host application + /// + /// + /// + /// + private static async Task PublishScriptDiagnostics( + ScriptFile scriptFile, + ScriptFileMarker[] semanticMarkers, + EventContext eventContext) + { + var allMarkers = scriptFile.SyntaxMarkers != null + ? scriptFile.SyntaxMarkers.Concat(semanticMarkers) + : semanticMarkers; + + // Always send syntax and semantic errors. We want to + // make sure no out-of-date markers are being displayed. + await eventContext.SendEvent( + PublishDiagnosticsNotification.Type, + new PublishDiagnosticsNotification + { + Uri = scriptFile.ClientFilePath, + Diagnostics = + allMarkers + .Select(GetDiagnosticFromMarker) + .ToArray() + }); + } + + /// + /// Convert a ScriptFileMarker to a Diagnostic that is Language Service compatible + /// + /// + /// + private static Diagnostic GetDiagnosticFromMarker(ScriptFileMarker scriptFileMarker) + { + return new Diagnostic + { + Severity = MapDiagnosticSeverity(scriptFileMarker.Level), + Message = scriptFileMarker.Message, + Range = new Range + { + // TODO: What offsets should I use? + Start = new Position + { + Line = scriptFileMarker.ScriptRegion.StartLineNumber - 1, + Character = scriptFileMarker.ScriptRegion.StartColumnNumber - 1 + }, + End = new Position + { + Line = scriptFileMarker.ScriptRegion.EndLineNumber - 1, + Character = scriptFileMarker.ScriptRegion.EndColumnNumber - 1 + } + } + }; + } + + /// + /// Map ScriptFileMarker severity to Diagnostic severity + /// + /// + private static DiagnosticSeverity MapDiagnosticSeverity(ScriptFileMarkerLevel markerLevel) + { + switch (markerLevel) + { + case ScriptFileMarkerLevel.Error: + return DiagnosticSeverity.Error; + + case ScriptFileMarkerLevel.Warning: + return DiagnosticSeverity.Warning; + + case ScriptFileMarkerLevel.Information: + return DiagnosticSeverity.Information; + + default: + return DiagnosticSeverity.Error; + } + } + + #endregion + } +} diff --git a/src/ServiceHost/Program.cs b/src/ServiceHost/Program.cs index 6bfd0f24..02369811 100644 --- a/src/ServiceHost/Program.cs +++ b/src/ServiceHost/Program.cs @@ -2,11 +2,13 @@ // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; -using Microsoft.SqlTools.EditorServices.Protocol.Server; -using Microsoft.SqlTools.EditorServices.Session; using Microsoft.SqlTools.EditorServices.Utility; +using Microsoft.SqlTools.ServiceLayer.Hosting; +using Microsoft.SqlTools.ServiceLayer.SqlContext; +using Microsoft.SqlTools.ServiceLayer.WorkspaceServices; +using Microsoft.SqlTools.ServiceLayer.LanguageServices; -namespace Microsoft.SqlTools.ServiceHost +namespace Microsoft.SqlTools.ServiceLayer { /// /// Main application class for SQL Tools API Service Host executable @@ -25,16 +27,24 @@ namespace Microsoft.SqlTools.ServiceHost const string hostName = "SQL Tools Service Host"; const string hostProfileId = "SQLToolsService"; - Version hostVersion = new Version(1,0); + Version hostVersion = new Version(1,0); // set up the host details and profile paths var hostDetails = new HostDetails(hostName, hostProfileId, hostVersion); var profilePaths = new ProfilePaths(hostProfileId, "baseAllUsersPath", "baseCurrentUserPath"); + SqlToolsContext sqlToolsContext = new SqlToolsContext(hostDetails, profilePaths); - // create and run the language server - var languageServer = new LanguageServer(hostDetails, profilePaths); - languageServer.Start().Wait(); - languageServer.WaitForExit(); + // Grab the instance of the service host + ServiceHost serviceHost = ServiceHost.Instance; + + // Initialize the services that will be hosted here + WorkspaceService.Instance.InitializeService(serviceHost); + AutoCompleteService.Instance.InitializeService(serviceHost); + LanguageService.Instance.InitializeService(serviceHost, sqlToolsContext); + + // Start the service + serviceHost.Start().Wait(); + serviceHost.WaitForExit(); } } } diff --git a/src/ServiceHost/Server/LanguageServerBase.cs b/src/ServiceHost/Server/LanguageServerBase.cs deleted file mode 100644 index 0128484b..00000000 --- a/src/ServiceHost/Server/LanguageServerBase.cs +++ /dev/null @@ -1,84 +0,0 @@ -// -// 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.EditorServices.Protocol.LanguageServer; -using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol; -using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol.Channel; -using System.Threading.Tasks; - -namespace Microsoft.SqlTools.EditorServices.Protocol.Server -{ - public abstract class LanguageServerBase : ProtocolEndpoint - { - private bool isStarted; - private ChannelBase serverChannel; - private TaskCompletionSource serverExitedTask; - - public LanguageServerBase(ChannelBase serverChannel) : - base(serverChannel, MessageProtocolType.LanguageServer) - { - this.serverChannel = serverChannel; - } - - protected override Task OnStart() - { - // Register handlers for server lifetime messages - this.SetRequestHandler(ShutdownRequest.Type, this.HandleShutdownRequest); - this.SetEventHandler(ExitNotification.Type, this.HandleExitNotification); - - // Initialize the implementation class - this.Initialize(); - - return Task.FromResult(true); - } - - protected override async Task OnStop() - { - await this.Shutdown(); - } - - /// - /// Overridden by the subclass to provide initialization - /// logic after the server channel is started. - /// - protected abstract void Initialize(); - - /// - /// Can be overridden by the subclass to provide shutdown - /// logic before the server exits. Subclasses do not need - /// to invoke or return the value of the base implementation. - /// - protected virtual Task Shutdown() - { - // No default implementation yet. - return Task.FromResult(true); - } - - private async Task HandleShutdownRequest( - object shutdownParams, - RequestContext requestContext) - { - // Allow the implementor to shut down gracefully - await this.Shutdown(); - - await requestContext.SendResult(new object()); - } - - private async Task HandleExitNotification( - object exitParams, - EventContext eventContext) - { - // Stop the server channel - await this.Stop(); - - // Notify any waiter that the server has exited - if (this.serverExitedTask != null) - { - this.serverExitedTask.SetResult(true); - } - } - } -} - diff --git a/src/ServiceHost/ServiceHost.xproj b/src/ServiceHost/ServiceHost.xproj index ac743bab..358bb7c3 100644 --- a/src/ServiceHost/ServiceHost.xproj +++ b/src/ServiceHost/ServiceHost.xproj @@ -1,4 +1,4 @@ - + 14.0 @@ -7,14 +7,13 @@ {0D61DC2B-DA66-441D-B9D0-F76C98F780F9} - Microsoft.SqlTools.ServiceHost + Microsoft.SqlTools.ServiceLayer .\obj .\bin\ v4.5.2 - 2.0 - + \ No newline at end of file diff --git a/src/ServiceHost/Session/EditorSession.cs b/src/ServiceHost/Session/EditorSession.cs deleted file mode 100644 index 3c592a8f..00000000 --- a/src/ServiceHost/Session/EditorSession.cs +++ /dev/null @@ -1,75 +0,0 @@ -// -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. -// - -using System; -using Microsoft.SqlTools.EditorServices.Session; -using Microsoft.SqlTools.LanguageSupport; - -namespace Microsoft.SqlTools.EditorServices -{ - /// - /// Manages a single session for all editor services. This - /// includes managing all open script files for the session. - /// - public class EditorSession : IDisposable - { - #region Properties - - /// - /// Gets the Workspace instance for this session. - /// - public Workspace Workspace { get; private set; } - - /// - /// Gets or sets the Language Service - /// - /// - public LanguageService LanguageService { get; set; } - - /// - /// Gets the SqlToolsContext instance for this session. - /// - public SqlToolsContext SqlToolsContext { get; private set; } - - #endregion - - #region Public Methods - - /// - /// Starts the session using the provided IConsoleHost implementation - /// for the ConsoleService. - /// - /// - /// Provides details about the host application. - /// - /// - /// An object containing the profile paths for the session. - /// - public void StartSession(HostDetails hostDetails, ProfilePaths profilePaths) - { - // Initialize all services - this.SqlToolsContext = new SqlToolsContext(hostDetails, profilePaths); - this.LanguageService = new LanguageService(this.SqlToolsContext); - - // Create a workspace to contain open files - this.Workspace = new Workspace(this.SqlToolsContext.SqlToolsVersion); - } - - #endregion - - #region IDisposable Implementation - - /// - /// Disposes of any Runspaces that were created for the - /// services used in this session. - /// - public void Dispose() - { - } - - #endregion - - } -} diff --git a/src/ServiceHost/Session/OutputType.cs b/src/ServiceHost/Session/OutputType.cs deleted file mode 100644 index 8ba866d7..00000000 --- a/src/ServiceHost/Session/OutputType.cs +++ /dev/null @@ -1,41 +0,0 @@ -// -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. -// - -namespace Microsoft.SqlTools.EditorServices -{ - /// - /// Enumerates the types of output lines that will be sent - /// to an IConsoleHost implementation. - /// - public enum OutputType - { - /// - /// A normal output line, usually written with the or Write-Host or - /// Write-Output cmdlets. - /// - Normal, - - /// - /// A debug output line, written with the Write-Debug cmdlet. - /// - Debug, - - /// - /// A verbose output line, written with the Write-Verbose cmdlet. - /// - Verbose, - - /// - /// A warning output line, written with the Write-Warning cmdlet. - /// - Warning, - - /// - /// An error output line, written with the Write-Error cmdlet or - /// as a result of some error during SqlTools pipeline execution. - /// - Error - } -} diff --git a/src/ServiceHost/Session/OutputWrittenEventArgs.cs b/src/ServiceHost/Session/OutputWrittenEventArgs.cs deleted file mode 100644 index 4b1dbbe3..00000000 --- a/src/ServiceHost/Session/OutputWrittenEventArgs.cs +++ /dev/null @@ -1,65 +0,0 @@ -// -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. -// - -using System; - -namespace Microsoft.SqlTools.EditorServices -{ - /// - /// Provides details about output that has been written to the - /// SqlTools host. - /// - public class OutputWrittenEventArgs - { - /// - /// Gets the text of the output. - /// - public string OutputText { get; private set; } - - /// - /// Gets the type of the output. - /// - public OutputType OutputType { get; private set; } - - /// - /// Gets a boolean which indicates whether a newline - /// should be written after the output. - /// - public bool IncludeNewLine { get; private set; } - - /// - /// Gets the foreground color of the output text. - /// - public ConsoleColor ForegroundColor { get; private set; } - - /// - /// Gets the background color of the output text. - /// - public ConsoleColor BackgroundColor { get; private set; } - - /// - /// Creates an instance of the OutputWrittenEventArgs class. - /// - /// The text of the output. - /// A boolean which indicates whether a newline should be written after the output. - /// The type of the output. - /// The foreground color of the output text. - /// The background color of the output text. - public OutputWrittenEventArgs( - string outputText, - bool includeNewLine, - OutputType outputType, - ConsoleColor foregroundColor, - ConsoleColor backgroundColor) - { - this.OutputText = outputText; - this.IncludeNewLine = includeNewLine; - this.OutputType = outputType; - this.ForegroundColor = foregroundColor; - this.BackgroundColor = backgroundColor; - } - } -} - diff --git a/src/ServiceHost/Session/HostDetails.cs b/src/ServiceHost/SqlContext/HostDetails.cs similarity index 98% rename from src/ServiceHost/Session/HostDetails.cs rename to src/ServiceHost/SqlContext/HostDetails.cs index 1a5fc80d..1b78faa4 100644 --- a/src/ServiceHost/Session/HostDetails.cs +++ b/src/ServiceHost/SqlContext/HostDetails.cs @@ -5,7 +5,7 @@ using System; -namespace Microsoft.SqlTools.EditorServices.Session +namespace Microsoft.SqlTools.ServiceLayer.SqlContext { /// /// Contains details about the current host application (most diff --git a/src/ServiceHost/Session/ProfilePaths.cs b/src/ServiceHost/SqlContext/ProfilePaths.cs similarity index 98% rename from src/ServiceHost/Session/ProfilePaths.cs rename to src/ServiceHost/SqlContext/ProfilePaths.cs index 4af38521..f841970d 100644 --- a/src/ServiceHost/Session/ProfilePaths.cs +++ b/src/ServiceHost/SqlContext/ProfilePaths.cs @@ -3,12 +3,11 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using System; using System.Collections.Generic; using System.IO; using System.Linq; -namespace Microsoft.SqlTools.EditorServices.Session +namespace Microsoft.SqlTools.ServiceLayer.SqlContext { /// /// Provides profile path resolution behavior relative to the name diff --git a/src/ServiceHost/Session/SqlToolsContext.cs b/src/ServiceHost/SqlContext/SqlToolsContext.cs similarity index 81% rename from src/ServiceHost/Session/SqlToolsContext.cs rename to src/ServiceHost/SqlContext/SqlToolsContext.cs index d8016afd..d110f28c 100644 --- a/src/ServiceHost/Session/SqlToolsContext.cs +++ b/src/ServiceHost/SqlContext/SqlToolsContext.cs @@ -5,8 +5,11 @@ using System; -namespace Microsoft.SqlTools.EditorServices.Session +namespace Microsoft.SqlTools.ServiceLayer.SqlContext { + /// + /// Context for SQL Tools + /// public class SqlToolsContext { /// diff --git a/src/ServiceHost/Server/LanguageServerSettings.cs b/src/ServiceHost/SqlContext/SqlToolsSettings.cs similarity index 80% rename from src/ServiceHost/Server/LanguageServerSettings.cs rename to src/ServiceHost/SqlContext/SqlToolsSettings.cs index be09984a..07ea0ffe 100644 --- a/src/ServiceHost/Server/LanguageServerSettings.cs +++ b/src/ServiceHost/SqlContext/SqlToolsSettings.cs @@ -1,25 +1,29 @@ -// -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. -// - -using System.IO; +using System.IO; using Microsoft.SqlTools.EditorServices.Utility; -namespace Microsoft.SqlTools.EditorServices.Protocol.Server +namespace Microsoft.SqlTools.ServiceLayer.SqlContext { - public class LanguageServerSettings + /// + /// Class for serialization and deserialization of the settings the SQL Tools Service needs. + /// + public class SqlToolsSettings { - public bool EnableProfileLoading { get; set; } + // TODO: Is this needed? I can't make sense of this comment. + // NOTE: This property is capitalized as 'SqlTools' because the + // mode name sent from the client is written as 'SqlTools' and + // JSON.net is using camelCasing. + //public ServiceHostSettings SqlTools { get; set; } - public ScriptAnalysisSettings ScriptAnalysis { get; set; } - - public LanguageServerSettings() + public SqlToolsSettings() { this.ScriptAnalysis = new ScriptAnalysisSettings(); } - public void Update(LanguageServerSettings settings, string workspaceRootPath) + public bool EnableProfileLoading { get; set; } + + public ScriptAnalysisSettings ScriptAnalysis { get; set; } + + public void Update(SqlToolsSettings settings, string workspaceRootPath) { if (settings != null) { @@ -28,8 +32,10 @@ namespace Microsoft.SqlTools.EditorServices.Protocol.Server } } } - + /// + /// Sub class for serialization and deserialization of script analysis settings + /// public class ScriptAnalysisSettings { public bool? Enable { get; set; } @@ -77,14 +83,4 @@ namespace Microsoft.SqlTools.EditorServices.Protocol.Server } } } - - - public class LanguageServerSettingsWrapper - { - // NOTE: This property is capitalized as 'SqlTools' because the - // mode name sent from the client is written as 'SqlTools' and - // JSON.net is using camelCasing. - - public LanguageServerSettings SqlTools { get; set; } - } } diff --git a/src/ServiceHost/Workspace/BufferPosition.cs b/src/ServiceHost/WorkspaceServices/Contracts/BufferPosition.cs similarity index 98% rename from src/ServiceHost/Workspace/BufferPosition.cs rename to src/ServiceHost/WorkspaceServices/Contracts/BufferPosition.cs index 8f790d85..f74ade68 100644 --- a/src/ServiceHost/Workspace/BufferPosition.cs +++ b/src/ServiceHost/WorkspaceServices/Contracts/BufferPosition.cs @@ -5,7 +5,7 @@ using System.Diagnostics; -namespace Microsoft.SqlTools.EditorServices +namespace Microsoft.SqlTools.ServiceLayer.WorkspaceServices.Contracts { /// /// Provides details about a position in a file buffer. All diff --git a/src/ServiceHost/Workspace/BufferRange.cs b/src/ServiceHost/WorkspaceServices/Contracts/BufferRange.cs similarity index 98% rename from src/ServiceHost/Workspace/BufferRange.cs rename to src/ServiceHost/WorkspaceServices/Contracts/BufferRange.cs index 5d20598f..99316fe5 100644 --- a/src/ServiceHost/Workspace/BufferRange.cs +++ b/src/ServiceHost/WorkspaceServices/Contracts/BufferRange.cs @@ -6,7 +6,7 @@ using System; using System.Diagnostics; -namespace Microsoft.SqlTools.EditorServices +namespace Microsoft.SqlTools.ServiceLayer.WorkspaceServices.Contracts { /// /// Provides details about a range between two positions in diff --git a/src/ServiceHost/LanguageServer/Configuration.cs b/src/ServiceHost/WorkspaceServices/Contracts/Configuration.cs similarity index 80% rename from src/ServiceHost/LanguageServer/Configuration.cs rename to src/ServiceHost/WorkspaceServices/Contracts/Configuration.cs index b9ad87db..ff1e5096 100644 --- a/src/ServiceHost/LanguageServer/Configuration.cs +++ b/src/ServiceHost/WorkspaceServices/Contracts/Configuration.cs @@ -3,9 +3,9 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts; -namespace Microsoft.SqlTools.EditorServices.Protocol.LanguageServer +namespace Microsoft.SqlTools.ServiceLayer.WorkspaceServices.Contracts { public class DidChangeConfigurationNotification { diff --git a/src/ServiceHost/Workspace/FileChange.cs b/src/ServiceHost/WorkspaceServices/Contracts/FileChange.cs similarity index 93% rename from src/ServiceHost/Workspace/FileChange.cs rename to src/ServiceHost/WorkspaceServices/Contracts/FileChange.cs index 2f6efdf8..7e1af148 100644 --- a/src/ServiceHost/Workspace/FileChange.cs +++ b/src/ServiceHost/WorkspaceServices/Contracts/FileChange.cs @@ -3,7 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -namespace Microsoft.SqlTools.EditorServices +namespace Microsoft.SqlTools.ServiceLayer.WorkspaceServices.Contracts { /// /// Contains details relating to a content change in an open file. diff --git a/src/ServiceHost/Workspace/FilePosition.cs b/src/ServiceHost/WorkspaceServices/Contracts/FilePosition.cs similarity index 98% rename from src/ServiceHost/Workspace/FilePosition.cs rename to src/ServiceHost/WorkspaceServices/Contracts/FilePosition.cs index 2cb58745..01ed012d 100644 --- a/src/ServiceHost/Workspace/FilePosition.cs +++ b/src/ServiceHost/WorkspaceServices/Contracts/FilePosition.cs @@ -3,7 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -namespace Microsoft.SqlTools.EditorServices +namespace Microsoft.SqlTools.ServiceLayer.WorkspaceServices.Contracts { /// /// Provides details and operations for a buffer position in a diff --git a/src/ServiceHost/Workspace/ScriptFile.cs b/src/ServiceHost/WorkspaceServices/Contracts/ScriptFile.cs similarity index 96% rename from src/ServiceHost/Workspace/ScriptFile.cs rename to src/ServiceHost/WorkspaceServices/Contracts/ScriptFile.cs index 166b50ea..708bae70 100644 --- a/src/ServiceHost/Workspace/ScriptFile.cs +++ b/src/ServiceHost/WorkspaceServices/Contracts/ScriptFile.cs @@ -9,19 +9,13 @@ using System.Collections.Generic; using System.IO; using System.Linq; -namespace Microsoft.SqlTools.EditorServices +namespace Microsoft.SqlTools.ServiceLayer.WorkspaceServices.Contracts { /// /// Contains the details and contents of an open script file. /// public class ScriptFile { - #region Private Fields - - private Version SqlToolsVersion; - - #endregion - #region Properties /// @@ -120,18 +114,15 @@ namespace Microsoft.SqlTools.EditorServices /// The path at which the script file resides. /// The path which the client uses to identify the file. /// The TextReader to use for reading the file's contents. - /// The version of SqlTools for which the script is being parsed. public ScriptFile( string filePath, string clientFilePath, - TextReader textReader, - Version SqlToolsVersion) + TextReader textReader) { this.FilePath = filePath; this.ClientFilePath = clientFilePath; this.IsAnalysisEnabled = true; this.IsInMemory = Workspace.IsPathInMemory(filePath); - this.SqlToolsVersion = SqlToolsVersion; this.SetFileContents(textReader.ReadToEnd()); } @@ -142,17 +133,14 @@ namespace Microsoft.SqlTools.EditorServices /// The path at which the script file resides. /// The path which the client uses to identify the file. /// The initial contents of the script file. - /// The version of SqlTools for which the script is being parsed. public ScriptFile( string filePath, string clientFilePath, - string initialBuffer, - Version SqlToolsVersion) + string initialBuffer) { this.FilePath = filePath; this.ClientFilePath = clientFilePath; this.IsAnalysisEnabled = true; - this.SqlToolsVersion = SqlToolsVersion; this.SetFileContents(initialBuffer); } diff --git a/src/ServiceHost/Workspace/ScriptFileMarker.cs b/src/ServiceHost/WorkspaceServices/Contracts/ScriptFileMarker.cs similarity index 95% rename from src/ServiceHost/Workspace/ScriptFileMarker.cs rename to src/ServiceHost/WorkspaceServices/Contracts/ScriptFileMarker.cs index 87c2576c..35ba21fa 100644 --- a/src/ServiceHost/Workspace/ScriptFileMarker.cs +++ b/src/ServiceHost/WorkspaceServices/Contracts/ScriptFileMarker.cs @@ -3,7 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -namespace Microsoft.SqlTools.EditorServices +namespace Microsoft.SqlTools.ServiceLayer.WorkspaceServices.Contracts { /// /// Defines the message level of a script file marker. diff --git a/src/ServiceHost/Workspace/ScriptRegion.cs b/src/ServiceHost/WorkspaceServices/Contracts/ScriptRegion.cs similarity index 97% rename from src/ServiceHost/Workspace/ScriptRegion.cs rename to src/ServiceHost/WorkspaceServices/Contracts/ScriptRegion.cs index f2fa4ac8..1ac56d01 100644 --- a/src/ServiceHost/Workspace/ScriptRegion.cs +++ b/src/ServiceHost/WorkspaceServices/Contracts/ScriptRegion.cs @@ -5,7 +5,7 @@ //using System.Management.Automation.Language; -namespace Microsoft.SqlTools.EditorServices +namespace Microsoft.SqlTools.ServiceLayer.WorkspaceServices.Contracts { /// /// Contains details about a specific region of text in script file. diff --git a/src/ServiceHost/LanguageServer/TextDocument.cs b/src/ServiceHost/WorkspaceServices/Contracts/TextDocument.cs similarity index 97% rename from src/ServiceHost/LanguageServer/TextDocument.cs rename to src/ServiceHost/WorkspaceServices/Contracts/TextDocument.cs index 9f477374..0708316d 100644 --- a/src/ServiceHost/LanguageServer/TextDocument.cs +++ b/src/ServiceHost/WorkspaceServices/Contracts/TextDocument.cs @@ -4,9 +4,9 @@ // using System.Diagnostics; -using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts; -namespace Microsoft.SqlTools.EditorServices.Protocol.LanguageServer +namespace Microsoft.SqlTools.ServiceLayer.WorkspaceServices.Contracts { /// /// Defines a base parameter class for identifying a text document. diff --git a/src/ServiceHost/LanguageServer/WorkspaceSymbols.cs b/src/ServiceHost/WorkspaceServices/Contracts/WorkspaceSymbols.cs similarity index 91% rename from src/ServiceHost/LanguageServer/WorkspaceSymbols.cs rename to src/ServiceHost/WorkspaceServices/Contracts/WorkspaceSymbols.cs index 25a554b5..1b7731eb 100644 --- a/src/ServiceHost/LanguageServer/WorkspaceSymbols.cs +++ b/src/ServiceHost/WorkspaceServices/Contracts/WorkspaceSymbols.cs @@ -3,9 +3,9 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts; -namespace Microsoft.SqlTools.EditorServices.Protocol.LanguageServer +namespace Microsoft.SqlTools.ServiceLayer.WorkspaceServices.Contracts { public enum SymbolKind { diff --git a/src/ServiceHost/Workspace/Workspace.cs b/src/ServiceHost/WorkspaceServices/Workspace.cs similarity index 90% rename from src/ServiceHost/Workspace/Workspace.cs rename to src/ServiceHost/WorkspaceServices/Workspace.cs index 39e1d70f..921ecc7c 100644 --- a/src/ServiceHost/Workspace/Workspace.cs +++ b/src/ServiceHost/WorkspaceServices/Workspace.cs @@ -3,25 +3,25 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using Microsoft.SqlTools.EditorServices.Utility; using System; using System.Collections.Generic; using System.IO; using System.Text; using System.Text.RegularExpressions; using System.Linq; +using Microsoft.SqlTools.EditorServices.Utility; +using Microsoft.SqlTools.ServiceLayer.WorkspaceServices.Contracts; -namespace Microsoft.SqlTools.EditorServices +namespace Microsoft.SqlTools.ServiceLayer.WorkspaceServices { /// /// Manages a "workspace" of script files that are open for a particular /// editing session. Also helps to navigate references between ScriptFiles. /// - public class Workspace + public class Workspace : IDisposable { - #region Private Fields + #region Private Fields - private Version SqlToolsVersion; private Dictionary workspaceFiles = new Dictionary(); #endregion @@ -40,10 +40,8 @@ namespace Microsoft.SqlTools.EditorServices /// /// Creates a new instance of the Workspace class. /// - /// The version of SqlTools for which scripts will be parsed. - public Workspace(Version SqlToolsVersion) + public Workspace() { - this.SqlToolsVersion = SqlToolsVersion; } #endregion @@ -78,12 +76,7 @@ namespace Microsoft.SqlTools.EditorServices using (FileStream fileStream = new FileStream(resolvedFilePath, FileMode.Open, FileAccess.Read)) using (StreamReader streamReader = new StreamReader(fileStream, Encoding.UTF8)) { - scriptFile = - new ScriptFile( - resolvedFilePath, - filePath, - streamReader, - this.SqlToolsVersion); + scriptFile = new ScriptFile(resolvedFilePath, filePath,streamReader); this.workspaceFiles.Add(keyName, scriptFile); } @@ -169,12 +162,7 @@ namespace Microsoft.SqlTools.EditorServices ScriptFile scriptFile = null; if (!this.workspaceFiles.TryGetValue(keyName, out scriptFile)) { - scriptFile = - new ScriptFile( - resolvedFilePath, - filePath, - initialBuffer, - this.SqlToolsVersion); + scriptFile = new ScriptFile(resolvedFilePath, filePath, initialBuffer); this.workspaceFiles.Add(keyName, scriptFile); @@ -244,5 +232,17 @@ namespace Microsoft.SqlTools.EditorServices } #endregion + + #region IDisposable Implementation + + /// + /// Disposes of any Runspaces that were created for the + /// services used in this session. + /// + public void Dispose() + { + } + + #endregion } } diff --git a/src/ServiceHost/WorkspaceServices/WorkspaceService.cs b/src/ServiceHost/WorkspaceServices/WorkspaceService.cs new file mode 100644 index 00000000..13575121 --- /dev/null +++ b/src/ServiceHost/WorkspaceServices/WorkspaceService.cs @@ -0,0 +1,235 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.SqlTools.EditorServices.Utility; +using Microsoft.SqlTools.ServiceLayer.Hosting; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol; +using Microsoft.SqlTools.ServiceLayer.WorkspaceServices.Contracts; + +namespace Microsoft.SqlTools.ServiceLayer.WorkspaceServices +{ + /// + /// Class for handling requests/events that deal with the state of the workspace, including the + /// opening and closing of files, the changing of configuration, etc. + /// + /// + /// The type of the class used for serializing and deserializing the configuration. Must be the + /// actual type of the instance otherwise deserialization will be incomplete. + /// + public class WorkspaceService where TConfig : class, new() + { + + #region Singleton Instance Implementation + + private static readonly Lazy> instance = new Lazy>(() => new WorkspaceService()); + + public static WorkspaceService Instance + { + get { return instance.Value; } + } + + /// + /// Default, parameterless constructor. + /// TODO: Figure out how to make this truely singleton even with dependency injection for tests + /// + public WorkspaceService() + { + ConfigChangeCallbacks = new List(); + TextDocChangeCallbacks = new List(); + } + + #endregion + + #region Properties + + public Workspace Workspace { get; private set; } + + public TConfig CurrentSettings { get; private set; } + + /// + /// Delegate for callbacks that occur when the configuration for the workspace changes + /// + /// The settings that were just set + /// The settings before they were changed + /// Context of the event that triggered the callback + /// + public delegate Task ConfigChangeCallback(TConfig newSettings, TConfig oldSettings, EventContext eventContext); + + /// + /// Delegate for callbacks that occur when the current text document changes + /// + /// Array of files that changed + /// Context of the event raised for the changed files + public delegate Task TextDocChangeCallback(ScriptFile[] changedFiles, EventContext eventContext); + + /// + /// List of callbacks to call when the configuration of the workspace changes + /// + private List ConfigChangeCallbacks { get; set; } + + /// + /// List of callbacks to call when the current text document changes + /// + private List TextDocChangeCallbacks { get; set; } + + #endregion + + #region Public Methods + + public void InitializeService(ServiceHost serviceHost) + { + // Create a workspace that will handle state for the session + Workspace = new Workspace(); + CurrentSettings = new TConfig(); + + // Register the handlers for when changes to the workspae occur + serviceHost.SetEventHandler(DidChangeTextDocumentNotification.Type, HandleDidChangeTextDocumentNotification); + serviceHost.SetEventHandler(DidOpenTextDocumentNotification.Type, HandleDidOpenTextDocumentNotification); + serviceHost.SetEventHandler(DidCloseTextDocumentNotification.Type, HandleDidCloseTextDocumentNotification); + serviceHost.SetEventHandler(DidChangeConfigurationNotification.Type, HandleDidChangeConfigurationNotification); + + // Register an initialization handler that sets the workspace path + serviceHost.RegisterInitializeTask(async (parameters, contect) => + { + Logger.Write(LogLevel.Verbose, "Initializing workspace service"); + + if (Workspace != null) + { + Workspace.WorkspacePath = parameters.RootPath; + } + await Task.FromResult(0); + }); + + // Register a shutdown request that disposes the workspace + serviceHost.RegisterShutdownTask(async (parameters, context) => + { + Logger.Write(LogLevel.Verbose, "Shutting down workspace service"); + + if (Workspace != null) + { + Workspace.Dispose(); + Workspace = null; + } + await Task.FromResult(0); + }); + } + + /// + /// Adds a new task to be called when the configuration has been changed. Use this to + /// handle changing configuration and changing the current configuration. + /// + /// Task to handle the request + public void RegisterConfigChangeCallback(ConfigChangeCallback task) + { + ConfigChangeCallbacks.Add(task); + } + + /// + /// Adds a new task to be called when the text of a document changes. + /// + /// Delegate to call when the document changes + public void RegisterTextDocChangeCallback(TextDocChangeCallback task) + { + TextDocChangeCallbacks.Add(task); + } + + #endregion + + #region Event Handlers + + /// + /// Handles text document change events + /// + protected Task HandleDidChangeTextDocumentNotification( + DidChangeTextDocumentParams textChangeParams, + EventContext eventContext) + { + StringBuilder msg = new StringBuilder(); + msg.Append("HandleDidChangeTextDocumentNotification"); + List changedFiles = new List(); + + // A text change notification can batch multiple change requests + foreach (var textChange in textChangeParams.ContentChanges) + { + string fileUri = textChangeParams.TextDocument.Uri; + msg.AppendLine(String.Format(" File: {0}", fileUri)); + + ScriptFile changedFile = Workspace.GetFile(fileUri); + + changedFile.ApplyChange( + GetFileChangeDetails( + textChange.Range.Value, + textChange.Text)); + + changedFiles.Add(changedFile); + } + + Logger.Write(LogLevel.Verbose, msg.ToString()); + + var handlers = TextDocChangeCallbacks.Select(t => t(changedFiles.ToArray(), eventContext)); + return Task.WhenAll(handlers); + } + + protected Task HandleDidOpenTextDocumentNotification( + DidOpenTextDocumentNotification openParams, + EventContext eventContext) + { + Logger.Write(LogLevel.Verbose, "HandleDidOpenTextDocumentNotification"); + return Task.FromResult(true); + } + + protected Task HandleDidCloseTextDocumentNotification( + TextDocumentIdentifier closeParams, + EventContext eventContext) + { + Logger.Write(LogLevel.Verbose, "HandleDidCloseTextDocumentNotification"); + return Task.FromResult(true); + } + + /// + /// Handles the configuration change event + /// + protected async Task HandleDidChangeConfigurationNotification( + DidChangeConfigurationParams configChangeParams, + EventContext eventContext) + { + Logger.Write(LogLevel.Verbose, "HandleDidChangeConfigurationNotification"); + + // Propagate the changes to the event handlers + var configUpdateTasks = ConfigChangeCallbacks.Select( + t => t(configChangeParams.Settings, CurrentSettings, eventContext)); + await Task.WhenAll(configUpdateTasks); + } + + #endregion + + #region Private Helpers + + /// + /// Switch from 0-based offsets to 1 based offsets + /// + /// + /// + private static FileChange GetFileChangeDetails(Range changeRange, string insertString) + { + // The protocol's positions are zero-based so add 1 to all offsets + return new FileChange + { + InsertString = insertString, + Line = changeRange.Start.Line + 1, + Offset = changeRange.Start.Character + 1, + EndLine = changeRange.End.Line + 1, + EndOffset = changeRange.End.Character + 1 + }; + } + + #endregion + } +} diff --git a/test/ServiceHost.Test/Connection/ConnectionServiceTests.cs b/test/ServiceHost.Test/Connection/ConnectionServiceTests.cs index 6796183c..ed39ce2b 100644 --- a/test/ServiceHost.Test/Connection/ConnectionServiceTests.cs +++ b/test/ServiceHost.Test/Connection/ConnectionServiceTests.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; using Microsoft.SqlTools.Test.Utility; using Xunit; -namespace Microsoft.SqlTools.Test.Connection +namespace Microsoft.SqlTools.ServiceLayer.Test.Connection { /// /// Tests for the ServiceHost Connection Service tests diff --git a/test/ServiceHost.Test/LanguageServer/LanguageServiceTests.cs b/test/ServiceHost.Test/LanguageServer/LanguageServiceTests.cs index 36aac6b4..8f85869d 100644 --- a/test/ServiceHost.Test/LanguageServer/LanguageServiceTests.cs +++ b/test/ServiceHost.Test/LanguageServer/LanguageServiceTests.cs @@ -3,14 +3,12 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using Microsoft.SqlTools.EditorServices; -using Microsoft.SqlTools.EditorServices.Session; -using Microsoft.SqlTools.LanguageSupport; -using Microsoft.SqlTools.Test.Connection; +using Microsoft.SqlTools.ServiceLayer.LanguageServices; +using Microsoft.SqlTools.ServiceLayer.WorkspaceServices.Contracts; using Microsoft.SqlTools.Test.Utility; using Xunit; -namespace Microsoft.SqlTools.Test.LanguageServer +namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServer { /// /// Tests for the ServiceHost Language Service tests diff --git a/test/ServiceHost.Test/Message/MessageReaderWriterTests.cs b/test/ServiceHost.Test/Message/MessageReaderWriterTests.cs index 82e619f5..54fbf01f 100644 --- a/test/ServiceHost.Test/Message/MessageReaderWriterTests.cs +++ b/test/ServiceHost.Test/Message/MessageReaderWriterTests.cs @@ -3,15 +3,16 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol; -using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol.Serializers; using System; using System.IO; using System.Text; using System.Threading.Tasks; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol; +using HostingMessage = Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts.Message; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Serializers; using Xunit; -namespace Microsoft.SqlTools.EditorServices.Test.Protocol.MessageProtocol +namespace Microsoft.SqlTools.ServiceLayer.Test.Message { public class MessageReaderWriterTests { @@ -38,7 +39,7 @@ namespace Microsoft.SqlTools.EditorServices.Test.Protocol.MessageProtocol // Write the message and then roll back the stream to be read // TODO: This will need to be redone! - await messageWriter.WriteMessage(Message.Event("testEvent", null)); + await messageWriter.WriteMessage(HostingMessage.Event("testEvent", null)); outputStream.Seek(0, SeekOrigin.Begin); string expectedHeaderString = @@ -82,7 +83,7 @@ namespace Microsoft.SqlTools.EditorServices.Test.Protocol.MessageProtocol inputStream.Flush(); inputStream.Seek(0, SeekOrigin.Begin); - Message messageResult = messageReader.ReadMessage().Result; + HostingMessage messageResult = messageReader.ReadMessage().Result; Assert.Equal("testEvent", messageResult.Method); inputStream.Dispose(); @@ -117,7 +118,7 @@ namespace Microsoft.SqlTools.EditorServices.Test.Protocol.MessageProtocol // Read the written messages from the stream for (int i = 0; i < overflowMessageCount; i++) { - Message messageResult = messageReader.ReadMessage().Result; + HostingMessage messageResult = messageReader.ReadMessage().Result; Assert.Equal("testEvent", messageResult.Method); } @@ -145,7 +146,7 @@ namespace Microsoft.SqlTools.EditorServices.Test.Protocol.MessageProtocol inputStream.Flush(); inputStream.Seek(0, SeekOrigin.Begin); - Message messageResult = messageReader.ReadMessage().Result; + HostingMessage messageResult = messageReader.ReadMessage().Result; Assert.Equal("testEvent", messageResult.Method); inputStream.Dispose(); diff --git a/test/ServiceHost.Test/Message/TestMessageTypes.cs b/test/ServiceHost.Test/Message/TestMessageTypes.cs index cc5981dc..0ba08056 100644 --- a/test/ServiceHost.Test/Message/TestMessageTypes.cs +++ b/test/ServiceHost.Test/Message/TestMessageTypes.cs @@ -3,19 +3,16 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol; -using System; using System.Threading.Tasks; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol; -namespace Microsoft.SqlTools.EditorServices.Test.Protocol.MessageProtocol +namespace Microsoft.SqlTools.ServiceLayer.Test.Message { #region Request Types internal class TestRequest { - public Task ProcessMessage( - EditorSession editorSession, - MessageWriter messageWriter) + public Task ProcessMessage(MessageWriter messageWriter) { return Task.FromResult(false); } diff --git a/test/ServiceHost.Test/ServiceHost.Test.xproj b/test/ServiceHost.Test/ServiceHost.Test.xproj index 7e4a3242..cb4c13ed 100644 --- a/test/ServiceHost.Test/ServiceHost.Test.xproj +++ b/test/ServiceHost.Test/ServiceHost.Test.xproj @@ -7,7 +7,7 @@ 2d771d16-9d85-4053-9f79-e2034737deef - Microsoft.SqlTools.EditorServices.Test.Protocol + Microsoft.SqlTools.ServiceLayer.Test .\obj .\bin\ v4.5.2 @@ -15,5 +15,8 @@ 2.0 + + + \ No newline at end of file diff --git a/test/ServiceHost.Test/LanguageServer/JsonRpcMessageSerializerTests.cs b/test/ServiceHost.Test/ServiceHost/JsonRpcMessageSerializerTests.cs similarity index 90% rename from test/ServiceHost.Test/LanguageServer/JsonRpcMessageSerializerTests.cs rename to test/ServiceHost.Test/ServiceHost/JsonRpcMessageSerializerTests.cs index 9ec341c5..d50f02da 100644 --- a/test/ServiceHost.Test/LanguageServer/JsonRpcMessageSerializerTests.cs +++ b/test/ServiceHost.Test/ServiceHost/JsonRpcMessageSerializerTests.cs @@ -3,12 +3,12 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol; -using Microsoft.SqlTools.EditorServices.Protocol.MessageProtocol.Serializers; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Serializers; +using HostingMessage = Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts.Message; using Newtonsoft.Json.Linq; using Xunit; -namespace Microsoft.SqlTools.EditorServices.Test.Protocol.LanguageServer +namespace Microsoft.SqlTools.ServiceLayer.Test.ServiceHost { public class TestMessageContents { @@ -44,7 +44,7 @@ namespace Microsoft.SqlTools.EditorServices.Test.Protocol.LanguageServer { var messageObj = this.messageSerializer.SerializeMessage( - Message.Request( + HostingMessage.Request( MessageId, MethodName, MessageContent)); @@ -61,7 +61,7 @@ namespace Microsoft.SqlTools.EditorServices.Test.Protocol.LanguageServer { var messageObj = this.messageSerializer.SerializeMessage( - Message.Event( + HostingMessage.Event( MethodName, MessageContent)); @@ -76,7 +76,7 @@ namespace Microsoft.SqlTools.EditorServices.Test.Protocol.LanguageServer { var messageObj = this.messageSerializer.SerializeMessage( - Message.Response( + HostingMessage.Response( MessageId, null, MessageContent)); @@ -92,7 +92,7 @@ namespace Microsoft.SqlTools.EditorServices.Test.Protocol.LanguageServer { var messageObj = this.messageSerializer.SerializeMessage( - Message.ResponseError( + HostingMessage.ResponseError( MessageId, null, MessageContent)); diff --git a/test/ServiceHost.Test/Utility/TestObjects.cs b/test/ServiceHost.Test/Utility/TestObjects.cs index 22fc3f4d..4e086279 100644 --- a/test/ServiceHost.Test/Utility/TestObjects.cs +++ b/test/ServiceHost.Test/Utility/TestObjects.cs @@ -7,9 +7,9 @@ using System.Collections.Generic; using System.Threading.Tasks; -using Microsoft.SqlTools.EditorServices.Connection; -using Microsoft.SqlTools.EditorServices.Session; -using Microsoft.SqlTools.LanguageSupport; +using Microsoft.SqlTools.ServiceLayer.Connection; +using Microsoft.SqlTools.ServiceLayer.LanguageServices; +using Microsoft.SqlTools.ServiceLayer.SqlContext; using Xunit; namespace Microsoft.SqlTools.Test.Utility