/// <summary> /// Invoke this method at completion of event processing for the given analysis scope. /// It updates the analysis state of this event for each analyzer and if the event has been fully processed for all analyzers, then removes it from our event cache. /// </summary> public void OnCompilationEventProcessed(CompilationEvent compilationEvent, AnalysisScope analysisScope) { // Analyze if the symbol and all its declaring syntax references are analyzed. var symbolDeclaredEvent = compilationEvent as SymbolDeclaredCompilationEvent; if (symbolDeclaredEvent != null) { OnSymbolDeclaredEventProcessed(symbolDeclaredEvent, analysisScope.Analyzers); } // Check if event is fully analyzed for all analyzers. foreach (var analyzerState in _analyzerStates) { if (!analyzerState.IsEventAnalyzed(compilationEvent)) { return; } } // Remove the event from event map. lock (_gate) { UpdateEventsMap_NoLock(compilationEvent, add: false); } }
private Task ProcessEventAsync(CompilationEvent e, CancellationToken cancellationToken) { var symbolEvent = e as SymbolDeclaredCompilationEvent; if (symbolEvent != null) { return(ProcessSymbolDeclaredAsync(symbolEvent, cancellationToken)); } var completedEvent = e as CompilationUnitCompletedEvent; if (completedEvent != null) { return(ProcessCompilationUnitCompletedAsync(completedEvent, cancellationToken)); } var endEvent = e as CompilationCompletedEvent; if (endEvent != null) { return(ProcessCompilationCompletedAsync(endEvent, cancellationToken)); } if (e is CompilationStartedEvent) { // Ignore CompilationStartedEvent. return(null); } throw new InvalidOperationException("Unexpected compilation event of type " + e.GetType().Name); }
/// <summary> /// Invoke this method at completion of event processing for the given analysis scope. /// It updates the analysis state of this event for each analyzer and if the event has been fully processed for all analyzers, then removes it from our event cache. /// </summary> public async Task OnCompilationEventProcessedAsync(CompilationEvent compilationEvent, AnalysisScope analysisScope, CancellationToken cancellationToken) { // Analyze if the symbol and all its declaring syntax references are analyzed. var symbolDeclaredEvent = compilationEvent as SymbolDeclaredCompilationEvent; if (symbolDeclaredEvent != null) { await OnSymbolDeclaredEventProcessedAsync(symbolDeclaredEvent, analysisScope.Analyzers, cancellationToken).ConfigureAwait(false); } // Check if event is fully analyzed for all analyzers. foreach (var analyzerState in _analyzerStates) { var eventAnalyzed = await analyzerState.IsEventAnalyzedAsync(compilationEvent, cancellationToken).ConfigureAwait(false); if (!eventAnalyzed) { return; } } // Remove the event from event map. using (await _gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false)) { UpdateEventsMap_NoLock(compilationEvent, add: false); } if (symbolDeclaredEvent != null) { AnalyzerDriver.RemoveCachedDeclaringReferences(symbolDeclaredEvent.Symbol, symbolDeclaredEvent.Compilation); } }
private async Task ProcessEvent(CompilationEvent e, CancellationToken cancellationToken) { var symbolEvent = e as SymbolDeclaredCompilationEvent; if (symbolEvent != null) { await ProcessSymbolDeclared(symbolEvent, cancellationToken).ConfigureAwait(false); return; } var completedEvent = e as CompilationUnitCompletedEvent; if (completedEvent != null) { await ProcessCompilationUnitCompleted(completedEvent, cancellationToken).ConfigureAwait(false); return; } var endEvent = e as CompilationCompletedEvent; if (endEvent != null) { await ProcessCompilationCompleted(endEvent, cancellationToken).ConfigureAwait(false); return; } throw new InvalidOperationException("Unexpected compilation event of type " + e.GetType().Name); }
/// <summary> /// Invoke this method at completion of event processing for the given analyzers. /// It updates the analysis state of this event for each analyzer and if the event has been fully processed for all analyzers, then removes it from our event cache. /// </summary> public async Task OnCompilationEventProcessedAsync(CompilationEvent compilationEvent, ImmutableArray <DiagnosticAnalyzer> analyzers, Func <ISymbol, DiagnosticAnalyzer, Task> onSymbolAndMembersProcessedAsync) { // Analyze if the symbol and all its declaring syntax references are analyzed. var symbolDeclaredEvent = compilationEvent as SymbolDeclaredCompilationEvent; if (symbolDeclaredEvent != null) { await OnSymbolDeclaredEventProcessedAsync(symbolDeclaredEvent, analyzers, onSymbolAndMembersProcessedAsync).ConfigureAwait(false); } // Check if event is fully analyzed for all analyzers. foreach (var analyzerState in _analyzerStates) { if (!analyzerState.IsEventAnalyzed(compilationEvent)) { return; } } // Remove the event from event map. // Note: We do not pass in the cancellationToken to DisposableWait to ensure the state is updated. using (_gate.DisposableWait()) { UpdateEventsMap_NoLock(compilationEvent, add: false); } }
/// <summary> /// Marks the given event as fully analyzed for the given analyzers. /// </summary> public void MarkEventComplete(CompilationEvent compilationEvent, IEnumerable <DiagnosticAnalyzer> analyzers) { foreach (var analyzer in analyzers) { GetAnalyzerState(analyzer).MarkEventComplete(compilationEvent); } }
private static bool TryStartProcessingEvent(CompilationEvent nonSymbolCompilationEvent, DiagnosticAnalyzer analyzer, AnalysisScope analysisScope, AnalysisState analysisStateOpt, out AnalyzerStateData analyzerStateOpt) { Debug.Assert(!(nonSymbolCompilationEvent is SymbolDeclaredCompilationEvent)); Debug.Assert(analysisScope.Analyzers.Contains(analyzer)); analyzerStateOpt = null; return(analysisStateOpt == null || analysisStateOpt.TryStartProcessingEvent(nonSymbolCompilationEvent, analyzer, out analyzerStateOpt)); }
private void UpdateEventsMap_NoLock(CompilationEvent compilationEvent, bool add) { var symbolEvent = compilationEvent as SymbolDeclaredCompilationEvent; if (symbolEvent != null) { // Add/remove symbol events. // Any diagnostics request for a tree should trigger symbol and syntax node analysis for symbols with at least one declaring reference in the tree. foreach (var location in symbolEvent.Symbol.Locations) { if (location.SourceTree != null) { if (add) { AddPendingSourceEvent_NoLock(location.SourceTree, compilationEvent); } else { RemovePendingSourceEvent_NoLock(location.SourceTree, compilationEvent); } } } } else { // Add/remove compilation unit completed events. var compilationUnitCompletedEvent = compilationEvent as CompilationUnitCompletedEvent; if (compilationUnitCompletedEvent != null) { var tree = compilationUnitCompletedEvent.SemanticModel.SyntaxTree; if (add) { AddPendingSourceEvent_NoLock(tree, compilationEvent); } else { RemovePendingSourceEvent_NoLock(tree, compilationEvent); } } else if (compilationEvent is CompilationStartedEvent || compilationEvent is CompilationCompletedEvent) { // Add/remove compilation events. if (add) { _pendingNonSourceEvents.Add(compilationEvent); } else { _pendingNonSourceEvents.Remove(compilationEvent); } } else { throw new InvalidOperationException("Unexpected compilation event of type " + compilationEvent.GetType().Name); } } }
private static bool HasActionsForEvent(CompilationEvent compilationEvent, AnalyzerActionCounts actionCounts) { return(compilationEvent switch { CompilationStartedEvent => actionCounts.CompilationActionsCount > 0 || actionCounts.SyntaxTreeActionsCount > 0 || actionCounts.AdditionalFileActionsCount > 0, CompilationCompletedEvent => actionCounts.CompilationEndActionsCount > 0, SymbolDeclaredCompilationEvent => actionCounts.SymbolActionsCount > 0 || actionCounts.HasAnyExecutableCodeActions, _ => actionCounts.SemanticModelActionsCount > 0 });
public void OnCompilationEventGenerated(CompilationEvent compilationEvent, AnalyzerActionCounts actionCounts) { lock (_gate) { var symbolEvent = compilationEvent as SymbolDeclaredCompilationEvent; if (symbolEvent != null) { var needsAnalysis = false; var symbol = symbolEvent.Symbol; if (!AnalysisScope.ShouldSkipSymbolAnalysis(symbolEvent) && actionCounts.SymbolActionsCount > 0) { needsAnalysis = true; _pendingSymbols[symbol] = null; } if (!AnalysisScope.ShouldSkipDeclarationAnalysis(symbol) && (actionCounts.SyntaxNodeActionsCount > 0 || actionCounts.CodeBlockActionsCount > 0 || actionCounts.CodeBlockStartActionsCount > 0)) { foreach (var syntaxRef in symbolEvent.DeclaringSyntaxReferences) { needsAnalysis = true; _pendingDeclarations[syntaxRef.GetSyntax()] = null; } } if (!needsAnalysis) { return; } } else if (compilationEvent is CompilationStartedEvent) { if (actionCounts.SyntaxTreeActionsCount > 0) { var trees = compilationEvent.Compilation.SyntaxTrees; var map = new Dictionary <SyntaxTree, AnalyzerStateData>(trees.Count()); foreach (var tree in trees) { map[tree] = null; } _lazyPendingSyntaxAnalysisTrees = map; } if (actionCounts.CompilationActionsCount == 0) { return; } } _pendingEvents[compilationEvent] = null; } }
public void OnCompilationEventGenerated(CompilationEvent compilationEvent, AnalyzerActionCounts actionCounts) { lock (_gate) { var symbolEvent = compilationEvent as SymbolDeclaredCompilationEvent; if (symbolEvent != null) { var needsAnalysis = false; var symbol = symbolEvent.Symbol; var skipSymbolAnalysis = AnalysisScope.ShouldSkipSymbolAnalysis(symbolEvent); if (!skipSymbolAnalysis && actionCounts.SymbolActionsCount > 0) { needsAnalysis = true; _pendingSymbols[symbol] = null; } var skipDeclarationAnalysis = AnalysisScope.ShouldSkipDeclarationAnalysis(symbol); if (!skipDeclarationAnalysis && actionCounts.HasAnyExecutableCodeActions) { needsAnalysis = true; _pendingDeclarations[symbol] = null; } if (actionCounts.SymbolStartActionsCount > 0 && (!skipSymbolAnalysis || !skipDeclarationAnalysis)) { needsAnalysis = true; _lazyPendingSymbolEndAnalyses = _lazyPendingSymbolEndAnalyses ?? new Dictionary <ISymbol, AnalyzerStateData>(); _lazyPendingSymbolEndAnalyses[symbol] = null; } if (!needsAnalysis) { return; } } else if (compilationEvent is CompilationStartedEvent compilationStartedEvent) { var fileCount = actionCounts.SyntaxTreeActionsCount > 0 ? compilationEvent.Compilation.SyntaxTrees.Count() : 0; fileCount += actionCounts.AdditionalFileActionsCount > 0 ? compilationStartedEvent.AdditionalFiles.Length : 0; if (fileCount > 0) { _lazyFilesWithAnalysisData = new Dictionary <SourceOrAdditionalFile, AnalyzerStateData>(); _pendingSyntaxAnalysisFilesCount = fileCount; } if (actionCounts.CompilationActionsCount == 0) { return; } } _pendingEvents[compilationEvent] = null; } }
private void AddPendingSourceEvent_NoLock(SyntaxTree tree, CompilationEvent compilationEvent) { if (!_pendingSourceEvents.TryGetValue(tree, out HashSet <CompilationEvent> currentEvents)) { currentEvents = new HashSet <CompilationEvent>(); _pendingSourceEvents[tree] = currentEvents; _compilationData.RemoveCachedSemanticModel(tree); } currentEvents.Add(compilationEvent); }
private void RemovePendingSourceEvent_NoLock(SyntaxTree tree, CompilationEvent compilationEvent) { if (_pendingSourceEvents.TryGetValue(tree, out HashSet <CompilationEvent> currentEvents)) { if (currentEvents.Remove(compilationEvent) && currentEvents.Count == 0) { _pendingSourceEvents.Remove(tree); _compilationData.RemoveCachedSemanticModel(tree); } } }
private void AddPendingSourceEvent_NoLock(SyntaxTree tree, CompilationEvent compilationEvent) { if (!_pendingSourceEvents.TryGetValue(tree, out var currentEvents)) { currentEvents = new HashSet <CompilationEvent>(); _pendingSourceEvents[tree] = currentEvents; _semanticModelProvider.ClearCache(tree, compilationEvent.Compilation); } currentEvents.Add(compilationEvent); }
private void RemovePendingSourceEvent_NoLock(SyntaxTree tree, CompilationEvent compilationEvent) { if (_pendingSourceEvents.TryGetValue(tree, out var currentEvents)) { if (currentEvents.Remove(compilationEvent) && currentEvents.Count == 0) { _pendingSourceEvents.Remove(tree); _semanticModelProvider.ClearCache(tree, compilationEvent.Compilation); } } }
public bool TryStartProcessingEvent( CompilationEvent compilationEvent, [NotNullWhen(returnValue: true)] out AnalyzerStateData?state ) { return(TryStartProcessingEntity( compilationEvent, _pendingEvents, _analyzerStateDataPool, out state )); }
private void AddPendingSourceEvent_NoLock(SyntaxTree tree, CompilationEvent compilationEvent) { HashSet <CompilationEvent> currentEvents; if (!_pendingSourceEvents.TryGetValue(tree, out currentEvents)) { currentEvents = _compilationEventsPool.Allocate(); _pendingSourceEvents[tree] = currentEvents; } currentEvents.Add(compilationEvent); }
private void RemovePendingSourceEvent_NoLock(SyntaxTree tree, CompilationEvent compilationEvent) { HashSet <CompilationEvent> currentEvents; if (_pendingSourceEvents.TryGetValue(tree, out currentEvents)) { if (currentEvents.Remove(compilationEvent) && currentEvents.Count == 0) { _compilationEventsPool.Free(currentEvents); _pendingSourceEvents.Remove(tree); } } }
private void AddPendingSourceEvent_NoLock(SyntaxTree tree, CompilationEvent compilationEvent) { HashSet <CompilationEvent> currentEvents; if (!_pendingSourceEvents.TryGetValue(tree, out currentEvents)) { currentEvents = _compilationEventsPool.Allocate(); _pendingSourceEvents[tree] = currentEvents; AnalyzerDriver.RemoveCachedSemanticModel(tree, compilationEvent.Compilation); } currentEvents.Add(compilationEvent); }
public void OnCompilationEventGenerated(CompilationEvent compilationEvent, AnalyzerActionCounts actionCounts) { lock (_gate) { var symbolEvent = compilationEvent as SymbolDeclaredCompilationEvent; if (symbolEvent != null) { var needsAnalysis = false; var symbol = symbolEvent.Symbol; if (!AnalysisScope.ShouldSkipSymbolAnalysis(symbolEvent) && actionCounts.SymbolActionsCount > 0) { needsAnalysis = true; _pendingSymbols[symbol] = null; } if (!AnalysisScope.ShouldSkipDeclarationAnalysis(symbol) && actionCounts.HasAnyExecutableCodeActions) { needsAnalysis = true; _pendingDeclarations[symbol] = _currentlyAnalyzingDeclarationsMapPool.Allocate(); } if (!needsAnalysis) { return; } } else if (compilationEvent is CompilationStartedEvent) { if (actionCounts.SyntaxTreeActionsCount > 0) { var trees = compilationEvent.Compilation.SyntaxTrees; var map = new Dictionary <SyntaxTree, AnalyzerStateData>(trees.Count()); foreach (var tree in trees) { map[tree] = null; } _lazyPendingSyntaxAnalysisTrees = map; } if (actionCounts.CompilationActionsCount == 0) { return; } } _pendingEvents[compilationEvent] = null; } }
private static bool HasActionsForEvent(CompilationEvent compilationEvent, AnalyzerActionCounts actionCounts) { if (compilationEvent is CompilationStartedEvent) { return(actionCounts.CompilationActionsCount > 0 || actionCounts.SyntaxTreeActionsCount > 0); } else if (compilationEvent is CompilationCompletedEvent) { return(actionCounts.CompilationEndActionsCount > 0); } else if (compilationEvent is SymbolDeclaredCompilationEvent) { return(actionCounts.SymbolActionsCount > 0 || actionCounts.HasAnyExecutableCodeActions); } else { return(actionCounts.SemanticModelActionsCount > 0); } }
/// <summary> /// Executes the semantic model actions on the given semantic model. /// </summary> /// <param name="semanticModelActions">Semantic model actions to be executed.</param> /// <param name="analyzer">Analyzer whose actions are to be executed.</param> /// <param name="semanticModel">Semantic model to analyze.</param> /// <param name="compilationUnitCompletedEvent">Compilation event for semantic model analysis.</param> /// <param name="analysisScope">Scope for analyzer execution.</param> /// <param name="analysisStateOpt">An optional object to track analysis state.</param> public void ExecuteSemanticModelActions( ImmutableArray <SemanticModelAnalyzerAction> semanticModelActions, DiagnosticAnalyzer analyzer, SemanticModel semanticModel, CompilationEvent compilationUnitCompletedEvent, AnalysisScope analysisScope, AnalysisState analysisStateOpt) { AnalyzerStateData analyzerStateOpt = null; try { if (TryStartProcessingEvent(compilationUnitCompletedEvent, analyzer, analysisScope, analysisStateOpt, out analyzerStateOpt)) { ExecuteSemanticModelActionsCore(semanticModelActions, analyzer, semanticModel, analyzerStateOpt); analysisStateOpt?.MarkEventComplete(compilationUnitCompletedEvent, analyzer); } } finally { analyzerStateOpt?.ResetToReadyState(); } }
private static bool HasActionsForEvent(CompilationEvent compilationEvent, ActionCounts actionCounts) { if (compilationEvent is CompilationStartedEvent) { return(actionCounts.CompilationActionsCount > 0 || actionCounts.SyntaxTreeActionsCount > 0); } else if (compilationEvent is CompilationCompletedEvent) { return(actionCounts.CompilationEndActionsCount > 0); } else if (compilationEvent is SymbolDeclaredCompilationEvent) { return(actionCounts.CodeBlockActionsCount > 0 || actionCounts.CodeBlockStartActionsCount > 0 || actionCounts.SymbolActionsCount > 0 || actionCounts.SyntaxNodeActionsCount > 0); } else { return(actionCounts.SemanticModelActionsCount > 0); } }
private void GenerateSimulatedCompilatioNonSourceEvent(Compilation compilation, AnalyzerDriver driver, bool started, CancellationToken cancellationToken) { lock (_gate) { bool eventAlreadyGenerated = started ? _compilationStartGenerated : _compilationEndGenerated; if (eventAlreadyGenerated) { return; } CompilationEvent compilationEvent = started ? (CompilationEvent) new CompilationStartedEvent(compilation) : new CompilationCompletedEvent(compilation); ImmutableArray <CompilationEvent> events = ImmutableArray.Create(compilationEvent); OnCompilationEventsGenerated_NoLock(events, filterTreeOpt: null, driver: driver, cancellationToken: cancellationToken); if (started) { _compilationStartGenerated = true; } else { _compilationEndGenerated = true; } } }
/// <summary> /// Executes compilation actions or compilation end actions. /// </summary> /// <param name="compilationActions">Compilation actions to be executed.</param> /// <param name="analyzer">Analyzer whose actions are to be executed.</param> /// <param name="compilationEvent">Compilation event.</param> /// <param name="analysisScope">Scope for analyzer execution.</param> /// <param name="analysisStateOpt">An optional object to track analysis state.</param> public void ExecuteCompilationActions( ImmutableArray <CompilationAnalyzerAction> compilationActions, DiagnosticAnalyzer analyzer, CompilationEvent compilationEvent, AnalysisScope analysisScope, AnalysisState analysisStateOpt) { Debug.Assert(compilationEvent is CompilationStartedEvent || compilationEvent is CompilationCompletedEvent); AnalyzerStateData analyzerStateOpt = null; try { if (TryStartProcessingEvent(compilationEvent, analyzer, analysisScope, analysisStateOpt, out analyzerStateOpt)) { ExecuteCompilationActionsCore(compilationActions, analyzer, analyzerStateOpt); analysisStateOpt?.MarkEventComplete(compilationEvent, analyzer); } } finally { analyzerStateOpt?.ResetToReadyState(); } }
private void ExecuteCompilationActions( ImmutableDictionary<DiagnosticAnalyzer, ImmutableArray<CompilationAnalyzerAction>> compilationActionsMap, CompilationEvent compilationEvent, AnalysisScope analysisScope, AnalysisState analysisStateOpt, CancellationToken cancellationToken) { Debug.Assert(compilationEvent is CompilationStartedEvent || compilationEvent is CompilationCompletedEvent); try { foreach (var analyzer in analysisScope.Analyzers) { ImmutableArray<CompilationAnalyzerAction> compilationActions; if (compilationActionsMap.TryGetValue(analyzer, out compilationActions)) { analyzerExecutor.ExecuteCompilationActions(compilationActions, analyzer, compilationEvent, analysisScope, analysisStateOpt); } else { analysisStateOpt?.MarkEventComplete(compilationEvent, analyzer); } } } finally { compilationEvent.FlushCache(); } }
/// <summary> /// Marks the given event as fully analyzed for the given analyzer. /// </summary> public Task MarkEventCompleteAsync(CompilationEvent compilationEvent, DiagnosticAnalyzer analyzer, CancellationToken cancellationToken) { return GetAnalyzerState(analyzer).MarkEventCompleteAsync(compilationEvent, cancellationToken); }
private async Task ProcessEventAsync(CompilationEvent e, CancellationToken cancellationToken) { try { var processEventTask = ProcessEventCoreAsync(e, cancellationToken); if (processEventTask != null) { await processEventTask.ConfigureAwait(false); } } catch (OperationCanceledException) { // when just a single operation is cancelled, we continue processing events. // TODO: what is the desired behavior in this case? } }
/// <summary> /// Attempts to start processing a compilation event for the given analyzer. /// </summary> /// <returns> /// Returns false if the event has already been processed for the analyzer OR is currently being processed by another task. /// If true, then it returns a non-null <paramref name="state"/> representing partial analysis state for the given event for the given analyzer. /// </returns> public bool TryStartProcessingEvent(CompilationEvent compilationEvent, DiagnosticAnalyzer analyzer, out AnalyzerStateData state) { return _analyzerStateMap[analyzer].TryStartProcessingEvent(compilationEvent, out state); }
/// <summary> /// Marks the given event as fully analyzed for the given analyzer. /// </summary> public void MarkEventComplete(CompilationEvent compilationEvent, DiagnosticAnalyzer analyzer) { _analyzerStateMap[analyzer].MarkEventComplete(compilationEvent); }
/// <summary> /// Marks the given event as fully analyzed for the given analyzers. /// </summary> public void MarkEventComplete(CompilationEvent compilationEvent, IEnumerable<DiagnosticAnalyzer> analyzers) { foreach (var analyzer in analyzers) { GetAnalyzerState(analyzer).MarkEventComplete(compilationEvent); } }
/// <summary> /// Invoke this method at completion of event processing for the given analysis scope. /// It updates the analysis state of this event for each analyzer and if the event has been fully processed for all analyzers, then removes it from our event cache. /// </summary> public void OnCompilationEventProcessed(CompilationEvent compilationEvent, AnalysisScope analysisScope) { // Analyze if the symbol and all its declaring syntax references are analyzed. var symbolDeclaredEvent = compilationEvent as SymbolDeclaredCompilationEvent; if (symbolDeclaredEvent != null) { OnSymbolDeclaredEventProcessed(symbolDeclaredEvent, analysisScope.Analyzers); } // Check if event is fully analyzed for all analyzers. foreach (var analyzerState in _analyzerStateMap.Values) { if (!analyzerState.IsEventAnalyzed(compilationEvent)) { return; } } // Remove the event from event map. lock (_gate) { UpdateEventsMap_NoLock(compilationEvent, add: false); } }
private void AddPendingSourceEvent_NoLock(SyntaxTree tree, CompilationEvent compilationEvent) { HashSet<CompilationEvent> currentEvents; if (!_pendingSourceEvents.TryGetValue(tree, out currentEvents)) { currentEvents = new HashSet<CompilationEvent>(); _pendingSourceEvents[tree] = currentEvents; _compilationData.RemoveCachedSemanticModel(tree); } currentEvents.Add(compilationEvent); }
/// <summary> /// Attempts to start processing a compilation event for the given analyzer. /// </summary> /// <returns> /// Returns null if the event has already been processed for the analyzer OR is currently being processed by another task. /// Otherwise, returns a non-null state representing partial analysis state for the given event for the given analyzer. /// </returns> public Task<AnalyzerStateData> TryStartProcessingEventAsync(CompilationEvent compilationEvent, DiagnosticAnalyzer analyzer, CancellationToken cancellationToken) { return GetAnalyzerState(analyzer).TryStartProcessingEventAsync(compilationEvent, cancellationToken); }
/// <summary> /// Marks the given event as fully analyzed for the given analyzer. /// </summary> public void MarkEventComplete(CompilationEvent compilationEvent, DiagnosticAnalyzer analyzer) { GetAnalyzerState(analyzer).MarkEventComplete(compilationEvent); }
private void ProcessEvent(CompilationEvent e, AnalysisScope analysisScope, AnalysisState analysisStateOpt, CancellationToken cancellationToken) { ProcessEventCore(e, analysisScope, analysisStateOpt, cancellationToken); analysisStateOpt?.OnCompilationEventProcessed(e, analysisScope); }
private async Task ProcessEventAsync(CompilationEvent e, AnalysisScope analysisScope, AnalysisState analysisStateOpt, CancellationToken cancellationToken) { await ProcessEventCoreAsync(e, analysisScope, analysisStateOpt, cancellationToken).ConfigureAwait(false); if (analysisStateOpt != null) { await analysisStateOpt.OnCompilationEventProcessedAsync(e, analysisScope, cancellationToken).ConfigureAwait(false); } }
private static bool HasActionsForEvent(CompilationEvent compilationEvent, AnalyzerActionCounts actionCounts) { if (compilationEvent is CompilationStartedEvent) { return actionCounts.CompilationActionsCount > 0 || actionCounts.SyntaxTreeActionsCount > 0; } else if (compilationEvent is CompilationCompletedEvent) { return actionCounts.CompilationEndActionsCount > 0; } else if (compilationEvent is SymbolDeclaredCompilationEvent) { return actionCounts.SymbolActionsCount > 0 || actionCounts.HasAnyExecutableCodeActions; } else { return actionCounts.SemanticModelActionsCount > 0; } }
public bool IsEventAnalyzed(CompilationEvent compilationEvent) { return(IsEntityFullyProcessed(compilationEvent, _pendingEvents)); }
private void RemovePendingSourceEvent_NoLock(SyntaxTree tree, CompilationEvent compilationEvent) { HashSet<CompilationEvent> currentEvents; if (_pendingSourceEvents.TryGetValue(tree, out currentEvents)) { if (currentEvents.Remove(compilationEvent) && currentEvents.Count == 0) { _pendingSourceEvents.Remove(tree); _compilationData.RemoveCachedSemanticModel(tree); } } }
private Task ProcessEventCoreAsync(CompilationEvent e, CancellationToken cancellationToken) { var symbolEvent = e as SymbolDeclaredCompilationEvent; if (symbolEvent != null) { return ProcessSymbolDeclaredAsync(symbolEvent, cancellationToken); } var completedEvent = e as CompilationUnitCompletedEvent; if (completedEvent != null) { return ProcessCompilationUnitCompletedAsync(completedEvent, cancellationToken); } var endEvent = e as CompilationCompletedEvent; if (endEvent != null) { return ProcessCompilationCompletedAsync(endEvent, cancellationToken); } if (e is CompilationStartedEvent) { // Ignore CompilationStartedEvent. return null; } throw new InvalidOperationException("Unexpected compilation event of type " + e.GetType().Name); }
private static bool HasActionsForEvent(CompilationEvent compilationEvent, ActionCounts actionCounts) { if (compilationEvent is CompilationStartedEvent) { return actionCounts.CompilationActionsCount > 0 || actionCounts.SyntaxTreeActionsCount > 0; } else if (compilationEvent is CompilationCompletedEvent) { return actionCounts.CompilationEndActionsCount > 0; } else if (compilationEvent is SymbolDeclaredCompilationEvent) { return actionCounts.CodeBlockActionsCount > 0 || actionCounts.CodeBlockStartActionsCount > 0 || actionCounts.SymbolActionsCount > 0 || actionCounts.SyntaxNodeActionsCount > 0; } else { return actionCounts.SemanticModelActionsCount > 0; } }
private async Task ProcessEventAsync(CompilationEvent e, CancellationToken cancellationToken) { var symbolEvent = e as SymbolDeclaredCompilationEvent; if (symbolEvent != null) { await ProcessSymbolDeclared(symbolEvent, cancellationToken).ConfigureAwait(false); return; } var completedEvent = e as CompilationUnitCompletedEvent; if (completedEvent != null) { await ProcessCompilationUnitCompleted(completedEvent, cancellationToken).ConfigureAwait(false); return; } var endEvent = e as CompilationCompletedEvent; if (endEvent != null) { await ProcessCompilationCompletedAsync(endEvent, cancellationToken).ConfigureAwait(false); return; } throw new InvalidOperationException("Unexpected compilation event of type " + e.GetType().Name); }
private void ProcessEventCore(CompilationEvent e, AnalysisScope analysisScope, AnalysisState analysisStateOpt, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var symbolEvent = e as SymbolDeclaredCompilationEvent; if (symbolEvent != null) { ProcessSymbolDeclared(symbolEvent, analysisScope, analysisStateOpt, cancellationToken); return; } var completedEvent = e as CompilationUnitCompletedEvent; if (completedEvent != null) { ProcessCompilationUnitCompleted(completedEvent, analysisScope, analysisStateOpt, cancellationToken); return; } var endEvent = e as CompilationCompletedEvent; if (endEvent != null) { ProcessCompilationCompleted(endEvent, analysisScope, analysisStateOpt, cancellationToken); return; } var startedEvent = e as CompilationStartedEvent; if (startedEvent != null) { ProcessCompilationStarted(startedEvent, analysisScope, analysisStateOpt, cancellationToken); return; } throw new InvalidOperationException("Unexpected compilation event of type " + e.GetType().Name); }
public void MarkEventComplete(CompilationEvent compilationEvent) { MarkEntityProcessed(compilationEvent, _pendingEvents, _analyzerStateDataPool); }
/// <summary> /// Checks if the given event has been fully analyzed for the given analyzer. /// </summary> public bool IsEventComplete(CompilationEvent compilationEvent, DiagnosticAnalyzer analyzer) { return GetAnalyzerState(analyzer).IsEventAnalyzed(compilationEvent); }
/// <summary> /// Attempts to start processing a compilation event for the given analyzer. /// </summary> /// <returns> /// Returns false if the event has already been processed for the analyzer OR is currently being processed by another task. /// If true, then it returns a non-null <paramref name="state"/> representing partial analysis state for the given event for the given analyzer. /// </returns> public bool TryStartProcessingEvent(CompilationEvent compilationEvent, DiagnosticAnalyzer analyzer, out AnalyzerStateData state) { return(GetAnalyzerState(analyzer).TryStartProcessingEvent(compilationEvent, out state)); }
private void RemovePendingSourceEvent_NoLock(SyntaxTree tree, CompilationEvent compilationEvent) { HashSet<CompilationEvent> currentEvents; if (_pendingSourceEvents.TryGetValue(tree, out currentEvents)) { if (currentEvents.Remove(compilationEvent) && currentEvents.Count == 0) { _compilationEventsPool.Free(currentEvents); _pendingSourceEvents.Remove(tree); } } }
private async Task ExecuteCompilationActionsAsync( ImmutableDictionary<DiagnosticAnalyzer, ImmutableArray<CompilationAnalyzerAction>> compilationActionsMap, CompilationEvent compilationEvent, AnalysisScope analysisScope, AnalysisState analysisStateOpt, CancellationToken cancellationToken) { Debug.Assert(compilationEvent is CompilationStartedEvent || compilationEvent is CompilationCompletedEvent); try { foreach (var analyzer in analysisScope.Analyzers) { ImmutableArray<CompilationAnalyzerAction> compilationActions; if (compilationActionsMap.TryGetValue(analyzer, out compilationActions)) { await analyzerExecutor.ExecuteCompilationActionsAsync(compilationActions, analyzer, compilationEvent, analysisScope, analysisStateOpt).ConfigureAwait(false); } else if (analysisStateOpt != null) { await analysisStateOpt.MarkEventCompleteAsync(compilationEvent, analyzer, cancellationToken).ConfigureAwait(false); } } } finally { compilationEvent.FlushCache(); } }
private void AddPendingSourceEvent_NoLock(SyntaxTree tree, CompilationEvent compilationEvent) { HashSet<CompilationEvent> currentEvents; if (!_pendingSourceEvents.TryGetValue(tree, out currentEvents)) { currentEvents = _compilationEventsPool.Allocate(); _pendingSourceEvents[tree] = currentEvents; AnalyzerDriver.RemoveCachedSemanticModel(tree, compilationEvent.Compilation); } currentEvents.Add(compilationEvent); }
/// <summary> /// Checks if the given event has been fully analyzed for the given analyzer. /// </summary> public bool IsEventComplete(CompilationEvent compilationEvent, DiagnosticAnalyzer analyzer) { return(GetAnalyzerState(analyzer).IsEventAnalyzed(compilationEvent)); }
private void AddPendingSourceEvent_NoLock(SyntaxTree tree, CompilationEvent compilationEvent) { HashSet<CompilationEvent> currentEvents; if (!_pendingSourceEvents.TryGetValue(tree, out currentEvents)) { currentEvents = _compilationEventsPool.Allocate(); _pendingSourceEvents[tree] = currentEvents; } currentEvents.Add(compilationEvent); }