From 2a5ae06f123cffffe892f0c197f8274c5c2d66b9 Mon Sep 17 00:00:00 2001 From: Kevin Cunnane Date: Thu, 29 Jun 2017 17:03:11 -0700 Subject: [PATCH] Support "SQL" settings in addition to MSSQL (#398) * Support "SQL" settings in addition to MSSQL - Handles having 2 separate configuration definitions and merging / treating them as 1 throughout the app - If a settings group such as Intellisense is defined on mssql, it will override any generic SQL properties - Retains backwards compatibility with existing settings. --- .../Connection/ConnectionService.cs | 13 +-- .../CompoundSqlToolsSettingsValues.cs | 102 ++++++++++++++++++ .../SqlContext/ISqlToolsSettingsValues.cs | 33 ++++++ .../SqlContext/IntelliSenseSettings.cs | 1 + .../SqlContext/SqlToolsSettings.cs | 96 +++++++++-------- .../SqlContext/SqlToolsSettingsValues.cs | 55 ++++++++++ .../Formatter/FormatterSettingsTests.cs | 17 ++- .../QueryExecution/SettingsTests.cs | 10 +- 8 files changed, 261 insertions(+), 66 deletions(-) create mode 100644 src/Microsoft.SqlTools.ServiceLayer/SqlContext/CompoundSqlToolsSettingsValues.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/SqlContext/ISqlToolsSettingsValues.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/SqlContext/SqlToolsSettingsValues.cs diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs index 7e5391a5..a327d463 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs @@ -709,9 +709,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection serviceHost.SetRequestHandler(CancelConnectRequest.Type, HandleCancelConnectRequest); serviceHost.SetRequestHandler(DisconnectRequest.Type, HandleDisconnectRequest); serviceHost.SetRequestHandler(ListDatabasesRequest.Type, HandleListDatabasesRequest); - - // Register the configuration update handler - WorkspaceService.Instance.RegisterConfigChangeCallback(HandleDidChangeConfigurationNotification); } /// @@ -844,15 +841,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection await requestContext.SendError(ex.ToString()); } } - - public Task HandleDidChangeConfigurationNotification( - SqlToolsSettings newSettings, - SqlToolsSettings oldSettings, - EventContext eventContext) - { - return Task.FromResult(true); - } - + /// /// Build a connection string from a connection details instance /// diff --git a/src/Microsoft.SqlTools.ServiceLayer/SqlContext/CompoundSqlToolsSettingsValues.cs b/src/Microsoft.SqlTools.ServiceLayer/SqlContext/CompoundSqlToolsSettingsValues.cs new file mode 100644 index 00000000..f9c94e4c --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/SqlContext/CompoundSqlToolsSettingsValues.cs @@ -0,0 +1,102 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.SqlTools.Utility; +using Newtonsoft.Json; + +namespace Microsoft.SqlTools.ServiceLayer.SqlContext +{ + + /// + /// Handles backwards compatibility of settings by checking for settings in a priority list. If a settings + /// group such as Intellisense is defined on a serialized setting it's used in the order of mssql, then sql, then + /// falls back to a default value. + /// + public class CompoundToolsSettingsValues: ISqlToolsSettingsValues + { + private List priorityList = new List(); + private SqlToolsSettingsValues defaultValues; + public CompoundToolsSettingsValues(ISqlToolsSettingsValues mssql, ISqlToolsSettingsValues all) + { + Validate.IsNotNull(nameof(mssql), mssql); + Validate.IsNotNull(nameof(all), all); + priorityList.Add(mssql); + priorityList.Add(all); + // Always add in a fallback which has default values to be used. + defaultValues = new SqlToolsSettingsValues(createDefaults: true); + priorityList.Add(defaultValues); + } + + private T GetSettingOrDefault(Func lookup) + where T : new() + { + T value = priorityList.Select( (settings) => lookup(settings)).Where(val => val != null).FirstOrDefault(); + return value != null ? value : new T(); + } + + /// + /// Gets or sets the detailed IntelliSense settings + /// + public IntelliSenseSettings IntelliSense + { + get + { + return GetSettingOrDefault((settings) => settings.IntelliSense); + } + set + { + priorityList[0].IntelliSense = value; + } + } + + /// + /// Gets or sets the query execution settings + /// + public QueryExecutionSettings QueryExecutionSettings + { + get + { + return GetSettingOrDefault((settings) => settings.QueryExecutionSettings); + } + set + { + priorityList[0].QueryExecutionSettings = value; + } + } + + /// + /// Gets or sets the formatter settings + /// + public FormatterSettings Format + { + get + { + return GetSettingOrDefault((settings) => settings.Format); + } + set + { + priorityList[0].Format = value; + } + } + + /// + /// Gets or sets the object explorer settings + /// + public ObjectExplorerSettings ObjectExplorer + { + get + { + return GetSettingOrDefault((settings) => settings.ObjectExplorer); + } + set + { + priorityList[0].ObjectExplorer = value; + } + } + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/SqlContext/ISqlToolsSettingsValues.cs b/src/Microsoft.SqlTools.ServiceLayer/SqlContext/ISqlToolsSettingsValues.cs new file mode 100644 index 00000000..35ae0020 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/SqlContext/ISqlToolsSettingsValues.cs @@ -0,0 +1,33 @@ +// +// 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.SqlContext +{ + /// + /// Defines the common settings used by the tools service + /// + public interface ISqlToolsSettingsValues + { + /// + /// Intellisense specific settings + /// + IntelliSenseSettings IntelliSense { get; set; } + + /// + /// Query execution specific settings + /// + QueryExecutionSettings QueryExecutionSettings { get; set; } + + /// + /// Formatter settings + /// + FormatterSettings Format { get; set; } + + /// + /// Object Explorer specific settings + /// + ObjectExplorerSettings ObjectExplorer { get; set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/SqlContext/IntelliSenseSettings.cs b/src/Microsoft.SqlTools.ServiceLayer/SqlContext/IntelliSenseSettings.cs index 9d6caab3..44fd6277 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/SqlContext/IntelliSenseSettings.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/SqlContext/IntelliSenseSettings.cs @@ -57,6 +57,7 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlContext { if (settings != null) { + this.EnableIntellisense = settings.EnableIntellisense; this.EnableSuggestions = settings.EnableSuggestions; this.LowerCaseSuggestions = settings.LowerCaseSuggestions; this.EnableErrorChecking = settings.EnableErrorChecking; diff --git a/src/Microsoft.SqlTools.ServiceLayer/SqlContext/SqlToolsSettings.cs b/src/Microsoft.SqlTools.ServiceLayer/SqlContext/SqlToolsSettings.cs index d2ddf9b3..c7ba0541 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/SqlContext/SqlToolsSettings.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/SqlContext/SqlToolsSettings.cs @@ -3,6 +3,10 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.SqlTools.Utility; using Newtonsoft.Json; namespace Microsoft.SqlTools.ServiceLayer.SqlContext @@ -12,19 +16,17 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlContext /// public class SqlToolsSettings { - private SqlToolsSettingsValues sqlTools = null; + private ISqlToolsSettingsValues sqlTools = null; + private SqlToolsSettingsValues mssqlTools = null; + private SqlToolsSettingsValues allSqlTools = null; - /// - /// Gets or sets the underlying settings value object - /// - [JsonProperty("mssql")] - public SqlToolsSettingsValues SqlTools + public ISqlToolsSettingsValues SqlTools { get { if (this.sqlTools == null) { - this.sqlTools = new SqlToolsSettingsValues(); + this.sqlTools = new CompoundToolsSettingsValues(MssqlTools, AllSqlTools); } return this.sqlTools; } @@ -34,6 +36,46 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlContext } } + /// + /// Gets or sets the underlying settings value object + /// + [JsonProperty("mssql")] + public SqlToolsSettingsValues MssqlTools + { + get + { + if (this.mssqlTools == null) + { + this.mssqlTools = new SqlToolsSettingsValues(false); + } + return this.mssqlTools; + } + set + { + this.mssqlTools = value; + } + } + + /// + /// Gets or sets the underlying settings value object + /// + [JsonProperty("sql")] + public SqlToolsSettingsValues AllSqlTools + { + get + { + if (this.allSqlTools == null) + { + this.allSqlTools = new SqlToolsSettingsValues(false); + } + return this.allSqlTools; + } + set + { + this.sqlTools = value; + } + } + /// /// Query excution settings forwarding property /// @@ -50,7 +92,6 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlContext { if (settings != null) { - this.SqlTools.IntelliSense.EnableIntellisense = settings.SqlTools.IntelliSense.EnableIntellisense; this.SqlTools.IntelliSense.Update(settings.SqlTools.IntelliSense); } } @@ -102,43 +143,4 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlContext } } } - - /// - /// Class that is used to serialize and deserialize SQL Tools settings - /// - public class SqlToolsSettingsValues - { - /// - /// Initializes the Sql Tools settings values - /// - public SqlToolsSettingsValues() - { - IntelliSense = new IntelliSenseSettings(); - QueryExecutionSettings = new QueryExecutionSettings(); - Format = new FormatterSettings(); - } - - /// - /// Gets or sets the detailed IntelliSense settings - /// - public IntelliSenseSettings IntelliSense { get; set; } - - /// - /// Gets or sets the query execution settings - /// - [JsonProperty("query")] - public QueryExecutionSettings QueryExecutionSettings { get; set; } - - /// - /// Gets or sets the formatter settings - /// - [JsonProperty("format")] - public FormatterSettings Format { get; set; } - - /// - /// Gets or sets the formatter settings - /// - [JsonProperty("objectExplorer")] - public ObjectExplorerSettings ObjectExplorer { get; set; } - } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/SqlContext/SqlToolsSettingsValues.cs b/src/Microsoft.SqlTools.ServiceLayer/SqlContext/SqlToolsSettingsValues.cs new file mode 100644 index 00000000..077c1729 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/SqlContext/SqlToolsSettingsValues.cs @@ -0,0 +1,55 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.SqlTools.Utility; +using Newtonsoft.Json; + +namespace Microsoft.SqlTools.ServiceLayer.SqlContext +{ + /// + /// Class that is used to serialize and deserialize SQL Tools settings + /// + public class SqlToolsSettingsValues : ISqlToolsSettingsValues + { + /// + /// Initializes the Sql Tools settings values + /// + public SqlToolsSettingsValues(bool createDefaults = true) + { + if (createDefaults) + { + IntelliSense = new IntelliSenseSettings(); + QueryExecutionSettings = new QueryExecutionSettings(); + Format = new FormatterSettings(); + } + } + + /// + /// Gets or sets the detailed IntelliSense settings + /// + public IntelliSenseSettings IntelliSense { get; set; } + + /// + /// Gets or sets the query execution settings + /// + [JsonProperty("query")] + public QueryExecutionSettings QueryExecutionSettings { get; set; } + + /// + /// Gets or sets the formatter settings + /// + [JsonProperty("format")] + public FormatterSettings Format { get; set; } + + /// + /// Gets or sets the formatter settings + /// + [JsonProperty("objectExplorer")] + public ObjectExplorerSettings ObjectExplorer { get; set; } + } +} diff --git a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Formatter/FormatterSettingsTests.cs b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Formatter/FormatterSettingsTests.cs index 872b3fa5..6da2dc94 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Formatter/FormatterSettingsTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Formatter/FormatterSettingsTests.cs @@ -3,6 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // +using System.Globalization; using Microsoft.SqlTools.ServiceLayer.Formatter; using Microsoft.SqlTools.ServiceLayer.Formatter.Contracts; using Microsoft.SqlTools.ServiceLayer.SqlContext; @@ -28,10 +29,16 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Formatter [Fact] public void ValidateFormatSettingsParsedFromJson() { - const string settingsJson = @" + ValidateFormatSettings("mssql"); + ValidateFormatSettings("sql"); + } + + private static void ValidateFormatSettings(string settingsPropertyName) + { + string settingsJson = @" { ""params"": { - ""mssql"": { + """ + settingsPropertyName + @""": { ""format"": { useBracketForIdentifiers: true, placeCommasBeforeNextStatement: true, @@ -46,9 +53,9 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Formatter JObject message = JObject.Parse(settingsJson); JToken messageParams = null; - message.TryGetValue("params", out messageParams); + message.TryGetValue("params", out messageParams); SqlToolsSettings sqlToolsSettings = messageParams.ToObject(); - + Assert.True(sqlToolsSettings.SqlTools.Format.AlignColumnDefinitionsInColumns); Assert.Equal(CasingOptions.Lowercase, sqlToolsSettings.SqlTools.Format.DatatypeCasing); Assert.Equal(CasingOptions.Uppercase, sqlToolsSettings.SqlTools.Format.KeywordCasing); @@ -56,7 +63,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Formatter Assert.True(sqlToolsSettings.SqlTools.Format.PlaceSelectStatementReferencesOnNewLine); Assert.True(sqlToolsSettings.SqlTools.Format.UseBracketForIdentifiers); } - + [Fact] public void FormatOptionsMatchDefaultSettings() { diff --git a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/QueryExecution/SettingsTests.cs b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/QueryExecution/SettingsTests.cs index 7ff6ad58..69ae9dca 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/QueryExecution/SettingsTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/QueryExecution/SettingsTests.cs @@ -31,11 +31,17 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution [Fact] public void ValidateSettingsParsedFromJson() + { + ValidateSettings("mssql"); + ValidateSettings("sql"); + } + + private static void ValidateSettings(string settingsPropertyName) { // NOTE: Only testing displayBitAsNumber for now because it is the only one piped through - const string settingsJson = @"{" + string settingsJson = @"{" + @"""params"": {" - + @"""mssql"": {" + + @""""+settingsPropertyName+@""": {" + @"""query"": {" + @"displayBitAsNumber: false" + @"}"