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.
This commit is contained in:
Kevin Cunnane
2017-06-29 17:03:11 -07:00
committed by GitHub
parent 8f5b5b14ca
commit 2a5ae06f12
8 changed files with 261 additions and 66 deletions

View File

@@ -709,9 +709,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
serviceHost.SetRequestHandler(CancelConnectRequest.Type, HandleCancelConnectRequest); serviceHost.SetRequestHandler(CancelConnectRequest.Type, HandleCancelConnectRequest);
serviceHost.SetRequestHandler(DisconnectRequest.Type, HandleDisconnectRequest); serviceHost.SetRequestHandler(DisconnectRequest.Type, HandleDisconnectRequest);
serviceHost.SetRequestHandler(ListDatabasesRequest.Type, HandleListDatabasesRequest); serviceHost.SetRequestHandler(ListDatabasesRequest.Type, HandleListDatabasesRequest);
// Register the configuration update handler
WorkspaceService<SqlToolsSettings>.Instance.RegisterConfigChangeCallback(HandleDidChangeConfigurationNotification);
} }
/// <summary> /// <summary>
@@ -844,15 +841,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
await requestContext.SendError(ex.ToString()); await requestContext.SendError(ex.ToString());
} }
} }
public Task HandleDidChangeConfigurationNotification(
SqlToolsSettings newSettings,
SqlToolsSettings oldSettings,
EventContext eventContext)
{
return Task.FromResult(true);
}
/// <summary> /// <summary>
/// Build a connection string from a connection details instance /// Build a connection string from a connection details instance
/// </summary> /// </summary>

View File

@@ -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
{
/// <summary>
/// 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.
/// </summary>
public class CompoundToolsSettingsValues: ISqlToolsSettingsValues
{
private List<ISqlToolsSettingsValues> priorityList = new List<ISqlToolsSettingsValues>();
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<T>(Func<ISqlToolsSettingsValues, T> lookup)
where T : new()
{
T value = priorityList.Select( (settings) => lookup(settings)).Where(val => val != null).FirstOrDefault();
return value != null ? value : new T();
}
/// <summary>
/// Gets or sets the detailed IntelliSense settings
/// </summary>
public IntelliSenseSettings IntelliSense
{
get
{
return GetSettingOrDefault((settings) => settings.IntelliSense);
}
set
{
priorityList[0].IntelliSense = value;
}
}
/// <summary>
/// Gets or sets the query execution settings
/// </summary>
public QueryExecutionSettings QueryExecutionSettings
{
get
{
return GetSettingOrDefault((settings) => settings.QueryExecutionSettings);
}
set
{
priorityList[0].QueryExecutionSettings = value;
}
}
/// <summary>
/// Gets or sets the formatter settings
/// </summary>
public FormatterSettings Format
{
get
{
return GetSettingOrDefault((settings) => settings.Format);
}
set
{
priorityList[0].Format = value;
}
}
/// <summary>
/// Gets or sets the object explorer settings
/// </summary>
public ObjectExplorerSettings ObjectExplorer
{
get
{
return GetSettingOrDefault((settings) => settings.ObjectExplorer);
}
set
{
priorityList[0].ObjectExplorer = value;
}
}
}
}

View File

@@ -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
{
/// <summary>
/// Defines the common settings used by the tools service
/// </summary>
public interface ISqlToolsSettingsValues
{
/// <summary>
/// Intellisense specific settings
/// </summary>
IntelliSenseSettings IntelliSense { get; set; }
/// <summary>
/// Query execution specific settings
/// </summary>
QueryExecutionSettings QueryExecutionSettings { get; set; }
/// <summary>
/// Formatter settings
/// </summary>
FormatterSettings Format { get; set; }
/// <summary>
/// Object Explorer specific settings
/// </summary>
ObjectExplorerSettings ObjectExplorer { get; set; }
}
}

View File

