diff --git a/BUILD.md b/BUILD.md index 603d42b4..d8ab23ed 100644 --- a/BUILD.md +++ b/BUILD.md @@ -1,12 +1,36 @@ -# Usage +# Build -Run `build.(ps1|sh)` with the desired set of arguments (see below for options). -The build script itself is `build.cake`, written in C# using the Cake build automation system. -All build related activites should be encapsulated in this file for cross-platform access. +To build the vscode-mssql Service Layer, the most straight-forward way is open the source project +(./src/Microsoft.SqlTools.ServiceLayer/ folder), restore the project's NuGet dependencies (which +is done automatically in Visual Studio), and run the build task in VSCode or Visual Studio +(CtrlShiftB). This will compile the code and drop everything in +the ./bin/ folder off of the root of the project. This is the most simple way and will produce the +dll files you can run using the `dotnet` command. -# Arguments +If you need to do something special, read on for details about Cake. -## Primary +# Cake + +In addition to the standard build process, we have added a much more robust build system for +performing complicated build processes that require more than just compiling the code. As such +Cake ([cakebuild.net](http://www.cakebuild.net/)) was selected for the task. Running cake is only +necessary in the following scenarios + +* Regenerating resource files after adding a new string +* Packaging the Service Layer into a NuGet package + +## Cake Prerequisites + +Cake requires Mono to be installed on non-Windows machines as Cake is not built using .NET Core (yet). + +## Cake Usage + +Run `build.(cmd|ps1|sh)` with the desired set of arguments (see below for options). +The build script itself is `build.cake`, written in Cake's C#-like DSL using the Cake build automation system. + +## Arguments + +### Primary `-target=TargetName`: The name of the build task/target to execute (see below for listing and details). Defaults to `Default`. @@ -14,7 +38,7 @@ All build related activites should be encapsulated in this file for cross-platfo `-configuration=(Release|Debug)`: The configuration to build. Defaults to `Release`. -## Extra +### Extra `-test-configuration=(Release|Debug)`: The configuration to use for the unit tests. Defaults to `Debug`. @@ -24,7 +48,7 @@ All build related activites should be encapsulated in this file for cross-platfo `-archive`: Enable the generation of publishable archives after a build. -# Targets +## Targets **Default**: Alias for Local. @@ -41,9 +65,12 @@ All build related activites should be encapsulated in this file for cross-platfo **SetPackageVersions**: Updates the dependency versions found within `project.json` files using information from `depversion.json`. Used for maintainence within the project, not needed for end-users. More information below. -# Configuration files +**SRGen**: Generates a new version of the `sr.resx`, `sr.cs`, and `sr.designer.cs` files that contain + the string resources defined in `sr.strings`. Run this after adding a new string to `sr.strings` -## build.json +## Cake Configuration files + +### build.json A number of build-related options, including folder names for different entities. Interesting options: @@ -55,12 +82,12 @@ A number of build-related options, including folder names for different entities **"DotNetVersion"**: The .NET SDK version used for the build. Can be used to pin to a specific version. Using the string `Latest` will retrieve the latest version. -## depversion.json +### depversion.json A listing of all dependencies (and their desired versions) used by `project.json` files throughout the project. Allows for quick and automatic updates to the dependency version numbers using the **SetPackageVersions** target. -# Artifacts generated +## Artifacts Generated From Cake * Binaries of Microsoft.SqlTools.ServiceLayer and its libraries built for the local machine in `artifacts/publish/Microsoft.SqlTools.ServiceLayer/default/{framework}/` * Scripts to run Microsoft.SqlTools.ServiceLayer at `scripts/SQLTOOLSSERVICE(.Core)(.cmd)` @@ -69,7 +96,3 @@ Allows for quick and automatic updates to the dependency version numbers using t * Binaries of Microsoft.SqlTools.ServiceLayer and its libraries cross-compiled for other runtimes (if selected in **PopulateRuntimes**) `artifacts/publish/Microsoft.SqlTools.ServiceLayer/{runtime}/{framework}/` * Test logs in `artifacts/logs` * Archived binaries in `artifacts/package` (only if `-archive` used on command line) - -# Requirements - -The build system requires Mono to be installed on non-Windows machines as Cake is not built using .NET Core (yet). diff --git a/build.cake b/build.cake index 1b7c3b80..20276ba5 100644 --- a/build.cake +++ b/build.cake @@ -526,7 +526,7 @@ Task("SRGen") } // Run SRGen - var dotnetArgs = string.Format("{0} -or \"{1}\" -oc \"{2}\" -ns \"{3}\" -an \"{4}\" -cn SR -l CS \"{5}\"", + var dotnetArgs = string.Format("{0} -or \"{1}\" -oc \"{2}\" -ns \"{3}\" -an \"{4}\" -cn SR -l CS -dnx \"{5}\"", srgenPath, outputResx, outputCs, projectName, projectName, projectStrings); Information("{0}", dotnetArgs); Run(dotnetcli, dotnetArgs); diff --git a/scripts/packages.config b/scripts/packages.config index 296eeb59..54f9b711 100644 --- a/scripts/packages.config +++ b/scripts/packages.config @@ -2,5 +2,5 @@ - + diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs index c694ca93..6cdd62aa 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs @@ -9,11 +9,11 @@ using System.Data; using System.Data.Common; using System.Data.SqlClient; using System.Threading.Tasks; -using Microsoft.SqlTools.EditorServices.Utility; using Microsoft.SqlTools.ServiceLayer.Connection.Contracts; using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection; using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol; using Microsoft.SqlTools.ServiceLayer.SqlContext; +using Microsoft.SqlTools.ServiceLayer.Utility; using Microsoft.SqlTools.ServiceLayer.Workspace; namespace Microsoft.SqlTools.ServiceLayer.Connection @@ -73,7 +73,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection /// // Callback for ondisconnect handler /// - public delegate Task OnDisconnectHandler(ConnectionSummary summary); + public delegate Task OnDisconnectHandler(ConnectionSummary summary, string ownerUri); /// /// List of onconnection handlers @@ -125,14 +125,14 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection string paramValidationErrorMessage; if (connectionParams == null) { - return new ConnectResponse() + return new ConnectResponse { - Messages = "Error: Connection parameters cannot be null." + Messages = SR.ConnectionServiceConnectErrorNullParams }; } - else if (!connectionParams.IsValid(out paramValidationErrorMessage)) + if (!connectionParams.IsValid(out paramValidationErrorMessage)) { - return new ConnectResponse() + return new ConnectResponse { Messages = paramValidationErrorMessage }; @@ -241,7 +241,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection // Invoke callback notifications foreach (var activity in this.onDisconnectActivities) { - activity(info.ConnectionDetails); + activity(info.ConnectionDetails, disconnectParams.OwnerUri); } // Success @@ -257,14 +257,14 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection var owner = listDatabasesParams.OwnerUri; if (string.IsNullOrEmpty(owner)) { - throw new ArgumentException("OwnerUri cannot be null or empty"); + throw new ArgumentException(SR.ConnectionServiceListDbErrorNullOwnerUri); } // Use the existing connection as a base for the search ConnectionInfo info; if (!TryFindConnection(owner, out info)) { - throw new Exception("Specified OwnerUri \"" + owner + "\" does not have an existing connection"); + throw new Exception(SR.ConnectionServiceListDbErrorNotConnected(owner)); } ConnectionDetails connectionDetails = info.ConnectionDetails.Clone(); @@ -422,7 +422,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection case "SqlLogin": break; default: - throw new ArgumentException(string.Format("Invalid value \"{0}\" for AuthenticationType. Valid values are \"Integrated\" and \"SqlLogin\".", connectionDetails.AuthenticationType)); + throw new ArgumentException(SR.ConnectionServiceConnStringInvalidAuthType(connectionDetails.AuthenticationType)); } } if (connectionDetails.Encrypt.HasValue) @@ -469,7 +469,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection intent = ApplicationIntent.ReadWrite; break; default: - throw new ArgumentException(string.Format("Invalid value \"{0}\" for ApplicationIntent. Valid values are \"ReadWrite\" and \"ReadOnly\".", connectionDetails.ApplicationIntent)); + throw new ArgumentException(SR.ConnectionServiceConnStringInvalidIntent(connectionDetails.ApplicationIntent)); } connectionBuilder.ApplicationIntent = intent; } @@ -553,7 +553,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection catch (Exception e) { Logger.Write( - LogLevel.Error, + LogLevel.Error, string.Format( "Exception caught while trying to change database context to [{0}] for OwnerUri [{1}]. Exception:{2}", newDatabaseName, diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectParamsExtensions.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectParamsExtensions.cs index c345532d..7b581658 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectParamsExtensions.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectParamsExtensions.cs @@ -18,37 +18,30 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.Contracts errorMessage = string.Empty; if (string.IsNullOrEmpty(parameters.OwnerUri)) { - errorMessage = "Error: OwnerUri cannot be null or empty."; + errorMessage = SR.ConnectionParamsValidateNullOwnerUri; } else if (parameters.Connection == null) { - errorMessage = "Error: Connection details object cannot be null."; + errorMessage = SR.ConnectionParamsValidateNullConnection; } else if (string.IsNullOrEmpty(parameters.Connection.ServerName)) { - errorMessage = "Error: ServerName cannot be null or empty."; + errorMessage = SR.ConnectionParamsValidateNullServerName; } else if (string.IsNullOrEmpty(parameters.Connection.AuthenticationType) || parameters.Connection.AuthenticationType == "SqlLogin") { // For SqlLogin, username/password cannot be empty if (string.IsNullOrEmpty(parameters.Connection.UserName)) { - errorMessage = "Error: UserName cannot be null or empty when using SqlLogin authentication."; + errorMessage = SR.ConnectionParamsValidateNullSqlAuth("UserName"); } else if( string.IsNullOrEmpty(parameters.Connection.Password)) { - errorMessage = "Error: Password cannot be null or empty when using SqlLogin authentication."; + errorMessage = SR.ConnectionParamsValidateNullSqlAuth("Password"); } } - if (string.IsNullOrEmpty(errorMessage)) - { - return true; - } - else - { - return false; - } + return string.IsNullOrEmpty(errorMessage); } } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/AmbientSettings.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/AmbientSettings.cs index e56769dc..fc8e7302 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/AmbientSettings.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/AmbientSettings.cs @@ -6,7 +6,7 @@ using System; using System.Collections.Generic; using System.Reflection; -using Microsoft.SqlTools.EditorServices.Utility; +using Microsoft.SqlTools.ServiceLayer.Utility; namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection { diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/CachedServerInfo.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/CachedServerInfo.cs index 2a495a45..7646262c 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/CachedServerInfo.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/CachedServerInfo.cs @@ -8,7 +8,7 @@ using System.Collections.Concurrent; using System.Data; using System.Data.SqlClient; using System.Linq; -using Microsoft.SqlTools.EditorServices.Utility; +using Microsoft.SqlTools.ServiceLayer.Utility; namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection { diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/DbCommandWrapper.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/DbCommandWrapper.cs index 8620f461..e2652b42 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/DbCommandWrapper.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/DbCommandWrapper.cs @@ -6,7 +6,7 @@ using System; using System.Data; using System.Data.SqlClient; -using Microsoft.SqlTools.EditorServices.Utility; +using Microsoft.SqlTools.ServiceLayer.Utility; namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection { diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/DbConnectionWrapper.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/DbConnectionWrapper.cs index c1f1d437..2c340ef0 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/DbConnectionWrapper.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/DbConnectionWrapper.cs @@ -6,7 +6,7 @@ using System; using System.Data; using System.Data.SqlClient; -using Microsoft.SqlTools.EditorServices.Utility; +using Microsoft.SqlTools.ServiceLayer.Utility; namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection { diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableConnectionHelper.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableConnectionHelper.cs index 5069fdc9..4f31fcf3 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableConnectionHelper.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableConnectionHelper.cs @@ -11,7 +11,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Security; -using Microsoft.SqlTools.EditorServices.Utility; +using Microsoft.SqlTools.ServiceLayer.Utility; namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection { diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableSqlConnection.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableSqlConnection.cs index b949cd54..579e86f6 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableSqlConnection.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableSqlConnection.cs @@ -31,7 +31,7 @@ using System.Data.SqlClient; using System.Diagnostics; using System.Globalization; using System.Text; -using Microsoft.SqlTools.EditorServices.Utility; +using Microsoft.SqlTools.ServiceLayer.Utility; namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection { diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicy.DataTransferDetectionErrorStrategy.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicy.DataTransferDetectionErrorStrategy.cs index 8876fca7..a52619d2 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicy.DataTransferDetectionErrorStrategy.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicy.DataTransferDetectionErrorStrategy.cs @@ -4,7 +4,7 @@ // using System.Data.SqlClient; -using Microsoft.SqlTools.EditorServices.Utility; +using Microsoft.SqlTools.ServiceLayer.Utility; namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection { diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicy.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicy.cs index 9b554841..a2eb03fe 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicy.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicy.cs @@ -29,7 +29,7 @@ using System.Diagnostics; using System.Diagnostics.Contracts; using System.Globalization; using System.Threading; -using Microsoft.SqlTools.EditorServices.Utility; +using Microsoft.SqlTools.ServiceLayer.Utility; namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection { diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicyFactory.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicyFactory.cs index bed9680f..4ac025fb 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicyFactory.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicyFactory.cs @@ -6,7 +6,7 @@ using System; using System.Diagnostics; using System.Globalization; -using Microsoft.SqlTools.EditorServices.Utility; +using Microsoft.SqlTools.ServiceLayer.Utility; namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection { diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicyUtils.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicyUtils.cs index 8951a75a..800951d4 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicyUtils.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicyUtils.cs @@ -6,7 +6,7 @@ using System; using System.Collections.Generic; using System.Data.SqlClient; -using Microsoft.SqlTools.EditorServices.Utility; +using Microsoft.SqlTools.ServiceLayer.Utility; namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection { diff --git a/src/Microsoft.SqlTools.ServiceLayer/Credentials/Contracts/Credential.cs b/src/Microsoft.SqlTools.ServiceLayer/Credentials/Contracts/Credential.cs index be595ec8..d8c3d973 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Credentials/Contracts/Credential.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Credentials/Contracts/Credential.cs @@ -3,8 +3,8 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using Microsoft.SqlTools.EditorServices.Utility; using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts; +using Microsoft.SqlTools.ServiceLayer.Utility; namespace Microsoft.SqlTools.ServiceLayer.Credentials.Contracts { diff --git a/src/Microsoft.SqlTools.ServiceLayer/Credentials/CredentialService.cs b/src/Microsoft.SqlTools.ServiceLayer/Credentials/CredentialService.cs index f1a80807..cf4182fc 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Credentials/CredentialService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Credentials/CredentialService.cs @@ -6,12 +6,12 @@ using System; using System.Runtime.InteropServices; using System.Threading.Tasks; -using Microsoft.SqlTools.EditorServices.Utility; using Microsoft.SqlTools.ServiceLayer.Credentials.Contracts; using Microsoft.SqlTools.ServiceLayer.Credentials.Linux; using Microsoft.SqlTools.ServiceLayer.Credentials.OSX; using Microsoft.SqlTools.ServiceLayer.Credentials.Win32; using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol; +using Microsoft.SqlTools.ServiceLayer.Utility; namespace Microsoft.SqlTools.ServiceLayer.Credentials { diff --git a/src/Microsoft.SqlTools.ServiceLayer/Credentials/Linux/FileTokenStorage.cs b/src/Microsoft.SqlTools.ServiceLayer/Credentials/Linux/FileTokenStorage.cs index ef2c2a67..756421e4 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Credentials/Linux/FileTokenStorage.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Credentials/Linux/FileTokenStorage.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using Microsoft.SqlTools.EditorServices.Utility; using Microsoft.SqlTools.ServiceLayer.Credentials.Contracts; using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol; +using Microsoft.SqlTools.ServiceLayer.Utility; using Newtonsoft.Json; namespace Microsoft.SqlTools.ServiceLayer.Credentials.Linux diff --git a/src/Microsoft.SqlTools.ServiceLayer/Credentials/Linux/LinuxCredentialStore.cs b/src/Microsoft.SqlTools.ServiceLayer/Credentials/Linux/LinuxCredentialStore.cs index 6d6b5908..93350e83 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Credentials/Linux/LinuxCredentialStore.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Credentials/Linux/LinuxCredentialStore.cs @@ -10,8 +10,8 @@ using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.InteropServices; -using Microsoft.SqlTools.EditorServices.Utility; using Microsoft.SqlTools.ServiceLayer.Credentials.Contracts; +using Microsoft.SqlTools.ServiceLayer.Utility; namespace Microsoft.SqlTools.ServiceLayer.Credentials.Linux { diff --git a/src/Microsoft.SqlTools.ServiceLayer/Credentials/OSX/OSXCredentialStore.cs b/src/Microsoft.SqlTools.ServiceLayer/Credentials/OSX/OSXCredentialStore.cs index dc868040..8ea262b3 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Credentials/OSX/OSXCredentialStore.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Credentials/OSX/OSXCredentialStore.cs @@ -5,8 +5,8 @@ using System; using System.Runtime.InteropServices; -using Microsoft.SqlTools.EditorServices.Utility; using Microsoft.SqlTools.ServiceLayer.Credentials.Contracts; +using Microsoft.SqlTools.ServiceLayer.Utility; namespace Microsoft.SqlTools.ServiceLayer.Credentials.OSX { diff --git a/src/Microsoft.SqlTools.ServiceLayer/Credentials/Win32/CredentialResources.cs b/src/Microsoft.SqlTools.ServiceLayer/Credentials/Win32/CredentialResources.cs deleted file mode 100644 index d3834c42..00000000 --- a/src/Microsoft.SqlTools.ServiceLayer/Credentials/Win32/CredentialResources.cs +++ /dev/null @@ -1,16 +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.ServiceLayer.Credentials.Win32 -{ - // TODO Replace this strings class with a resx file - internal class CredentialResources - { - public const string PasswordLengthExceeded = "The password has exceeded 512 bytes."; - public const string TargetRequiredForDelete = "Target must be specified to delete a credential."; - public const string TargetRequiredForLookup = "Target must be specified to check existance of a credential."; - public const string CredentialDisposed = "Win32Credential object is already disposed."; - } -} diff --git a/src/Microsoft.SqlTools.ServiceLayer/Credentials/Win32/CredentialSet.cs b/src/Microsoft.SqlTools.ServiceLayer/Credentials/Win32/CredentialSet.cs index f94a0f57..54629b24 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Credentials/Win32/CredentialSet.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Credentials/Win32/CredentialSet.cs @@ -8,7 +8,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Runtime.InteropServices; -using Microsoft.SqlTools.EditorServices.Utility; +using Microsoft.SqlTools.ServiceLayer.Utility; namespace Microsoft.SqlTools.ServiceLayer.Credentials.Win32 { @@ -25,7 +25,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Credentials.Win32 { if (string.IsNullOrEmpty(target)) { - throw new ArgumentNullException("target"); + throw new ArgumentNullException(nameof(target)); } Target = target; } diff --git a/src/Microsoft.SqlTools.ServiceLayer/Credentials/Win32/NativeMethods.cs b/src/Microsoft.SqlTools.ServiceLayer/Credentials/Win32/NativeMethods.cs index 1e43205c..33d7d75b 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Credentials/Win32/NativeMethods.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Credentials/Win32/NativeMethods.cs @@ -81,7 +81,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Credentials.Win32 } else { - throw new InvalidOperationException("Invalid CriticalHandle!"); + throw new InvalidOperationException(SR.CredentialsServiceInvalidCriticalHandle); } } @@ -89,7 +89,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Credentials.Win32 // Often, you need to use Pinvoke to make a call into the Win32 API to release the // handle. In this case, however, we can use the Marshal class to release the unmanaged memory. - override protected bool ReleaseHandle() + protected override bool ReleaseHandle() { // If the handle was set, free it. Return success. if (!IsInvalid) diff --git a/src/Microsoft.SqlTools.ServiceLayer/Credentials/Win32/Win32Credential.cs b/src/Microsoft.SqlTools.ServiceLayer/Credentials/Win32/Win32Credential.cs index 21c1c8b9..34ae08cc 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Credentials/Win32/Win32Credential.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Credentials/Win32/Win32Credential.cs @@ -78,7 +78,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Credentials.Win32 { if (disposed) { - throw new ObjectDisposedException(CredentialResources.CredentialDisposed); + throw new ObjectDisposedException(SR.CredentialServiceWin32CredentialDisposed); } } @@ -205,7 +205,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Credentials.Win32 byte[] passwordBytes = Encoding.Unicode.GetBytes(Password); if (Password.Length > (512)) { - throw new ArgumentOutOfRangeException(CredentialResources.PasswordLengthExceeded); + throw new ArgumentOutOfRangeException(SR.CredentialsServicePasswordLengthExceeded); } NativeMethods.CREDENTIAL credential = new NativeMethods.CREDENTIAL(); @@ -232,7 +232,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Credentials.Win32 if (string.IsNullOrEmpty(Target)) { - throw new InvalidOperationException(CredentialResources.TargetRequiredForDelete); + throw new InvalidOperationException(SR.CredentialsServiceTargetForDelete); } StringBuilder target = string.IsNullOrEmpty(Target) ? new StringBuilder() : new StringBuilder(Target); @@ -264,7 +264,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Credentials.Win32 if (string.IsNullOrEmpty(Target)) { - throw new InvalidOperationException(CredentialResources.TargetRequiredForLookup); + throw new InvalidOperationException(SR.CredentialsServiceTargetForLookup); } using (Win32Credential existing = new Win32Credential { Target = Target, Type = Type }) diff --git a/src/Microsoft.SqlTools.ServiceLayer/Credentials/Win32/Win32CredentialStore.cs b/src/Microsoft.SqlTools.ServiceLayer/Credentials/Win32/Win32CredentialStore.cs index 8a219854..dffb23a7 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Credentials/Win32/Win32CredentialStore.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Credentials/Win32/Win32CredentialStore.cs @@ -3,8 +3,8 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using Microsoft.SqlTools.EditorServices.Utility; using Microsoft.SqlTools.ServiceLayer.Credentials.Contracts; +using Microsoft.SqlTools.ServiceLayer.Utility; namespace Microsoft.SqlTools.ServiceLayer.Credentials.Win32 { diff --git a/src/Microsoft.SqlTools.ServiceLayer/Hosting/Protocol/MessageDispatcher.cs b/src/Microsoft.SqlTools.ServiceLayer/Hosting/Protocol/MessageDispatcher.cs index c4cf5365..ef7b842d 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Hosting/Protocol/MessageDispatcher.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Hosting/Protocol/MessageDispatcher.cs @@ -11,7 +11,7 @@ using System.Threading.Tasks; using Microsoft.SqlTools.ServiceLayer.Hosting.Contracts; using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Channel; using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts; -using Microsoft.SqlTools.EditorServices.Utility; +using Microsoft.SqlTools.ServiceLayer.Utility; namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol { diff --git a/src/Microsoft.SqlTools.ServiceLayer/Hosting/Protocol/MessageReader.cs b/src/Microsoft.SqlTools.ServiceLayer/Hosting/Protocol/MessageReader.cs index e70f33f4..2f36ac3d 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Hosting/Protocol/MessageReader.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Hosting/Protocol/MessageReader.cs @@ -8,9 +8,9 @@ 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 Microsoft.SqlTools.ServiceLayer.Utility; using Newtonsoft.Json.Linq; namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol @@ -146,8 +146,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol // ending suddenly). For now, just terminate the language // server immediately. // TODO: Provide a more graceful shutdown path - throw new EndOfStreamException( - "MessageReader's input stream ended unexpectedly, terminating."); + throw new EndOfStreamException(SR.HostingUnexpectedEndOfStream); } return true; @@ -186,7 +185,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol int currentLength = header.IndexOf(':'); if (currentLength == -1) { - throw new ArgumentException("Message header must separate key and value using :"); + throw new ArgumentException(SR.HostingHeaderMissingColon); } var key = header.Substring(0, currentLength); @@ -198,13 +197,13 @@ namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol string contentLengthString; if (!this.messageHeaders.TryGetValue("Content-Length", out contentLengthString)) { - throw new MessageParseException("", "Fatal error: Content-Length header must be provided."); + throw new MessageParseException("", SR.HostingHeaderMissingContentLengthHeader); } // Parse the content length to an integer if (!int.TryParse(contentLengthString, out this.expectedContentLength)) { - throw new MessageParseException("", "Fatal error: Content-Length value is not an integer."); + throw new MessageParseException("", SR.HostingHeaderMissingContentLengthValue); } } catch (Exception) diff --git a/src/Microsoft.SqlTools.ServiceLayer/Hosting/Protocol/MessageWriter.cs b/src/Microsoft.SqlTools.ServiceLayer/Hosting/Protocol/MessageWriter.cs index b269f750..8b0c0cef 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Hosting/Protocol/MessageWriter.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Hosting/Protocol/MessageWriter.cs @@ -6,9 +6,9 @@ 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 Microsoft.SqlTools.ServiceLayer.Utility; using Newtonsoft.Json; using Newtonsoft.Json.Linq; diff --git a/src/Microsoft.SqlTools.ServiceLayer/Hosting/ServiceHost.cs b/src/Microsoft.SqlTools.ServiceLayer/Hosting/ServiceHost.cs index f252d3c6..326cf5ed 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Hosting/ServiceHost.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Hosting/ServiceHost.cs @@ -7,11 +7,11 @@ 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; using System.Reflection; +using Microsoft.SqlTools.ServiceLayer.Utility; namespace Microsoft.SqlTools.ServiceLayer.Hosting { diff --git a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/AutoCompleteHelper.cs b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/AutoCompleteHelper.cs index 1069e18d..ffc9811c 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/AutoCompleteHelper.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/AutoCompleteHelper.cs @@ -4,8 +4,13 @@ // using System.Collections.Generic; +using Microsoft.SqlServer.Management.SqlParser.Binder; using Microsoft.SqlServer.Management.SqlParser.Intellisense; +using Microsoft.SqlServer.Management.SqlParser.Parser; +using Microsoft.SqlTools.ServiceLayer.Connection; using Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts; +using Microsoft.SqlTools.ServiceLayer.SqlContext; +using Microsoft.SqlTools.ServiceLayer.Workspace; using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts; namespace Microsoft.SqlTools.ServiceLayer.LanguageServices @@ -487,7 +492,6 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices Label = autoCompleteItem.Title, Kind = CompletionItemKind.Variable, Detail = autoCompleteItem.Title, - Documentation = autoCompleteItem.Description, TextEdit = new TextEdit { NewText = autoCompleteItem.Title, @@ -510,5 +514,76 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices return completions.ToArray(); } + + /// + /// Preinitialize the parser and binder with common metadata. + /// This should front load the long binding wait to the time the + /// connection is established. Once this is completed other binding + /// requests should be faster. + /// + /// + /// + internal static void PrepopulateCommonMetadata(ConnectionInfo info, ScriptParseInfo scriptInfo) + { + if (scriptInfo.IsConnected) + { + var scriptFile = WorkspaceService.Instance.Workspace.GetFile(info.OwnerUri); + LanguageService.Instance.ParseAndBind(scriptFile, info); + + if (scriptInfo.BuildingMetadataEvent.WaitOne(LanguageService.OnConnectionWaitTimeout)) + { + try + { + scriptInfo.BuildingMetadataEvent.Reset(); + + // parse a simple statement that returns common metadata + ParseResult parseResult = Parser.Parse( + "select ", + scriptInfo.ParseOptions); + + List parseResults = new List(); + parseResults.Add(parseResult); + scriptInfo.Binder.Bind( + parseResults, + info.ConnectionDetails.DatabaseName, + BindMode.Batch); + + // get the completion list from SQL Parser + var suggestions = Resolver.FindCompletions( + parseResult, 1, 8, + scriptInfo.MetadataDisplayInfoProvider); + + // this forces lazy evaluation of the suggestion metadata + AutoCompleteHelper.ConvertDeclarationsToCompletionItems(suggestions, 1, 8, 8); + + parseResult = Parser.Parse( + "exec ", + scriptInfo.ParseOptions); + + parseResults = new List(); + parseResults.Add(parseResult); + scriptInfo.Binder.Bind( + parseResults, + info.ConnectionDetails.DatabaseName, + BindMode.Batch); + + // get the completion list from SQL Parser + suggestions = Resolver.FindCompletions( + parseResult, 1, 6, + scriptInfo.MetadataDisplayInfoProvider); + + // this forces lazy evaluation of the suggestion metadata + AutoCompleteHelper.ConvertDeclarationsToCompletionItems(suggestions, 1, 6, 6); + } + catch + { + } + finally + { + scriptInfo.BuildingMetadataEvent.Set(); + } + } + } + } } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/LanguageService.cs b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/LanguageService.cs index d43840a2..cc834adc 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/LanguageService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/LanguageService.cs @@ -8,16 +8,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; -using Microsoft.SqlTools.EditorServices.Utility; -using Microsoft.SqlTools.ServiceLayer.Connection; -using Microsoft.SqlTools.ServiceLayer.Connection.Contracts; -using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection; -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.Workspace; -using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts; using Microsoft.SqlServer.Management.Common; using Microsoft.SqlServer.Management.SqlParser; using Microsoft.SqlServer.Management.SqlParser.Binder; @@ -25,28 +15,41 @@ using Microsoft.SqlServer.Management.SqlParser.Intellisense; using Microsoft.SqlServer.Management.SqlParser.MetadataProvider; using Microsoft.SqlServer.Management.SqlParser.Parser; using Microsoft.SqlServer.Management.SmoMetadataProvider; - +using Microsoft.SqlTools.ServiceLayer.Connection; +using Microsoft.SqlTools.ServiceLayer.Connection.Contracts; +using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection; +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.Utility; +using Microsoft.SqlTools.ServiceLayer.Workspace; +using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts; using Location = Microsoft.SqlTools.ServiceLayer.Workspace.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. + /// Main class for Language Service functionality including anything that requires knowledge of + /// the language to perform, such as definitions, intellisense, etc. /// public sealed class LanguageService { - public const string DefaultBatchSeperator = "GO"; + internal const string DefaultBatchSeperator = "GO"; - private const int DiagnosticParseDelay = 750; + internal const int DiagnosticParseDelay = 750; - private const int FindCompletionsTimeout = 3000; + internal const int FindCompletionsTimeout = 3000; - private const int FindCompletionStartTimeout = 50; + internal const int FindCompletionStartTimeout = 50; - private const int OnConnectionWaitTimeout = 30000; + internal const int OnConnectionWaitTimeout = 300000; - private bool ShouldEnableAutocomplete() + private object parseMapLock = new object(); + + private ScriptParseInfo currentCompletionParseInfo; + + internal bool ShouldEnableAutocomplete() { return true; } @@ -106,12 +109,12 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices private static CancellationTokenSource ExistingRequestCancellation { get; set; } - private SqlToolsSettings CurrentSettings + internal SqlToolsSettings CurrentSettings { get { return WorkspaceService.Instance.CurrentSettings; } } - private Workspace.Workspace CurrentWorkspace + internal Workspace.Workspace CurrentWorkspace { get { return WorkspaceService.Instance.Workspace; } } @@ -120,7 +123,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices /// Gets or sets the current SQL Tools context /// /// - private SqlToolsContext Context { get; set; } + internal SqlToolsContext Context { get; set; } #endregion @@ -197,11 +200,25 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices await requestContext.SendResult(completionItems); } + /// + /// Handle the resolve completion request event to provide additional + /// autocomplete metadata to the currently select completion item + /// + /// + /// + /// + private static async Task HandleCompletionResolveRequest( + CompletionItem completionItem, + RequestContext requestContext) + { + completionItem = LanguageService.Instance.ResolveCompletionItem(completionItem); + await requestContext.SendResult(completionItem); + } + private static async Task HandleDefinitionRequest( TextDocumentPosition textDocumentPosition, RequestContext requestContext) { - Logger.Write(LogLevel.Verbose, "HandleDefinitionRequest"); await Task.FromResult(true); } @@ -209,15 +226,6 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices ReferencesParams referencesParams, RequestContext requestContext) { - Logger.Write(LogLevel.Verbose, "HandleReferencesRequest"); - await Task.FromResult(true); - } - - private static async Task HandleCompletionResolveRequest( - CompletionItem completionItem, - RequestContext requestContext) - { - Logger.Write(LogLevel.Verbose, "HandleCompletionResolveRequest"); await Task.FromResult(true); } @@ -225,7 +233,6 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices TextDocumentPosition textDocumentPosition, RequestContext requestContext) { - Logger.Write(LogLevel.Verbose, "HandleSignatureHelpRequest"); await Task.FromResult(true); } @@ -233,7 +240,6 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices TextDocumentPosition textDocumentPosition, RequestContext requestContext) { - Logger.Write(LogLevel.Verbose, "HandleDocumentHighlightRequest"); await Task.FromResult(true); } @@ -241,7 +247,6 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices TextDocumentPosition textDocumentPosition, RequestContext requestContext) { - Logger.Write(LogLevel.Verbose, "HandleHoverRequest"); await Task.FromResult(true); } @@ -259,9 +264,12 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices ScriptFile scriptFile, EventContext eventContext) { - await this.RunScriptDiagnostics( - new ScriptFile[] { scriptFile }, - eventContext); + if (!IsPreviewWindow(scriptFile)) + { + await RunScriptDiagnostics( + new ScriptFile[] { scriptFile }, + eventContext); + } await Task.FromResult(true); } @@ -328,8 +336,10 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices /// it is the last URI connected to a particular connection, /// then remove the cache. /// - public async Task RemoveAutoCompleteCacheUriReference(ConnectionSummary summary) + public async Task RemoveAutoCompleteCacheUriReference(ConnectionSummary summary, string ownerUri) { + RemoveScriptParseInfo(ownerUri); + // currently this method is disabled, but we need to reimplement now that the // implementation of the 'cache' has changed. await Task.FromResult(0); @@ -343,16 +353,8 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices /// public ParseResult ParseAndBind(ScriptFile scriptFile, ConnectionInfo connInfo) { - ScriptParseInfo parseInfo = null; - if (this.ScriptParseInfoMap.ContainsKey(scriptFile.ClientFilePath)) - { - parseInfo = this.ScriptParseInfoMap[scriptFile.ClientFilePath]; - } - else - { - parseInfo = new ScriptParseInfo(); - this.ScriptParseInfoMap.Add(scriptFile.ClientFilePath, parseInfo); - } + // get or create the current parse info object + ScriptParseInfo parseInfo = GetScriptParseInfo(scriptFile.ClientFilePath, createIfNotExists: true); if (parseInfo.BuildingMetadataEvent.WaitOne(LanguageService.FindCompletionsTimeout)) { @@ -399,7 +401,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices } /// - /// Update the cached autocomplete candidate list when the user connects to a database + /// Update the autocomplete metadata provider when the user connects to a database /// /// public async Task UpdateLanguageServiceOnConnection(ConnectionInfo info) @@ -408,43 +410,37 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices { if (ShouldEnableAutocomplete()) { - ScriptParseInfo scriptInfo = - this.ScriptParseInfoMap.ContainsKey(info.OwnerUri) - ? this.ScriptParseInfoMap[info.OwnerUri] - : new ScriptParseInfo(); - - try + ScriptParseInfo scriptInfo = GetScriptParseInfo(info.OwnerUri, createIfNotExists: true); + if (scriptInfo.BuildingMetadataEvent.WaitOne(LanguageService.OnConnectionWaitTimeout)) { - scriptInfo.BuildingMetadataEvent.WaitOne(LanguageService.OnConnectionWaitTimeout); - scriptInfo.BuildingMetadataEvent.Reset(); - - var sqlConn = info.SqlConnection as ReliableSqlConnection; - if (sqlConn != null) + try { - ServerConnection serverConn = new ServerConnection(sqlConn.GetUnderlyingConnection()); - scriptInfo.MetadataDisplayInfoProvider = new MetadataDisplayInfoProvider(); - scriptInfo.MetadataProvider = SmoMetadataProvider.CreateConnectedProvider(serverConn); - scriptInfo.Binder = BinderProvider.CreateBinder(scriptInfo.MetadataProvider); - scriptInfo.ServerConnection = new ServerConnection(sqlConn.GetUnderlyingConnection()); - this.ScriptParseInfoMap[info.OwnerUri] = scriptInfo; + scriptInfo.BuildingMetadataEvent.Reset(); + var sqlConn = info.SqlConnection as ReliableSqlConnection; + if (sqlConn != null) + { + ServerConnection serverConn = new ServerConnection(sqlConn.GetUnderlyingConnection()); + scriptInfo.MetadataDisplayInfoProvider = new MetadataDisplayInfoProvider(); + scriptInfo.MetadataProvider = SmoMetadataProvider.CreateConnectedProvider(serverConn); + scriptInfo.Binder = BinderProvider.CreateBinder(scriptInfo.MetadataProvider); + scriptInfo.ServerConnection = new ServerConnection(sqlConn.GetUnderlyingConnection()); + scriptInfo.IsConnected = true; + } + } + catch (Exception) + { + scriptInfo.IsConnected = false; + } + finally + { + // Set Metadata Build event to Signal state. + // (Tell Language Service that I am ready with Metadata Provider Object) + scriptInfo.BuildingMetadataEvent.Set(); } } - catch (Exception) - { - scriptInfo.IsConnected = false; - } - finally - { - // Set Metadata Build event to Signal state. - // (Tell Language Service that I am ready with Metadata Provider Object) - scriptInfo.BuildingMetadataEvent.Set(); - } - if (scriptInfo.IsConnected) - { - var scriptFile = WorkspaceService.Instance.Workspace.GetFile(info.OwnerUri); - ParseAndBind(scriptFile, info); - } + // populate SMO metadata provider with most common info + AutoCompleteHelper.PrepopulateCommonMetadata(info, scriptInfo); } }); } @@ -467,6 +463,28 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices || !string.Equals(prevSqlText, currentSqlText); } + /// + /// Resolves the details and documentation for a completion item + /// + /// + internal CompletionItem ResolveCompletionItem(CompletionItem completionItem) + { + var scriptParseInfo = LanguageService.Instance.currentCompletionParseInfo; + if (scriptParseInfo != null && scriptParseInfo.CurrentSuggestions != null) + { + foreach (var suggestion in scriptParseInfo.CurrentSuggestions) + { + if (string.Equals(suggestion.Title, completionItem.Label)) + { + completionItem.Detail = suggestion.DatabaseQualifiedName; + completionItem.Documentation = suggestion.Description; + break; + } + } + } + return completionItem; + } + /// /// Return the completion item list for the current text position. /// This method does not await cache builds since it expects to return quickly @@ -480,20 +498,22 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices string filePath = textDocumentPosition.TextDocument.Uri; int startLine = textDocumentPosition.Position.Line; int startColumn = TextUtilities.PositionOfPrevDelimeter( - scriptFile.Contents, + scriptFile.Contents, textDocumentPosition.Position.Line, textDocumentPosition.Position.Character); int endColumn = textDocumentPosition.Position.Character; + this.currentCompletionParseInfo = null; + // Take a reference to the list at a point in time in case we update and replace the list - if (connInfo == null - || !LanguageService.Instance.ScriptParseInfoMap.ContainsKey(textDocumentPosition.TextDocument.Uri)) + + ScriptParseInfo scriptParseInfo = GetScriptParseInfo(textDocumentPosition.TextDocument.Uri); + if (connInfo == null || scriptParseInfo == null) { return AutoCompleteHelper.GetDefaultCompletionItems(startLine, startColumn, endColumn); } // reparse and bind the SQL statement if needed - var scriptParseInfo = ScriptParseInfoMap[textDocumentPosition.TextDocument.Uri]; if (RequiresReparse(scriptParseInfo, scriptFile)) { ParseAndBind(scriptFile, connInfo); @@ -512,15 +532,18 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices try { // get the completion list from SQL Parser - var suggestions = Resolver.FindCompletions( + scriptParseInfo.CurrentSuggestions = Resolver.FindCompletions( scriptParseInfo.ParseResult, textDocumentPosition.Position.Line + 1, textDocumentPosition.Position.Character + 1, scriptParseInfo.MetadataDisplayInfoProvider); + // cache the current script parse info object to resolve completions later + this.currentCompletionParseInfo = scriptParseInfo; + // convert the suggestion list to the VS Code format return AutoCompleteHelper.ConvertDeclarationsToCompletionItems( - suggestions, + scriptParseInfo.CurrentSuggestions, startLine, startColumn, endColumn); @@ -686,5 +709,76 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices } #endregion + + private void AddOrUpdateScriptParseInfo(string uri, ScriptParseInfo scriptInfo) + { + lock (this.parseMapLock) + { + if (this.ScriptParseInfoMap.ContainsKey(uri)) + { + this.ScriptParseInfoMap[uri] = scriptInfo; + } + else + { + this.ScriptParseInfoMap.Add(uri, scriptInfo); + } + + } + } + + private ScriptParseInfo GetScriptParseInfo(string uri, bool createIfNotExists = false) + { + lock (this.parseMapLock) + { + if (this.ScriptParseInfoMap.ContainsKey(uri)) + { + return this.ScriptParseInfoMap[uri]; + } + else if (createIfNotExists) + { + ScriptParseInfo scriptInfo = new ScriptParseInfo(); + this.ScriptParseInfoMap.Add(uri, scriptInfo); + return scriptInfo; + } + else + { + return null; + } + } + } + + private bool RemoveScriptParseInfo(string uri) + { + lock (this.parseMapLock) + { + if (this.ScriptParseInfoMap.ContainsKey(uri)) + { + var scriptInfo = this.ScriptParseInfoMap[uri]; + scriptInfo.ServerConnection.Disconnect(); + scriptInfo.ServerConnection = null; + return this.ScriptParseInfoMap.Remove(uri); + } + else + { + return false; + } + } + } + + /// + /// Returns a flag indicating if the ScriptFile refers to the output window. + /// + /// + private bool IsPreviewWindow(ScriptFile scriptFile) + { + if (scriptFile != null && !string.IsNullOrWhiteSpace(scriptFile.ClientFilePath)) + { + return scriptFile.ClientFilePath.StartsWith("tsqloutput:"); + } + else + { + return false; + } + } } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/ScriptParseInfo.cs b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/ScriptParseInfo.cs index 48fb2cce..7dca96ab 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/ScriptParseInfo.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/ScriptParseInfo.cs @@ -3,14 +3,16 @@ // 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 Microsoft.SqlServer.Management.Common; using Microsoft.SqlServer.Management.SmoMetadataProvider; using Microsoft.SqlServer.Management.SqlParser.Binder; using Microsoft.SqlServer.Management.SqlParser.Common; +using Microsoft.SqlServer.Management.SqlParser.Intellisense; using Microsoft.SqlServer.Management.SqlParser.MetadataProvider; using Microsoft.SqlServer.Management.SqlParser.Parser; -using System; -using System.Threading; namespace Microsoft.SqlTools.ServiceLayer.LanguageServices { @@ -33,7 +35,6 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices get { return this.buildingMetadataEvent; } } - /// /// Gets or sets a flag determining is the LanguageService is connected /// @@ -56,7 +57,6 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices isQuotedIdentifierSet: true, compatibilityLevel: DatabaseCompatibilityLevel, transactSqlVersion: TransactSqlVersion); - this.IsConnected = true; } } @@ -143,6 +143,11 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices /// public MetadataDisplayInfoProvider MetadataDisplayInfoProvider { get; set; } + /// + /// Gets or sets the current autocomplete suggestion list + /// + public IEnumerable CurrentSuggestions { get; set; } + /// /// Gets the database compatibility level from a server version /// diff --git a/src/Microsoft.SqlTools.ServiceLayer/Program.cs b/src/Microsoft.SqlTools.ServiceLayer/Program.cs index 377afe9d..3e5a8655 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Program.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Program.cs @@ -2,7 +2,6 @@ // 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.Utility; using Microsoft.SqlTools.ServiceLayer.Hosting; using Microsoft.SqlTools.ServiceLayer.SqlContext; using Microsoft.SqlTools.ServiceLayer.Workspace; @@ -10,6 +9,7 @@ using Microsoft.SqlTools.ServiceLayer.LanguageServices; using Microsoft.SqlTools.ServiceLayer.Connection; using Microsoft.SqlTools.ServiceLayer.QueryExecution; using Microsoft.SqlTools.ServiceLayer.Credentials; +using Microsoft.SqlTools.ServiceLayer.Utility; namespace Microsoft.SqlTools.ServiceLayer { diff --git a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Batch.cs b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Batch.cs index 98e857ca..2c3781d5 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Batch.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Batch.cs @@ -10,10 +10,10 @@ using System.Data.SqlClient; using System.Linq; using System.Threading; using System.Threading.Tasks; -using Microsoft.SqlTools.EditorServices.Utility; using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection; using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts; using Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage; +using Microsoft.SqlTools.ServiceLayer.Utility; namespace Microsoft.SqlTools.ServiceLayer.QueryExecution { @@ -22,8 +22,6 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution /// public class Batch : IDisposable { - private const string RowsAffectedFormat = "({0} row(s) affected)"; - #region Member Variables /// @@ -160,8 +158,8 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution { // Create a message with the number of affected rows -- IF the query affects rows resultMessages.Add(reader.RecordsAffected >= 0 - ? string.Format(RowsAffectedFormat, reader.RecordsAffected) - : "Command(s) completed successfully."); + ? SR.QueryServiceAffectedRows(reader.RecordsAffected) + : SR.QueryServiceCompletedSuccessfully); continue; } @@ -173,7 +171,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution resultSets.Add(resultSet); // Add a message for the number of rows the query returned - resultMessages.Add(string.Format(RowsAffectedFormat, resultSet.RowCount)); + resultMessages.Add(SR.QueryServiceAffectedRows(reader.RecordsAffected)); } while (await reader.NextResultAsync(cancellationToken)); } } @@ -214,8 +212,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution // Sanity check to make sure we have valid numbers if (resultSetIndex < 0 || resultSetIndex >= resultSets.Count) { - throw new ArgumentOutOfRangeException(nameof(resultSetIndex), "Result set index cannot be less than 0" + - "or greater than the number of result sets"); + throw new ArgumentOutOfRangeException(nameof(resultSetIndex), SR.QueryServiceSubsetResultSetOutOfRange); } // Retrieve the result set @@ -256,9 +253,8 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution if (sqlError != null) { int lineNumber = sqlError.LineNumber + StartLine; - string message = String.Format("Msg {0}, Level {1}, State {2}, Line {3}{4}{5}", - sqlError.Number, sqlError.Class, sqlError.State, lineNumber, - Environment.NewLine, sqlError.Message); + string message = SR.QueryServiceErrorFormat(sqlError.Number, sqlError.Class, sqlError.State, + lineNumber, Environment.NewLine, sqlError.Message); resultMessages.Add(message); } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Contracts/DbColumnWrapper.cs b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Contracts/DbColumnWrapper.cs index d7d43248..7574a7de 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Contracts/DbColumnWrapper.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Contracts/DbColumnWrapper.cs @@ -195,8 +195,9 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts { get { - // TODO: Localize - return string.IsNullOrEmpty(internalColumn.ColumnName) ? "(No column name)" : internalColumn.ColumnName; + return string.IsNullOrEmpty(internalColumn.ColumnName) + ? SR.QueryServiceColumnNull + : internalColumn.ColumnName; } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/DataStorage/FileStreamWrapper.cs b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/DataStorage/FileStreamWrapper.cs index 3a6c3ecf..b8737cb9 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/DataStorage/FileStreamWrapper.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/DataStorage/FileStreamWrapper.cs @@ -6,6 +6,7 @@ using System; using System.Diagnostics; using System.IO; +using Microsoft.SqlTools.ServiceLayer.Utility; namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage { @@ -51,17 +52,11 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage public void Init(string fileName, int bufferLength, FileAccess accessMethod) { // Sanity check for valid buffer length, fileName, and accessMethod - if (bufferLength <= 0) - { - throw new ArgumentOutOfRangeException(nameof(bufferLength), "Buffer length must be a positive value"); - } - if (string.IsNullOrWhiteSpace(fileName)) - { - throw new ArgumentNullException(nameof(fileName), "File name cannot be null or whitespace"); - } + Validate.IsGreaterThan(nameof(bufferLength), bufferLength, 0); + Validate.IsNotNullOrEmptyString(nameof(fileName), fileName); if (accessMethod == FileAccess.Write) { - throw new ArgumentException("Access method cannot be write-only", nameof(fileName)); + throw new ArgumentException(SR.QueryServiceFileWrapperWriteOnly, nameof(fileName)); } // Setup the buffer @@ -95,7 +90,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage // Make sure that we're initialized before performing operations if (buffer == null) { - throw new InvalidOperationException("FileStreamWrapper must be initialized before performing operations"); + throw new InvalidOperationException(SR.QueryServiceFileWrapperNotInitialized); } MoveTo(offset); @@ -135,11 +130,11 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage // Make sure that we're initialized before performing operations if (buffer == null) { - throw new InvalidOperationException("FileStreamWrapper must be initialized before performing operations"); + throw new InvalidOperationException(SR.QueryServiceFileWrapperNotInitialized); } if (!fileStream.CanWrite) { - throw new InvalidOperationException("This FileStreamWrapper canot be used for writing"); + throw new InvalidOperationException(SR.QueryServiceFileWrapperReadOnly); } int bytesCopied = 0; @@ -172,11 +167,11 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage // Make sure that we're initialized before performing operations if (buffer == null) { - throw new InvalidOperationException("FileStreamWrapper must be initialized before performing operations"); + throw new InvalidOperationException(SR.QueryServiceFileWrapperNotInitialized); } if (!fileStream.CanWrite) { - throw new InvalidOperationException("This FileStreamWrapper cannot be used for writing"); + throw new InvalidOperationException(SR.QueryServiceFileWrapperReadOnly); } // Make sure we are at the right place in the file diff --git a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/DataStorage/ServiceBufferFileStreamReader.cs b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/DataStorage/ServiceBufferFileStreamReader.cs index b6c23349..9772744f 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/DataStorage/ServiceBufferFileStreamReader.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/DataStorage/ServiceBufferFileStreamReader.cs @@ -80,7 +80,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage // Workaround .NET bug, see sqlbu# 440643 and vswhidbey# 599834 // TODO: Is this workaround necessary for .NET Core? - if (colType == null && sqlVariantTypeResult.Value == "System.Data.SqlTypes.SqlSingle") + if (colType == null && sqlVariantTypeResult.Value == @"System.Data.SqlTypes.SqlSingle") { colType = typeof(SqlSingle); } diff --git a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/DataStorage/ServiceBufferFileStreamWriter.cs b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/DataStorage/ServiceBufferFileStreamWriter.cs index c978bade..dfc36487 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/DataStorage/ServiceBufferFileStreamWriter.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/DataStorage/ServiceBufferFileStreamWriter.cs @@ -10,6 +10,7 @@ using System.IO; using System.Linq; using System.Text; using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts; +using Microsoft.SqlTools.ServiceLayer.Utility; namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage { @@ -603,10 +604,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage /// Number of bytes used to store the string public int WriteString(string sVal) { - if (sVal == null) - { - throw new ArgumentNullException(nameof(sVal), "String to store must be non-null."); - } + Validate.IsNotNull(nameof(sVal), sVal); int iTotalLen; if (0 == sVal.Length) // special case of 0 length string @@ -640,10 +638,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage /// Number of bytes used to store the byte[] public int WriteBytes(byte[] bytesVal, int iLen) { - if (bytesVal == null) - { - throw new ArgumentNullException(nameof(bytesVal), "Byte array to store must be non-null."); - } + Validate.IsNotNull(nameof(bytesVal), bytesVal); int iTotalLen; if (0 == iLen) // special case of 0 length byte array "0x" diff --git a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/DataStorage/StorageDataReader.cs b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/DataStorage/StorageDataReader.cs index f63046b1..1e45d437 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/DataStorage/StorageDataReader.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/DataStorage/StorageDataReader.cs @@ -13,8 +13,8 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using System.Xml; -using Microsoft.SqlTools.EditorServices.Utility; using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts; +using Microsoft.SqlTools.ServiceLayer.Utility; namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage { @@ -135,7 +135,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage { if (maxNumBytesToReturn <= 0) { - throw new ArgumentOutOfRangeException(nameof(maxNumBytesToReturn), "Maximum number of bytes to return must be greater than zero."); + throw new ArgumentOutOfRangeException(nameof(maxNumBytesToReturn), SR.QueryServiceDataReaderByteCountInvalid); } //first, ask provider how much data it has and calculate the final # of bytes @@ -177,7 +177,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage { if (maxCharsToReturn <= 0) { - throw new ArgumentOutOfRangeException(nameof(maxCharsToReturn), "Maximum number of chars to return must be greater than zero"); + throw new ArgumentOutOfRangeException(nameof(maxCharsToReturn), SR.QueryServiceDataReaderCharCountInvalid); } //first, ask provider how much data it has and calculate the final # of chars @@ -221,37 +221,47 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage /// String public string GetXmlWithMaxCapacity(int iCol, int maxCharsToReturn) { - if (supportSqlXml) + if (maxCharsToReturn <= 0) { - SqlXml sm = GetSqlXml(iCol); - if (sm == null) - { - return null; - } + throw new ArgumentOutOfRangeException(nameof(maxCharsToReturn), SR.QueryServiceDataReaderXmlCountInvalid); + } - //this code is mostly copied from SqlClient implementation of returning value for XML data type - StringWriterWithMaxCapacity sw = new StringWriterWithMaxCapacity(null, maxCharsToReturn); - XmlWriterSettings writerSettings = new XmlWriterSettings - { - CloseOutput = false, - ConformanceLevel = ConformanceLevel.Fragment - }; - // don't close the memory stream - XmlWriter ww = XmlWriter.Create(sw, writerSettings); + // If we're not in SQL XML mode, just return the entire thing as a string + if (!supportSqlXml) + { + object o = GetValue(iCol); + return o?.ToString(); + } - XmlReader reader = sm.CreateReader(); + // We have SQL XML support, so write it properly + SqlXml sm = GetSqlXml(iCol); + if (sm == null) + { + return null; + } + + // Setup the writer so that we don't close the memory stream and can process fragments + // of XML + XmlWriterSettings writerSettings = new XmlWriterSettings + { + CloseOutput = false, // don't close the memory stream + ConformanceLevel = ConformanceLevel.Fragment + }; + + using (StringWriterWithMaxCapacity sw = new StringWriterWithMaxCapacity(null, maxCharsToReturn)) + using (XmlWriter ww = XmlWriter.Create(sw, writerSettings)) + using (XmlReader reader = sm.CreateReader()) + { reader.Read(); while (!reader.EOF) { ww.WriteNode(reader, true); } + ww.Flush(); return sw.ToString(); } - - object o = GetValue(iCol); - return o?.ToString(); } #endregion diff --git a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Query.cs b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Query.cs index 74193d8b..c4f49b2a 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Query.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Query.cs @@ -14,6 +14,7 @@ using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection; using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts; using Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage; using Microsoft.SqlTools.ServiceLayer.SqlContext; +using Microsoft.SqlTools.ServiceLayer.Utility; namespace Microsoft.SqlTools.ServiceLayer.QueryExecution { @@ -67,22 +68,10 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution public Query(string queryText, ConnectionInfo connection, QueryExecutionSettings settings, IFileStreamFactory outputFactory) { // Sanity check for input - if (string.IsNullOrEmpty(queryText)) - { - throw new ArgumentNullException(nameof(queryText), "Query text cannot be null"); - } - if (connection == null) - { - throw new ArgumentNullException(nameof(connection), "Connection cannot be null"); - } - if (settings == null) - { - throw new ArgumentNullException(nameof(settings), "Settings cannot be null"); - } - if (outputFactory == null) - { - throw new ArgumentNullException(nameof(outputFactory), "Output file factory cannot be null"); - } + Validate.IsNotNullOrEmptyString(nameof(queryText), queryText); + Validate.IsNotNull(nameof(connection), connection); + Validate.IsNotNull(nameof(settings), settings); + Validate.IsNotNull(nameof(outputFactory), outputFactory); // Initialize the internal state QueryText = queryText; @@ -165,7 +154,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution // Make sure that the query hasn't completed execution if (HasExecuted) { - throw new InvalidOperationException("The query has already completed, it cannot be cancelled."); + throw new InvalidOperationException(SR.QueryServiceCancelAlreadyCompleted); } // Issue the cancellation token for the query @@ -218,7 +207,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution SqlConnection conn = sender as SqlConnection; if (conn == null) { - throw new InvalidOperationException("Sender for OnInfoMessage event must be a SqlConnection"); + throw new InvalidOperationException(SR.QueryServiceMessageSenderNotSql); } foreach(SqlError error in args.Errors) @@ -244,14 +233,13 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution // Sanity check that the results are available if (!HasExecuted) { - throw new InvalidOperationException("The query has not completed, yet."); + throw new InvalidOperationException(SR.QueryServiceSubsetNotCompleted); } // Sanity check to make sure that the batch is within bounds if (batchIndex < 0 || batchIndex >= Batches.Length) { - throw new ArgumentOutOfRangeException(nameof(batchIndex), "Result set index cannot be less than 0" + - "or greater than the number of result sets"); + throw new ArgumentOutOfRangeException(nameof(batchIndex), SR.QueryServiceSubsetBatchOutOfRange); } return Batches[batchIndex].GetSubset(resultSetIndex, startRow, rowCount); diff --git a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/QueryExecutionService.cs b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/QueryExecutionService.cs index 24d4de09..5d4e1ad5 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/QueryExecutionService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/QueryExecutionService.cs @@ -149,7 +149,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution { await requestContext.SendResult(new QueryExecuteSubsetResult { - Message = "The requested query does not exist." + Message = SR.QueryServiceRequestsNoQuery }); return; } @@ -197,7 +197,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution { await requestContext.SendResult(new QueryDisposeResult { - Messages = "Failed to dispose query, ID not found." + Messages = SR.QueryServiceRequestsNoQuery }); return; } @@ -225,7 +225,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution { await requestContext.SendResult(new QueryCancelResult { - Messages = "Failed to cancel query, ID not found." + Messages = SR.QueryServiceRequestsNoQuery }); return; } @@ -239,7 +239,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution // It really shouldn't be possible to get to this scenario, but we'll cover it anyhow await requestContext.SendResult(new QueryCancelResult { - Messages = "Query successfully cancelled, failed to dispose query. ID not found." + Messages = SR.QueryServiceCancelDisposeFailed }); return; } @@ -272,7 +272,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution { await requestContext.SendResult(new SaveResultRequestResult { - Messages = "Failed to save results, ID not found." + Messages = SR.QueryServiceRequestsNoQuery }); return; } @@ -295,6 +295,9 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution await csvFile.WriteLineAsync( string.Join( ",", row.Select( field => SaveResults.EncodeCsvField((field != null) ? field.ToString(): string.Empty)))); } } + + // Successfully wrote file, send success result + await requestContext.SendResult(new SaveResultRequestResult { Messages = null }); } catch(Exception ex) { @@ -304,13 +307,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution File.Delete(saveParams.FilePath); } await requestContext.SendError(ex.Message); - return; } - await requestContext.SendResult(new SaveResultRequestResult - { - Messages = "Success" - }); - return; } /// @@ -361,6 +358,8 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution } jsonWriter.WriteEndArray(); } + + await requestContext.SendResult(new SaveResultRequestResult { Messages = null }); } catch(Exception ex) { @@ -370,13 +369,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution File.Delete(saveParams.FilePath); } await requestContext.SendError(ex.Message); - return; } - await requestContext.SendResult(new SaveResultRequestResult - { - Messages = "Success" - }); - return; } #endregion @@ -392,7 +385,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution { await requestContext.SendResult(new QueryExecuteResult { - Messages = "This editor is not connected to a database." + Messages = SR.QueryServiceQueryInvalidOwnerUri }); return null; } @@ -413,15 +406,14 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution { await requestContext.SendResult(new QueryExecuteResult { - Messages = "A query is already in progress for this editor session." + - "Please cancel this query or wait for its completion." + Messages = SR.QueryServiceQueryInProgress }); return null; } return newQuery; } - catch (ArgumentNullException ane) + catch (ArgumentException ane) { await requestContext.SendResult(new QueryExecuteResult { Messages = ane.Message }); return null; diff --git a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/ResultSet.cs b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/ResultSet.cs index 41978255..b4dd411d 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/ResultSet.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/ResultSet.cs @@ -64,10 +64,8 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution public ResultSet(DbDataReader reader, IFileStreamFactory factory) { // Sanity check to make sure we got a reader - if (reader == null) - { - throw new ArgumentNullException(nameof(reader), "Reader cannot be null"); - } + Validate.IsNotNull(nameof(reader), SR.QueryServiceResultSetReaderNull); + DataReader = new StorageDataReader(reader); // Initialize the storage @@ -134,18 +132,17 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution // Sanity check to make sure that the results have been read beforehand if (!hasBeenRead || fileStreamReader == null) { - throw new InvalidOperationException("Cannot read subset unless the results have been read from the server"); + throw new InvalidOperationException(SR.QueryServiceResultSetNotRead); } // Sanity check to make sure that the row and the row count are within bounds if (startRow < 0 || startRow >= RowCount) { - throw new ArgumentOutOfRangeException(nameof(startRow), "Start row cannot be less than 0 " + - "or greater than the number of rows in the resultset"); + throw new ArgumentOutOfRangeException(nameof(startRow), SR.QueryServiceResultSetStartRowOutOfRange); } if (rowCount <= 0) { - throw new ArgumentOutOfRangeException(nameof(rowCount), "Row count must be a positive integer"); + throw new ArgumentOutOfRangeException(nameof(rowCount), SR.QueryServiceResultSetRowCountOutOfRange); } return Task.Factory.StartNew(() => @@ -177,7 +174,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution // If we can initialize the columns using the column schema, use that if (!DataReader.DbDataReader.CanGetColumnSchema()) { - throw new InvalidOperationException("Could not retrieve column schema for result set."); + throw new InvalidOperationException(SR.QueryServiceResultSetNoColumnSchema); } Columns = DataReader.Columns; long currentFileOffset = 0; diff --git a/src/Microsoft.SqlTools.ServiceLayer/SqlContext/SqlToolsSettings.cs b/src/Microsoft.SqlTools.ServiceLayer/SqlContext/SqlToolsSettings.cs index e21dcb47..ccf3f3fe 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/SqlContext/SqlToolsSettings.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/SqlContext/SqlToolsSettings.cs @@ -1,5 +1,5 @@ using System.IO; -using Microsoft.SqlTools.EditorServices.Utility; +using Microsoft.SqlTools.ServiceLayer.Utility; namespace Microsoft.SqlTools.ServiceLayer.SqlContext { diff --git a/src/Microsoft.SqlTools.ServiceLayer/Utility/AsyncContext.cs b/src/Microsoft.SqlTools.ServiceLayer/Utility/AsyncContext.cs index c0baa889..79f2418f 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Utility/AsyncContext.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Utility/AsyncContext.cs @@ -7,7 +7,7 @@ using System; using System.Threading; using System.Threading.Tasks; -namespace Microsoft.SqlTools.EditorServices.Utility +namespace Microsoft.SqlTools.ServiceLayer.Utility { /// /// Simplifies the setup of a SynchronizationContext for the use diff --git a/src/Microsoft.SqlTools.ServiceLayer/Utility/AsyncContextThread.cs b/src/Microsoft.SqlTools.ServiceLayer/Utility/AsyncContextThread.cs index 7b7947a5..12e3f6fa 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Utility/AsyncContextThread.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Utility/AsyncContextThread.cs @@ -7,7 +7,7 @@ using System; using System.Threading; using System.Threading.Tasks; -namespace Microsoft.SqlTools.EditorServices.Utility +namespace Microsoft.SqlTools.ServiceLayer.Utility { /// /// Provides a simplified interface for creating a new thread diff --git a/src/Microsoft.SqlTools.ServiceLayer/Utility/AsyncLock.cs b/src/Microsoft.SqlTools.ServiceLayer/Utility/AsyncLock.cs index b12983ce..c8dbd49a 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Utility/AsyncLock.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Utility/AsyncLock.cs @@ -7,7 +7,7 @@ using System; using System.Threading; using System.Threading.Tasks; -namespace Microsoft.SqlTools.EditorServices.Utility +namespace Microsoft.SqlTools.ServiceLayer.Utility { /// /// Provides a simple wrapper over a SemaphoreSlim to allow diff --git a/src/Microsoft.SqlTools.ServiceLayer/Utility/AsyncQueue.cs b/src/Microsoft.SqlTools.ServiceLayer/Utility/AsyncQueue.cs index c899ee78..e71f8cec 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Utility/AsyncQueue.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Utility/AsyncQueue.cs @@ -8,7 +8,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace Microsoft.SqlTools.EditorServices.Utility +namespace Microsoft.SqlTools.ServiceLayer.Utility { /// /// Provides a synchronized queue which can be used from within async diff --git a/src/Microsoft.SqlTools.ServiceLayer/Utility/Extensions.cs b/src/Microsoft.SqlTools.ServiceLayer/Utility/Extensions.cs index c73bc03c..ba8a4750 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Utility/Extensions.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Utility/Extensions.cs @@ -5,7 +5,7 @@ using System; -namespace Microsoft.SqlTools.EditorServices.Utility +namespace Microsoft.SqlTools.ServiceLayer.Utility { internal static class ObjectExtensions { diff --git a/src/Microsoft.SqlTools.ServiceLayer/Utility/Logger.cs b/src/Microsoft.SqlTools.ServiceLayer/Utility/Logger.cs index ef785177..5c4adae4 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Utility/Logger.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Utility/Logger.cs @@ -9,7 +9,7 @@ using System.IO; using System.Runtime.CompilerServices; using System.Text; -namespace Microsoft.SqlTools.EditorServices.Utility +namespace Microsoft.SqlTools.ServiceLayer.Utility { /// /// Defines the level indicators for log messages. @@ -131,6 +131,7 @@ namespace Microsoft.SqlTools.EditorServices.Utility internal class LogWriter : IDisposable { + private object logLock = new object(); private TextWriter textWriter; private LogLevel minimumLogLevel = LogLevel.Verbose; @@ -170,24 +171,28 @@ namespace Microsoft.SqlTools.EditorServices.Utility if (this.textWriter != null && logLevel >= this.minimumLogLevel) { - // Print the timestamp and log level - this.textWriter.WriteLine( - "{0} [{1}] - Method \"{2}\" at line {3} of {4}\r\n", - DateTime.Now, - logLevel.ToString().ToUpper(), - callerName, - callerLineNumber, - callerSourceFile); - - // Print out indented message lines - foreach (var messageLine in logMessage.Split('\n')) + // System.IO is not thread safe + lock (this.logLock) { - this.textWriter.WriteLine(" " + messageLine.TrimEnd()); - } + // Print the timestamp and log level + this.textWriter.WriteLine( + "{0} [{1}] - Method \"{2}\" at line {3} of {4}\r\n", + DateTime.Now, + logLevel.ToString().ToUpper(), + callerName, + callerLineNumber, + callerSourceFile); - // Finish with a newline and flush the writer - this.textWriter.WriteLine(); - this.textWriter.Flush(); + // Print out indented message lines + foreach (var messageLine in logMessage.Split('\n')) + { + this.textWriter.WriteLine(" " + messageLine.TrimEnd()); + } + + // Finish with a newline and flush the writer + this.textWriter.WriteLine(); + this.textWriter.Flush(); + } } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/Utility/TextUtilities.cs b/src/Microsoft.SqlTools.ServiceLayer/Utility/TextUtilities.cs index 0da32040..0da84f43 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Utility/TextUtilities.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Utility/TextUtilities.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.Utility +namespace Microsoft.SqlTools.ServiceLayer.Utility { public static class TextUtilities { diff --git a/src/Microsoft.SqlTools.ServiceLayer/Utility/ThreadSynchronizationContext.cs b/src/Microsoft.SqlTools.ServiceLayer/Utility/ThreadSynchronizationContext.cs index 2389bbb0..7bd9a97d 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Utility/ThreadSynchronizationContext.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Utility/ThreadSynchronizationContext.cs @@ -7,7 +7,7 @@ using System; using System.Collections.Concurrent; using System.Threading; -namespace Microsoft.SqlTools.EditorServices.Utility +namespace Microsoft.SqlTools.ServiceLayer.Utility { /// /// Provides a SynchronizationContext implementation that can be used diff --git a/src/Microsoft.SqlTools.ServiceLayer/Utility/Validate.cs b/src/Microsoft.SqlTools.ServiceLayer/Utility/Validate.cs index 880716c1..77d1a13d 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Utility/Validate.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Utility/Validate.cs @@ -6,7 +6,7 @@ using System; using System.Collections.Generic; -namespace Microsoft.SqlTools.EditorServices.Utility +namespace Microsoft.SqlTools.ServiceLayer.Utility { /// /// Provides common validation methods to simplify method diff --git a/src/Microsoft.SqlTools.ServiceLayer/Workspace/Contracts/BufferRange.cs b/src/Microsoft.SqlTools.ServiceLayer/Workspace/Contracts/BufferRange.cs index f8253d02..7d96c49d 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Workspace/Contracts/BufferRange.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Workspace/Contracts/BufferRange.cs @@ -57,11 +57,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace.Contracts { if (start > end) { - throw new ArgumentException( - string.Format( - "Start position ({0}, {1}) must come before or be equal to the end position ({2}, {3}).", - start.Line, start.Column, - end.Line, end.Column)); + throw new ArgumentException(SR.WorkspaceServiceBufferPositionOutOfOrder(start.Line, start.Column, + end.Line, end.Column)); } this.Start = start; diff --git a/src/Microsoft.SqlTools.ServiceLayer/Workspace/Contracts/ScriptFile.cs b/src/Microsoft.SqlTools.ServiceLayer/Workspace/Contracts/ScriptFile.cs index 74592ae5..43f064e6 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Workspace/Contracts/ScriptFile.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Workspace/Contracts/ScriptFile.cs @@ -3,11 +3,11 @@ // 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.Linq; +using Microsoft.SqlTools.ServiceLayer.Utility; namespace Microsoft.SqlTools.ServiceLayer.Workspace.Contracts { @@ -230,7 +230,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace.Contracts { if (line < 1 || line > this.FileLines.Count + 1) { - throw new ArgumentOutOfRangeException("Position is outside of file line range."); + throw new ArgumentOutOfRangeException(nameof(line), SR.WorkspaceServicePositionLineOutOfRange); } // The maximum column is either one past the length of the string @@ -240,10 +240,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace.Contracts if (column < 1 || column > maxColumn) { - throw new ArgumentOutOfRangeException( - string.Format( - "Position is outside of column range for line {0}.", - line)); + throw new ArgumentOutOfRangeException(nameof(column), SR.WorkspaceServicePositionColumnOutOfRange(line)); } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/Workspace/Workspace.cs b/src/Microsoft.SqlTools.ServiceLayer/Workspace/Workspace.cs index 070337a7..80fe6a9f 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Workspace/Workspace.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Workspace/Workspace.cs @@ -9,7 +9,7 @@ using System.IO; using System.Text; using System.Text.RegularExpressions; using System.Linq; -using Microsoft.SqlTools.EditorServices.Utility; +using Microsoft.SqlTools.ServiceLayer.Utility; using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts; namespace Microsoft.SqlTools.ServiceLayer.Workspace diff --git a/src/Microsoft.SqlTools.ServiceLayer/Workspace/WorkspaceService.cs b/src/Microsoft.SqlTools.ServiceLayer/Workspace/WorkspaceService.cs index 0e5e4a25..c1fe5080 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Workspace/WorkspaceService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Workspace/WorkspaceService.cs @@ -8,9 +8,9 @@ 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.Utility; using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts; namespace Microsoft.SqlTools.ServiceLayer.Workspace diff --git a/src/Microsoft.SqlTools.ServiceLayer/sr.Designer.cs b/src/Microsoft.SqlTools.ServiceLayer/sr.Designer.cs new file mode 100644 index 00000000..50d8c09d --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/sr.Designer.cs @@ -0,0 +1,467 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Microsoft.SqlTools.ServiceLayer { + using System; + using System.Reflection; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class sr { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + internal sr() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.SqlTools.ServiceLayer.sr", typeof(sr).GetTypeInfo().Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Connection details object cannot be null. + /// + public static string ConnectionParamsValidateNullConnection { + get { + return ResourceManager.GetString("ConnectionParamsValidateNullConnection", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to OwnerUri cannot be null or empty. + /// + public static string ConnectionParamsValidateNullOwnerUri { + get { + return ResourceManager.GetString("ConnectionParamsValidateNullOwnerUri", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ServerName cannot be null or empty. + /// + public static string ConnectionParamsValidateNullServerName { + get { + return ResourceManager.GetString("ConnectionParamsValidateNullServerName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} cannot be null or empty when using SqlLogin authentication. + /// + public static string ConnectionParamsValidateNullSqlAuth { + get { + return ResourceManager.GetString("ConnectionParamsValidateNullSqlAuth", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Connection parameters cannot be null. + /// + public static string ConnectionServiceConnectErrorNullParams { + get { + return ResourceManager.GetString("ConnectionServiceConnectErrorNullParams", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid value '{0}' for AuthenticationType. Valid values are 'Integrated' and 'SqlLogin'.. + /// + public static string ConnectionServiceConnStringInvalidAuthType { + get { + return ResourceManager.GetString("ConnectionServiceConnStringInvalidAuthType", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid value '{0}' for ApplicationIntent. Valid values are 'ReadWrite' and 'ReadOnly'.. + /// + public static string ConnectionServiceConnStringInvalidIntent { + get { + return ResourceManager.GetString("ConnectionServiceConnStringInvalidIntent", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SpecifiedUri '{0}' does not have existing connection. + /// + public static string ConnectionServiceListDbErrorNotConnected { + get { + return ResourceManager.GetString("ConnectionServiceListDbErrorNotConnected", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to OwnerUri cannot be null or empty. + /// + public static string ConnectionServiceListDbErrorNullOwnerUri { + get { + return ResourceManager.GetString("ConnectionServiceListDbErrorNullOwnerUri", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Win32Credential object is already disposed. + /// + public static string CredentialServiceWin32CredentialDisposed { + get { + return ResourceManager.GetString("CredentialServiceWin32CredentialDisposed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid CriticalHandle!. + /// + public static string CredentialsServiceInvalidCriticalHandle { + get { + return ResourceManager.GetString("CredentialsServiceInvalidCriticalHandle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The password has exceeded 512 bytes. + /// + public static string CredentialsServicePasswordLengthExceeded { + get { + return ResourceManager.GetString("CredentialsServicePasswordLengthExceeded", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Target must be specified to delete a credential. + /// + public static string CredentialsServiceTargetForDelete { + get { + return ResourceManager.GetString("CredentialsServiceTargetForDelete", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Target must be specified to check existance of a credential. + /// + public static string CredentialsServiceTargetForLookup { + get { + return ResourceManager.GetString("CredentialsServiceTargetForLookup", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Message header must separate key and value using ':'. + /// + public static string HostingHeaderMissingColon { + get { + return ResourceManager.GetString("HostingHeaderMissingColon", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Fatal error: Content-Length header must be provided. + /// + public static string HostingHeaderMissingContentLengthHeader { + get { + return ResourceManager.GetString("HostingHeaderMissingContentLengthHeader", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Fatal error: Content-Length value is not an integer. + /// + public static string HostingHeaderMissingContentLengthValue { + get { + return ResourceManager.GetString("HostingHeaderMissingContentLengthValue", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to MessageReader's input stream ended unexpectedly, terminating. + /// + public static string HostingUnexpectedEndOfStream { + get { + return ResourceManager.GetString("HostingUnexpectedEndOfStream", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ({0} row(s) affected). + /// + public static string QueryServiceAffectedRows { + get { + return ResourceManager.GetString("QueryServiceAffectedRows", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The query has already completed, it cannot be cancelled. + /// + public static string QueryServiceCancelAlreadyCompleted { + get { + return ResourceManager.GetString("QueryServiceCancelAlreadyCompleted", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Query successfully cancelled, failed to dispose query. Owner URI not found.. + /// + public static string QueryServiceCancelDisposeFailed { + get { + return ResourceManager.GetString("QueryServiceCancelDisposeFailed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to (No column name). + /// + public static string QueryServiceColumnNull { + get { + return ResourceManager.GetString("QueryServiceColumnNull", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Command(s) copleted successfully.. + /// + public static string QueryServiceCompletedSuccessfully { + get { + return ResourceManager.GetString("QueryServiceCompletedSuccessfully", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Maximum number of bytes to return must be greater than zero. + /// + public static string QueryServiceDataReaderByteCountInvalid { + get { + return ResourceManager.GetString("QueryServiceDataReaderByteCountInvalid", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Maximum number of chars to return must be greater than zero. + /// + public static string QueryServiceDataReaderCharCountInvalid { + get { + return ResourceManager.GetString("QueryServiceDataReaderCharCountInvalid", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Maximum number of XML bytes to return must be greater than zero. + /// + public static string QueryServiceDataReaderXmlCountInvalid { + get { + return ResourceManager.GetString("QueryServiceDataReaderXmlCountInvalid", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Msg {0}, Level {1}, State {2}, Line {3}{4}{5}. + /// + public static string QueryServiceErrorFormat { + get { + return ResourceManager.GetString("QueryServiceErrorFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to FileStreamWrapper must be initialized before performing operations. + /// + public static string QueryServiceFileWrapperNotInitialized { + get { + return ResourceManager.GetString("QueryServiceFileWrapperNotInitialized", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This FileStreamWrapper cannot be used for writing. + /// + public static string QueryServiceFileWrapperReadOnly { + get { + return ResourceManager.GetString("QueryServiceFileWrapperReadOnly", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Access method cannot be write-only. + /// + public static string QueryServiceFileWrapperWriteOnly { + get { + return ResourceManager.GetString("QueryServiceFileWrapperWriteOnly", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sender for OnInfoMessage event must be a SqlConnection. + /// + public static string QueryServiceMessageSenderNotSql { + get { + return ResourceManager.GetString("QueryServiceMessageSenderNotSql", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A query is already in progress for this editor session. Please cancel this query or wait for its completion.. + /// + public static string QueryServiceQueryInProgress { + get { + return ResourceManager.GetString("QueryServiceQueryInProgress", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This editor is not connected to a database. + /// + public static string QueryServiceQueryInvalidOwnerUri { + get { + return ResourceManager.GetString("QueryServiceQueryInvalidOwnerUri", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The requested query does not exist. + /// + public static string QueryServiceRequestsNoQuery { + get { + return ResourceManager.GetString("QueryServiceRequestsNoQuery", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Could not retrieve column schema for result set. + /// + public static string QueryServiceResultSetNoColumnSchema { + get { + return ResourceManager.GetString("QueryServiceResultSetNoColumnSchema", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot read subset unless the results have been read from the server. + /// + public static string QueryServiceResultSetNotRead { + get { + return ResourceManager.GetString("QueryServiceResultSetNotRead", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Reader cannot be null. + /// + public static string QueryServiceResultSetReaderNull { + get { + return ResourceManager.GetString("QueryServiceResultSetReaderNull", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Row count must be a positive integer. + /// + public static string QueryServiceResultSetRowCountOutOfRange { + get { + return ResourceManager.GetString("QueryServiceResultSetRowCountOutOfRange", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Start row cannot be less than 0 or greater than the number of rows in the result set. + /// + public static string QueryServiceResultSetStartRowOutOfRange { + get { + return ResourceManager.GetString("QueryServiceResultSetStartRowOutOfRange", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Batch index cannot be less than 0 or greater than the number of batches. + /// + public static string QueryServiceSubsetBatchOutOfRange { + get { + return ResourceManager.GetString("QueryServiceSubsetBatchOutOfRange", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The query has not completed, yet. + /// + public static string QueryServiceSubsetNotCompleted { + get { + return ResourceManager.GetString("QueryServiceSubsetNotCompleted", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Result set index cannot be less than 0 or greater than the number of result sets. + /// + public static string QueryServiceSubsetResultSetOutOfRange { + get { + return ResourceManager.GetString("QueryServiceSubsetResultSetOutOfRange", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Start position ({0}, {1}) must come before or be equal to the end position ({2}, {3}). + /// + public static string WorkspaceServiceBufferPositionOutOfOrder { + get { + return ResourceManager.GetString("WorkspaceServiceBufferPositionOutOfOrder", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Position is outside of column range for line {0}. + /// + public static string WorkspaceServicePositionColumnOutOfRange { + get { + return ResourceManager.GetString("WorkspaceServicePositionColumnOutOfRange", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Position is outside of file line range. + /// + public static string WorkspaceServicePositionLineOutOfRange { + get { + return ResourceManager.GetString("WorkspaceServicePositionLineOutOfRange", resourceCulture); + } + } + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/sr.cs b/src/Microsoft.SqlTools.ServiceLayer/sr.cs new file mode 100644 index 00000000..3d484e62 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/sr.cs @@ -0,0 +1,551 @@ +// WARNING: +// This file was generated by the Microsoft DataWarehouse String Resource Tool 1.37.0.0 +// from information in sr.strings +// DO NOT MODIFY THIS FILE'S CONTENTS, THEY WILL BE OVERWRITTEN +// +namespace Microsoft.SqlTools.ServiceLayer +{ + using System; + using System.Reflection; + using System.Resources; + using System.Globalization; + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class SR + { + protected SR() + { } + + public static CultureInfo Culture + { + get + { + return Keys.Culture; + } + set + { + Keys.Culture = value; + } + } + + + public static string ConnectionServiceConnectErrorNullParams + { + get + { + return Keys.GetString(Keys.ConnectionServiceConnectErrorNullParams); + } + } + + public static string ConnectionServiceListDbErrorNullOwnerUri + { + get + { + return Keys.GetString(Keys.ConnectionServiceListDbErrorNullOwnerUri); + } + } + + public static string ConnectionParamsValidateNullOwnerUri + { + get + { + return Keys.GetString(Keys.ConnectionParamsValidateNullOwnerUri); + } + } + + public static string ConnectionParamsValidateNullConnection + { + get + { + return Keys.GetString(Keys.ConnectionParamsValidateNullConnection); + } + } + + public static string ConnectionParamsValidateNullServerName + { + get + { + return Keys.GetString(Keys.ConnectionParamsValidateNullServerName); + } + } + + public static string CredentialsServiceInvalidCriticalHandle + { + get + { + return Keys.GetString(Keys.CredentialsServiceInvalidCriticalHandle); + } + } + + public static string CredentialsServicePasswordLengthExceeded + { + get + { + return Keys.GetString(Keys.CredentialsServicePasswordLengthExceeded); + } + } + + public static string CredentialsServiceTargetForDelete + { + get + { + return Keys.GetString(Keys.CredentialsServiceTargetForDelete); + } + } + + public static string CredentialsServiceTargetForLookup + { + get + { + return Keys.GetString(Keys.CredentialsServiceTargetForLookup); + } + } + + public static string CredentialServiceWin32CredentialDisposed + { + get + { + return Keys.GetString(Keys.CredentialServiceWin32CredentialDisposed); + } + } + + public static string HostingUnexpectedEndOfStream + { + get + { + return Keys.GetString(Keys.HostingUnexpectedEndOfStream); + } + } + + public static string HostingHeaderMissingColon + { + get + { + return Keys.GetString(Keys.HostingHeaderMissingColon); + } + } + + public static string HostingHeaderMissingContentLengthHeader + { + get + { + return Keys.GetString(Keys.HostingHeaderMissingContentLengthHeader); + } + } + + public static string HostingHeaderMissingContentLengthValue + { + get + { + return Keys.GetString(Keys.HostingHeaderMissingContentLengthValue); + } + } + + public static string QueryServiceCancelAlreadyCompleted + { + get + { + return Keys.GetString(Keys.QueryServiceCancelAlreadyCompleted); + } + } + + public static string QueryServiceCancelDisposeFailed + { + get + { + return Keys.GetString(Keys.QueryServiceCancelDisposeFailed); + } + } + + public static string QueryServiceSubsetNotCompleted + { + get + { + return Keys.GetString(Keys.QueryServiceSubsetNotCompleted); + } + } + + public static string QueryServiceSubsetBatchOutOfRange + { + get + { + return Keys.GetString(Keys.QueryServiceSubsetBatchOutOfRange); + } + } + + public static string QueryServiceSubsetResultSetOutOfRange + { + get + { + return Keys.GetString(Keys.QueryServiceSubsetResultSetOutOfRange); + } + } + + public static string QueryServiceDataReaderByteCountInvalid + { + get + { + return Keys.GetString(Keys.QueryServiceDataReaderByteCountInvalid); + } + } + + public static string QueryServiceDataReaderCharCountInvalid + { + get + { + return Keys.GetString(Keys.QueryServiceDataReaderCharCountInvalid); + } + } + + public static string QueryServiceDataReaderXmlCountInvalid + { + get + { + return Keys.GetString(Keys.QueryServiceDataReaderXmlCountInvalid); + } + } + + public static string QueryServiceFileWrapperWriteOnly + { + get + { + return Keys.GetString(Keys.QueryServiceFileWrapperWriteOnly); + } + } + + public static string QueryServiceFileWrapperNotInitialized + { + get + { + return Keys.GetString(Keys.QueryServiceFileWrapperNotInitialized); + } + } + + public static string QueryServiceFileWrapperReadOnly + { + get + { + return Keys.GetString(Keys.QueryServiceFileWrapperReadOnly); + } + } + + public static string QueryServiceCompletedSuccessfully + { + get + { + return Keys.GetString(Keys.QueryServiceCompletedSuccessfully); + } + } + + public static string QueryServiceColumnNull + { + get + { + return Keys.GetString(Keys.QueryServiceColumnNull); + } + } + + public static string QueryServiceRequestsNoQuery + { + get + { + return Keys.GetString(Keys.QueryServiceRequestsNoQuery); + } + } + + public static string QueryServiceQueryInvalidOwnerUri + { + get + { + return Keys.GetString(Keys.QueryServiceQueryInvalidOwnerUri); + } + } + + public static string QueryServiceQueryInProgress + { + get + { + return Keys.GetString(Keys.QueryServiceQueryInProgress); + } + } + + public static string QueryServiceMessageSenderNotSql + { + get + { + return Keys.GetString(Keys.QueryServiceMessageSenderNotSql); + } + } + + public static string QueryServiceResultSetReaderNull + { + get + { + return Keys.GetString(Keys.QueryServiceResultSetReaderNull); + } + } + + public static string QueryServiceResultSetNotRead + { + get + { + return Keys.GetString(Keys.QueryServiceResultSetNotRead); + } + } + + public static string QueryServiceResultSetStartRowOutOfRange + { + get + { + return Keys.GetString(Keys.QueryServiceResultSetStartRowOutOfRange); + } + } + + public static string QueryServiceResultSetRowCountOutOfRange + { + get + { + return Keys.GetString(Keys.QueryServiceResultSetRowCountOutOfRange); + } + } + + public static string QueryServiceResultSetNoColumnSchema + { + get + { + return Keys.GetString(Keys.QueryServiceResultSetNoColumnSchema); + } + } + + public static string WorkspaceServicePositionLineOutOfRange + { + get + { + return Keys.GetString(Keys.WorkspaceServicePositionLineOutOfRange); + } + } + + public static string ConnectionServiceListDbErrorNotConnected(string uri) + { + return Keys.GetString(Keys.ConnectionServiceListDbErrorNotConnected, uri); + } + + public static string ConnectionServiceConnStringInvalidAuthType(string authType) + { + return Keys.GetString(Keys.ConnectionServiceConnStringInvalidAuthType, authType); + } + + public static string ConnectionServiceConnStringInvalidIntent(string intent) + { + return Keys.GetString(Keys.ConnectionServiceConnStringInvalidIntent, intent); + } + + public static string ConnectionParamsValidateNullSqlAuth(string component) + { + return Keys.GetString(Keys.ConnectionParamsValidateNullSqlAuth, component); + } + + public static string QueryServiceAffectedRows(int rows) + { + return Keys.GetString(Keys.QueryServiceAffectedRows, rows); + } + + public static string QueryServiceErrorFormat(int msg, int lvl, int state, int line, string newLine, string message) + { + return Keys.GetString(Keys.QueryServiceErrorFormat, msg, lvl, state, line, newLine, message); + } + + public static string WorkspaceServicePositionColumnOutOfRange(int line) + { + return Keys.GetString(Keys.WorkspaceServicePositionColumnOutOfRange, line); + } + + public static string WorkspaceServiceBufferPositionOutOfOrder(int sLine, int sCol, int eLine, int eCol) + { + return Keys.GetString(Keys.WorkspaceServiceBufferPositionOutOfOrder, sLine, sCol, eLine, eCol); + } + + [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class Keys + { + static ResourceManager resourceManager = new ResourceManager("Microsoft.SqlTools.ServiceLayer.SR", typeof(SR).GetTypeInfo().Assembly); + + static CultureInfo _culture = null; + + + public const string ConnectionServiceConnectErrorNullParams = "ConnectionServiceConnectErrorNullParams"; + + + public const string ConnectionServiceListDbErrorNullOwnerUri = "ConnectionServiceListDbErrorNullOwnerUri"; + + + public const string ConnectionServiceListDbErrorNotConnected = "ConnectionServiceListDbErrorNotConnected"; + + + public const string ConnectionServiceConnStringInvalidAuthType = "ConnectionServiceConnStringInvalidAuthType"; + + + public const string ConnectionServiceConnStringInvalidIntent = "ConnectionServiceConnStringInvalidIntent"; + + + public const string ConnectionParamsValidateNullOwnerUri = "ConnectionParamsValidateNullOwnerUri"; + + + public const string ConnectionParamsValidateNullConnection = "ConnectionParamsValidateNullConnection"; + + + public const string ConnectionParamsValidateNullServerName = "ConnectionParamsValidateNullServerName"; + + + public const string ConnectionParamsValidateNullSqlAuth = "ConnectionParamsValidateNullSqlAuth"; + + + public const string CredentialsServiceInvalidCriticalHandle = "CredentialsServiceInvalidCriticalHandle"; + + + public const string CredentialsServicePasswordLengthExceeded = "CredentialsServicePasswordLengthExceeded"; + + + public const string CredentialsServiceTargetForDelete = "CredentialsServiceTargetForDelete"; + + + public const string CredentialsServiceTargetForLookup = "CredentialsServiceTargetForLookup"; + + + public const string CredentialServiceWin32CredentialDisposed = "CredentialServiceWin32CredentialDisposed"; + + + public const string HostingUnexpectedEndOfStream = "HostingUnexpectedEndOfStream"; + + + public const string HostingHeaderMissingColon = "HostingHeaderMissingColon"; + + + public const string HostingHeaderMissingContentLengthHeader = "HostingHeaderMissingContentLengthHeader"; + + + public const string HostingHeaderMissingContentLengthValue = "HostingHeaderMissingContentLengthValue"; + + + public const string QueryServiceCancelAlreadyCompleted = "QueryServiceCancelAlreadyCompleted"; + + + public const string QueryServiceCancelDisposeFailed = "QueryServiceCancelDisposeFailed"; + + + public const string QueryServiceSubsetNotCompleted = "QueryServiceSubsetNotCompleted"; + + + public const string QueryServiceSubsetBatchOutOfRange = "QueryServiceSubsetBatchOutOfRange"; + + + public const string QueryServiceSubsetResultSetOutOfRange = "QueryServiceSubsetResultSetOutOfRange"; + + + public const string QueryServiceDataReaderByteCountInvalid = "QueryServiceDataReaderByteCountInvalid"; + + + public const string QueryServiceDataReaderCharCountInvalid = "QueryServiceDataReaderCharCountInvalid"; + + + public const string QueryServiceDataReaderXmlCountInvalid = "QueryServiceDataReaderXmlCountInvalid"; + + + public const string QueryServiceFileWrapperWriteOnly = "QueryServiceFileWrapperWriteOnly"; + + + public const string QueryServiceFileWrapperNotInitialized = "QueryServiceFileWrapperNotInitialized"; + + + public const string QueryServiceFileWrapperReadOnly = "QueryServiceFileWrapperReadOnly"; + + + public const string QueryServiceAffectedRows = "QueryServiceAffectedRows"; + + + public const string QueryServiceCompletedSuccessfully = "QueryServiceCompletedSuccessfully"; + + + public const string QueryServiceErrorFormat = "QueryServiceErrorFormat"; + + + public const string QueryServiceColumnNull = "QueryServiceColumnNull"; + + + public const string QueryServiceRequestsNoQuery = "QueryServiceRequestsNoQuery"; + + + public const string QueryServiceQueryInvalidOwnerUri = "QueryServiceQueryInvalidOwnerUri"; + + + public const string QueryServiceQueryInProgress = "QueryServiceQueryInProgress"; + + + public const string QueryServiceMessageSenderNotSql = "QueryServiceMessageSenderNotSql"; + + + public const string QueryServiceResultSetReaderNull = "QueryServiceResultSetReaderNull"; + + + public const string QueryServiceResultSetNotRead = "QueryServiceResultSetNotRead"; + + + public const string QueryServiceResultSetStartRowOutOfRange = "QueryServiceResultSetStartRowOutOfRange"; + + + public const string QueryServiceResultSetRowCountOutOfRange = "QueryServiceResultSetRowCountOutOfRange"; + + + public const string QueryServiceResultSetNoColumnSchema = "QueryServiceResultSetNoColumnSchema"; + + + public const string WorkspaceServicePositionLineOutOfRange = "WorkspaceServicePositionLineOutOfRange"; + + + public const string WorkspaceServicePositionColumnOutOfRange = "WorkspaceServicePositionColumnOutOfRange"; + + + public const string WorkspaceServiceBufferPositionOutOfOrder = "WorkspaceServiceBufferPositionOutOfOrder"; + + + private Keys() + { } + + public static CultureInfo Culture + { + get + { + return _culture; + } + set + { + _culture = value; + } + } + + public static string GetString(string key) + { + return resourceManager.GetString(key, _culture); + } + + + public static string GetString(string key, object arg0) + { + return string.Format(global::System.Globalization.CultureInfo.CurrentCulture, resourceManager.GetString(key, _culture), arg0); + } + + + public static string GetString(string key, object arg0, object arg1, object arg2, object arg3) + { + return string.Format(global::System.Globalization.CultureInfo.CurrentCulture, resourceManager.GetString(key, _culture), arg0, arg1, arg2, arg3); + } + + + public static string GetString(string key, object arg0, object arg1, object arg2, object arg3, object arg4, object arg5) + { + return string.Format(global::System.Globalization.CultureInfo.CurrentCulture, resourceManager.GetString(key, _culture), arg0, arg1, arg2, arg3, arg4, arg5); + } + + } + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/sr.resx b/src/Microsoft.SqlTools.ServiceLayer/sr.resx new file mode 100644 index 00000000..c83b9a1c --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/sr.resx @@ -0,0 +1,308 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Connection parameters cannot be null + + + + OwnerUri cannot be null or empty + + + + SpecifiedUri '{0}' does not have existing connection + . + Parameters: 0 - uri (string) + + + Invalid value '{0}' for AuthenticationType. Valid values are 'Integrated' and 'SqlLogin'. + . + Parameters: 0 - authType (string) + + + Invalid value '{0}' for ApplicationIntent. Valid values are 'ReadWrite' and 'ReadOnly'. + . + Parameters: 0 - intent (string) + + + OwnerUri cannot be null or empty + + + + Connection details object cannot be null + + + + ServerName cannot be null or empty + + + + {0} cannot be null or empty when using SqlLogin authentication + . + Parameters: 0 - component (string) + + + Invalid CriticalHandle! + + + + The password has exceeded 512 bytes + + + + Target must be specified to delete a credential + + + + Target must be specified to check existance of a credential + + + + Win32Credential object is already disposed + + + + MessageReader's input stream ended unexpectedly, terminating + + + + Message header must separate key and value using ':' + + + + Fatal error: Content-Length header must be provided + + + + Fatal error: Content-Length value is not an integer + + + + The query has already completed, it cannot be cancelled + + + + Query successfully cancelled, failed to dispose query. Owner URI not found. + + + + The query has not completed, yet + + + + Batch index cannot be less than 0 or greater than the number of batches + + + + Result set index cannot be less than 0 or greater than the number of result sets + + + + Maximum number of bytes to return must be greater than zero + + + + Maximum number of chars to return must be greater than zero + + + + Maximum number of XML bytes to return must be greater than zero + + + + Access method cannot be write-only + + + + FileStreamWrapper must be initialized before performing operations + + + + This FileStreamWrapper cannot be used for writing + + + + ({0} row(s) affected) + . + Parameters: 0 - rows (int) + + + Command(s) copleted successfully. + + + + Msg {0}, Level {1}, State {2}, Line {3}{4}{5} + . + Parameters: 0 - msg (int), 1 - lvl (int), 2 - state (int), 3 - line (int), 4 - newLine (string), 5 - message (string) + + + (No column name) + + + + The requested query does not exist + + + + This editor is not connected to a database + + + + A query is already in progress for this editor session. Please cancel this query or wait for its completion. + + + + Sender for OnInfoMessage event must be a SqlConnection + + + + Reader cannot be null + + + + Cannot read subset unless the results have been read from the server + + + + Start row cannot be less than 0 or greater than the number of rows in the result set + + + + Row count must be a positive integer + + + + Could not retrieve column schema for result set + + + + Position is outside of file line range + + + + Position is outside of column range for line {0} + . + Parameters: 0 - line (int) + + + Start position ({0}, {1}) must come before or be equal to the end position ({2}, {3}) + . + Parameters: 0 - sLine (int), 1 - sCol (int), 2 - eLine (int), 3 - eCol (int) + + diff --git a/src/Microsoft.SqlTools.ServiceLayer/sr.strings b/src/Microsoft.SqlTools.ServiceLayer/sr.strings new file mode 100644 index 00000000..444e0af8 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/sr.strings @@ -0,0 +1,141 @@ +# String resource file +# +# When processed by the String Resource Tool, this file generates +# both a .CS and a .RESX file with the same name as the file. +# The .CS file contains a class which can be used to access these +# string resources, including the ability to format in +# parameters, which are identified with the .NET {x} format +# (see String.Format help). +# +# Comments below assume the file name is SR.strings. +# +# Lines starting with a semicolon ";" are also treated as comments, but +# in a future version they will be extracted and made available in LocStudio +# Put your comments to localizers _before_ the string they apply to. +# +# SMO build specific comment +# after generating the .resx file, run srgen on it and get the .resx file +# please remember to also check that .resx in, along with the +# .strings and .cs files + +[strings] + +############################################################################ +# Connection Service + +ConnectionServiceConnectErrorNullParams = Connection parameters cannot be null + +ConnectionServiceListDbErrorNullOwnerUri = OwnerUri cannot be null or empty + +ConnectionServiceListDbErrorNotConnected(string uri) = SpecifiedUri '{0}' does not have existing connection + +ConnectionServiceConnStringInvalidAuthType(string authType) = Invalid value '{0}' for AuthenticationType. Valid values are 'Integrated' and 'SqlLogin'. + +ConnectionServiceConnStringInvalidIntent(string intent) = Invalid value '{0}' for ApplicationIntent. Valid values are 'ReadWrite' and 'ReadOnly'. + +###### +### Connection Params Validation Errors + +ConnectionParamsValidateNullOwnerUri = OwnerUri cannot be null or empty + +ConnectionParamsValidateNullConnection = Connection details object cannot be null + +ConnectionParamsValidateNullServerName = ServerName cannot be null or empty + +ConnectionParamsValidateNullSqlAuth(string component) = {0} cannot be null or empty when using SqlLogin authentication + +############################################################################ +# Credentials Service + +CredentialsServiceInvalidCriticalHandle = Invalid CriticalHandle! + +CredentialsServicePasswordLengthExceeded = The password has exceeded 512 bytes + +CredentialsServiceTargetForDelete = Target must be specified to delete a credential + +CredentialsServiceTargetForLookup = Target must be specified to check existance of a credential + +CredentialServiceWin32CredentialDisposed = Win32Credential object is already disposed + +############################################################################ +# Hosting + +HostingUnexpectedEndOfStream = MessageReader's input stream ended unexpectedly, terminating + +HostingHeaderMissingColon = Message header must separate key and value using ':' + +HostingHeaderMissingContentLengthHeader = Fatal error: Content-Length header must be provided + +HostingHeaderMissingContentLengthValue = Fatal error: Content-Length value is not an integer + +############################################################################ +# Query Execution Service + +### Cancel Request + +QueryServiceCancelAlreadyCompleted = The query has already completed, it cannot be cancelled + +QueryServiceCancelDisposeFailed = Query successfully cancelled, failed to dispose query. Owner URI not found. + +### Subset Request + +QueryServiceSubsetNotCompleted = The query has not completed, yet + +QueryServiceSubsetBatchOutOfRange = Batch index cannot be less than 0 or greater than the number of batches + +QueryServiceSubsetResultSetOutOfRange = Result set index cannot be less than 0 or greater than the number of result sets + +### Data Reader Exceptions + +QueryServiceDataReaderByteCountInvalid = Maximum number of bytes to return must be greater than zero + +QueryServiceDataReaderCharCountInvalid = Maximum number of chars to return must be greater than zero + +QueryServiceDataReaderXmlCountInvalid = Maximum number of XML bytes to return must be greater than zero + +### File Stream Wrapper Exceptions + +QueryServiceFileWrapperWriteOnly = Access method cannot be write-only + +QueryServiceFileWrapperNotInitialized = FileStreamWrapper must be initialized before performing operations + +QueryServiceFileWrapperReadOnly = This FileStreamWrapper cannot be used for writing + +### Query Request + +QueryServiceAffectedRows(int rows) = ({0} row(s) affected) + +QueryServiceCompletedSuccessfully = Command(s) copleted successfully. + +QueryServiceErrorFormat(int msg, int lvl, int state, int line, string newLine, string message) = Msg {0}, Level {1}, State {2}, Line {3}{4}{5} + +QueryServiceColumnNull = (No column name) + +QueryServiceRequestsNoQuery = The requested query does not exist + +QueryServiceQueryInvalidOwnerUri = This editor is not connected to a database + +QueryServiceQueryInProgress = A query is already in progress for this editor session. Please cancel this query or wait for its completion. + +QueryServiceMessageSenderNotSql = Sender for OnInfoMessage event must be a SqlConnection + +QueryServiceResultSetReaderNull = Reader cannot be null + +### MSC + +QueryServiceResultSetNotRead = Cannot read subset unless the results have been read from the server + +QueryServiceResultSetStartRowOutOfRange = Start row cannot be less than 0 or greater than the number of rows in the result set + +QueryServiceResultSetRowCountOutOfRange = Row count must be a positive integer + +QueryServiceResultSetNoColumnSchema = Could not retrieve column schema for result set + +############################################################################ +# Workspace Service + +WorkspaceServicePositionLineOutOfRange = Position is outside of file line range + +WorkspaceServicePositionColumnOutOfRange(int line) = Position is outside of column range for line {0} + +WorkspaceServiceBufferPositionOutOfOrder(int sLine, int sCol, int eLine, int eCol) = Start position ({0}, {1}) must come before or be equal to the end position ({2}, {3}) \ No newline at end of file diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test/Connection/ConnectionServiceTests.cs b/test/Microsoft.SqlTools.ServiceLayer.Test/Connection/ConnectionServiceTests.cs index 07c202cb..82b5aca3 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.Test/Connection/ConnectionServiceTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.Test/Connection/ConnectionServiceTests.cs @@ -138,8 +138,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Connection // register disconnect callback connectionService.RegisterOnDisconnectTask( - (result) => { + (result, uri) => { callbackInvoked = true; + Assert.True(uri.Equals(ownerUri)); return Task.FromResult(true); } ); @@ -433,8 +434,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Connection // register disconnect callback connectionService.RegisterOnDisconnectTask( - (result) => { + (result, uri) => { callbackInvoked = true; + Assert.True(uri.Equals(ownerUri)); return Task.FromResult(true); } ); diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test/LanguageServer/LanguageServiceTests.cs b/test/Microsoft.SqlTools.ServiceLayer.Test/LanguageServer/LanguageServiceTests.cs index bb07c56a..34f7e405 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.Test/LanguageServer/LanguageServiceTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.Test/LanguageServer/LanguageServiceTests.cs @@ -21,9 +21,13 @@ using Microsoft.SqlServer.Management.SqlParser.MetadataProvider; using Microsoft.SqlServer.Management.SqlParser.Parser; using Microsoft.SqlTools.ServiceLayer.Connection; using Microsoft.SqlTools.ServiceLayer.Connection.Contracts; +using Microsoft.SqlTools.ServiceLayer.Credentials; using Microsoft.SqlTools.ServiceLayer.LanguageServices; +using Microsoft.SqlTools.ServiceLayer.QueryExecution; +using Microsoft.SqlTools.ServiceLayer.SqlContext; using Microsoft.SqlTools.ServiceLayer.Test.QueryExecution; using Microsoft.SqlTools.ServiceLayer.Test.Utility; +using Microsoft.SqlTools.ServiceLayer.Workspace; using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts; using Microsoft.SqlTools.Test.Utility; using Moq; @@ -148,6 +152,150 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices #endregion + #region "General Language Service tests" + + /// + /// Check that autocomplete is enabled by default + /// + [Fact] + public void CheckAutocompleteEnabledByDefault() + { + // get test service + LanguageService service = TestObjects.GetTestLanguageService(); + Assert.True(service.ShouldEnableAutocomplete()); + } + + /// + /// Test the service initialization code path and verify nothing throws + /// + [Fact] + public void ServiceInitiailzation() + { + InitializeTestServices(); + + Assert.True(LanguageService.Instance.Context != null); + Assert.True(LanguageService.Instance.ConnectionServiceInstance != null); + Assert.True(LanguageService.Instance.CurrentSettings != null); + Assert.True(LanguageService.Instance.CurrentWorkspace != null); + + LanguageService.Instance.ConnectionServiceInstance = null; + Assert.True(LanguageService.Instance.ConnectionServiceInstance == null); + } + + /// + /// Test the service initialization code path and verify nothing throws + /// + [Fact] + public void UpdateLanguageServiceOnConnection() + { + string ownerUri = "file://my/sample/file.sql"; + var connectionService = TestObjects.GetTestConnectionService(); + var connectionResult = + connectionService + .Connect(new ConnectParams() + { + OwnerUri = ownerUri, + Connection = TestObjects.GetTestConnectionDetails() + }); + + ConnectionInfo connInfo = null; + connectionService.TryFindConnection(ownerUri, out connInfo); + + var task = LanguageService.Instance.UpdateLanguageServiceOnConnection(connInfo); + task.Wait(); + } + + /// + /// Test the service initialization code path and verify nothing throws + /// + [Fact] + public void PrepopulateCommonMetadata() + { + InitializeTestServices(); + + string sqlFilePath = GetTestSqlFile(); + ScriptFile scriptFile = WorkspaceService.Instance.Workspace.GetFile(sqlFilePath); + + string ownerUri = scriptFile.ClientFilePath; + var connectionService = TestObjects.GetTestConnectionService(); + var connectionResult = + connectionService + .Connect(new ConnectParams() + { + OwnerUri = ownerUri, + Connection = TestObjects.GetTestConnectionDetails() + }); + + ConnectionInfo connInfo = null; + connectionService.TryFindConnection(ownerUri, out connInfo); + + ScriptParseInfo scriptInfo = new ScriptParseInfo(); + scriptInfo.IsConnected = true; + + AutoCompleteHelper.PrepopulateCommonMetadata(connInfo, scriptInfo); + } + + private string GetTestSqlFile() + { + string filePath = Path.Combine( + Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), + "sqltest.sql"); + + if (File.Exists(filePath)) + { + File.Delete(filePath); + } + + File.WriteAllText(filePath, "SELECT * FROM sys.objects\n"); + + return filePath; + } + + private void InitializeTestServices() + { + const string hostName = "SQL Tools Service Host"; + const string hostProfileId = "SQLToolsService"; + 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); + + // Grab the instance of the service host + Hosting.ServiceHost serviceHost = Hosting.ServiceHost.Instance; + + // Start the service + serviceHost.Start().Wait(); + + // Initialize the services that will be hosted here + WorkspaceService.Instance.InitializeService(serviceHost); + LanguageService.Instance.InitializeService(serviceHost, sqlToolsContext); + ConnectionService.Instance.InitializeService(serviceHost); + CredentialService.Instance.InitializeService(serviceHost); + QueryExecutionService.Instance.InitializeService(serviceHost); + + serviceHost.Initialize(); + } + + private Hosting.ServiceHost GetTestServiceHost() + { + // set up the host details and profile paths + var hostDetails = new HostDetails("Test Service Host", "SQLToolsService", new Version(1,0)); + var profilePaths = new ProfilePaths("SQLToolsService", "baseAllUsersPath", "baseCurrentUserPath"); + SqlToolsContext context = new SqlToolsContext(hostDetails, profilePaths); + + // Grab the instance of the service host + Hosting.ServiceHost host = Hosting.ServiceHost.Instance; + + // Start the service + host.Start().Wait(); + + return host; + } + + #endregion + #region "Autocomplete Tests" // This test currently requires a live database connection to initialize diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test/QueryExecution/DataStorage/FileStreamWrapperTests.cs b/test/Microsoft.SqlTools.ServiceLayer.Test/QueryExecution/DataStorage/FileStreamWrapperTests.cs index 5911c577..1ee471fd 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.Test/QueryExecution/DataStorage/FileStreamWrapperTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.Test/QueryExecution/DataStorage/FileStreamWrapperTests.cs @@ -26,7 +26,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution.DataStorage // ... It should throw an argument null exception using (FileStreamWrapper fsw = new FileStreamWrapper()) { - Assert.Throws(() => fsw.Init(fileName, 8192, FileAccess.Read)); + Assert.Throws(() => fsw.Init(fileName, 8192, FileAccess.Read)); } } diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test/QueryExecution/ExecuteTests.cs b/test/Microsoft.SqlTools.ServiceLayer.Test/QueryExecution/ExecuteTests.cs index bda6ca0d..868b9b86 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.Test/QueryExecution/ExecuteTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.Test/QueryExecution/ExecuteTests.cs @@ -229,7 +229,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution // ... I create a query that has a null query text // Then: // ... It should throw an exception - Assert.Throws(() => + Assert.Throws(() => new Query(null, Common.CreateTestConnectionInfo(null, false), new QueryExecutionSettings(), Common.GetFileStreamFactory())); } diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test/QueryExecution/SaveResultsTests.cs b/test/Microsoft.SqlTools.ServiceLayer.Test/QueryExecution/SaveResultsTests.cs index b359705a..99e77f5d 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.Test/QueryExecution/SaveResultsTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.Test/QueryExecution/SaveResultsTests.cs @@ -32,16 +32,21 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution queryService.HandleExecuteRequest(executeParams, executeRequest.Object).Wait(); // Request to save the results as csv with correct parameters - var saveParams = new SaveResultsAsCsvRequestParams { OwnerUri = Common.OwnerUri, ResultSetIndex = 0, BatchIndex = 0 }; - saveParams.FilePath = "testwrite.csv"; - saveParams.IncludeHeaders = true; + var saveParams = new SaveResultsAsCsvRequestParams + { + OwnerUri = Common.OwnerUri, + ResultSetIndex = 0, + BatchIndex = 0, + FilePath = "testwrite_1.csv", + IncludeHeaders = true + }; SaveResultRequestResult result = null; var saveRequest = GetSaveResultsContextMock(qcr => result = qcr, null); queryService.ActiveQueries[Common.OwnerUri].Batches[0] = Common.GetBasicExecutedBatch(); queryService.HandleSaveResultsAsCsvRequest(saveParams, saveRequest.Object).Wait(); // Expect to see a file successfully created in filepath and a success message - Assert.Equal("Success", result.Messages); + Assert.Null(result.Messages); Assert.True(File.Exists(saveParams.FilePath)); VerifySaveResultsCallCount(saveRequest, Times.Once(), Times.Never()); @@ -65,15 +70,13 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution queryService.HandleExecuteRequest(executeParams, executeRequest.Object).Wait(); // Request to save the results as csv with incorrect filepath - var saveParams = new SaveResultsAsCsvRequestParams { OwnerUri = Common.OwnerUri, ResultSetIndex = 0, BatchIndex = 0 }; - if (RuntimeInformation.IsOSPlatform( OSPlatform.Windows)) + var saveParams = new SaveResultsAsCsvRequestParams { - saveParams.FilePath = "G:\\test.csv"; - } - else - { - saveParams.FilePath = "/test.csv"; - } + OwnerUri = Common.OwnerUri, + ResultSetIndex = 0, + BatchIndex = 0, + FilePath = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "G:\\test.csv" : "/test.csv" + }; // SaveResultRequestResult result = null; string errMessage = null; var saveRequest = GetSaveResultsContextMock( null, err => errMessage = (string) err); @@ -99,14 +102,19 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution queryService.HandleExecuteRequest(executeParams, executeRequest.Object).Wait(); // Request to save the results as csv with query that is no longer active - var saveParams = new SaveResultsAsCsvRequestParams { OwnerUri = "falseuri", ResultSetIndex = 0, BatchIndex = 0 }; - saveParams.FilePath = "testwrite.csv"; + var saveParams = new SaveResultsAsCsvRequestParams + { + OwnerUri = "falseuri", + ResultSetIndex = 0, + BatchIndex = 0, + FilePath = "testwrite_3.csv" + }; SaveResultRequestResult result = null; var saveRequest = GetSaveResultsContextMock(qcr => result = qcr, null); queryService.HandleSaveResultsAsCsvRequest(saveParams, saveRequest.Object).Wait(); // Expect message that save failed - Assert.Equal("Failed to save results, ID not found.", result.Messages); + Assert.NotNull(result.Messages); Assert.False(File.Exists(saveParams.FilePath)); VerifySaveResultsCallCount(saveRequest, Times.Once(), Times.Never()); } @@ -124,15 +132,20 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution queryService.HandleExecuteRequest(executeParams, executeRequest.Object).Wait(); // Request to save the results as json with correct parameters - var saveParams = new SaveResultsAsJsonRequestParams { OwnerUri = Common.OwnerUri, ResultSetIndex = 0, BatchIndex = 0 }; - saveParams.FilePath = "testwrite.json"; + var saveParams = new SaveResultsAsJsonRequestParams + { + OwnerUri = Common.OwnerUri, + ResultSetIndex = 0, + BatchIndex = 0, + FilePath = "testwrite_4.json" + }; SaveResultRequestResult result = null; var saveRequest = GetSaveResultsContextMock(qcr => result = qcr, null); queryService.ActiveQueries[Common.OwnerUri].Batches[0] = Common.GetBasicExecutedBatch(); queryService.HandleSaveResultsAsJsonRequest(saveParams, saveRequest.Object).Wait(); // Expect to see a file successfully created in filepath and a success message - Assert.Equal("Success", result.Messages); + Assert.Null(result.Messages); Assert.True(File.Exists(saveParams.FilePath)); VerifySaveResultsCallCount(saveRequest, Times.Once(), Times.Never()); @@ -156,15 +169,13 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution queryService.HandleExecuteRequest(executeParams, executeRequest.Object).Wait(); // Request to save the results as json with incorrect filepath - var saveParams = new SaveResultsAsJsonRequestParams { OwnerUri = Common.OwnerUri, ResultSetIndex = 0, BatchIndex = 0 }; - if (RuntimeInformation.IsOSPlatform( OSPlatform.Windows)) + var saveParams = new SaveResultsAsJsonRequestParams { - saveParams.FilePath = "G:\\test.json"; - } - else - { - saveParams.FilePath = "/test.json"; - } + OwnerUri = Common.OwnerUri, + ResultSetIndex = 0, + BatchIndex = 0, + FilePath = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "G:\\test.json" : "/test.json" + }; // SaveResultRequestResult result = null; string errMessage = null; var saveRequest = GetSaveResultsContextMock( null, err => errMessage = (string) err); @@ -190,8 +201,13 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution queryService.HandleExecuteRequest(executeParams, executeRequest.Object).Wait(); // Request to save the results as json with query that is no longer active - var saveParams = new SaveResultsAsJsonRequestParams { OwnerUri = "falseuri", ResultSetIndex = 0, BatchIndex = 0 }; - saveParams.FilePath = "testwrite.json"; + var saveParams = new SaveResultsAsJsonRequestParams + { + OwnerUri = "falseuri", + ResultSetIndex = 0, + BatchIndex = 0, + FilePath = "testwrite_6.json" + }; SaveResultRequestResult result = null; var saveRequest = GetSaveResultsContextMock(qcr => result = qcr, null); queryService.HandleSaveResultsAsJsonRequest(saveParams, saveRequest.Object).Wait(); diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test/ServiceHost/LoggerTests.cs b/test/Microsoft.SqlTools.ServiceLayer.Test/ServiceHost/LoggerTests.cs index c5ea101a..6ee303f7 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.Test/ServiceHost/LoggerTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.Test/ServiceHost/LoggerTests.cs @@ -5,7 +5,7 @@ using System; using System.IO; using System.Linq; -using Microsoft.SqlTools.EditorServices.Utility; +using Microsoft.SqlTools.ServiceLayer.Utility; using Xunit; namespace Microsoft.SqlTools.ServiceLayer.Test.ServiceHost @@ -28,7 +28,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.ServiceHost => fileName.Contains("sqltools_") && fileName.EndsWith(".log", StringComparison.OrdinalIgnoreCase)) .ToList() - .ForEach(fileName => File.Delete(fileName)); + .ForEach(File.Delete); // initialize the logger Logger.Initialize( @@ -40,9 +40,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.ServiceHost // find the name of the new log file string logFileName = Directory.GetFiles(Directory.GetCurrentDirectory()) - .Where(fileName - => fileName.Contains("sqltools_") - && fileName.EndsWith(".log", StringComparison.OrdinalIgnoreCase)).SingleOrDefault(); + .SingleOrDefault(fileName => + fileName.Contains("sqltools_") + && fileName.EndsWith(".log", StringComparison.OrdinalIgnoreCase)); // validate the log file was created with desired name Assert.True(!string.IsNullOrWhiteSpace(logFileName)); diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test/project.json b/test/Microsoft.SqlTools.ServiceLayer.Test/project.json index 06a46957..4e5318f5 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.Test/project.json +++ b/test/Microsoft.SqlTools.ServiceLayer.Test/project.json @@ -15,10 +15,10 @@ "System.ComponentModel.TypeConverter": "4.1.0", "xunit": "2.1.0", "dotnet-test-xunit": "1.0.0-rc2-192208-24", - "moq": "4.6.36-alpha", "Microsoft.SqlTools.ServiceLayer": { "target": "project" - } + }, + "Moq": "4.6.36-alpha" }, "testRunner": "xunit", "frameworks": {