diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/SemanticTokensRefreshNotifier.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/SemanticTokensRefreshNotifier.cs deleted file mode 100644 index 20cb0794c44..00000000000 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/SemanticTokensRefreshNotifier.cs +++ /dev/null @@ -1,56 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.ComponentModel.Composition; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.ExternalAccess.Razor; -using Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; -using Microsoft.CodeAnalysis.Razor.Workspaces.Settings; -using Microsoft.VisualStudio.Razor.LanguageClient.Cohost; -using Microsoft.VisualStudio.Threading; - -namespace Microsoft.AspNetCore.Razor.LanguageServer; - -[Export(typeof(IRazorCohostStartupService))] -[method: ImportingConstructor] -internal sealed class SemanticTokensRefreshNotifier(IClientSettingsManager clientSettingsManager) : IRazorCohostStartupService, IDisposable -{ - private readonly IClientSettingsManager _clientSettingsManager = clientSettingsManager; - - private IRazorClientLanguageServerManager? _razorClientLanguageServerManager; - private bool _lastColorBackground; - - public int Order => WellKnownStartupOrder.Default; - - public Task StartupAsync(VSInternalClientCapabilities clientCapabilities, RazorCohostRequestContext requestContext, CancellationToken cancellationToken) - { - _razorClientLanguageServerManager = requestContext.GetRequiredService(); - - if (clientCapabilities.Workspace?.SemanticTokens?.RefreshSupport ?? false) - { - _lastColorBackground = _clientSettingsManager.GetClientSettings().AdvancedSettings.ColorBackground; - _clientSettingsManager.ClientSettingsChanged += ClientSettingsManager_ClientSettingsChanged; - } - - return Task.CompletedTask; - } - - private void ClientSettingsManager_ClientSettingsChanged(object sender, EventArgs e) - { - var colorBackground = _clientSettingsManager.GetClientSettings().AdvancedSettings.ColorBackground; - if (colorBackground == _lastColorBackground) - { - return; - } - - _lastColorBackground = colorBackground; - _razorClientLanguageServerManager.AssumeNotNull().SendNotificationAsync(Methods.WorkspaceSemanticTokensRefreshName, CancellationToken.None).Forget(); - } - - public void Dispose() - { - _clientSettingsManager.ClientSettingsChanged -= ClientSettingsManager_ClientSettingsChanged; - } -} diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Options/OptionsStorage.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Options/OptionsStorage.cs index 01db1266b91..c6c8570685a 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Options/OptionsStorage.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Options/OptionsStorage.cs @@ -2,18 +2,21 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Collections.Generic; using System.Collections.Immutable; using System.ComponentModel.Composition; +using System.Linq; using System.Threading.Tasks; -using Microsoft.AspNetCore.Razor; using Microsoft.AspNetCore.Razor.PooledObjects; using Microsoft.CodeAnalysis.Razor.Logging; using Microsoft.CodeAnalysis.Razor.Settings; using Microsoft.CodeAnalysis.Razor.Telemetry; using Microsoft.Internal.VisualStudio.Shell.Interop; using Microsoft.VisualStudio.Razor.Settings; +using Microsoft.VisualStudio.Settings; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; +using Microsoft.VisualStudio.Shell.Settings; using Microsoft.VisualStudio.Threading; using Microsoft.VisualStudio.Utilities.UnifiedSettings; @@ -23,12 +26,73 @@ namespace Microsoft.VisualStudio.Razor.LanguageClient.Options; [Export(typeof(IAdvancedSettingsStorage))] internal class OptionsStorage : IAdvancedSettingsStorage, IDisposable { + private readonly WritableSettingsStore _writableSettingsStore; + private readonly Lazy _telemetryReporter; private readonly JoinableTask _initializeTask; private ImmutableArray _taskListDescriptors = []; private ISettingsReader? _unifiedSettingsReader; private IDisposable? _unifiedSettingsSubscription; private bool _changedBeforeSubscription; + public bool FormatOnType + { + get => GetBool(SettingsNames.FormatOnType.LegacyName, defaultValue: true); + set => SetBool(SettingsNames.FormatOnType.LegacyName, value); + } + + public bool AutoClosingTags + { + get => GetBool(SettingsNames.AutoClosingTags.LegacyName, defaultValue: true); + set => SetBool(SettingsNames.AutoClosingTags.LegacyName, value); + } + + public bool AutoInsertAttributeQuotes + { + get => GetBool(SettingsNames.AutoInsertAttributeQuotes.LegacyName, defaultValue: true); + set => SetBool(SettingsNames.AutoInsertAttributeQuotes.LegacyName, value); + } + + public bool ColorBackground + { + get => GetBool(SettingsNames.ColorBackground.LegacyName, defaultValue: false); + set => SetBool(SettingsNames.ColorBackground.LegacyName, value); + } + + public bool CodeBlockBraceOnNextLine + { + get => GetBool(SettingsNames.CodeBlockBraceOnNextLine.LegacyName, defaultValue: false); + set => SetBool(SettingsNames.CodeBlockBraceOnNextLine.LegacyName, value); + } + + public bool CommitElementsWithSpace + { + get => GetBool(SettingsNames.CommitElementsWithSpace.LegacyName, defaultValue: true); + set => SetBool(SettingsNames.CommitElementsWithSpace.LegacyName, value); + } + + public SnippetSetting Snippets + { + get => (SnippetSetting)GetInt(SettingsNames.Snippets.LegacyName, (int)SnippetSetting.All); + set => SetInt(SettingsNames.Snippets.LegacyName, (int)value); + } + + public LogLevel LogLevel + { + get => (LogLevel)GetInt(SettingsNames.LogLevel.LegacyName, (int)LogLevel.Warning); + set => SetInt(SettingsNames.LogLevel.LegacyName, (int)value); + } + + public bool FormatOnPaste + { + get => GetBool(SettingsNames.FormatOnPaste.LegacyName, defaultValue: true); + set => SetBool(SettingsNames.FormatOnPaste.LegacyName, value); + } + + public ImmutableArray TaskListDescriptors + { + get { return _taskListDescriptors; } + } + [ImportingConstructor] public OptionsStorage( SVsServiceProvider synchronousServiceProvider, @@ -36,11 +100,17 @@ public OptionsStorage( Lazy telemetryReporter, JoinableTaskContext joinableTaskContext) { + var shellSettingsManager = new ShellSettingsManager(synchronousServiceProvider); + _writableSettingsStore = shellSettingsManager.GetWritableSettingsStore(SettingsScope.UserSettings); + + _writableSettingsStore.CreateCollection(SettingsNames.LegacyCollection); + _telemetryReporter = telemetryReporter; + _initializeTask = joinableTaskContext.Factory.RunAsync(async () => { - var unifiedSettingsManager = await serviceProvider.GetServiceAsync(); + var unifiedSettingsManager = await serviceProvider.GetServiceAsync(); _unifiedSettingsReader = unifiedSettingsManager.GetReader(); - _unifiedSettingsSubscription = _unifiedSettingsReader.SubscribeToChanges(OnUnifiedSettingsChanged, SettingsNames.AllSettings); + _unifiedSettingsSubscription = _unifiedSettingsReader.SubscribeToChanges(OnUnifiedSettingsChanged, SettingsNames.AllSettings.Select(s => s.UnifiedName).ToArray()); await GetTaskListDescriptorsAsync(joinableTaskContext.Factory, serviceProvider); }); @@ -98,41 +168,44 @@ public async Task OnChangedAsync(Action changed) private EventHandler? _changed; public ClientAdvancedSettings GetAdvancedSettings() - => new( - GetBool(SettingsNames.FormatOnType, defaultValue: true), - GetBool(SettingsNames.AutoClosingTags, defaultValue: true), - GetBool(SettingsNames.AutoInsertAttributeQuotes, defaultValue: true), - GetBool(SettingsNames.ColorBackground, defaultValue: false), - GetBool(SettingsNames.CodeBlockBraceOnNextLine, defaultValue: false), - GetBool(SettingsNames.CommitElementsWithSpace, defaultValue: true), - GetEnum(SettingsNames.Snippets, SnippetSetting.All), - GetEnum(SettingsNames.LogLevel, LogLevel.Warning), - GetBool(SettingsNames.FormatOnPaste, defaultValue: true), - _taskListDescriptors); + => new(FormatOnType, AutoClosingTags, AutoInsertAttributeQuotes, ColorBackground, CodeBlockBraceOnNextLine, CommitElementsWithSpace, Snippets, LogLevel, FormatOnPaste, TaskListDescriptors); public bool GetBool(string name, bool defaultValue) { - if (_unifiedSettingsReader.AssumeNotNull().GetValue(name) is { Outcome: SettingRetrievalOutcome.Success, Value: { } unifiedValue }) + if (_writableSettingsStore.PropertyExists(SettingsNames.LegacyCollection, name)) { - return unifiedValue; + return _writableSettingsStore.GetBoolean(SettingsNames.LegacyCollection, name); } return defaultValue; } - public T GetEnum(string name, T defaultValue) where T : struct, Enum + public void SetBool(string name, bool value) { - if (_unifiedSettingsReader.AssumeNotNull().GetValue(name) is { Outcome: SettingRetrievalOutcome.Success, Value: { } unifiedValue }) + _writableSettingsStore.SetBoolean(SettingsNames.LegacyCollection, name, value); + _telemetryReporter.Value.ReportEvent("OptionChanged", Severity.Normal, new Property(name, value)); + + NotifyChange(); + } + + public int GetInt(string name, int defaultValue) + { + if (_writableSettingsStore.PropertyExists(SettingsNames.LegacyCollection, name)) { - if (Enum.TryParse(unifiedValue, ignoreCase: true, out var parsed)) - { - return parsed; - } + return _writableSettingsStore.GetInt32(SettingsNames.LegacyCollection, name); } return defaultValue; } + public void SetInt(string name, int value) + { + _writableSettingsStore.SetInt32(SettingsNames.LegacyCollection, name, value); + _telemetryReporter.Value.ReportEvent("OptionChanged", Severity.Normal, new Property(name, value)); + + NotifyChange(); + } + private void NotifyChange() { _initializeTask.Join(); diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Options/SettingsNames.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Options/SettingsNames.cs index 6200ae8f810..be05198edf1 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Options/SettingsNames.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Options/SettingsNames.cs @@ -5,19 +5,22 @@ namespace Microsoft.VisualStudio.Razor.LanguageClient.Options; internal static class SettingsNames { - public const string UnifiedCollection = "languages.razor.advanced"; + public record Setting(string LegacyName, string UnifiedName); - public static readonly string FormatOnType = UnifiedCollection + ".formatOnType"; - public static readonly string AutoClosingTags = UnifiedCollection + ".autoClosingTags"; - public static readonly string AutoInsertAttributeQuotes = UnifiedCollection + ".autoInsertAttributeQuotes"; - public static readonly string ColorBackground = UnifiedCollection + ".colorBackground"; - public static readonly string CodeBlockBraceOnNextLine = UnifiedCollection + ".codeBlockBraceOnNextLine"; - public static readonly string CommitElementsWithSpace = UnifiedCollection + ".commitCharactersWithSpace"; - public static readonly string Snippets = UnifiedCollection + ".snippets"; - public static readonly string LogLevel = UnifiedCollection + ".logLevel"; - public static readonly string FormatOnPaste = UnifiedCollection + ".formatOnPaste"; + public const string LegacyCollection = "Razor"; + public const string UnifiedCollection = "textEditor.razor.advanced"; - public static readonly string[] AllSettings = + public static readonly Setting FormatOnType = new("FormatOnType", UnifiedCollection + ".formatOnType"); + public static readonly Setting AutoClosingTags = new("AutoClosingTags", UnifiedCollection + ".autoClosingTags"); + public static readonly Setting AutoInsertAttributeQuotes = new("AutoInsertAttributeQuotes", UnifiedCollection + ".autoInsertAttributeQuotes"); + public static readonly Setting ColorBackground = new("ColorBackground", UnifiedCollection + ".colorBackground"); + public static readonly Setting CodeBlockBraceOnNextLine = new("CodeBlockBraceOnNextLine", UnifiedCollection + ".codeBlockBraceOnNextLine"); + public static readonly Setting CommitElementsWithSpace = new("CommitElementsWithSpace", UnifiedCollection + ".commitCharactersWithSpace"); + public static readonly Setting Snippets = new("Snippets", UnifiedCollection + ".snippets"); + public static readonly Setting LogLevel = new("LogLevel", UnifiedCollection + ".logLevel"); + public static readonly Setting FormatOnPaste = new("FormatOnPaste", UnifiedCollection + ".formatOnPaste"); + + public static readonly Setting[] AllSettings = [ FormatOnType, AutoClosingTags,