@@ -57,6 +57,7 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlContext
{ {
if (settings != null) if (settings != null)
{ {
this.EnableIntellisense = settings.EnableIntellisense;
this.EnableSuggestions = settings.EnableSuggestions; this.EnableSuggestions = settings.EnableSuggestions;
this.LowerCaseSuggestions = settings.LowerCaseSuggestions; this.LowerCaseSuggestions = settings.LowerCaseSuggestions;
this.EnableErrorChecking = settings.EnableErrorChecking; this.EnableErrorChecking = settings.EnableErrorChecking;

View File

@@ -3,6 +3,10 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // 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; using Newtonsoft.Json;
namespace Microsoft.SqlTools.ServiceLayer.SqlContext namespace Microsoft.SqlTools.ServiceLayer.SqlContext
@@ -12,19 +16,17 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlContext
/// </summary> /// </summary>
public class SqlToolsSettings public class SqlToolsSettings
{ {
private SqlToolsSettingsValues sqlTools = null; private ISqlToolsSettingsValues sqlTools = null;
private SqlToolsSettingsValues mssqlTools = null;
private SqlToolsSettingsValues allSqlTools = null;
/// <summary> public ISqlToolsSettingsValues SqlTools
/// Gets or sets the underlying settings value object
/// </summary>
[JsonProperty("mssql")]
public SqlToolsSettingsValues SqlTools
{ {
get get
{ {
if (this.sqlTools == null) if (this.sqlTools == null)
{ {
this.sqlTools = new SqlToolsSettingsValues(); this.sqlTools = new CompoundToolsSettingsValues(MssqlTools, AllSqlTools);
} }
return this.sqlTools; return this.sqlTools;
} }
@@ -34,6 +36,46 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlContext
} }
} }
/// <summary>
/// Gets or sets the underlying settings value object
/// </summary>
[JsonProperty("mssql")]
public SqlToolsSettingsValues MssqlTools
{
get
{
if (this.mssqlTools == null)
{
this.mssqlTools = new SqlToolsSettingsValues(false);
}
return this.mssqlTools;
}
set
{
this.mssqlTools = value;
}
}
/// <summary>
/// Gets or sets the underlying settings value object
/// </summary>
[JsonProperty("sql")]
public SqlToolsSettingsValues AllSqlTools
{
get
{
if (this.allSqlTools == null)
{
this.allSqlTools = new SqlToolsSettingsValues(false);
}
return this.allSqlTools;
}
set
{
this.sqlTools = value;
}
}
/// <summary> /// <summary>
/// Query excution settings forwarding property /// Query excution settings forwarding property
/// </summary> /// </summary>
@@ -50,7 +92,6 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlContext
{ {
if (settings != null) if (settings != null)
{ {
this.SqlTools.IntelliSense.EnableIntellisense = settings.SqlTools.IntelliSense.EnableIntellisense;
this.SqlTools.IntelliSense.Update(settings.SqlTools.IntelliSense); this.SqlTools.IntelliSense.Update(settings.SqlTools.IntelliSense);
} }
} }
@@ -102,43 +143,4 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlContext
} }
} }
} }
/// <summary>
/// Class that is used to serialize and deserialize SQL Tools settings
/// </summary>
public class SqlToolsSettingsValues
{
/// <summary>
/// Initializes the Sql Tools settings values
/// </summary>
public SqlToolsSettingsValues()
{
IntelliSense = new IntelliSenseSettings();
QueryExecutionSettings = new QueryExecutionSettings();
Format = new FormatterSettings();
}
/// <summary>
/// Gets or sets the detailed IntelliSense settings
/// </summary>
public IntelliSenseSettings IntelliSense { get; set; }
/// <summary>
/// Gets or sets the query execution settings
/// </summary>
[JsonProperty("query")]
public QueryExecutionSettings QueryExecutionSettings { get; set; }
/// <summary>
/// Gets or sets the formatter settings
/// </summary>
[JsonProperty("format")]
public FormatterSettings Format { get; set; }
/// <summary>
/// Gets or sets the formatter settings
/// </summary>
[JsonProperty("objectExplorer")]
public ObjectExplorerSettings ObjectExplorer { get; set; }
}
} }

View File

