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 new file mode 100644 index 00000000000..20cb0794c44 --- /dev/null +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/SemanticTokensRefreshNotifier.cs @@ -0,0 +1,56 @@ +// 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 c6c8570685a..01db1266b91 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,21 +2,18 @@ // 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; @@ -26,73 +23,12 @@ 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, @@ -100,17 +36,11 @@ 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.Select(s => s.UnifiedName).ToArray()); + _unifiedSettingsSubscription = _unifiedSettingsReader.SubscribeToChanges(OnUnifiedSettingsChanged, SettingsNames.AllSettings); await GetTaskListDescriptorsAsync(joinableTaskContext.Factory, serviceProvider); }); @@ -168,44 +98,41 @@ public async Task OnChangedAsync(Action changed) private EventHandler? _changed; public ClientAdvancedSettings GetAdvancedSettings() - => new(FormatOnType, AutoClosingTags, AutoInsertAttributeQuotes, ColorBackground, CodeBlockBraceOnNextLine, CommitElementsWithSpace, Snippets, LogLevel, FormatOnPaste, TaskListDescriptors); + => 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); public bool GetBool(string name, bool defaultValue) { - if (_writableSettingsStore.PropertyExists(SettingsNames.LegacyCollection, name)) + if (_unifiedSettingsReader.AssumeNotNull().GetValue(name) is { Outcome: SettingRetrievalOutcome.Success, Value: { } unifiedValue }) { - return _writableSettingsStore.GetBoolean(SettingsNames.LegacyCollection, name); + return unifiedValue; } return defaultValue; } - public void SetBool(string name, bool value) + public T GetEnum(string name, T defaultValue) where T : struct, Enum { - _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 (_unifiedSettingsReader.AssumeNotNull().GetValue(name) is { Outcome: SettingRetrievalOutcome.Success, Value: { } unifiedValue }) { - return _writableSettingsStore.GetInt32(SettingsNames.LegacyCollection, name); + if (Enum.TryParse(unifiedValue, ignoreCase: true, out var parsed)) + { + return parsed; + } } 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 be05198edf1..6200ae8f810 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,22 +5,19 @@ namespace Microsoft.VisualStudio.Razor.LanguageClient.Options; internal static class SettingsNames { - public record Setting(string LegacyName, string UnifiedName); + public const string UnifiedCollection = "languages.razor.advanced"; - public const string LegacyCollection = "Razor"; - public const string UnifiedCollection = "textEditor.razor.advanced"; + 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 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 = + public static readonly string[] AllSettings = [ FormatOnType, AutoClosingTags,