From 43e14b495217279022e9b3ca868210be64483821 Mon Sep 17 00:00:00 2001 From: Jason Malinowski Date: Thu, 2 Sep 2021 17:42:21 -0700 Subject: [PATCH 1/7] Wire up the feature flag properly for opening source generated files --- .../Def/Implementation/Workspace/SourceGeneratedFileManager.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/VisualStudio/Core/Def/Implementation/Workspace/SourceGeneratedFileManager.cs b/src/VisualStudio/Core/Def/Implementation/Workspace/SourceGeneratedFileManager.cs index d2bb72cf532c6..754dc3b3fd7da 100644 --- a/src/VisualStudio/Core/Def/Implementation/Workspace/SourceGeneratedFileManager.cs +++ b/src/VisualStudio/Core/Def/Implementation/Workspace/SourceGeneratedFileManager.cs @@ -389,7 +389,8 @@ public async ValueTask RefreshFileAsync(CancellationToken cancellationToken) // If the file isn't already open, open it now. We may transition between opening and closing // if the file is repeatedly appearing and disappearing. - var connectToWorkspace = _workspace.Options.GetOption(Options.EnableOpeningInWorkspace) ?? false; + var connectToWorkspace = _workspace.Options.GetOption(Options.EnableOpeningInWorkspace) ?? + _workspace.Options.GetOption(Options.EnableOpeningInWorkspaceFeatureFlag); if (connectToWorkspace && !_workspace.IsDocumentOpen(_documentIdentity.DocumentId)) { From 006a4adece2381ca4652c3b903e991193dc70068 Mon Sep 17 00:00:00 2001 From: Jason Malinowski Date: Thu, 2 Sep 2021 17:43:54 -0700 Subject: [PATCH 2/7] Fix stale comments --- .../CSharp/Impl/Options/AdvancedOptionPageControl.xaml.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml.cs b/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml.cs index 1168b5f29b288..ea972366fdc65 100644 --- a/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml.cs +++ b/src/VisualStudio/CSharp/Impl/Options/AdvancedOptionPageControl.xaml.cs @@ -52,7 +52,7 @@ public AdvancedOptionPageControl(OptionStore optionStore, IComponentModel compon BindToOption(Show_Remove_Unused_References_command_in_Solution_Explorer_experimental, FeatureOnOffOptions.OfferRemoveUnusedReferences, () => { // If the option has not been set by the user, check if the option to remove unused references - // is enabled from experimentation. If so, default to that. Otherwise default to disabled + // is enabled from experimentation. If so, default to that. return optionStore.GetOption(FeatureOnOffOptions.OfferRemoveUnusedReferencesFeatureFlag); }); @@ -93,7 +93,7 @@ public AdvancedOptionPageControl(OptionStore optionStore, IComponentModel compon BindToOption(ComputeQuickActionsAsynchronouslyExperimental, SuggestionsOptions.Asynchronous, () => { // 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 + // If so, default to that. return optionStore.GetOption(SuggestionsOptions.AsynchronousFeatureFlag); }); @@ -106,7 +106,7 @@ public AdvancedOptionPageControl(OptionStore optionStore, IComponentModel compon BindToOption(Enable_all_features_in_opened_files_from_source_generators, SourceGeneratedFileManager.Options.EnableOpeningInWorkspace, () => { // 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 + // If so, default to that. return optionStore.GetOption(SourceGeneratedFileManager.Options.EnableOpeningInWorkspaceFeatureFlag); }); From d1ba2824b109efac27171a43eca7ff2c0b9a1c8b Mon Sep 17 00:00:00 2001 From: Chris Sienkiewicz Date: Fri, 3 Sep 2021 11:05:00 -0700 Subject: [PATCH 3/7] Source generators/timing (#55892) * Add logging event source * Track timing information in the generator driver - Expose via runrunresult and ETW - Extract out helper from event source - Add extension methods to create a start/stop pair of events the driver can use --- .../SourceGeneration/StateTableTests.cs | 3 +- .../Core/Portable/CodeAnalysisEventSource.cs | 41 ++++++++++ .../DefaultAnalyzerAssemblyLoader.Core.cs | 1 + .../SourceGeneration/GeneratorDriver.cs | 21 ++--- .../SourceGeneration/GeneratorDriverState.cs | 13 +++- .../SourceGeneration/GeneratorState.cs | 15 ++-- .../GeneratorTimerExtensions.cs | 76 +++++++++++++++++++ .../Portable/SourceGeneration/RunResults.cs | 16 +++- 8 files changed, 165 insertions(+), 21 deletions(-) create mode 100644 src/Compilers/Core/Portable/CodeAnalysisEventSource.cs create mode 100644 src/Compilers/Core/Portable/SourceGeneration/GeneratorTimerExtensions.cs diff --git a/src/Compilers/CSharp/Test/Semantic/SourceGeneration/StateTableTests.cs b/src/Compilers/CSharp/Test/Semantic/SourceGeneration/StateTableTests.cs index d314e3f09d2c9..816d4e3c1783a 100644 --- a/src/Compilers/CSharp/Test/Semantic/SourceGeneration/StateTableTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/SourceGeneration/StateTableTests.cs @@ -408,7 +408,8 @@ private DriverStateTable.Builder GetBuilder(DriverStateTable previous) ImmutableArray.Empty, ImmutableArray.Empty, previous, - disabledOutputs: IncrementalGeneratorOutputKind.None); + disabledOutputs: IncrementalGeneratorOutputKind.None, + runtime: TimeSpan.Zero); return new DriverStateTable.Builder(c, state, ImmutableArray.Empty); } diff --git a/src/Compilers/Core/Portable/CodeAnalysisEventSource.cs b/src/Compilers/Core/Portable/CodeAnalysisEventSource.cs new file mode 100644 index 0000000000000..814f53c8b732d --- /dev/null +++ b/src/Compilers/Core/Portable/CodeAnalysisEventSource.cs @@ -0,0 +1,41 @@ +// 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; +using System.Diagnostics.Tracing; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis +{ + [EventSource(Name = "Microsoft-CodeAnalysis-General")] + internal sealed class CodeAnalysisEventSource : EventSource + { + public static readonly CodeAnalysisEventSource Log = new CodeAnalysisEventSource(); + + public static class Keywords + { + public const EventKeywords Performance = (EventKeywords)1; + } + + public static class Tasks + { + public const EventTask GeneratorDriverRunTime = (EventTask)1; + public const EventTask SingleGeneratorRunTime = (EventTask)2; + } + + private CodeAnalysisEventSource() { } + + [Event(1, Keywords = Keywords.Performance, Level = EventLevel.Informational, Opcode = EventOpcode.Start, Task = Tasks.GeneratorDriverRunTime)] + internal void StartGeneratorDriverRunTime(string id) => WriteEvent(1, id); + + [Event(2, Message = "Generators ran for {0} ticks", Keywords = Keywords.Performance, Level = EventLevel.Informational, Opcode = EventOpcode.Stop, Task = Tasks.GeneratorDriverRunTime)] + internal void StopGeneratorDriverRunTime(long elapsedTicks, string id) => WriteEvent(2, elapsedTicks, id); + + [Event(3, Keywords = Keywords.Performance, Level = EventLevel.Informational, Opcode = EventOpcode.Start, Task = Tasks.SingleGeneratorRunTime)] + internal void StartSingleGeneratorRunTime(string generatorName, string assemblyPath, string id) => WriteEvent(3, generatorName, assemblyPath, id); + + [Event(4, Message = "Generator {0} ran for {2} ticks", Keywords = Keywords.Performance, Level = EventLevel.Informational, Opcode = EventOpcode.Stop, Task = Tasks.SingleGeneratorRunTime)] + internal void StopSingleGeneratorRunTime(string generatorName, string assemblyPath, long elapsedTicks, string id) => WriteEvent(4, generatorName, assemblyPath, elapsedTicks, id); + } +} diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/DefaultAnalyzerAssemblyLoader.Core.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/DefaultAnalyzerAssemblyLoader.Core.cs index 056a15e06accb..44ed80f281c67 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/DefaultAnalyzerAssemblyLoader.Core.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/DefaultAnalyzerAssemblyLoader.Core.cs @@ -40,6 +40,7 @@ internal class DefaultAnalyzerAssemblyLoader : AnalyzerAssemblyLoader "System.Console", "System.Diagnostics.Debug", "System.Diagnostics.StackTrace", + "System.Diagnostics.Tracing", "System.IO.Compression", "System.IO.FileSystem", "System.Linq", diff --git a/src/Compilers/Core/Portable/SourceGeneration/GeneratorDriver.cs b/src/Compilers/Core/Portable/SourceGeneration/GeneratorDriver.cs index 7781268c3fff8..ed97912b9c46e 100644 --- a/src/Compilers/Core/Portable/SourceGeneration/GeneratorDriver.cs +++ b/src/Compilers/Core/Portable/SourceGeneration/GeneratorDriver.cs @@ -36,7 +36,7 @@ internal GeneratorDriver(GeneratorDriverState state) internal GeneratorDriver(ParseOptions parseOptions, ImmutableArray generators, AnalyzerConfigOptionsProvider optionsProvider, ImmutableArray additionalTexts, GeneratorDriverOptions driverOptions) { (var filteredGenerators, var incrementalGenerators) = GetIncrementalGenerators(generators, SourceExtension); - _state = new GeneratorDriverState(parseOptions, optionsProvider, filteredGenerators, incrementalGenerators, additionalTexts, ImmutableArray.Create(new GeneratorState[filteredGenerators.Length]), DriverStateTable.Empty, driverOptions.DisabledOutputs); + _state = new GeneratorDriverState(parseOptions, optionsProvider, filteredGenerators, incrementalGenerators, additionalTexts, ImmutableArray.Create(new GeneratorState[filteredGenerators.Length]), DriverStateTable.Empty, driverOptions.DisabledOutputs, runtime: TimeSpan.Zero); } public GeneratorDriver RunGenerators(Compilation compilation, CancellationToken cancellationToken = default) @@ -135,8 +135,9 @@ public GeneratorDriverRunResult GetRunResult() => new GeneratorRunResult(generator, diagnostics: generatorState.Diagnostics, exception: generatorState.Exception, - generatedSources: getGeneratorSources(generatorState))); - return new GeneratorDriverRunResult(results); + generatedSources: getGeneratorSources(generatorState), + elapsedTime: generatorState.ElapsedTime)); + return new GeneratorDriverRunResult(results, _state.RunTime); static ImmutableArray getGeneratorSources(GeneratorState generatorState) { @@ -158,10 +159,11 @@ internal GeneratorDriverState RunGeneratorsCore(Compilation compilation, Diagnos // with no generators, there is no work to do if (_state.Generators.IsEmpty) { - return _state.With(stateTable: DriverStateTable.Empty); + return _state.With(stateTable: DriverStateTable.Empty, runTime: TimeSpan.Zero); } // run the actual generation + using var timer = CodeAnalysisEventSource.Log.CreateGeneratorDriverRunTimer(); var state = _state; var stateBuilder = ArrayBuilder.GetInstance(state.Generators.Length); var constantSourcesBuilder = ArrayBuilder.GetInstance(); @@ -244,21 +246,22 @@ internal GeneratorDriverState RunGeneratorsCore(Compilation compilation, Diagnos continue; } + using var generatorTimer = CodeAnalysisEventSource.Log.CreateSingleGeneratorRunTimer(state.Generators[i]); try { var context = UpdateOutputs(generatorState.OutputNodes, IncrementalGeneratorOutputKind.Source | IncrementalGeneratorOutputKind.Implementation, cancellationToken, driverStateBuilder); (var sources, var generatorDiagnostics) = context.ToImmutableAndFree(); generatorDiagnostics = FilterDiagnostics(compilation, generatorDiagnostics, driverDiagnostics: diagnosticsBag, cancellationToken); - stateBuilder[i] = new GeneratorState(generatorState.Info, generatorState.PostInitTrees, generatorState.InputNodes, generatorState.OutputNodes, ParseAdditionalSources(state.Generators[i], sources, cancellationToken), generatorDiagnostics); + stateBuilder[i] = new GeneratorState(generatorState.Info, generatorState.PostInitTrees, generatorState.InputNodes, generatorState.OutputNodes, ParseAdditionalSources(state.Generators[i], sources, cancellationToken), generatorDiagnostics, generatorTimer.Elapsed); } catch (UserFunctionException ufe) { - stateBuilder[i] = SetGeneratorException(MessageProvider, stateBuilder[i], state.Generators[i], ufe.InnerException, diagnosticsBag); + stateBuilder[i] = SetGeneratorException(MessageProvider, stateBuilder[i], state.Generators[i], ufe.InnerException, diagnosticsBag, generatorTimer.Elapsed); } } - state = state.With(stateTable: driverStateBuilder.ToImmutable(), generatorStates: stateBuilder.ToImmutableAndFree()); + state = state.With(stateTable: driverStateBuilder.ToImmutable(), generatorStates: stateBuilder.ToImmutableAndFree(), runTime: timer.Elapsed); return state; } @@ -290,7 +293,7 @@ private ImmutableArray ParseAdditionalSources(ISourceGenera return trees.ToImmutableAndFree(); } - private static GeneratorState SetGeneratorException(CommonMessageProvider provider, GeneratorState generatorState, ISourceGenerator generator, Exception e, DiagnosticBag? diagnosticBag, bool isInit = false) + private static GeneratorState SetGeneratorException(CommonMessageProvider provider, GeneratorState generatorState, ISourceGenerator generator, Exception e, DiagnosticBag? diagnosticBag, TimeSpan? runTime = null, bool isInit = false) { var errorCode = isInit ? provider.WRN_GeneratorFailedDuringInitialization : provider.WRN_GeneratorFailedDuringGeneration; @@ -313,7 +316,7 @@ private static GeneratorState SetGeneratorException(CommonMessageProvider provid var diagnostic = Diagnostic.Create(descriptor, Location.None, generator.GetGeneratorType().Name, e.GetType().Name, e.Message); diagnosticBag?.Add(diagnostic); - return new GeneratorState(generatorState.Info, e, diagnostic); + return new GeneratorState(generatorState.Info, e, diagnostic, runTime ?? TimeSpan.Zero); } private static ImmutableArray FilterDiagnostics(Compilation compilation, ImmutableArray generatorDiagnostics, DiagnosticBag? driverDiagnostics, CancellationToken cancellationToken) diff --git a/src/Compilers/Core/Portable/SourceGeneration/GeneratorDriverState.cs b/src/Compilers/Core/Portable/SourceGeneration/GeneratorDriverState.cs index 39de8bb8755eb..0506ee2eabecd 100644 --- a/src/Compilers/Core/Portable/SourceGeneration/GeneratorDriverState.cs +++ b/src/Compilers/Core/Portable/SourceGeneration/GeneratorDriverState.cs @@ -2,6 +2,7 @@ // 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; using System.Collections.Immutable; using System.Diagnostics; using Microsoft.CodeAnalysis.Diagnostics; @@ -17,7 +18,8 @@ internal GeneratorDriverState(ParseOptions parseOptions, ImmutableArray additionalTexts, ImmutableArray generatorStates, DriverStateTable stateTable, - IncrementalGeneratorOutputKind disabledOutputs) + IncrementalGeneratorOutputKind disabledOutputs, + TimeSpan runtime) { Generators = sourceGenerators; IncrementalGenerators = incrementalGenerators; @@ -27,6 +29,7 @@ internal GeneratorDriverState(ParseOptions parseOptions, OptionsProvider = optionsProvider; StateTable = stateTable; DisabledOutputs = disabledOutputs; + RunTime = runtime; Debug.Assert(Generators.Length == GeneratorStates.Length); Debug.Assert(IncrementalGenerators.Length == GeneratorStates.Length); } @@ -80,6 +83,8 @@ internal GeneratorDriverState(ParseOptions parseOptions, /// internal readonly IncrementalGeneratorOutputKind DisabledOutputs; + internal readonly TimeSpan RunTime; + internal GeneratorDriverState With( ImmutableArray? sourceGenerators = null, ImmutableArray? incrementalGenerators = null, @@ -88,7 +93,8 @@ internal GeneratorDriverState With( DriverStateTable? stateTable = null, ParseOptions? parseOptions = null, AnalyzerConfigOptionsProvider? optionsProvider = null, - IncrementalGeneratorOutputKind? disabledOutputs = null) + IncrementalGeneratorOutputKind? disabledOutputs = null, + TimeSpan? runTime = null) { return new GeneratorDriverState( parseOptions ?? this.ParseOptions, @@ -98,7 +104,8 @@ internal GeneratorDriverState With( additionalTexts ?? this.AdditionalTexts, generatorStates ?? this.GeneratorStates, stateTable ?? this.StateTable, - disabledOutputs ?? this.DisabledOutputs + disabledOutputs ?? this.DisabledOutputs, + runTime ?? this.RunTime ); } } diff --git a/src/Compilers/Core/Portable/SourceGeneration/GeneratorState.cs b/src/Compilers/Core/Portable/SourceGeneration/GeneratorState.cs index bb32957b68036..251c8fd25b1f4 100644 --- a/src/Compilers/Core/Portable/SourceGeneration/GeneratorState.cs +++ b/src/Compilers/Core/Portable/SourceGeneration/GeneratorState.cs @@ -32,27 +32,27 @@ public GeneratorState(GeneratorInfo info, ImmutableArray po /// Creates a new generator state that contains information, constant trees and an execution pipeline /// public GeneratorState(GeneratorInfo info, ImmutableArray postInitTrees, ImmutableArray inputNodes, ImmutableArray outputNodes) - : this(info, postInitTrees, inputNodes, outputNodes, ImmutableArray.Empty, ImmutableArray.Empty, exception: null) + : this(info, postInitTrees, inputNodes, outputNodes, ImmutableArray.Empty, ImmutableArray.Empty, exception: null, elapsedTime: TimeSpan.Zero) { } /// /// Creates a new generator state that contains an exception and the associated diagnostic /// - public GeneratorState(GeneratorInfo info, Exception e, Diagnostic error) - : this(info, ImmutableArray.Empty, ImmutableArray.Empty, ImmutableArray.Empty, ImmutableArray.Empty, ImmutableArray.Create(error), exception: e) + public GeneratorState(GeneratorInfo info, Exception e, Diagnostic error, TimeSpan elapsedTime) + : this(info, ImmutableArray.Empty, ImmutableArray.Empty, ImmutableArray.Empty, ImmutableArray.Empty, ImmutableArray.Create(error), exception: e, elapsedTime) { } /// /// Creates a generator state that contains results /// - public GeneratorState(GeneratorInfo info, ImmutableArray postInitTrees, ImmutableArray inputNodes, ImmutableArray outputNodes, ImmutableArray generatedTrees, ImmutableArray diagnostics) - : this(info, postInitTrees, inputNodes, outputNodes, generatedTrees, diagnostics, exception: null) + public GeneratorState(GeneratorInfo info, ImmutableArray postInitTrees, ImmutableArray inputNodes, ImmutableArray outputNodes, ImmutableArray generatedTrees, ImmutableArray diagnostics, TimeSpan elapsedTime) + : this(info, postInitTrees, inputNodes, outputNodes, generatedTrees, diagnostics, exception: null, elapsedTime) { } - private GeneratorState(GeneratorInfo info, ImmutableArray postInitTrees, ImmutableArray inputNodes, ImmutableArray outputNodes, ImmutableArray generatedTrees, ImmutableArray diagnostics, Exception? exception) + private GeneratorState(GeneratorInfo info, ImmutableArray postInitTrees, ImmutableArray inputNodes, ImmutableArray outputNodes, ImmutableArray generatedTrees, ImmutableArray diagnostics, Exception? exception, TimeSpan elapsedTime) { this.Initialized = true; this.PostInitTrees = postInitTrees; @@ -62,6 +62,7 @@ private GeneratorState(GeneratorInfo info, ImmutableArray p this.Info = info; this.Diagnostics = diagnostics; this.Exception = exception; + this.ElapsedTime = elapsedTime; } internal bool Initialized { get; } @@ -78,6 +79,8 @@ private GeneratorState(GeneratorInfo info, ImmutableArray p internal Exception? Exception { get; } + internal TimeSpan ElapsedTime { get; } + internal ImmutableArray Diagnostics { get; } } } diff --git a/src/Compilers/Core/Portable/SourceGeneration/GeneratorTimerExtensions.cs b/src/Compilers/Core/Portable/SourceGeneration/GeneratorTimerExtensions.cs new file mode 100644 index 0000000000000..eb5a0be3710e3 --- /dev/null +++ b/src/Compilers/Core/Portable/SourceGeneration/GeneratorTimerExtensions.cs @@ -0,0 +1,76 @@ +// 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; +using System.Collections.Generic; +using System.Diagnostics.Tracing; +using System.Text; +using Roslyn.Utilities; +using static Microsoft.CodeAnalysis.CodeAnalysisEventSource; + +namespace Microsoft.CodeAnalysis +{ + internal static class GeneratorTimerExtensions + { + public static RunTimer CreateGeneratorDriverRunTimer(this CodeAnalysisEventSource eventSource) + { + if (eventSource.IsEnabled(EventLevel.Informational, Keywords.Performance)) + { + var id = Guid.NewGuid().ToString(); + eventSource.StartGeneratorDriverRunTime(id); + return new RunTimer(t => eventSource.StopGeneratorDriverRunTime(t.Ticks, id)); + } + else + { + return new RunTimer(); + } + } + + public static RunTimer CreateSingleGeneratorRunTimer(this CodeAnalysisEventSource eventSource, ISourceGenerator generator) + { + if (eventSource.IsEnabled(EventLevel.Informational, Keywords.Performance)) + { + var id = Guid.NewGuid().ToString(); + var type = generator.GetGeneratorType(); + eventSource.StartSingleGeneratorRunTime(type.FullName!, type.Assembly.Location, id); + return new RunTimer(t => eventSource.StopSingleGeneratorRunTime(type.FullName!, type.Assembly.Location, t.Ticks, id)); + } + else + { + return new RunTimer(); + } + } + + internal readonly struct RunTimer : IDisposable + { + private readonly SharedStopwatch _timer; + private readonly Action? _callback; + + public TimeSpan Elapsed => _timer.Elapsed; + + public RunTimer() + { + // start twice to improve accuracy. See AnalyzerExecutor.ExecuteAndCatchIfThrows for more details + _ = SharedStopwatch.StartNew(); + _timer = SharedStopwatch.StartNew(); + _callback = null; + } + + public RunTimer(Action callback) + : this() + { + _callback = callback; + } + + public void Dispose() + { + if (_callback is not null) + { + var elapsed = _timer.Elapsed; + _callback(elapsed); + } + } + } + } +} diff --git a/src/Compilers/Core/Portable/SourceGeneration/RunResults.cs b/src/Compilers/Core/Portable/SourceGeneration/RunResults.cs index 35cbc4f4dc326..55276370f57b5 100644 --- a/src/Compilers/Core/Portable/SourceGeneration/RunResults.cs +++ b/src/Compilers/Core/Portable/SourceGeneration/RunResults.cs @@ -19,9 +19,10 @@ public class GeneratorDriverRunResult private ImmutableArray _lazyGeneratedTrees; - internal GeneratorDriverRunResult(ImmutableArray results) + internal GeneratorDriverRunResult(ImmutableArray results, TimeSpan elapsedTime) { this.Results = results; + ElapsedTime = elapsedTime; } /// @@ -29,6 +30,11 @@ internal GeneratorDriverRunResult(ImmutableArray results) /// public ImmutableArray Results { get; } + /// + /// The wall clock time that this generator pass took to execute. + /// + internal TimeSpan ElapsedTime { get; } + /// /// The s produced by all generators run during this generation pass. /// @@ -71,7 +77,7 @@ public ImmutableArray GeneratedTrees /// public readonly struct GeneratorRunResult { - internal GeneratorRunResult(ISourceGenerator generator, ImmutableArray generatedSources, ImmutableArray diagnostics, Exception? exception) + internal GeneratorRunResult(ISourceGenerator generator, ImmutableArray generatedSources, ImmutableArray diagnostics, Exception? exception, TimeSpan elapsedTime) { Debug.Assert(exception is null || (generatedSources.IsEmpty && diagnostics.Length == 1)); @@ -79,6 +85,7 @@ internal GeneratorRunResult(ISourceGenerator generator, ImmutableArray @@ -108,6 +115,11 @@ internal GeneratorRunResult(ISourceGenerator generator, ImmutableArray public Exception? Exception { get; } + + /// + /// The wall clock time that elapsed while this generator was running. + /// + internal TimeSpan ElapsedTime { get; } } /// From 28d4d9d9869cf2b37e3e700e1057adf367fe9cd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Matou=C5=A1ek?= Date: Fri, 3 Sep 2021 14:35:50 -0700 Subject: [PATCH 4/7] Remove unused ServiceComponentOnOffOptions (#56154) --- ...DiagnosticsClassificationTaggerProvider.cs | 2 +- .../DiagnosticsSquiggleTaggerProvider.cs | 2 +- .../DiagnosticsSuggestionTaggerProvider.cs | 2 +- .../Diagnostics/DiagnosticProviderTests.vb | 39 +------------------ .../DefaultDiagnosticAnalyzerService.cs | 9 +---- ...sticAnalyzerService_IncrementalAnalyzer.cs | 9 +---- .../Options/ServiceComponentOnOffOptions.cs | 18 --------- .../ServiceComponentOnOffOptionsProvider.cs | 28 ------------- 8 files changed, 6 insertions(+), 103 deletions(-) delete mode 100644 src/Features/Core/Portable/Shared/Options/ServiceComponentOnOffOptions.cs delete mode 100644 src/Features/Core/Portable/Shared/Options/ServiceComponentOnOffOptionsProvider.cs diff --git a/src/EditorFeatures/Core/Implementation/Diagnostics/DiagnosticsClassificationTaggerProvider.cs b/src/EditorFeatures/Core/Implementation/Diagnostics/DiagnosticsClassificationTaggerProvider.cs index 420d916dc24d0..4f80225d950f1 100644 --- a/src/EditorFeatures/Core/Implementation/Diagnostics/DiagnosticsClassificationTaggerProvider.cs +++ b/src/EditorFeatures/Core/Implementation/Diagnostics/DiagnosticsClassificationTaggerProvider.cs @@ -32,7 +32,7 @@ namespace Microsoft.CodeAnalysis.Editor.Implementation.Diagnostics [TagType(typeof(ClassificationTag))] internal partial class DiagnosticsClassificationTaggerProvider : AbstractDiagnosticsTaggerProvider { - private static readonly IEnumerable> s_tagSourceOptions = new[] { EditorComponentOnOffOptions.Tagger, InternalFeatureOnOffOptions.Classification, ServiceComponentOnOffOptions.DiagnosticProvider }; + private static readonly IEnumerable> s_tagSourceOptions = new[] { EditorComponentOnOffOptions.Tagger, InternalFeatureOnOffOptions.Classification }; private readonly ClassificationTypeMap _typeMap; private readonly ClassificationTag _classificationTag; diff --git a/src/EditorFeatures/Core/Implementation/Diagnostics/DiagnosticsSquiggleTaggerProvider.cs b/src/EditorFeatures/Core/Implementation/Diagnostics/DiagnosticsSquiggleTaggerProvider.cs index 3ff1ec5c0b98e..17a62b90d5e54 100644 --- a/src/EditorFeatures/Core/Implementation/Diagnostics/DiagnosticsSquiggleTaggerProvider.cs +++ b/src/EditorFeatures/Core/Implementation/Diagnostics/DiagnosticsSquiggleTaggerProvider.cs @@ -28,7 +28,7 @@ namespace Microsoft.CodeAnalysis.Editor.Implementation.Diagnostics internal partial class DiagnosticsSquiggleTaggerProvider : AbstractDiagnosticsAdornmentTaggerProvider { private static readonly IEnumerable> s_tagSourceOptions = - ImmutableArray.Create(EditorComponentOnOffOptions.Tagger, InternalFeatureOnOffOptions.Squiggles, ServiceComponentOnOffOptions.DiagnosticProvider); + ImmutableArray.Create(EditorComponentOnOffOptions.Tagger, InternalFeatureOnOffOptions.Squiggles); protected override IEnumerable> Options => s_tagSourceOptions; diff --git a/src/EditorFeatures/Core/Implementation/Diagnostics/DiagnosticsSuggestionTaggerProvider.cs b/src/EditorFeatures/Core/Implementation/Diagnostics/DiagnosticsSuggestionTaggerProvider.cs index 219bd48ea4278..550b4330b4f06 100644 --- a/src/EditorFeatures/Core/Implementation/Diagnostics/DiagnosticsSuggestionTaggerProvider.cs +++ b/src/EditorFeatures/Core/Implementation/Diagnostics/DiagnosticsSuggestionTaggerProvider.cs @@ -28,7 +28,7 @@ internal partial class DiagnosticsSuggestionTaggerProvider : AbstractDiagnosticsAdornmentTaggerProvider { private static readonly IEnumerable> s_tagSourceOptions = - ImmutableArray.Create(EditorComponentOnOffOptions.Tagger, InternalFeatureOnOffOptions.Squiggles, ServiceComponentOnOffOptions.DiagnosticProvider); + ImmutableArray.Create(EditorComponentOnOffOptions.Tagger, InternalFeatureOnOffOptions.Squiggles); protected override IEnumerable> Options => s_tagSourceOptions; diff --git a/src/EditorFeatures/Test2/Diagnostics/DiagnosticProviderTests.vb b/src/EditorFeatures/Test2/Diagnostics/DiagnosticProviderTests.vb index 34eae7c6195c6..38561611d1d28 100644 --- a/src/EditorFeatures/Test2/Diagnostics/DiagnosticProviderTests.vb +++ b/src/EditorFeatures/Test2/Diagnostics/DiagnosticProviderTests.vb @@ -203,35 +203,6 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.Diagnostics.UnitTests VerifyAllAvailableDiagnostics(test, diagnostics, ordered:=False) End Sub - - Public Sub TestDiagnosticsFromTurnedOff() - Dim test = - - - class Program - { - - - void Test() - { - int a = 5 - "2"; - } - } - - - - - Class GooClass - Sub Blah() End Sub - End Class - - - - - Dim diagnostics = - - VerifyAllAvailableDiagnostics(test, diagnostics, ordered:=False, enabled:=False) - End Sub - Public Sub WarningsAsErrors() Dim test = @@ -283,17 +254,9 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.Diagnostics.UnitTests VerifyAllAvailableDiagnostics(test, diagnostics) End Sub - Private Shared Sub VerifyAllAvailableDiagnostics(test As XElement, diagnostics As XElement, Optional ordered As Boolean = True, Optional enabled As Boolean = True) + Private Shared Sub VerifyAllAvailableDiagnostics(test As XElement, diagnostics As XElement, Optional ordered As Boolean = True) Using workspace = TestWorkspace.CreateWorkspace(test, composition:=s_composition) - ' turn off diagnostic - If Not enabled Then - workspace.TryApplyChanges(workspace.CurrentSolution.WithOptions(workspace.Options _ - .WithChangedOption(ServiceComponentOnOffOptions.DiagnosticProvider, False) _ - .WithChangedOption(SolutionCrawlerOptions.BackgroundAnalysisScopeOption, LanguageNames.CSharp, BackgroundAnalysisScope.Default) _ - .WithChangedOption(SolutionCrawlerOptions.BackgroundAnalysisScopeOption, LanguageNames.VisualBasic, BackgroundAnalysisScope.Default))) - End If - Dim registrationService = workspace.Services.GetService(Of ISolutionCrawlerRegistrationService)() registrationService.Register(workspace) diff --git a/src/Features/Core/Portable/Diagnostics/DefaultDiagnosticAnalyzerService.cs b/src/Features/Core/Portable/Diagnostics/DefaultDiagnosticAnalyzerService.cs index 571d91a2d788b..66714ac6169eb 100644 --- a/src/Features/Core/Portable/Diagnostics/DefaultDiagnosticAnalyzerService.cs +++ b/src/Features/Core/Portable/Diagnostics/DefaultDiagnosticAnalyzerService.cs @@ -36,14 +36,7 @@ public DefaultDiagnosticAnalyzerService( } public IIncrementalAnalyzer CreateIncrementalAnalyzer(Workspace workspace) - { - if (!workspace.Options.GetOption(ServiceComponentOnOffOptions.DiagnosticProvider)) - { - return null; - } - - return new DefaultDiagnosticIncrementalAnalyzer(this, workspace); - } + => new DefaultDiagnosticIncrementalAnalyzer(this, workspace); public event EventHandler DiagnosticsUpdated; public event EventHandler DiagnosticsCleared { add { } remove { } } diff --git a/src/Features/Core/Portable/Diagnostics/DiagnosticAnalyzerService_IncrementalAnalyzer.cs b/src/Features/Core/Portable/Diagnostics/DiagnosticAnalyzerService_IncrementalAnalyzer.cs index da10c4b1912a2..647c9d0dbc23e 100644 --- a/src/Features/Core/Portable/Diagnostics/DiagnosticAnalyzerService_IncrementalAnalyzer.cs +++ b/src/Features/Core/Portable/Diagnostics/DiagnosticAnalyzerService_IncrementalAnalyzer.cs @@ -20,14 +20,7 @@ namespace Microsoft.CodeAnalysis.Diagnostics internal partial class DiagnosticAnalyzerService : IIncrementalAnalyzerProvider { public IIncrementalAnalyzer CreateIncrementalAnalyzer(Workspace workspace) - { - if (!workspace.Options.GetOption(ServiceComponentOnOffOptions.DiagnosticProvider)) - { - return null; - } - - return _map.GetValue(workspace, _createIncrementalAnalyzer); - } + => _map.GetValue(workspace, _createIncrementalAnalyzer); public void ShutdownAnalyzerFrom(Workspace workspace) { diff --git a/src/Features/Core/Portable/Shared/Options/ServiceComponentOnOffOptions.cs b/src/Features/Core/Portable/Shared/Options/ServiceComponentOnOffOptions.cs deleted file mode 100644 index 67e5078c2c9a6..0000000000000 --- a/src/Features/Core/Portable/Shared/Options/ServiceComponentOnOffOptions.cs +++ /dev/null @@ -1,18 +0,0 @@ -// 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. - -#nullable disable - -using Microsoft.CodeAnalysis.Options; - -namespace Microsoft.CodeAnalysis.Shared.Options -{ - /// - /// options to indicate whether a certain component in Roslyn is enabled or not - /// - internal static class ServiceComponentOnOffOptions - { - public static readonly Option2 DiagnosticProvider = new(nameof(ServiceComponentOnOffOptions), nameof(DiagnosticProvider), defaultValue: true); - } -} diff --git a/src/Features/Core/Portable/Shared/Options/ServiceComponentOnOffOptionsProvider.cs b/src/Features/Core/Portable/Shared/Options/ServiceComponentOnOffOptionsProvider.cs deleted file mode 100644 index 958f9b891c536..0000000000000 --- a/src/Features/Core/Portable/Shared/Options/ServiceComponentOnOffOptionsProvider.cs +++ /dev/null @@ -1,28 +0,0 @@ -// 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. - -#nullable disable - -using System; -using System.Collections.Immutable; -using System.Composition; -using Microsoft.CodeAnalysis.Host.Mef; -using Microsoft.CodeAnalysis.Options; -using Microsoft.CodeAnalysis.Options.Providers; - -namespace Microsoft.CodeAnalysis.Shared.Options -{ - [ExportOptionProvider, Shared] - internal class ServiceComponentOnOffOptionsProvider : IOptionProvider - { - [ImportingConstructor] - [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public ServiceComponentOnOffOptionsProvider() - { - } - - public ImmutableArray Options { get; } = ImmutableArray.Create( - ServiceComponentOnOffOptions.DiagnosticProvider); - } -} From fd9a5f808b4982f7595e232beb5e6f508a9bb8f8 Mon Sep 17 00:00:00 2001 From: Jason Malinowski Date: Tue, 31 Aug 2021 15:42:25 -0700 Subject: [PATCH 5/7] #nullable enable a bit of the rename dashboard --- .../InlineRename/Dashboard/DashboardAdornmentManager.cs | 4 +--- .../InlineRename/Dashboard/DashboardAdornmentProvider.cs | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/EditorFeatures/Core.Wpf/InlineRename/Dashboard/DashboardAdornmentManager.cs b/src/EditorFeatures/Core.Wpf/InlineRename/Dashboard/DashboardAdornmentManager.cs index 3ae7ef9e9af79..1ce59d0756f1a 100644 --- a/src/EditorFeatures/Core.Wpf/InlineRename/Dashboard/DashboardAdornmentManager.cs +++ b/src/EditorFeatures/Core.Wpf/InlineRename/Dashboard/DashboardAdornmentManager.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - using System; using System.Linq; using System.Runtime.CompilerServices; @@ -75,7 +73,7 @@ private static bool ViewIncludesBufferFromWorkspace(IWpfTextView textView, Works .Any(); } - private static Workspace GetWorkspace(SourceTextContainer textContainer) + private static Workspace? GetWorkspace(SourceTextContainer textContainer) { Workspace.TryGetWorkspace(textContainer, out var workspace); return workspace; diff --git a/src/EditorFeatures/Core.Wpf/InlineRename/Dashboard/DashboardAdornmentProvider.cs b/src/EditorFeatures/Core.Wpf/InlineRename/Dashboard/DashboardAdornmentProvider.cs index a178abce22309..38fba9146b530 100644 --- a/src/EditorFeatures/Core.Wpf/InlineRename/Dashboard/DashboardAdornmentProvider.cs +++ b/src/EditorFeatures/Core.Wpf/InlineRename/Dashboard/DashboardAdornmentProvider.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - using System; using System.Collections.ObjectModel; using System.ComponentModel.Composition; @@ -36,7 +34,7 @@ internal class DashboardAdornmentProvider : IWpfTextViewConnectionListener [Order(After = PredefinedAdornmentLayers.TextMarker)] [Order(After = PredefinedAdornmentLayers.CurrentLineHighlighter)] [Order(After = PredefinedAdornmentLayers.Squiggle)] - internal readonly AdornmentLayerDefinition AdornmentLayer; + internal readonly AdornmentLayerDefinition? AdornmentLayer; [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] From 074fe49d50ae7c0d44404af1b517cdd1045ebaf4 Mon Sep 17 00:00:00 2001 From: Jason Malinowski Date: Tue, 31 Aug 2021 15:46:24 -0700 Subject: [PATCH 6/7] Don't reference VS Shell binaries in EditorFeatures.Wpf EditorFeatures.Wpf is supposed to be independent of the VS Shell, the idea is this layer can be hosted in other applications using the VS editor but not VS itself. This re-adds indirection for fetching the dashboard colors, but now only does it when the dashboard is opened. While I was here I ended up renaming CodeAnalysisColors to DashboardColors which is a bit clearer what it is. --- .../Core.Wpf/CodeAnalysisColors.cs | 20 ----------- .../InlineRename/Dashboard/Dashboard.xaml | 14 ++++---- .../Dashboard/DashboardAdornmentManager.cs | 6 ++++ .../Dashboard/DashboardAdornmentProvider.cs | 8 +++-- .../InlineRename/Dashboard/DashboardColors.cs | 24 ++++++++++++++ .../{Colors.xaml => DashboardColors.xaml} | 4 +++ .../Dashboard/IDashboardColorUpdater.cs | 14 ++++++++ ...oft.CodeAnalysis.EditorFeatures.Wpf.csproj | 2 -- .../InlineRename/DashboardColorUpdater.cs | 33 +++++++++++++++++++ 9 files changed, 93 insertions(+), 32 deletions(-) delete mode 100644 src/EditorFeatures/Core.Wpf/CodeAnalysisColors.cs create mode 100644 src/EditorFeatures/Core.Wpf/InlineRename/Dashboard/DashboardColors.cs rename src/EditorFeatures/Core.Wpf/InlineRename/Dashboard/{Colors.xaml => DashboardColors.xaml} (67%) create mode 100644 src/EditorFeatures/Core.Wpf/InlineRename/Dashboard/IDashboardColorUpdater.cs create mode 100644 src/VisualStudio/Core/Def/Implementation/InlineRename/DashboardColorUpdater.cs diff --git a/src/EditorFeatures/Core.Wpf/CodeAnalysisColors.cs b/src/EditorFeatures/Core.Wpf/CodeAnalysisColors.cs deleted file mode 100644 index 50fba1f95cbcd..0000000000000 --- a/src/EditorFeatures/Core.Wpf/CodeAnalysisColors.cs +++ /dev/null @@ -1,20 +0,0 @@ -// 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.VisualStudio.PlatformUI; -using Microsoft.VisualStudio.Shell; - -namespace Microsoft.CodeAnalysis.Editor.Shared.Utilities -{ - internal static class CodeAnalysisColors - { - // Use VS color keys in order to support theming. - public static object SystemCaptionTextColorKey => EnvironmentColors.SystemWindowTextColorKey; - public static object CheckBoxTextBrushKey => EnvironmentColors.SystemWindowTextBrushKey; - public static object SystemCaptionTextBrushKey => EnvironmentColors.SystemWindowTextBrushKey; - public static object BackgroundBrushKey => VsBrushes.CommandBarGradientBeginKey; - public static object ButtonStyleKey => VsResourceKeys.ButtonStyleKey; - public static object AccentBarColorKey => EnvironmentColors.FileTabInactiveDocumentBorderEdgeBrushKey; - } -} diff --git a/src/EditorFeatures/Core.Wpf/InlineRename/Dashboard/Dashboard.xaml b/src/EditorFeatures/Core.Wpf/InlineRename/Dashboard/Dashboard.xaml index a9bc286f46dd5..18c0b5beaba69 100644 --- a/src/EditorFeatures/Core.Wpf/InlineRename/Dashboard/Dashboard.xaml +++ b/src/EditorFeatures/Core.Wpf/InlineRename/Dashboard/Dashboard.xaml @@ -4,11 +4,9 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" - xmlns:me="clr-namespace:Microsoft.CodeAnalysis.Editor" xmlns:imaging="clr-namespace:Microsoft.VisualStudio.Imaging;assembly=Microsoft.VisualStudio.Imaging" xmlns:imagecatalog="clr-namespace:Microsoft.VisualStudio.Imaging;assembly=Microsoft.VisualStudio.ImageCatalog" xmlns:rename="clr-namespace:Microsoft.CodeAnalysis.Editor.Implementation.InlineRename" - xmlns:utilities="clr-namespace:Microsoft.CodeAnalysis.Editor.Shared.Utilities" x:ClassModifier="internal" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300" MinWidth="300" @@ -26,15 +24,15 @@ - + - +