From ea41f07f5ac4f01418a7571e79ee0d6f1f92d717 Mon Sep 17 00:00:00 2001 From: Shen Chen Date: Thu, 24 Jun 2021 15:13:06 -0700 Subject: [PATCH 01/16] Check the experiment service --- .../Core/Shared/Options/FeatureOnOffOptions.cs | 4 ++-- .../Impl/Options/AdvancedOptionPageControl.xaml | 4 ++++ .../Options/AdvancedOptionPageControl.xaml.cs | 8 +++++++- .../InheritanceMarginTaggerProvider.cs | 16 ++++++++++++++-- .../Impl/Options/AdvancedOptionPageControl.xaml | 4 ++++ .../Options/AdvancedOptionPageControl.xaml.vb | 7 ++++++- .../Experiments/IExperimentationService.cs | 1 + 7 files changed, 38 insertions(+), 6 deletions(-) diff --git a/src/EditorFeatures/Core/Shared/Options/FeatureOnOffOptions.cs b/src/EditorFeatures/Core/Shared/Options/FeatureOnOffOptions.cs index 9bead18bb9cb5..039aa8727007e 100644 --- a/src/EditorFeatures/Core/Shared/Options/FeatureOnOffOptions.cs +++ b/src/EditorFeatures/Core/Shared/Options/FeatureOnOffOptions.cs @@ -78,10 +78,10 @@ internal static class FeatureOnOffOptions nameof(FeatureOnOffOptions), nameof(OfferRemoveUnusedReferences), defaultValue: true, storageLocations: new RoamingProfileStorageLocation($"TextEditor.{nameof(OfferRemoveUnusedReferences)}")); - public static readonly PerLanguageOption2 ShowInheritanceMargin = + public static readonly PerLanguageOption2 ShowInheritanceMargin = new(nameof(FeatureOnOffOptions), nameof(ShowInheritanceMargin), - defaultValue: false, + defaultValue: null, new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.ShowInheritanceMargin")); public static readonly Option2 AutomaticallyCompleteStatementOnSemicolon = new( diff --git a/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml b/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml index ae4749eab75e5..af459faad4c98 100644 --- a/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml +++ b/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml @@ -271,6 +271,10 @@ diff --git a/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml.cs b/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml.cs index d8c3a9da9b8b3..86e656a5253f8 100644 --- a/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml.cs +++ b/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml.cs @@ -130,7 +130,7 @@ public AdvancedOptionPageControl(OptionStore optionStore, IComponentModel compon BindToOption(ShowHintsForLambdaParameterTypes, InlineHintsOptions.ForLambdaParameterTypes, LanguageNames.CSharp); BindToOption(ShowHintsForImplicitObjectCreation, InlineHintsOptions.ForImplicitObjectCreation, LanguageNames.CSharp); - BindToOption(ShowInheritanceMargin, FeatureOnOffOptions.ShowInheritanceMargin, LanguageNames.CSharp); + ShowInheritanceMargin.IsChecked = OptionStore.GetOption(FeatureOnOffOptions.ShowInheritanceMargin, LanguageNames.CSharp); } // Since this dialog is constructed once for the lifetime of the application and VS Theme can be changed after the application has started, @@ -218,5 +218,11 @@ private void DisplayInlineTypeHints_Unchecked(object sender, RoutedEventArgs e) this.OptionStore.SetOption(InlineHintsOptions.EnabledForTypes, LanguageNames.CSharp, false); UpdateInlineHintsOptions(); } + + private void ShowInheritanceMargin_Changed(object sender, RoutedEventArgs e) + { + this.ShowInheritanceMargin.IsThreeState = false; + this.OptionStore.SetOption(FeatureOnOffOptions.ShowInheritanceMargin, LanguageNames.CSharp, this.ShowInheritanceMargin.IsChecked); + } } } diff --git a/src/VisualStudio/Core/Def/Implementation/InheritanceMargin/InheritanceMarginTaggerProvider.cs b/src/VisualStudio/Core/Def/Implementation/InheritanceMargin/InheritanceMarginTaggerProvider.cs index 1a8be7aeef315..c06ce7c742841 100644 --- a/src/VisualStudio/Core/Def/Implementation/InheritanceMargin/InheritanceMarginTaggerProvider.cs +++ b/src/VisualStudio/Core/Def/Implementation/InheritanceMargin/InheritanceMarginTaggerProvider.cs @@ -15,10 +15,12 @@ using Microsoft.CodeAnalysis.Editor.Shared.Tagging; using Microsoft.CodeAnalysis.Editor.Shared.Utilities; using Microsoft.CodeAnalysis.Editor.Tagging; +using Microsoft.CodeAnalysis.Experiments; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.InheritanceMargin; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.TestHooks; +using Microsoft.VisualStudio.Debugger.ComponentInterfaces; using Microsoft.VisualStudio.Text; using Microsoft.VisualStudio.Text.Editor; using Microsoft.VisualStudio.Text.Tagging; @@ -45,6 +47,8 @@ public InheritanceMarginTaggerProvider( protected override TaggerDelay EventChangeDelay => TaggerDelay.OnIdle; + private bool? _experimentEnabled = null; + protected override ITaggerEventSource CreateEventSource(ITextView textViewOpt, ITextBuffer subjectBuffer) // Because we use frozen-partial documents for semantic classification, we may end up with incomplete // semantics (esp. during solution load). Because of this, we also register to hear when the full @@ -84,8 +88,16 @@ protected override async Task ProduceTagsAsync( var cancellationToken = context.CancellationToken; var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - var featureEnabled = options.GetOption(FeatureOnOffOptions.ShowInheritanceMargin); - if (!featureEnabled) + + var optionIsChecked = options.GetOption(FeatureOnOffOptions.ShowInheritanceMargin); + if (_experimentEnabled is null) + { + var experimentationService = document.Project.Solution.Workspace.Services.GetRequiredService(); + _experimentEnabled = experimentationService.IsExperimentEnabled(WellKnownExperimentNames.InheritanceMargin); + } + + var shouldEnableFeature = optionIsChecked == true || (_experimentEnabled == true && optionIsChecked == null); + if (!shouldEnableFeature) { return; } diff --git a/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml b/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml index 4d6d131fb3d37..d8f64d98ae626 100644 --- a/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml +++ b/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml @@ -249,6 +249,10 @@ diff --git a/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml.vb b/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml.vb index 66fcb6d69b248..5f9913e323078 100644 --- a/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml.vb +++ b/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml.vb @@ -146,7 +146,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Options BindToOption(SuppressHintsWhenParameterNameMatchesTheMethodsIntent, InlineHintsOptions.SuppressForParametersThatMatchMethodIntent, LanguageNames.VisualBasic) BindToOption(SuppressHintsWhenParameterNamesDifferOnlyBySuffix, InlineHintsOptions.SuppressForParametersThatDifferOnlyBySuffix, LanguageNames.VisualBasic) - BindToOption(ShowInheritanceMargin, FeatureOnOffOptions.ShowInheritanceMargin, LanguageNames.VisualBasic) + ShowInheritanceMargin.IsChecked = optionStore.GetOption(FeatureOnOffOptions.ShowInheritanceMargin, LanguageNames.VisualBasic) End Sub ' Since this dialog is constructed once for the lifetime of the application and VS Theme can be changed after the application has started, @@ -182,5 +182,10 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Options Me.OptionStore.SetOption(InlineHintsOptions.EnabledForParameters, LanguageNames.VisualBasic, False) UpdateInlineHintsOptions() End Sub + + Private Sub ShowInheritanceMargin_Changed(sender As Object, e As RoutedEventArgs) + Me.ShowInheritanceMargin.IsThreeState = False + Me.OptionStore.SetOption(FeatureOnOffOptions.ShowInheritanceMargin, LanguageNames.VisualBasic, Me.ShowInheritanceMargin.IsChecked) + End Sub End Class End Namespace diff --git a/src/Workspaces/Core/Portable/Experiments/IExperimentationService.cs b/src/Workspaces/Core/Portable/Experiments/IExperimentationService.cs index 881f40c78a723..66b3335e96d61 100644 --- a/src/Workspaces/Core/Portable/Experiments/IExperimentationService.cs +++ b/src/Workspaces/Core/Portable/Experiments/IExperimentationService.cs @@ -41,5 +41,6 @@ internal static class WellKnownExperimentNames public const string CloudCache = "Roslyn.CloudCache"; public const string UnnamedSymbolCompletionDisabled = "Roslyn.UnnamedSymbolCompletionDisabled"; public const string RazorLspEditorFeatureFlag = "Razor.LSP.Editor"; + public const string InheritanceMargin = "Roslyn.InheritanceMargin"; } } From 87735a2be99c3fd719363231f438620ebbec1ede Mon Sep 17 00:00:00 2001 From: Shen Chen Date: Thu, 24 Jun 2021 15:44:37 -0700 Subject: [PATCH 02/16] Add telemtry to count time --- .../AbstractInheritanceMarginService.cs | 16 +++++++++++----- .../InheritanceMarginTaggerProvider.cs | 7 ++++++- .../Compiler/Core/Log/FunctionId.cs | 3 +++ 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/EditorFeatures/Core/InheritanceMargin/AbstractInheritanceMarginService.cs b/src/EditorFeatures/Core/InheritanceMargin/AbstractInheritanceMarginService.cs index 19ccfd66c8666..39348d1281c3e 100644 --- a/src/EditorFeatures/Core/InheritanceMargin/AbstractInheritanceMarginService.cs +++ b/src/EditorFeatures/Core/InheritanceMargin/AbstractInheritanceMarginService.cs @@ -6,6 +6,7 @@ using System.Collections.Immutable; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Internal.Log; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.SymbolMapping; @@ -76,11 +77,16 @@ public async ValueTask> GetInheritanceMemb } var solution = project.Solution; - var serializedInheritanceMarginItems = await GetInheritanceMemberItemAsync( - solution, - project.Id, - symbolKeyAndLineNumbers, - cancellationToken).ConfigureAwait(false); + var serializedInheritanceMarginItems = ImmutableArray.Empty; + using (Logger.LogBlock(FunctionId.InheritanceMargin_TraverseInheritanceChain, cancellationToken)) + { + serializedInheritanceMarginItems = await GetInheritanceMemberItemAsync( + solution, + project.Id, + symbolKeyAndLineNumbers, + cancellationToken).ConfigureAwait(false); + } + return await serializedInheritanceMarginItems.SelectAsArrayAsync( (serializedItem, _) => InheritanceMarginItem.ConvertAsync(solution, serializedItem, cancellationToken), cancellationToken).ConfigureAwait(false); } diff --git a/src/VisualStudio/Core/Def/Implementation/InheritanceMargin/InheritanceMarginTaggerProvider.cs b/src/VisualStudio/Core/Def/Implementation/InheritanceMargin/InheritanceMarginTaggerProvider.cs index c06ce7c742841..a9c3cb7db31e2 100644 --- a/src/VisualStudio/Core/Def/Implementation/InheritanceMargin/InheritanceMarginTaggerProvider.cs +++ b/src/VisualStudio/Core/Def/Implementation/InheritanceMargin/InheritanceMarginTaggerProvider.cs @@ -18,6 +18,7 @@ using Microsoft.CodeAnalysis.Experiments; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.InheritanceMargin; +using Microsoft.CodeAnalysis.Internal.Log; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.TestHooks; using Microsoft.VisualStudio.Debugger.ComponentInterfaces; @@ -111,10 +112,14 @@ protected override async Task ProduceTagsAsync( return; } - var inheritanceMemberItems = await inheritanceMarginInfoService.GetInheritanceMemberItemsAsync( + var inheritanceMemberItems = ImmutableArray.Empty; + using (Logger.LogBlock(FunctionId.InheritanceMargin_GetInheritanceMemberItems, cancellationToken)) + { + inheritanceMemberItems = await inheritanceMarginInfoService.GetInheritanceMemberItemsAsync( document, spanToTag.SnapshotSpan.Span.ToTextSpan(), cancellationToken).ConfigureAwait(false); + } if (inheritanceMemberItems.IsEmpty) { diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Log/FunctionId.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Log/FunctionId.cs index fcec5874bb816..27eefda1e4951 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Log/FunctionId.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Log/FunctionId.cs @@ -522,5 +522,8 @@ internal enum FunctionId ValueTracking_Command = 490, ValueTracking_TrackValueSource = 491, + + InheritanceMargin_GetInheritanceMemberItems = 492, + InheritanceMargin_TraverseInheritanceChain = 493, } } From 5c00bcd1c17e0860ad53ab8568d4b2e6284c3c5c Mon Sep 17 00:00:00 2001 From: Shen Chen Date: Thu, 24 Jun 2021 16:09:10 -0700 Subject: [PATCH 03/16] Change the trace level to information --- .../Core/InheritanceMargin/AbstractInheritanceMarginService.cs | 2 +- .../InheritanceMargin/InheritanceMarginTaggerProvider.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/EditorFeatures/Core/InheritanceMargin/AbstractInheritanceMarginService.cs b/src/EditorFeatures/Core/InheritanceMargin/AbstractInheritanceMarginService.cs index 39348d1281c3e..58cef244a6391 100644 --- a/src/EditorFeatures/Core/InheritanceMargin/AbstractInheritanceMarginService.cs +++ b/src/EditorFeatures/Core/InheritanceMargin/AbstractInheritanceMarginService.cs @@ -78,7 +78,7 @@ public async ValueTask> GetInheritanceMemb var solution = project.Solution; var serializedInheritanceMarginItems = ImmutableArray.Empty; - using (Logger.LogBlock(FunctionId.InheritanceMargin_TraverseInheritanceChain, cancellationToken)) + using (Logger.LogBlock(FunctionId.InheritanceMargin_TraverseInheritanceChain, cancellationToken, LogLevel.Information)) { serializedInheritanceMarginItems = await GetInheritanceMemberItemAsync( solution, diff --git a/src/VisualStudio/Core/Def/Implementation/InheritanceMargin/InheritanceMarginTaggerProvider.cs b/src/VisualStudio/Core/Def/Implementation/InheritanceMargin/InheritanceMarginTaggerProvider.cs index a9c3cb7db31e2..a14bb61a6de92 100644 --- a/src/VisualStudio/Core/Def/Implementation/InheritanceMargin/InheritanceMarginTaggerProvider.cs +++ b/src/VisualStudio/Core/Def/Implementation/InheritanceMargin/InheritanceMarginTaggerProvider.cs @@ -113,7 +113,7 @@ protected override async Task ProduceTagsAsync( } var inheritanceMemberItems = ImmutableArray.Empty; - using (Logger.LogBlock(FunctionId.InheritanceMargin_GetInheritanceMemberItems, cancellationToken)) + using (Logger.LogBlock(FunctionId.InheritanceMargin_GetInheritanceMemberItems, cancellationToken, LogLevel.Information)) { inheritanceMemberItems = await inheritanceMarginInfoService.GetInheritanceMemberItemsAsync( document, From 39f4e230df5ff2f9dd3b0a66a04c12bc13e67f54 Mon Sep 17 00:00:00 2001 From: Shen Chen Date: Thu, 24 Jun 2021 16:23:39 -0700 Subject: [PATCH 04/16] Remove unused using --- .../InheritanceMargin/InheritanceMarginTaggerProvider.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/VisualStudio/Core/Def/Implementation/InheritanceMargin/InheritanceMarginTaggerProvider.cs b/src/VisualStudio/Core/Def/Implementation/InheritanceMargin/InheritanceMarginTaggerProvider.cs index a14bb61a6de92..7f7357b82ad73 100644 --- a/src/VisualStudio/Core/Def/Implementation/InheritanceMargin/InheritanceMarginTaggerProvider.cs +++ b/src/VisualStudio/Core/Def/Implementation/InheritanceMargin/InheritanceMarginTaggerProvider.cs @@ -21,7 +21,6 @@ using Microsoft.CodeAnalysis.Internal.Log; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.TestHooks; -using Microsoft.VisualStudio.Debugger.ComponentInterfaces; using Microsoft.VisualStudio.Text; using Microsoft.VisualStudio.Text.Editor; using Microsoft.VisualStudio.Text.Tagging; From 9a7ddac1553d9f7e61dabfda54b8cf5e4e844972 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Thu, 24 Jun 2021 17:49:53 -0700 Subject: [PATCH 05/16] Expose completion options to IntelliCode --- .../Api/IntelliCodeCompletionOptions.cs | 16 ++++++++++++++++ .../Microsoft.CodeAnalysis.Features.csproj | 1 + 2 files changed, 17 insertions(+) create mode 100644 src/Features/Core/Portable/ExternalAccess/IntelliCode/Api/IntelliCodeCompletionOptions.cs diff --git a/src/Features/Core/Portable/ExternalAccess/IntelliCode/Api/IntelliCodeCompletionOptions.cs b/src/Features/Core/Portable/ExternalAccess/IntelliCode/Api/IntelliCodeCompletionOptions.cs new file mode 100644 index 0000000000000..fe59bf815df21 --- /dev/null +++ b/src/Features/Core/Portable/ExternalAccess/IntelliCode/Api/IntelliCodeCompletionOptions.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.CodeAnalysis.Completion; +using Microsoft.CodeAnalysis.Options; + +namespace Microsoft.CodeAnalysis.ExternalAccess.IntelliCode.Api +{ + internal static class IntelliCodeCompletionOptions + { + public static PerLanguageOption TriggerOnTyping { get; } = (PerLanguageOption)CompletionOptions.TriggerOnTyping; + + public static PerLanguageOption TriggerOnTypingLetters { get; } = (PerLanguageOption)CompletionOptions.TriggerOnTypingLetters2; + } +} diff --git a/src/Features/Core/Portable/Microsoft.CodeAnalysis.Features.csproj b/src/Features/Core/Portable/Microsoft.CodeAnalysis.Features.csproj index 0bc851e83fe87..853b177c2a3b0 100644 --- a/src/Features/Core/Portable/Microsoft.CodeAnalysis.Features.csproj +++ b/src/Features/Core/Portable/Microsoft.CodeAnalysis.Features.csproj @@ -100,6 +100,7 @@ + From c4ec84592b9901ed2ec91233adab4d18a2b7b130 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Thu, 24 Jun 2021 17:53:29 -0700 Subject: [PATCH 06/16] Define IIntelliCodeArgumentDefaultsSource for IntelliCode integration with argument completion --- .../Api/IIntelliCodeArgumentDefaultsSource.cs | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 src/EditorFeatures/Core/ExternalAccess/IntelliCode/Api/IIntelliCodeArgumentDefaultsSource.cs diff --git a/src/EditorFeatures/Core/ExternalAccess/IntelliCode/Api/IIntelliCodeArgumentDefaultsSource.cs b/src/EditorFeatures/Core/ExternalAccess/IntelliCode/Api/IIntelliCodeArgumentDefaultsSource.cs new file mode 100644 index 0000000000000..7ac6a9ac08fe5 --- /dev/null +++ b/src/EditorFeatures/Core/ExternalAccess/IntelliCode/Api/IIntelliCodeArgumentDefaultsSource.cs @@ -0,0 +1,58 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Immutable; +using System.Threading.Tasks; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Utilities; + +namespace Microsoft.CodeAnalysis.ExternalAccess.IntelliCode.Api +{ + /// + /// Provides a list of possible default arguments for method calls. + /// + /// + /// This is a MEF component and should be exported with and attributes + /// and optional and attributes. + /// An instance of is selected + /// first by matching ContentType with content type of the , and then by order. + /// Only one is used in a given view. + /// + /// Only one will used for any given . The sources are + /// ordered by the Order attribute. The first source (if any) that satisfies the ContentType and TextViewRoles + /// attributes will be the source used to provide defaults. + /// + /// + /// + /// [Export(typeof(IIntelliCodeArgumentDefaultsSource))] + /// [Name(nameof(IntelliCodeArgumentDefaultsSource))] + /// [ContentType("text")] + /// [TextViewRoles(PredefinedTextViewRoles.Editable)] + /// [Order(Before = "OtherCompletionDefaultsSource")] + /// public class IntelliCodeArgumentDefaultsSource : IIntelliCodeArgumentDefaultsSource + /// + /// + /// + internal interface IIntelliCodeArgumentDefaultsSource + { + /// + /// Gets a list of possible default arguments for a method signature. + /// + /// View for which the defaults are desired. + /// A list of possible default arguments for a method signature. + /// + /// The returned value will always be in the form of a "complete" set of arguments, including the leading and trailing parenthesis. + /// For example: + /// + /// () + /// (args[0]) + /// (args.Length) + /// (value: args.Length) + /// + /// + /// Some of the proposals may be syntactically/semantically invalid (and can be ignored by the caller). + /// + Task> GetArgumentDefaultsAsync(ITextView view); + } +} From 5cb76b702eae2473343a7672516b04e9ad49a4d0 Mon Sep 17 00:00:00 2001 From: Shen Chen Date: Fri, 25 Jun 2021 10:33:46 -0700 Subject: [PATCH 07/16] Use binding instead of tri state check box --- .../AbstractInheritanceMarginService.cs | 14 +++++--------- .../Impl/Options/AdvancedOptionPageControl.xaml | 4 ---- .../Impl/Options/AdvancedOptionPageControl.xaml.cs | 11 ++++------- .../Impl/Options/AdvancedOptionPageControl.xaml | 4 ---- .../Impl/Options/AdvancedOptionPageControl.xaml.vb | 12 ++++++------ 5 files changed, 15 insertions(+), 30 deletions(-) diff --git a/src/EditorFeatures/Core/InheritanceMargin/AbstractInheritanceMarginService.cs b/src/EditorFeatures/Core/InheritanceMargin/AbstractInheritanceMarginService.cs index 58cef244a6391..2f3d589224ea4 100644 --- a/src/EditorFeatures/Core/InheritanceMargin/AbstractInheritanceMarginService.cs +++ b/src/EditorFeatures/Core/InheritanceMargin/AbstractInheritanceMarginService.cs @@ -77,15 +77,11 @@ public async ValueTask> GetInheritanceMemb } var solution = project.Solution; - var serializedInheritanceMarginItems = ImmutableArray.Empty; - using (Logger.LogBlock(FunctionId.InheritanceMargin_TraverseInheritanceChain, cancellationToken, LogLevel.Information)) - { - serializedInheritanceMarginItems = await GetInheritanceMemberItemAsync( - solution, - project.Id, - symbolKeyAndLineNumbers, - cancellationToken).ConfigureAwait(false); - } + var serializedInheritanceMarginItems = await GetInheritanceMemberItemAsync( + solution, + project.Id, + symbolKeyAndLineNumbers, + cancellationToken).ConfigureAwait(false); return await serializedInheritanceMarginItems.SelectAsArrayAsync( (serializedItem, _) => InheritanceMarginItem.ConvertAsync(solution, serializedItem, cancellationToken), cancellationToken).ConfigureAwait(false); diff --git a/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml b/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml index af459faad4c98..ae4749eab75e5 100644 --- a/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml +++ b/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml @@ -271,10 +271,6 @@ diff --git a/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml.cs b/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml.cs index 86e656a5253f8..30135ffd47a90 100644 --- a/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml.cs +++ b/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml.cs @@ -130,7 +130,10 @@ public AdvancedOptionPageControl(OptionStore optionStore, IComponentModel compon BindToOption(ShowHintsForLambdaParameterTypes, InlineHintsOptions.ForLambdaParameterTypes, LanguageNames.CSharp); BindToOption(ShowHintsForImplicitObjectCreation, InlineHintsOptions.ForImplicitObjectCreation, LanguageNames.CSharp); - ShowInheritanceMargin.IsChecked = OptionStore.GetOption(FeatureOnOffOptions.ShowInheritanceMargin, LanguageNames.CSharp); + // If the option has not been set by the user, check if the option is enabled from experimentation. + // If so, default to that. Otherwise default to disabled + BindToOption(ShowInheritanceMargin, FeatureOnOffOptions.ShowInheritanceMargin, LanguageNames.CSharp, () => + experimentationService?.IsExperimentEnabled(WellKnownExperimentNames.InheritanceMargin) ?? false); } // Since this dialog is constructed once for the lifetime of the application and VS Theme can be changed after the application has started, @@ -218,11 +221,5 @@ private void DisplayInlineTypeHints_Unchecked(object sender, RoutedEventArgs e) this.OptionStore.SetOption(InlineHintsOptions.EnabledForTypes, LanguageNames.CSharp, false); UpdateInlineHintsOptions(); } - - private void ShowInheritanceMargin_Changed(object sender, RoutedEventArgs e) - { - this.ShowInheritanceMargin.IsThreeState = false; - this.OptionStore.SetOption(FeatureOnOffOptions.ShowInheritanceMargin, LanguageNames.CSharp, this.ShowInheritanceMargin.IsChecked); - } } } diff --git a/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml b/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml index d8f64d98ae626..4d6d131fb3d37 100644 --- a/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml +++ b/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml @@ -249,10 +249,6 @@ diff --git a/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml.vb b/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml.vb index 5f9913e323078..ba84bbeddd0db 100644 --- a/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml.vb +++ b/src/VisualStudio/VisualBasic/Impl/Options/AdvancedOptionPageControl.xaml.vb @@ -146,7 +146,12 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Options BindToOption(SuppressHintsWhenParameterNameMatchesTheMethodsIntent, InlineHintsOptions.SuppressForParametersThatMatchMethodIntent, LanguageNames.VisualBasic) BindToOption(SuppressHintsWhenParameterNamesDifferOnlyBySuffix, InlineHintsOptions.SuppressForParametersThatDifferOnlyBySuffix, LanguageNames.VisualBasic) - ShowInheritanceMargin.IsChecked = optionStore.GetOption(FeatureOnOffOptions.ShowInheritanceMargin, LanguageNames.VisualBasic) + BindToOption(ShowInheritanceMargin, FeatureOnOffOptions.ShowInheritanceMargin, LanguageNames.VisualBasic, + Function() + ' If the option has not been set by the user, check if the option Is enabled from experimentation. + ' If so, default to that. Otherwise default to disabled + Return If(experimentationService?.IsExperimentEnabled(WellKnownExperimentNames.InheritanceMargin), False) + End Function) End Sub ' Since this dialog is constructed once for the lifetime of the application and VS Theme can be changed after the application has started, @@ -182,10 +187,5 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Options Me.OptionStore.SetOption(InlineHintsOptions.EnabledForParameters, LanguageNames.VisualBasic, False) UpdateInlineHintsOptions() End Sub - - Private Sub ShowInheritanceMargin_Changed(sender As Object, e As RoutedEventArgs) - Me.ShowInheritanceMargin.IsThreeState = False - Me.OptionStore.SetOption(FeatureOnOffOptions.ShowInheritanceMargin, LanguageNames.VisualBasic, Me.ShowInheritanceMargin.IsChecked) - End Sub End Class End Namespace From 41734a71f6fa9f3f485aa4b573acdffd58442a0a Mon Sep 17 00:00:00 2001 From: David Barbet Date: Thu, 24 Jun 2021 10:22:53 -0700 Subject: [PATCH 08/16] Query IDocumentTrackingService for active document when we are not passed a project context in an LSP request. --- .../Protocol/Extensions/Extensions.cs | 29 +++++-- .../Diagnostics/PullDiagnosticTests.cs | 83 +++++++++++++++---- 2 files changed, 89 insertions(+), 23 deletions(-) diff --git a/src/Features/LanguageServer/Protocol/Extensions/Extensions.cs b/src/Features/LanguageServer/Protocol/Extensions/Extensions.cs index 02a9fcff145b2..d88808f153745 100644 --- a/src/Features/LanguageServer/Protocol/Extensions/Extensions.cs +++ b/src/Features/LanguageServer/Protocol/Extensions/Extensions.cs @@ -93,17 +93,30 @@ public static T FindDocumentInProjectContext(this ImmutableArray documents if (documents.Length > 1) { // We have more than one document; try to find the one that matches the right context - if (documentIdentifier is VSTextDocumentIdentifier vsDocumentIdentifier) + if (documentIdentifier is VSTextDocumentIdentifier vsDocumentIdentifier && vsDocumentIdentifier.ProjectContext != null) { - if (vsDocumentIdentifier.ProjectContext != null) + var projectId = ProtocolConversions.ProjectContextToProjectId(vsDocumentIdentifier.ProjectContext); + var matchingDocument = documents.FirstOrDefault(d => d.Project.Id == projectId); + + if (matchingDocument != null) { - var projectId = ProtocolConversions.ProjectContextToProjectId(vsDocumentIdentifier.ProjectContext); - var matchingDocument = documents.FirstOrDefault(d => d.Project.Id == projectId); + return matchingDocument; + } + } + else + { + // We were not passed a project context. This can happen when the LSP powered NavBar is not enabled. + // This branch should be removed when we're using the LSP based navbar in all scenarios. + + // Lookup the active document and determine if any of the documents from the request URI match. + var solution = documents.First().Project.Solution; + var service = solution.Workspace.Services.GetRequiredService(); - if (matchingDocument != null) - { - return matchingDocument; - } + var activeDocument = service.GetActiveDocument(solution); + var matchingDocument = documents.FirstOrDefault(d => d.Id == activeDocument?.Id); + if (matchingDocument != null) + { + return matchingDocument; } } } diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Diagnostics/PullDiagnosticTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/Diagnostics/PullDiagnosticTests.cs index aced34618d550..b4ecb81c61e21 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/Diagnostics/PullDiagnosticTests.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/Diagnostics/PullDiagnosticTests.cs @@ -7,9 +7,11 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Editor.Test; using Microsoft.CodeAnalysis.Editor.UnitTests.Diagnostics; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; using Microsoft.CodeAnalysis.LanguageServer.Handler; +using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.TestHooks; using Microsoft.CodeAnalysis.SolutionCrawler; using Microsoft.CodeAnalysis.Text; @@ -33,7 +35,7 @@ public async Task TestNoDocumentDiagnosticsForClosedFilesWithFSAOff() var document = testLspServer.GetCurrentSolution().Projects.Single().Documents.Single(); - var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, document); + var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, document.GetURI()); Assert.Empty(results); } @@ -53,7 +55,7 @@ public async Task TestDocumentDiagnosticsForOpenFilesWithFSAOff() await OpenDocumentAsync(testLspServer, document); var results = await RunGetDocumentPullDiagnosticsAsync( - testLspServer, testLspServer.GetCurrentSolution().Projects.Single().Documents.Single()); + testLspServer, document.GetURI()); Assert.Equal("CS1513", results.Single().Diagnostics.Single().Code); } @@ -72,7 +74,7 @@ public async Task TestNoDocumentDiagnosticsForOpenFilesWithFSAOffIfInPushMode() await OpenDocumentAsync(testLspServer, document); - var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, document); + var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, document.GetURI()); Assert.Empty(results.Single().Diagnostics); } @@ -98,7 +100,7 @@ public async Task TestDocumentDiagnosticsForRemovedDocument() await WaitForDiagnosticsAsync(workspace); var results = await testLspServer.ExecuteRequestAsync( MSLSPMethods.DocumentPullDiagnosticName, - CreateDocumentDiagnosticParams(document), + CreateDocumentDiagnosticParams(document.GetURI()), new LSP.ClientCapabilities(), clientName: null, CancellationToken.None); @@ -136,13 +138,13 @@ public async Task TestNoChangeIfDocumentDiagnosticsCalledTwice() await OpenDocumentAsync(testLspServer, document); - var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, document); + var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, document.GetURI()); Assert.Equal("CS1513", results.Single().Diagnostics.Single().Code); var resultId = results.Single().ResultId; results = await RunGetDocumentPullDiagnosticsAsync( - testLspServer, testLspServer.GetCurrentSolution().Projects.Single().Documents.Single(), previousResultId: resultId); + testLspServer, document.GetURI(), previousResultId: resultId); Assert.Null(results.Single().Diagnostics); Assert.Equal(resultId, results.Single().ResultId); @@ -162,13 +164,13 @@ public async Task TestDocumentDiagnosticsRemovedAfterErrorIsFixed() await OpenDocumentAsync(testLspServer, document); - var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, document); + var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, document.GetURI()); Assert.Equal("CS1513", results[0].Diagnostics.Single().Code); await InsertTextAsync(testLspServer, document, buffer.CurrentSnapshot.Length, "}"); - results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, testLspServer.GetCurrentSolution().Projects.Single().Documents.Single()); + results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, document.GetURI()); Assert.Empty(results[0].Diagnostics); } @@ -186,7 +188,7 @@ public async Task TestDocumentDiagnosticsRemainAfterErrorIsNotFixed() var document = testLspServer.GetCurrentSolution().Projects.Single().Documents.Single(); await OpenDocumentAsync(testLspServer, document); - var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, document); + var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, document.GetURI()); Assert.Equal("CS1513", results[0].Diagnostics.Single().Code); Assert.Equal(new Position { Line = 0, Character = 9 }, results[0].Diagnostics.Single().Range.Start); @@ -195,7 +197,7 @@ public async Task TestDocumentDiagnosticsRemainAfterErrorIsNotFixed() await InsertTextAsync(testLspServer, document, position: 0, text: " "); results = await RunGetDocumentPullDiagnosticsAsync( - testLspServer, testLspServer.GetCurrentSolution().Projects.Single().Documents.Single(), + testLspServer, document.GetURI(), previousResultId: results[0].ResultId); Assert.Equal("CS1513", results[0].Diagnostics.Single().Code); @@ -233,12 +235,56 @@ public async Task TestStreamingDocumentDiagnostics() await OpenDocumentAsync(testLspServer, document); var progress = BufferedProgress.Create(null); - var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, testLspServer.GetCurrentSolution().Projects.Single().Documents.Single(), progress: progress); + var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, document.GetURI(), progress: progress); Assert.Null(results); Assert.Equal("CS1513", progress.GetValues()!.Single().Diagnostics.Single().Code); } + [Fact] + public async Task TestDocumentDiagnosticsForOpenFilesUsesActiveContext() + { + var documentText = +@"#if ONE +class A { +#endif +class B {"; + var workspaceXml = +@$" + + {documentText} + + + {documentText} + +"; + + using var testLspServer = CreateTestWorkspaceFromXml(workspaceXml, BackgroundAnalysisScope.OpenFilesAndProjects); + + var csproj1Document = testLspServer.GetCurrentSolution().Projects.Where(p => p.Name == "CSProj1").Single().Documents.First(); + var csproj2Document = testLspServer.GetCurrentSolution().Projects.Where(p => p.Name == "CSProj2").Single().Documents.First(); + + // Open either of the documents, LSP is just tracking the URI and text. + await OpenDocumentAsync(testLspServer, csproj1Document); + + // Set the active context to be document from CSProj2 + var documentTrackingService = (TestDocumentTrackingService)testLspServer.TestWorkspace.Services.GetRequiredService(); + documentTrackingService.SetActiveDocument(csproj2Document.Id); + + var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, csproj2Document.GetURI()); + Assert.Equal("CS1513", results.Single().Diagnostics.Single().Code); + var vsDiagnostic = (LSP.VSDiagnostic)results.Single().Diagnostics.Single(); + Assert.Equal("CSProj2", vsDiagnostic.Projects.Single().ProjectName); + + // Set the active context to be document from CSProj1 + documentTrackingService.SetActiveDocument(csproj1Document.Id); + + results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, csproj1Document.GetURI()); + Assert.Equal(2, results.Single().Diagnostics!.Length); + Assert.All(results.Single().Diagnostics, d => Assert.Equal("CS1513", d.Code)); + Assert.All(results.Single().Diagnostics, d => Assert.Equal("CSProj1", ((VSDiagnostic)d).Projects.Single().ProjectName)); + } + #endregion #region Workspace Diagnostics @@ -439,7 +485,7 @@ public async Task TestStreamingWorkspaceDiagnostics() private static async Task RunGetDocumentPullDiagnosticsAsync( TestLspServer testLspServer, - Document document, + Uri uri, string? previousResultId = null, IProgress? progress = null) { @@ -447,7 +493,7 @@ private static async Task RunGetDocumentPullDiagnosticsAsync var result = await testLspServer.ExecuteRequestAsync( MSLSPMethods.DocumentPullDiagnosticName, - CreateDocumentDiagnosticParams(document, previousResultId, progress), + CreateDocumentDiagnosticParams(uri, previousResultId, progress), new LSP.ClientCapabilities(), clientName: null, CancellationToken.None); @@ -482,13 +528,13 @@ private static async Task WaitForDiagnosticsAsync(TestWorkspace workspace) } private static DocumentDiagnosticsParams CreateDocumentDiagnosticParams( - Document document, + Uri uri, string? previousResultId = null, IProgress? progress = null) { return new DocumentDiagnosticsParams { - TextDocument = ProtocolConversions.DocumentToTextDocumentIdentifier(document), + TextDocument = new LSP.TextDocumentIdentifier { Uri = uri }, PreviousResultId = previousResultId, PartialResultToken = progress, }; @@ -512,6 +558,13 @@ private TestLspServer CreateTestWorkspaceWithDiagnostics(string markup, Backgrou return testLspServer; } + private TestLspServer CreateTestWorkspaceFromXml(string xmlMarkup, BackgroundAnalysisScope scope, bool pullDiagnostics = true) + { + var testLspServer = CreateXmlTestLspServer(xmlMarkup, out _); + InitializeDiagnostics(scope, testLspServer.TestWorkspace, pullDiagnostics); + return testLspServer; + } + private TestLspServer CreateTestWorkspaceWithDiagnostics(string[] markups, BackgroundAnalysisScope scope, bool pullDiagnostics = true) { var testLspServer = CreateTestLspServer(markups, out _); From ee53ed35ae3163787e9f02971ffffc2f18677766 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Fri, 25 Jun 2021 14:39:28 -0700 Subject: [PATCH 09/16] Avoid costly calls to GetAllStateSets inside ContainsDiagnostics Fixes #54400 --- ...gnosticIncrementalAnalyzer.StateManager.cs | 46 +++++++++++++++++++ .../EngineV2/DiagnosticIncrementalAnalyzer.cs | 13 ++---- 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.StateManager.cs b/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.StateManager.cs index 3d398a1b76fc5..a483dbe3b8649 100644 --- a/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.StateManager.cs +++ b/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.StateManager.cs @@ -188,6 +188,52 @@ public ImmutableArray CreateBuildOnlyProjectStateSet(Project project) return stateSets.ToImmutable(); } + /// + /// Determines if any of the state sets in match a specified predicate. + /// + /// + /// This method avoids the performance overhead of calling for the + /// specific case where the result is only used for testing if any element meets certain conditions. + /// + public bool HasAnyHostStateSet(Func match, TArg arg) + { + foreach (var (_, hostStateSet) in _hostAnalyzerStateMap) + { + foreach (var stateSet in hostStateSet.OrderedStateSets) + { + if (match(stateSet, arg)) + return true; + } + } + + return false; + } + + /// + /// Determines if any of the state sets in for a specific project + /// match a specified predicate. + /// + /// + /// This method avoids the performance overhead of calling for the + /// specific case where the result is only used for testing if any element meets certain conditions. + /// + /// Note that host state sets (i.e. ones retured by are not tested + /// by this method. + /// + public bool HasAnyProjectStateSet(ProjectId projectId, Func match, TArg arg) + { + if (_projectAnalyzerStateMap.TryGetValue(projectId, out var entry)) + { + foreach (var (_, stateSet) in entry.StateSetMap) + { + if (match(stateSet, arg)) + return true; + } + } + + return false; + } + public bool OnProjectRemoved(IEnumerable stateSets, ProjectId projectId) { var removed = false; diff --git a/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.cs b/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.cs index 1366c6d094351..dfe9aaba981bf 100644 --- a/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.cs +++ b/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.cs @@ -11,7 +11,6 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeStyle; -using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.PooledObjects; @@ -64,17 +63,11 @@ public DiagnosticIncrementalAnalyzer( internal DiagnosticAnalyzerInfoCache DiagnosticAnalyzerInfoCache => _diagnosticAnalyzerRunner.AnalyzerInfoCache; + [PerformanceSensitive("https://github.com/dotnet/roslyn/issues/54400", Constraint = "Avoid calling GetAllHostStateSets on this hot path.")] public bool ContainsDiagnostics(ProjectId projectId) { - foreach (var stateSet in _stateManager.GetStateSets(projectId)) - { - if (stateSet.ContainsAnyDocumentOrProjectDiagnostics(projectId)) - { - return true; - } - } - - return false; + return _stateManager.HasAnyHostStateSet(static (stateSet, arg) => stateSet.ContainsAnyDocumentOrProjectDiagnostics(arg), projectId) + || _stateManager.HasAnyProjectStateSet(projectId, static (stateSet, arg) => stateSet.ContainsAnyDocumentOrProjectDiagnostics(arg), projectId); } public bool NeedsReanalysisOnOptionChanged(object sender, OptionChangedEventArgs e) From a935a8daf1eb69166d4f2c9b212c367160dd92c3 Mon Sep 17 00:00:00 2001 From: Shen Chen Date: Fri, 25 Jun 2021 11:38:03 -0700 Subject: [PATCH 10/16] Clean code --- .../Core/InheritanceMargin/AbstractInheritanceMarginService.cs | 2 -- .../Compiler/Core/Log/FunctionId.cs | 1 - 2 files changed, 3 deletions(-) diff --git a/src/EditorFeatures/Core/InheritanceMargin/AbstractInheritanceMarginService.cs b/src/EditorFeatures/Core/InheritanceMargin/AbstractInheritanceMarginService.cs index 2f3d589224ea4..19ccfd66c8666 100644 --- a/src/EditorFeatures/Core/InheritanceMargin/AbstractInheritanceMarginService.cs +++ b/src/EditorFeatures/Core/InheritanceMargin/AbstractInheritanceMarginService.cs @@ -6,7 +6,6 @@ using System.Collections.Immutable; using System.Threading; using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Internal.Log; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.SymbolMapping; @@ -82,7 +81,6 @@ public async ValueTask> GetInheritanceMemb project.Id, symbolKeyAndLineNumbers, cancellationToken).ConfigureAwait(false); - return await serializedInheritanceMarginItems.SelectAsArrayAsync( (serializedItem, _) => InheritanceMarginItem.ConvertAsync(solution, serializedItem, cancellationToken), cancellationToken).ConfigureAwait(false); } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Log/FunctionId.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Log/FunctionId.cs index 27eefda1e4951..d29e741700762 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Log/FunctionId.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Log/FunctionId.cs @@ -524,6 +524,5 @@ internal enum FunctionId ValueTracking_TrackValueSource = 491, InheritanceMargin_GetInheritanceMemberItems = 492, - InheritanceMargin_TraverseInheritanceChain = 493, } } From 5605038cd5bf9e605e8c1d9f69ca202e6ed1abbf Mon Sep 17 00:00:00 2001 From: David Barbet Date: Fri, 25 Jun 2021 17:36:43 -0700 Subject: [PATCH 11/16] Switch to correct workspace api to get active context --- .../Protocol/Extensions/Extensions.cs | 14 ++++---------- .../Diagnostics/PullDiagnosticTests.cs | 14 +++++++------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/src/Features/LanguageServer/Protocol/Extensions/Extensions.cs b/src/Features/LanguageServer/Protocol/Extensions/Extensions.cs index d88808f153745..f149a00bbba7e 100644 --- a/src/Features/LanguageServer/Protocol/Extensions/Extensions.cs +++ b/src/Features/LanguageServer/Protocol/Extensions/Extensions.cs @@ -88,7 +88,7 @@ private static ImmutableArray FilterDocumentsByClientName(ImmutableArr return documents.FindDocumentInProjectContext(documentIdentifier); } - public static T FindDocumentInProjectContext(this ImmutableArray documents, TextDocumentIdentifier documentIdentifier) where T : TextDocument + public static Document FindDocumentInProjectContext(this ImmutableArray documents, TextDocumentIdentifier documentIdentifier) { if (documents.Length > 1) { @@ -108,16 +108,10 @@ public static T FindDocumentInProjectContext(this ImmutableArray documents // We were not passed a project context. This can happen when the LSP powered NavBar is not enabled. // This branch should be removed when we're using the LSP based navbar in all scenarios. - // Lookup the active document and determine if any of the documents from the request URI match. var solution = documents.First().Project.Solution; - var service = solution.Workspace.Services.GetRequiredService(); - - var activeDocument = service.GetActiveDocument(solution); - var matchingDocument = documents.FirstOrDefault(d => d.Id == activeDocument?.Id); - if (matchingDocument != null) - { - return matchingDocument; - } + // Lookup which of the linked documents is currently active in the workspace. + var documentIdInCurrentContext = solution.Workspace.GetDocumentIdInCurrentContext(documents.First().Id); + return solution.GetRequiredDocument(documentIdInCurrentContext); } } diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Diagnostics/PullDiagnosticTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/Diagnostics/PullDiagnosticTests.cs index b4ecb81c61e21..44473a03355e2 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/Diagnostics/PullDiagnosticTests.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/Diagnostics/PullDiagnosticTests.cs @@ -264,21 +264,21 @@ class B {"; var csproj1Document = testLspServer.GetCurrentSolution().Projects.Where(p => p.Name == "CSProj1").Single().Documents.First(); var csproj2Document = testLspServer.GetCurrentSolution().Projects.Where(p => p.Name == "CSProj2").Single().Documents.First(); - // Open either of the documents, LSP is just tracking the URI and text. + // Open either of the documents via LSP, we're tracking the URI and text. await OpenDocumentAsync(testLspServer, csproj1Document); - // Set the active context to be document from CSProj2 - var documentTrackingService = (TestDocumentTrackingService)testLspServer.TestWorkspace.Services.GetRequiredService(); - documentTrackingService.SetActiveDocument(csproj2Document.Id); + // This opens all documents in the workspace and ensures buffers are created. + testLspServer.TestWorkspace.GetTestDocument(csproj1Document.Id).GetTextBuffer(); + // Set CSProj2 as the active context and get diagnostics. + testLspServer.TestWorkspace.SetDocumentContext(csproj2Document.Id); var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, csproj2Document.GetURI()); Assert.Equal("CS1513", results.Single().Diagnostics.Single().Code); var vsDiagnostic = (LSP.VSDiagnostic)results.Single().Diagnostics.Single(); Assert.Equal("CSProj2", vsDiagnostic.Projects.Single().ProjectName); - // Set the active context to be document from CSProj1 - documentTrackingService.SetActiveDocument(csproj1Document.Id); - + // Set CSProj1 as the active context and get diagnostics. + testLspServer.TestWorkspace.SetDocumentContext(csproj1Document.Id); results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, csproj1Document.GetURI()); Assert.Equal(2, results.Single().Diagnostics!.Length); Assert.All(results.Single().Diagnostics, d => Assert.Equal("CS1513", d.Code)); From 59140f98967a9ddaae8e012eac22bb083b5ae6b9 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Sat, 26 Jun 2021 21:42:14 -0700 Subject: [PATCH 12/16] Insertion depends on DARC publishing (#54420) --- azure-pipelines-official.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/azure-pipelines-official.yml b/azure-pipelines-official.yml index a95070c72c9c4..2d407b6e37e49 100644 --- a/azure-pipelines-official.yml +++ b/azure-pipelines-official.yml @@ -291,7 +291,9 @@ stages: vmImage: vs2017-win2016 - stage: insert - dependsOn: build + dependsOn: + - build + - publish_using_darc displayName: Insert to VS jobs: From 41b2da74fb5e3842f50410bae69c4968d3581068 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Sun, 27 Jun 2021 19:19:47 -0700 Subject: [PATCH 13/16] Set AutoComplete based on CreateDraftPR --- azure-pipelines-official.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/azure-pipelines-official.yml b/azure-pipelines-official.yml index 2d407b6e37e49..974f0deb76c9f 100644 --- a/azure-pipelines-official.yml +++ b/azure-pipelines-official.yml @@ -332,6 +332,7 @@ stages: Write-Host "##vso[task.setvariable variable=Insertion.InsertToolset]$($branchData.insertToolset)" } + Write-Host "##vso[task.setvariable variable=Insertion.AutoComplete]$(-not $branchData.insertionCreateDraftPR)" Write-Host "##vso[task.setvariable variable=ComponentBranchName]$branchName" Write-Host "##vso[task.setvariable variable=VSBranchName]$($branchData.vsBranch)" displayName: Set Insertion Variables @@ -339,7 +340,7 @@ stages: - powershell: | mv RoslynTools.VisualStudioInsertionTool.* RIT .\RIT\tools\OneOffInsertion.ps1 ` - -autoComplete "false" ` + -autoComplete "$(Insertion.AutoComplete)" ` -buildQueueName "$(Build.DefinitionName)" ` -cherryPick "(default)" ` -clientId "$(ClientId)" ` From 695b279a419d008f972fd202dfd3882f80e026c8 Mon Sep 17 00:00:00 2001 From: Andrew Hall Date: Mon, 28 Jun 2021 12:48:40 -0700 Subject: [PATCH 14/16] Fix window missing title. Move string to resources --- .../Core/Def/ValueTracking/ValueTrackingToolWindow.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/VisualStudio/Core/Def/ValueTracking/ValueTrackingToolWindow.cs b/src/VisualStudio/Core/Def/ValueTracking/ValueTrackingToolWindow.cs index 35e8fe5ab766b..c47b9d092cc54 100644 --- a/src/VisualStudio/Core/Def/ValueTracking/ValueTrackingToolWindow.cs +++ b/src/VisualStudio/Core/Def/ValueTracking/ValueTrackingToolWindow.cs @@ -47,7 +47,7 @@ public ValueTrackingToolWindow() : base(null) _rootGrid.Children.Add(new TextBlock() { - Text = "Select an appropriate symbol to start value tracking" + Text = ServicesVSResources.Select_an_appropriate_symbol_to_start_value_tracking }); Content = _rootGrid; @@ -56,6 +56,7 @@ public ValueTrackingToolWindow() : base(null) public ValueTrackingToolWindow(ValueTrackingTreeViewModel viewModel) : base(null) { + Caption = ServicesVSResources.Value_Tracking; Content = _rootGrid; ViewModel = viewModel; } From 21a4b69dcee917f6db26196da7532031c97c6a8e Mon Sep 17 00:00:00 2001 From: Andrew Hall Date: Mon, 28 Jun 2021 12:49:36 -0700 Subject: [PATCH 15/16] Move string to resources --- src/VisualStudio/Core/Def/ServicesVSResources.resx | 3 +++ src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf | 5 +++++ src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf | 5 +++++ src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf | 5 +++++ src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf | 5 +++++ src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf | 5 +++++ src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf | 5 +++++ src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf | 5 +++++ src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf | 5 +++++ src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf | 5 +++++ src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf | 5 +++++ src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf | 5 +++++ .../Core/Def/xlf/ServicesVSResources.zh-Hans.xlf | 5 +++++ .../Core/Def/xlf/ServicesVSResources.zh-Hant.xlf | 5 +++++ 14 files changed, 68 insertions(+) diff --git a/src/VisualStudio/Core/Def/ServicesVSResources.resx b/src/VisualStudio/Core/Def/ServicesVSResources.resx index 1a85cc3e0ac41..caabce2d12c40 100644 --- a/src/VisualStudio/Core/Def/ServicesVSResources.resx +++ b/src/VisualStudio/Core/Def/ServicesVSResources.resx @@ -1770,4 +1770,7 @@ I agree to all of the foregoing: Inherited interfaces + + Select an appropriate symbol to start value tracking + \ No newline at end of file diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf index eed27c0ec20f3..099d2851e104e 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf @@ -987,6 +987,11 @@ Nastavení hledání + + Select an appropriate symbol to start value tracking + Select an appropriate symbol to start value tracking + + Select destination Vybrat cíl diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf index e0488f1591f4b..9f1002b4bfab0 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf @@ -987,6 +987,11 @@ Sucheinstellungen + + Select an appropriate symbol to start value tracking + Select an appropriate symbol to start value tracking + + Select destination Ziel auswählen diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf index 8b7c7ff04b098..969c9d02e88fd 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf @@ -987,6 +987,11 @@ Buscar configuración + + Select an appropriate symbol to start value tracking + Select an appropriate symbol to start value tracking + + Select destination Seleccionar destino diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf index 56e2d67f2eaaf..679fc6a454c49 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf @@ -987,6 +987,11 @@ Paramètres de recherche + + Select an appropriate symbol to start value tracking + Select an appropriate symbol to start value tracking + + Select destination Sélectionner la destination diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf index d87d41eacdd17..5248bd7d012ab 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf @@ -987,6 +987,11 @@ Impostazioni di ricerca + + Select an appropriate symbol to start value tracking + Select an appropriate symbol to start value tracking + + Select destination Seleziona destinazione diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf index eda507eab1eeb..9ebdfc4fada3b 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf @@ -987,6 +987,11 @@ 検索設定 + + Select an appropriate symbol to start value tracking + Select an appropriate symbol to start value tracking + + Select destination 宛先の選択 diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf index a1cad2cd2fe46..5517b47a90ea3 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf @@ -987,6 +987,11 @@ 검색 설정 + + Select an appropriate symbol to start value tracking + Select an appropriate symbol to start value tracking + + Select destination 대상 선택 diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf index bbb21c2156123..a88cbdc00479b 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf @@ -987,6 +987,11 @@ Ustawienia wyszukiwania + + Select an appropriate symbol to start value tracking + Select an appropriate symbol to start value tracking + + Select destination Wybierz miejsce docelowe diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf index 9ed72b71b0abd..631be6dc09509 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf @@ -987,6 +987,11 @@ Pesquisar as Configurações + + Select an appropriate symbol to start value tracking + Select an appropriate symbol to start value tracking + + Select destination Selecionar destino diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf index cc7baa287280e..43e37e7fb7556 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf @@ -987,6 +987,11 @@ Параметры поиска + + Select an appropriate symbol to start value tracking + Select an appropriate symbol to start value tracking + + Select destination Выбрать место назначения diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf index f287f0a741a49..2d6bb68bb0380 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf @@ -987,6 +987,11 @@ Arama Ayarları + + Select an appropriate symbol to start value tracking + Select an appropriate symbol to start value tracking + + Select destination Hedef seçin diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf index 0253635bf84b5..3496d40d78a79 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf @@ -987,6 +987,11 @@ 搜索设置 + + Select an appropriate symbol to start value tracking + Select an appropriate symbol to start value tracking + + Select destination 选择目标 diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf index 43eb2cb038fa7..aa3dee1116470 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf @@ -987,6 +987,11 @@ 搜尋設定 + + Select an appropriate symbol to start value tracking + Select an appropriate symbol to start value tracking + + Select destination 選取目的地 From 3844415e543b297a26bb15b4f4e6255f90c0866d Mon Sep 17 00:00:00 2001 From: David Wengier Date: Tue, 29 Jun 2021 07:45:03 +1000 Subject: [PATCH 16/16] Merge pull request #54453 from davidwengier/FixBuild --- .../ProtocolUnitTests/Diagnostics/PullDiagnosticTests.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Features/LanguageServer/ProtocolUnitTests/Diagnostics/PullDiagnosticTests.cs b/src/Features/LanguageServer/ProtocolUnitTests/Diagnostics/PullDiagnosticTests.cs index 390154eb27916..4e031801aadc8 100644 --- a/src/Features/LanguageServer/ProtocolUnitTests/Diagnostics/PullDiagnosticTests.cs +++ b/src/Features/LanguageServer/ProtocolUnitTests/Diagnostics/PullDiagnosticTests.cs @@ -97,7 +97,7 @@ public async Task TestNoDocumentDiagnosticsForOpenFilesIfDefaultAndFeatureFlagOf var testExperimentationService = (TestExperimentationService)testLspServer.TestWorkspace.Services.GetRequiredService(); testExperimentationService.SetExperimentOption(WellKnownExperimentNames.LspPullDiagnosticsFeatureFlag, false); - var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, document); + var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, document.GetURI()); Assert.Empty(results.Single().Diagnostics); } @@ -116,7 +116,7 @@ public async Task TestDocumentDiagnosticsForOpenFilesIfDefaultAndFeatureFlagOn() var testExperimentationService = (TestExperimentationService)testLspServer.TestWorkspace.Services.GetRequiredService(); testExperimentationService.SetExperimentOption(WellKnownExperimentNames.LspPullDiagnosticsFeatureFlag, true); - var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, document); + var results = await RunGetDocumentPullDiagnosticsAsync(testLspServer, document.GetURI()); Assert.Equal("CS1513", results.Single().Diagnostics.Single().Code); } @@ -605,7 +605,7 @@ private TestLspServer CreateTestWorkspaceWithDiagnostics(string markup, Backgrou private TestLspServer CreateTestWorkspaceFromXml(string xmlMarkup, BackgroundAnalysisScope scope, bool pullDiagnostics = true) { var testLspServer = CreateXmlTestLspServer(xmlMarkup, out _); - InitializeDiagnostics(scope, testLspServer.TestWorkspace, pullDiagnostics); + InitializeDiagnostics(scope, testLspServer.TestWorkspace, pullDiagnostics ? DiagnosticMode.Pull : DiagnosticMode.Push); return testLspServer; }