22// The .NET Foundation licenses this file to you under the MIT license.
33// See the LICENSE file in the project root for more information.
44
5+ #nullable enable
6+
57using System ;
68using System . Collections . Generic ;
79using System . Collections . Immutable ;
810using System . Diagnostics ;
11+ using System . Diagnostics . CodeAnalysis ;
912using System . Linq ;
10- using System . Runtime . CompilerServices ;
1113using System . Threading ;
1214using System . Threading . Tasks ;
1315using Microsoft . CodeAnalysis . Diagnostics . Telemetry ;
@@ -49,7 +51,15 @@ internal partial class AnalysisState
4951 /// <summary>
5052 /// Action counts per-analyzer.
5153 /// </summary>
52- private ImmutableDictionary < DiagnosticAnalyzer , AnalyzerActionCounts > _lazyAnalyzerActionCountsMap ;
54+ private ImmutableDictionary < DiagnosticAnalyzer , AnalyzerActionCounts > ? _lazyAnalyzerActionCountsMap ;
55+ private ImmutableDictionary < DiagnosticAnalyzer , AnalyzerActionCounts > AnalyzerActionCountsMap
56+ {
57+ get
58+ {
59+ Debug . Assert ( _lazyAnalyzerActionCountsMap != null ) ;
60+ return _lazyAnalyzerActionCountsMap ;
61+ }
62+ }
5363
5464 private readonly HashSet < ISymbol > _partialSymbolsWithGeneratedSourceEvents ;
5565 private readonly CompilationData _compilationData ;
@@ -66,7 +76,6 @@ public AnalysisState(ImmutableArray<DiagnosticAnalyzer> analyzers, CompilationDa
6676 _compilationOptions = compilationOptions ;
6777 _pendingSourceEvents = new Dictionary < SyntaxTree , HashSet < CompilationEvent > > ( ) ;
6878 _pendingNonSourceEvents = new HashSet < CompilationEvent > ( ) ;
69- _lazyAnalyzerActionCountsMap = null ;
7079 _partialSymbolsWithGeneratedSourceEvents = new HashSet < ISymbol > ( ) ;
7180 _compilationEventsPool = new ObjectPool < HashSet < CompilationEvent > > ( ( ) => new HashSet < CompilationEvent > ( ) ) ;
7281 _pooledEventsWithAnyActionsSet = new HashSet < CompilationEvent > ( ) ;
@@ -118,19 +127,17 @@ public async Task OnCompilationEventsGeneratedAsync(ImmutableArray<CompilationEv
118127
119128 private void OnCompilationEventsGenerated_NoLock ( ImmutableArray < CompilationEvent > compilationEvents )
120129 {
121- Debug . Assert ( _lazyAnalyzerActionCountsMap != null ) ;
122-
123130 // Add the events to our global pending events map.
124131 AddToEventsMap_NoLock ( compilationEvents ) ;
125132
126133 // Mark the events for analysis for each analyzer.
127- ArrayBuilder < ISymbol > newPartialSymbols = null ;
134+ ArrayBuilder < ISymbol > ? newPartialSymbols = null ;
128135 Debug . Assert ( _pooledEventsWithAnyActionsSet . Count == 0 ) ;
129136 foreach ( var kvp in _analyzerStateMap )
130137 {
131138 var analyzer = kvp . Key ;
132139 var analyzerState = _analyzerStates [ kvp . Value ] ;
133- var actionCounts = _lazyAnalyzerActionCountsMap [ analyzer ] ;
140+ var actionCounts = AnalyzerActionCountsMap [ analyzer ] ;
134141
135142 foreach ( var compilationEvent in compilationEvents )
136143 {
@@ -148,7 +155,7 @@ private void OnCompilationEventsGenerated_NoLock(ImmutableArray<CompilationEvent
148155 }
149156 else
150157 {
151- newPartialSymbols = newPartialSymbols ?? ArrayBuilder < ISymbol > . GetInstance ( ) ;
158+ newPartialSymbols ??= ArrayBuilder < ISymbol > . GetInstance ( ) ;
152159 newPartialSymbols . Add ( symbolDeclaredEvent . Symbol ) ;
153160 }
154161 }
@@ -184,8 +191,7 @@ private void AddToEventsMap_NoLock(ImmutableArray<CompilationEvent> compilationE
184191
185192 private void UpdateEventsMap_NoLock ( CompilationEvent compilationEvent , bool add )
186193 {
187- var symbolEvent = compilationEvent as SymbolDeclaredCompilationEvent ;
188- if ( symbolEvent != null )
194+ if ( compilationEvent is SymbolDeclaredCompilationEvent symbolEvent )
189195 {
190196 // Add/remove symbol events.
191197 // Any diagnostics request for a tree should trigger symbol and syntax node analysis for symbols with at least one declaring reference in the tree.
@@ -207,8 +213,7 @@ private void UpdateEventsMap_NoLock(CompilationEvent compilationEvent, bool add)
207213 else
208214 {
209215 // Add/remove compilation unit completed events.
210- var compilationUnitCompletedEvent = compilationEvent as CompilationUnitCompletedEvent ;
211- if ( compilationUnitCompletedEvent != null )
216+ if ( compilationEvent is CompilationUnitCompletedEvent compilationUnitCompletedEvent )
212217 {
213218 var tree = compilationUnitCompletedEvent . SemanticModel . SyntaxTree ;
214219 if ( add )
@@ -241,8 +246,7 @@ private void UpdateEventsMap_NoLock(CompilationEvent compilationEvent, bool add)
241246
242247 private void AddPendingSourceEvent_NoLock ( SyntaxTree tree , CompilationEvent compilationEvent )
243248 {
244- HashSet < CompilationEvent > currentEvents ;
245- if ( ! _pendingSourceEvents . TryGetValue ( tree , out currentEvents ) )
249+ if ( ! _pendingSourceEvents . TryGetValue ( tree , out var currentEvents ) )
246250 {
247251 currentEvents = new HashSet < CompilationEvent > ( ) ;
248252 _pendingSourceEvents [ tree ] = currentEvents ;
@@ -254,8 +258,7 @@ private void AddPendingSourceEvent_NoLock(SyntaxTree tree, CompilationEvent comp
254258
255259 private void RemovePendingSourceEvent_NoLock ( SyntaxTree tree , CompilationEvent compilationEvent )
256260 {
257- HashSet < CompilationEvent > currentEvents ;
258- if ( _pendingSourceEvents . TryGetValue ( tree , out currentEvents ) )
261+ if ( _pendingSourceEvents . TryGetValue ( tree , out var currentEvents ) )
259262 {
260263 if ( currentEvents . Remove ( compilationEvent ) && currentEvents . Count == 0 )
261264 {
@@ -283,35 +286,21 @@ private async Task EnsureAnalyzerActionCountsInitializedAsync(AnalyzerDriver dri
283286 internal async Task < AnalyzerActionCounts > GetOrComputeAnalyzerActionCountsAsync ( DiagnosticAnalyzer analyzer , AnalyzerDriver driver , CancellationToken cancellationToken )
284287 {
285288 await EnsureAnalyzerActionCountsInitializedAsync ( driver , cancellationToken ) . ConfigureAwait ( false ) ;
286- return _lazyAnalyzerActionCountsMap [ analyzer ] ;
289+ return AnalyzerActionCountsMap [ analyzer ] ;
287290 }
288291
289292 internal AnalyzerActionCounts GetAnalyzerActionCounts ( DiagnosticAnalyzer analyzer )
290- {
291- Debug . Assert ( _lazyAnalyzerActionCountsMap != null ) ;
292- return _lazyAnalyzerActionCountsMap [ analyzer ] ;
293- }
293+ => AnalyzerActionCountsMap [ analyzer ] ;
294294
295295 private static bool HasActionsForEvent ( CompilationEvent compilationEvent , AnalyzerActionCounts actionCounts )
296296 {
297- if ( compilationEvent is CompilationStartedEvent )
298- {
299- return actionCounts . CompilationActionsCount > 0 ||
300- actionCounts . SyntaxTreeActionsCount > 0 ||
301- actionCounts . AdditionalFileActionsCount > 0 ;
302- }
303- else if ( compilationEvent is CompilationCompletedEvent )
297+ return compilationEvent switch
304298 {
305- return actionCounts . CompilationEndActionsCount > 0 ;
306- }
307- else if ( compilationEvent is SymbolDeclaredCompilationEvent )
308- {
309- return actionCounts . SymbolActionsCount > 0 || actionCounts . HasAnyExecutableCodeActions ;
310- }
311- else
312- {
313- return actionCounts . SemanticModelActionsCount > 0 ;
314- }
299+ CompilationStartedEvent => actionCounts . CompilationActionsCount > 0 || actionCounts . SyntaxTreeActionsCount > 0 || actionCounts . AdditionalFileActionsCount > 0 ,
300+ CompilationCompletedEvent => actionCounts . CompilationEndActionsCount > 0 ,
301+ SymbolDeclaredCompilationEvent => actionCounts . SymbolActionsCount > 0 || actionCounts . HasAnyExecutableCodeActions ,
302+ _ => actionCounts . SemanticModelActionsCount > 0
303+ } ;
315304 }
316305
317306 private async Task OnSymbolDeclaredEventProcessedAsync (
@@ -336,8 +325,7 @@ private async Task OnSymbolDeclaredEventProcessedAsync(
336325 public async Task OnCompilationEventProcessedAsync ( CompilationEvent compilationEvent , ImmutableArray < DiagnosticAnalyzer > analyzers , Func < ISymbol , DiagnosticAnalyzer , Task > onSymbolAndMembersProcessedAsync )
337326 {
338327 // Analyze if the symbol and all its declaring syntax references are analyzed.
339- var symbolDeclaredEvent = compilationEvent as SymbolDeclaredCompilationEvent ;
340- if ( symbolDeclaredEvent != null )
328+ if ( compilationEvent is SymbolDeclaredCompilationEvent symbolDeclaredEvent )
341329 {
342330 await OnSymbolDeclaredEventProcessedAsync ( symbolDeclaredEvent , analyzers , onSymbolAndMembersProcessedAsync ) . ConfigureAwait ( false ) ;
343331 }
@@ -387,12 +375,11 @@ private HashSet<CompilationEvent> GetPendingEvents_NoLock(ImmutableArray<Diagnos
387375 /// </summary>
388376 private ImmutableArray < CompilationEvent > GetPendingEvents_NoLock ( ImmutableArray < DiagnosticAnalyzer > analyzers , SyntaxTree tree )
389377 {
390- HashSet < CompilationEvent > compilationEventsForTree ;
391- if ( _pendingSourceEvents . TryGetValue ( tree , out compilationEventsForTree ) )
378+ if ( _pendingSourceEvents . TryGetValue ( tree , out var compilationEventsForTree ) )
392379 {
393380 if ( compilationEventsForTree ? . Count > 0 )
394381 {
395- HashSet < CompilationEvent > pendingEvents = null ;
382+ HashSet < CompilationEvent > ? pendingEvents = null ;
396383 try
397384 {
398385 pendingEvents = GetPendingEvents_NoLock ( analyzers ) ;
@@ -433,7 +420,7 @@ public ImmutableArray<CompilationEvent> GetPendingEvents(
433420
434421 private ImmutableArray < CompilationEvent > GetPendingEvents_NoLock ( ImmutableArray < DiagnosticAnalyzer > analyzers , bool includeSourceEvents , bool includeNonSourceEvents )
435422 {
436- HashSet < CompilationEvent > pendingEvents = null , uniqueEvents = null ;
423+ HashSet < CompilationEvent > ? pendingEvents = null , uniqueEvents = null ;
437424 try
438425 {
439426 pendingEvents = GetPendingEvents_NoLock ( analyzers ) ;
@@ -473,7 +460,7 @@ private ImmutableArray<CompilationEvent> GetPendingEvents_NoLock(ImmutableArray<
473460 }
474461 }
475462
476- private void Free ( HashSet < CompilationEvent > events )
463+ private void Free ( HashSet < CompilationEvent > ? events )
477464 {
478465 if ( events != null )
479466 {
@@ -533,12 +520,9 @@ public bool HasPendingSymbolAnalysis(AnalysisScope analysisScope, CancellationTo
533520
534521 private ImmutableArray < SymbolDeclaredCompilationEvent > GetPendingSymbolDeclaredEvents ( SyntaxTree tree , CancellationToken cancellationToken )
535522 {
536- Debug . Assert ( tree != null ) ;
537-
538523 using ( _gate . DisposableWait ( cancellationToken ) )
539524 {
540- HashSet < CompilationEvent > compilationEvents ;
541- if ( ! _pendingSourceEvents . TryGetValue ( tree , out compilationEvents ) )
525+ if ( ! _pendingSourceEvents . TryGetValue ( tree , out var compilationEvents ) )
542526 {
543527 return ImmutableArray < SymbolDeclaredCompilationEvent > . Empty ;
544528 }
@@ -554,7 +538,10 @@ private ImmutableArray<SymbolDeclaredCompilationEvent> GetPendingSymbolDeclaredE
554538 /// Returns false if the event has already been processed for the analyzer OR is currently being processed by another task.
555539 /// If true, then it returns a non-null <paramref name="state"/> representing partial analysis state for the given event for the given analyzer.
556540 /// </returns>
557- public bool TryStartProcessingEvent ( CompilationEvent compilationEvent , DiagnosticAnalyzer analyzer , out AnalyzerStateData state )
541+ public bool TryStartProcessingEvent (
542+ CompilationEvent compilationEvent ,
543+ DiagnosticAnalyzer analyzer ,
544+ [ NotNullWhen ( returnValue : true ) ] out AnalyzerStateData ? state )
558545 {
559546 return GetAnalyzerState ( analyzer ) . TryStartProcessingEvent ( compilationEvent , out state ) ;
560547 }
@@ -602,7 +589,7 @@ public bool IsEventComplete(CompilationEvent compilationEvent, DiagnosticAnalyze
602589 /// Returns false if the symbol has already been processed for the analyzer OR is currently being processed by another task.
603590 /// If true, then it returns a non-null <paramref name="state"/> representing partial analysis state for the given symbol for the given analyzer.
604591 /// </returns>
605- public bool TryStartAnalyzingSymbol ( ISymbol symbol , DiagnosticAnalyzer analyzer , out AnalyzerStateData state )
592+ public bool TryStartAnalyzingSymbol ( ISymbol symbol , DiagnosticAnalyzer analyzer , [ NotNullWhen ( returnValue : true ) ] out AnalyzerStateData ? state )
606593 {
607594 return GetAnalyzerState ( analyzer ) . TryStartAnalyzingSymbol ( symbol , out state ) ;
608595 }
@@ -614,7 +601,7 @@ public bool TryStartAnalyzingSymbol(ISymbol symbol, DiagnosticAnalyzer analyzer,
614601 /// Returns false if the symbol end actions have already been executed for the analyzer OR are currently being executed by another task.
615602 /// If true, then it returns a non-null <paramref name="state"/> representing partial analysis state for the given symbol end actions for the given analyzer.
616603 /// </returns>
617- public bool TryStartSymbolEndAnalysis ( ISymbol symbol , DiagnosticAnalyzer analyzer , out AnalyzerStateData state )
604+ public bool TryStartSymbolEndAnalysis ( ISymbol symbol , DiagnosticAnalyzer analyzer , [ NotNullWhen ( returnValue : true ) ] out AnalyzerStateData ? state )
618605 {
619606 return GetAnalyzerState ( analyzer ) . TryStartSymbolEndAnalysis ( symbol , out state ) ;
620607 }
@@ -678,7 +665,11 @@ public bool IsSymbolEndAnalysisComplete(ISymbol symbol, DiagnosticAnalyzer analy
678665 /// Returns false if the declaration has already been processed for the analyzer OR is currently being processed by another task.
679666 /// If true, then it returns a non-null <paramref name="state"/> representing partial analysis state for the given declaration for the given analyzer.
680667 /// </returns>
681- public bool TryStartAnalyzingDeclaration ( ISymbol symbol , int declarationIndex , DiagnosticAnalyzer analyzer , out DeclarationAnalyzerStateData state )
668+ public bool TryStartAnalyzingDeclaration (
669+ ISymbol symbol ,
670+ int declarationIndex ,
671+ DiagnosticAnalyzer analyzer ,
672+ [ NotNullWhen ( returnValue : true ) ] out DeclarationAnalyzerStateData ? state )
682673 {
683674 return GetAnalyzerState ( analyzer ) . TryStartAnalyzingDeclaration ( symbol , declarationIndex , out state ) ;
684675 }
@@ -750,7 +741,10 @@ public void MarkDeclarationsComplete(ISymbol symbol, IEnumerable<DiagnosticAnaly
750741 /// Returns false if the file has already been processed for the analyzer OR is currently being processed by another task.
751742 /// If true, then it returns a non-null <paramref name="state"/> representing partial syntax analysis state for the given tree for the given analyzer.
752743 /// </returns>
753- public bool TryStartSyntaxAnalysis ( SourceOrAdditionalFile file , DiagnosticAnalyzer analyzer , out AnalyzerStateData state )
744+ public bool TryStartSyntaxAnalysis (
745+ SourceOrAdditionalFile file ,
746+ DiagnosticAnalyzer analyzer ,
747+ [ NotNullWhen ( returnValue : true ) ] out AnalyzerStateData ? state )
754748 {
755749 return GetAnalyzerState ( analyzer ) . TryStartSyntaxAnalysis ( file , out state ) ;
756750 }
0 commit comments