@@ -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
{
/// <summary>
/// Class that is used to serialize and deserialize SQL Tools settings
/// </summary>
public class SqlToolsSettingsValues : ISqlToolsSettingsValues
{
/// <summary>
/// Initializes the Sql Tools settings values
/// </summary>
public SqlToolsSettingsValues(bool createDefaults = true)
{
if (createDefaults)
{
IntelliSense = new IntelliSenseSettings();
QueryExecutionSettings = new QueryExecutionSettings();
Format = new FormatterSettings();
}
}
/// <summary>
/// Gets or sets the detailed IntelliSense settings
/// </summary>
public IntelliSenseSettings IntelliSense { get; set; }
/// <summary>
/// Gets or sets the query execution settings
/// </summary>
[JsonProperty("query")]
public QueryExecutionSettings QueryExecutionSettings { get; set; }
/// <summary>
/// Gets or sets the formatter settings
/// </summary>
[JsonProperty("format")]
public FormatterSettings Format { get; set; }
/// <summary>
/// Gets or sets the formatter settings
/// </summary>
[JsonProperty("objectExplorer")]
public ObjectExplorerSettings ObjectExplorer { get; set; }
}
}

View File

@@ -3,6 +3,7 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // 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;
using Microsoft.SqlTools.ServiceLayer.Formatter.Contracts; using Microsoft.SqlTools.ServiceLayer.Formatter.Contracts;
using Microsoft.SqlTools.ServiceLayer.SqlContext; using Microsoft.SqlTools.ServiceLayer.SqlContext;
@@ -28,10 +29,16 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Formatter
[Fact] [Fact]
public void ValidateFormatSettingsParsedFromJson() public void ValidateFormatSettingsParsedFromJson()
{ {
const string settingsJson = @" ValidateFormatSettings("mssql");
ValidateFormatSettings("sql");
}
private static void ValidateFormatSettings(string settingsPropertyName)
{
string settingsJson = @"
{ {
""params"": { ""params"": {
""mssql"": { """ + settingsPropertyName + @""": {
""format"": { ""format"": {
useBracketForIdentifiers: true, useBracketForIdentifiers: true,
placeCommasBeforeNextStatement: true, placeCommasBeforeNextStatement: true,
@@ -46,9 +53,9 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Formatter
JObject message = JObject.Parse(settingsJson); JObject message = JObject.Parse(settingsJson);
JToken messageParams = null; JToken messageParams = null;
message.TryGetValue("params", out messageParams); message.TryGetValue("params", out messageParams);
SqlToolsSettings sqlToolsSettings = messageParams.ToObject<SqlToolsSettings>(); SqlToolsSettings sqlToolsSettings = messageParams.ToObject<SqlToolsSettings>();
Assert.True(sqlToolsSettings.SqlTools.Format.AlignColumnDefinitionsInColumns); Assert.True(sqlToolsSettings.SqlTools.Format.AlignColumnDefinitionsInColumns);
Assert.Equal(CasingOptions.Lowercase, sqlToolsSettings.SqlTools.Format.DatatypeCasing); Assert.Equal(CasingOptions.Lowercase, sqlToolsSettings.SqlTools.Format.DatatypeCasing);
Assert.Equal(CasingOptions.Uppercase, sqlToolsSettings.SqlTools.Format.KeywordCasing); 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.PlaceSelectStatementReferencesOnNewLine);
Assert.True(sqlToolsSettings.SqlTools.Format.UseBracketForIdentifiers); Assert.True(sqlToolsSettings.SqlTools.Format.UseBracketForIdentifiers);
} }
[Fact] [Fact]
public void FormatOptionsMatchDefaultSettings() public void FormatOptionsMatchDefaultSettings()
{ {

View File

@@ -31,11 +31,17 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution
[Fact] [Fact]
public void ValidateSettingsParsedFromJson() 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 // NOTE: Only testing displayBitAsNumber for now because it is the only one piped through
const string settingsJson = @"{" string settingsJson = @"{"
+ @"""params"": {" + @"""params"": {"
+ @"""mssql"": {" + @""""+settingsPropertyName+@""": {"
+ @"""query"": {" + @"""query"": {"
+ @"displayBitAsNumber: false" + @"displayBitAsNumber: false"
+ @"}" + @"}"