public void ExecuteSyntaxNodeActions <TLanguageKindEnum>( IEnumerable <SyntaxNode> nodesToAnalyze, IDictionary <TLanguageKindEnum, ImmutableArray <SyntaxNodeAnalyzerAction <TLanguageKindEnum> > > nodeActionsByKind, DiagnosticAnalyzer analyzer, SemanticModel model, Func <SyntaxNode, TLanguageKindEnum> getKind, TextSpan filterSpan, SyntaxReference declaration, AnalysisScope analysisScope, AnalysisState analysisStateOpt) where TLanguageKindEnum : struct { DeclarationAnalyzerStateData analyzerStateOpt = null; try { if (TryStartAnalyzingSyntaxRefence(declaration, analyzer, analysisScope, analysisStateOpt, out analyzerStateOpt)) { ExecuteSyntaxNodeActionsCore(nodesToAnalyze, nodeActionsByKind, analyzer, model, getKind, filterSpan, analyzerStateOpt); } } finally { analyzerStateOpt?.ResetToReadyState(); } }
/// <summary> /// Executes the symbol actions on the given symbol. /// </summary> /// <param name="symbolActions">Symbol actions to be executed.</param> /// <param name="analyzer">Analyzer whose actions are to be executed.</param> /// <param name="symbol">Symbol to be analyzed.</param> /// <param name="overriddenAddDiagnostic">Overridden add diagnostic delegate.</param> /// <param name="overriddenAddLocalDiagnostic">Overridden add local diagnostic delegate.</param> /// <param name="overriddenAddNonLocalDiagnostic">Overridden add non-local diagnostic delegate.</param> /// <param name="getTopMostNodeForAnalysis">Delegate to get topmost declaration node for a symbol declaration reference.</param> /// <param name="analysisScope">Scope for analyzer execution.</param> /// <param name="analysisStateOpt">An optional object to track analysis state.</param> public void ExecuteSymbolActions( ImmutableArray <SymbolAnalyzerAction> symbolActions, DiagnosticAnalyzer analyzer, ISymbol symbol, Action <Diagnostic> overriddenAddDiagnostic, Action <Diagnostic, DiagnosticAnalyzer, bool> overriddenAddLocalDiagnostic, Action <Diagnostic, DiagnosticAnalyzer> overriddenAddNonLocalDiagnostic, Func <ISymbol, SyntaxReference, Compilation, SyntaxNode> getTopMostNodeForAnalysis, AnalysisScope analysisScope, AnalysisState analysisStateOpt) { AnalyzerStateData analyzerStateOpt = null; try { if (TryStartAnalyzingSymbol(symbol, analyzer, analysisScope, analysisStateOpt, out analyzerStateOpt)) { ExecuteSymbolActionsCore(symbolActions, analyzer, symbol, overriddenAddDiagnostic, overriddenAddLocalDiagnostic, overriddenAddNonLocalDiagnostic, getTopMostNodeForAnalysis, analyzerStateOpt); analysisStateOpt?.MarkSymbolComplete(symbol, analyzer); } } finally { analyzerStateOpt?.ResetToReadyState(); } }
public void ExecuteCodeBlockActions <TLanguageKindEnum>( IEnumerable <CodeBlockStartAnalyzerAction <TLanguageKindEnum> > codeBlockStartActions, IEnumerable <CodeBlockAnalyzerAction> codeBlockActions, IEnumerable <CodeBlockAnalyzerAction> codeBlockEndActions, DiagnosticAnalyzer analyzer, SyntaxNode declaredNode, ISymbol declaredSymbol, ImmutableArray <SyntaxNode> executableCodeBlocks, SemanticModel semanticModel, Func <SyntaxNode, TLanguageKindEnum> getKind, SyntaxReference declaration, AnalysisScope analysisScope, AnalysisState analysisStateOpt) where TLanguageKindEnum : struct { DeclarationAnalyzerStateData analyzerStateOpt = null; try { if (TryStartAnalyzingSyntaxRefence(declaration, analyzer, analysisScope, analysisStateOpt, out analyzerStateOpt)) { ExecuteCodeBlockActionsCore(codeBlockStartActions, codeBlockActions, codeBlockEndActions, analyzer, declaredNode, declaredSymbol, executableCodeBlocks, semanticModel, getKind, analyzerStateOpt?.CodeBlockAnalysisState); } } finally { analyzerStateOpt?.ResetToReadyState(); } }
private CompilationWithAnalyzers(Compilation compilation, ImmutableArray <DiagnosticAnalyzer> analyzers, CompilationWithAnalyzersOptions analysisOptions, CancellationToken cancellationToken) { VerifyArguments(compilation, analyzers, analysisOptions); _compilation = compilation.WithEventQueue(new AsyncQueue <CompilationEvent>()); _analyzers = analyzers; _analysisOptions = analysisOptions; _cancellationToken = cancellationToken; _analysisState = new AnalysisState(analyzers); _analysisResult = new AnalysisResult(analysisOptions.LogAnalyzerExecutionTime, analyzers); _driverPool = new ObjectPool <AnalyzerDriver>(() => compilation.AnalyzerForLanguage(analyzers, AnalyzerManager.Instance)); _executingConcurrentTreeTasksOpt = analysisOptions.ConcurrentAnalysis ? new Dictionary <SyntaxTree, Tuple <Task, CancellationTokenSource> >() : null; _concurrentTreeTaskTokensOpt = analysisOptions.ConcurrentAnalysis ? new Dictionary <Task, int>() : null; _executingCompilationOrNonConcurrentTreeTask = null; }
/// <summary> /// Executes the syntax tree actions on the given syntax tree. /// </summary> /// <param name="syntaxTreeActions">Syntax tree actions to be executed.</param> /// <param name="analyzer">Analyzer whose actions are to be executed.</param> /// <param name="tree">Syntax tree to analyze.</param> /// <param name="analysisScope">Scope for analyzer execution.</param> /// <param name="analysisStateOpt">An optional object to track analysis state.</param> public void ExecuteSyntaxTreeActions( ImmutableArray <SyntaxTreeAnalyzerAction> syntaxTreeActions, DiagnosticAnalyzer analyzer, SyntaxTree tree, AnalysisScope analysisScope, AnalysisState analysisStateOpt) { AnalyzerStateData analyzerStateOpt = null; try { if (TryStartSyntaxAnalysis(tree, analyzer, analysisScope, analysisStateOpt, out analyzerStateOpt)) { ExecuteSyntaxTreeActionsCore(syntaxTreeActions, analyzer, tree, analyzerStateOpt); analysisStateOpt?.MarkSyntaxAnalysisComplete(tree, analyzer); } } finally { analyzerStateOpt?.ResetToReadyState(); } }
/// <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(); } }
/// <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 CompilationWithAnalyzers(Compilation compilation, ImmutableArray<DiagnosticAnalyzer> analyzers, CompilationWithAnalyzersOptions analysisOptions, CancellationToken cancellationToken) { VerifyArguments(compilation, analyzers, analysisOptions); _compilation = compilation.WithEventQueue(new AsyncQueue<CompilationEvent>()); _analyzers = analyzers; _analysisOptions = analysisOptions; _cancellationToken = cancellationToken; _analysisState = new AnalysisState(analyzers); _analysisResult = new AnalysisResult(analysisOptions.LogAnalyzerExecutionTime, analyzers); _driverPool = new ObjectPool<AnalyzerDriver>(() => compilation.AnalyzerForLanguage(analyzers, AnalyzerManager.Instance)); _executingConcurrentTreeTasksOpt = analysisOptions.ConcurrentAnalysis ? new Dictionary<SyntaxTree, Tuple<Task, CancellationTokenSource>>() : null; _concurrentTreeTaskTokensOpt = analysisOptions.ConcurrentAnalysis ? new Dictionary<Task, int>() : null; _executingCompilationOrNonConcurrentTreeTask = null; }
private static bool TryStartAnalyzingSyntaxRefence(SyntaxReference syntaxReference, DiagnosticAnalyzer analyzer, AnalysisScope analysisScope, AnalysisState analysisStateOpt, out DeclarationAnalyzerStateData analyzerStateOpt) { Debug.Assert(analysisScope.Analyzers.Contains(analyzer)); analyzerStateOpt = null; return(analysisStateOpt == null || analysisStateOpt.TryStartAnalyzingDeclaration(syntaxReference, analyzer, out analyzerStateOpt)); }
protected abstract bool TryExecuteDeclaringReferenceActions(SymbolDeclaredCompilationEvent symbolEvent, AnalysisScope analysisScope, AnalysisState analysisStateOpt, bool isGeneratedCodeSymbol, CancellationToken cancellationToken);
private void ProcessCompilationCompleted(CompilationCompletedEvent endEvent, AnalysisScope analysisScope, AnalysisState analysisStateOpt, CancellationToken cancellationToken) { ExecuteCompilationActions(_compilationEndActionsMap, endEvent, analysisScope, analysisStateOpt, cancellationToken); }
/// <summary> /// Tries to execute symbol and declaration actions for the given symbol. /// </summary> /// <returns> /// True, if successfully executed the actions for the given analysis scope OR no actions were required to be executed for the given analysis scope. /// False, otherwise. /// </returns> private bool TryProcessSymbolDeclared(SymbolDeclaredCompilationEvent symbolEvent, AnalysisScope analysisScope, AnalysisState analysisStateOpt, CancellationToken cancellationToken) { try { // Attempt to execute all analyzer actions. var success = true; var symbol = symbolEvent.Symbol; var isGeneratedCodeSymbol = IsGeneratedCodeSymbol(symbol); if (!AnalysisScope.ShouldSkipSymbolAnalysis(symbolEvent) && !TryExecuteSymbolActions(symbolEvent, analysisScope, analysisStateOpt, isGeneratedCodeSymbol, cancellationToken)) { success = false; } if (!AnalysisScope.ShouldSkipDeclarationAnalysis(symbol) && !TryExecuteDeclaringReferenceActions(symbolEvent, analysisScope, analysisStateOpt, isGeneratedCodeSymbol, cancellationToken)) { success = false; } return success; } finally { symbolEvent.FlushCache(); } }
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 async Task ExecutePrimaryAnalysisTaskAsync(AnalysisScope analysisScope, AnalysisState analysisStateOpt, bool usingPrePopulatedEventQueue, CancellationToken cancellationToken) { Debug.Assert(analysisScope != null); Debug.Assert(WhenInitializedTask != null); await WhenInitializedTask.ConfigureAwait(false); if (WhenInitializedTask.IsFaulted) { OnDriverException(WhenInitializedTask, this.analyzerExecutor, analysisScope.Analyzers); } else if (!WhenInitializedTask.IsCanceled) { this.analyzerExecutor = this.analyzerExecutor.WithCancellationToken(cancellationToken); await ProcessCompilationEventsAsync(analysisScope, analysisStateOpt, usingPrePopulatedEventQueue, cancellationToken).ConfigureAwait(false); } }
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 Task ProcessCompilationCompletedAsync(CompilationCompletedEvent endEvent, AnalysisScope analysisScope, AnalysisState analysisStateOpt, CancellationToken cancellationToken) { return ExecuteCompilationActionsAsync(_compilationEndActionsMap, endEvent, analysisScope, analysisStateOpt, cancellationToken); }
private async Task ProcessSymbolDeclaredAsync(SymbolDeclaredCompilationEvent symbolEvent, AnalysisScope analysisScope, AnalysisState analysisStateOpt, CancellationToken cancellationToken) { try { // Execute all analyzer actions. var symbol = symbolEvent.Symbol; var references = symbolEvent.DeclaringSyntaxReferences; if (!AnalysisScope.ShouldSkipSymbolAnalysis(symbolEvent)) { await ExecuteSymbolActionsAsync(symbolEvent, analysisScope, analysisStateOpt, cancellationToken).ConfigureAwait(false); } if (!AnalysisScope.ShouldSkipDeclarationAnalysis(symbol)) { await ExecuteDeclaringReferenceActionsAsync(symbolEvent, analysisScope, analysisStateOpt, cancellationToken).ConfigureAwait(false); } } finally { symbolEvent.FlushCache(); } }
private void ExecuteSymbolActions(SymbolDeclaredCompilationEvent symbolEvent, AnalysisScope analysisScope, AnalysisState analysisStateOpt, CancellationToken cancellationToken) { var symbol = symbolEvent.Symbol; if (!analysisScope.ShouldAnalyze(symbol)) { return; } foreach (var analyzer in analysisScope.Analyzers) { // Invoke symbol analyzers only for source symbols. ImmutableArray<ImmutableArray<SymbolAnalyzerAction>> actionsByKind; if (_symbolActionsByKind.TryGetValue(analyzer, out actionsByKind) && (int)symbol.Kind < actionsByKind.Length) { analyzerExecutor.ExecuteSymbolActions(actionsByKind[(int)symbol.Kind], analyzer, symbol, GetTopmostNodeForAnalysis, analysisScope, analysisStateOpt); } else { analysisStateOpt?.MarkSymbolComplete(symbol, analyzer); } } }
private async Task ProcessCompilationEventsAsync(AnalysisScope analysisScope, AnalysisState analysisStateOpt, bool prePopulatedEventQueue, CancellationToken cancellationToken) { try { CompilationCompletedEvent completedEvent = null; if (analysisScope.ConcurrentAnalysis) { // Kick off worker tasks to process all compilation events (except the compilation end event) in parallel. // Compilation end event must be processed after all other events. var workerCount = prePopulatedEventQueue ? Math.Min(CompilationEventQueue.Count, _workerCount) : _workerCount; var workerTasks = new Task<CompilationCompletedEvent>[workerCount]; for (int i = 0; i < workerCount; i++) { workerTasks[i] = ProcessCompilationEventsCoreAsync(analysisScope, analysisStateOpt, prePopulatedEventQueue, cancellationToken); } cancellationToken.ThrowIfCancellationRequested(); // Kick off tasks to execute syntax tree actions. var syntaxTreeActionsTask = Task.Run(() => ExecuteSyntaxTreeActions(analysisScope, analysisStateOpt, cancellationToken)); // Wait for all worker threads to complete processing events. await Task.WhenAll(workerTasks.Concat(syntaxTreeActionsTask)).ConfigureAwait(false); for (int i = 0; i < workerCount; i++) { if (workerTasks[i].Status == TaskStatus.RanToCompletion && workerTasks[i].Result != null) { completedEvent = workerTasks[i].Result; break; } } } else { completedEvent = await ProcessCompilationEventsCoreAsync(analysisScope, analysisStateOpt, prePopulatedEventQueue, cancellationToken).ConfigureAwait(false); ExecuteSyntaxTreeActions(analysisScope, analysisStateOpt, cancellationToken); } // Finally process the compilation completed event, if any. if (completedEvent != null) { ProcessEvent(completedEvent, analysisScope, analysisStateOpt, cancellationToken); } } catch (Exception e) when (FatalError.ReportUnlessCanceled(e)) { throw ExceptionUtilities.Unreachable; } }
/// <summary> /// Attaches a pre-populated event queue to the driver and processes all events in the queue. /// </summary> /// <param name="eventQueue">Compilation events to analyze.</param> /// <param name="analysisScope">Scope of analysis.</param> /// <param name="analysisStateOpt">An optional object to track partial analysis state.</param> /// <param name="cancellationToken">Cancellation token to abort analysis.</param> /// <remarks>Driver must be initialized before invoking this method, i.e. <see cref="Initialize(AnalyzerExecutor, DiagnosticQueue, CancellationToken)"/> method must have been invoked and <see cref="WhenInitializedTask"/> must be non-null.</remarks> internal async Task AttachQueueAndProcessAllEventsAsync(AsyncQueue<CompilationEvent> eventQueue, AnalysisScope analysisScope, AnalysisState analysisStateOpt, CancellationToken cancellationToken) { try { if (_initializeSucceeded) { this.CompilationEventQueue = eventQueue; _queueRegistration = default(CancellationTokenRegistration); await ExecutePrimaryAnalysisTaskAsync(analysisScope, analysisStateOpt, usingPrePopulatedEventQueue: true, cancellationToken: cancellationToken).ConfigureAwait(false); _primaryTask = Task.FromResult(true); } } finally { if (_primaryTask == null) { // Set primaryTask to be a cancelled task. var tcs = new TaskCompletionSource<int>(); tcs.SetCanceled(); _primaryTask = tcs.Task; } } }
private async Task ExecuteSyntaxTreeActionsAsync(AnalysisScope analysisScope, AnalysisState analysisStateOpt, CancellationToken cancellationToken) { if (analysisScope.IsTreeAnalysis && !analysisScope.IsSyntaxOnlyTreeAnalysis) { // For partial analysis, only execute syntax tree actions if performing syntax analysis. return; } foreach (var tree in analysisScope.SyntaxTrees) { foreach (var analyzer in analysisScope.Analyzers) { cancellationToken.ThrowIfCancellationRequested(); ImmutableArray<SyntaxTreeAnalyzerAction> syntaxTreeActions; if (_syntaxTreeActionsMap.TryGetValue(analyzer, out syntaxTreeActions)) { // Execute actions for a given analyzer sequentially. await analyzerExecutor.ExecuteSyntaxTreeActionsAsync(syntaxTreeActions, analyzer, tree, analysisScope, analysisStateOpt).ConfigureAwait(false); } else if (analysisStateOpt != null) { await analysisStateOpt.MarkSyntaxAnalysisCompleteAsync(tree, analyzer, cancellationToken).ConfigureAwait(false); } } } }
private void ExecuteSyntaxTreeActions(AnalysisScope analysisScope, AnalysisState analysisStateOpt, CancellationToken cancellationToken) { if (analysisScope.IsTreeAnalysis && !analysisScope.IsSyntaxOnlyTreeAnalysis) { // For partial analysis, only execute syntax tree actions if performing syntax analysis. return; } foreach (var tree in analysisScope.SyntaxTrees) { foreach (var analyzer in analysisScope.Analyzers) { cancellationToken.ThrowIfCancellationRequested(); ImmutableArray<SyntaxTreeAnalyzerAction> syntaxTreeActions; if (_syntaxTreeActionsMap.TryGetValue(analyzer, out syntaxTreeActions)) { // Execute actions for a given analyzer sequentially. analyzerExecutor.ExecuteSyntaxTreeActions(syntaxTreeActions, analyzer, tree, analysisScope, analysisStateOpt); } else { analysisStateOpt?.MarkSyntaxAnalysisComplete(tree, analyzer); } } } }
private void ProcessSymbolDeclared(SymbolDeclaredCompilationEvent symbolEvent, AnalysisScope analysisScope, AnalysisState analysisStateOpt, CancellationToken cancellationToken) { try { // Execute all analyzer actions. var symbol = symbolEvent.Symbol; var references = symbolEvent.DeclaringSyntaxReferences; if (!AnalysisScope.ShouldSkipSymbolAnalysis(symbolEvent)) { ExecuteSymbolActions(symbolEvent, analysisScope, analysisStateOpt, cancellationToken); } if (!AnalysisScope.ShouldSkipDeclarationAnalysis(symbol)) { ExecuteDeclaringReferenceActions(symbolEvent, analysisScope, analysisStateOpt, cancellationToken); } } finally { symbolEvent.FlushCache(); } }
private async Task<CompilationCompletedEvent> ProcessCompilationEventsCoreAsync(AnalysisScope analysisScope, AnalysisState analysisStateOpt, bool prePopulatedEventQueue, CancellationToken cancellationToken) { try { CompilationCompletedEvent completedEvent = null; while (true) { cancellationToken.ThrowIfCancellationRequested(); if (CompilationEventQueue.Count == 0 && (prePopulatedEventQueue || CompilationEventQueue.IsCompleted)) { break; } CompilationEvent e; try { if (!prePopulatedEventQueue) { e = await CompilationEventQueue.DequeueAsync(cancellationToken).ConfigureAwait(false); } else if (!CompilationEventQueue.TryDequeue(out e)) { return completedEvent; } } catch (TaskCanceledException) when (!prePopulatedEventQueue) { // When the queue is completed with a pending DequeueAsync return then a // TaskCanceledException will be thrown. This just signals the queue is // complete and we should finish processing it. Debug.Assert(CompilationEventQueue.IsCompleted, "DequeueAsync should never throw unless the AsyncQueue<T> is completed."); break; } // Don't process the compilation completed event as other worker threads might still be processing other compilation events. // The caller will wait for all workers to complete and finally process this event. var compilationCompletedEvent = e as CompilationCompletedEvent; if (compilationCompletedEvent != null) { completedEvent = compilationCompletedEvent; continue; } ProcessEvent(e, analysisScope, analysisStateOpt, cancellationToken); } return completedEvent; } catch (Exception e) when (FatalError.ReportUnlessCanceled(e)) { throw ExceptionUtilities.Unreachable; } }
protected abstract void ExecuteDeclaringReferenceActions(SymbolDeclaredCompilationEvent symbolEvent, AnalysisScope analysisScope, AnalysisState analysisStateOpt, CancellationToken cancellationToken);
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); }
/// <summary> /// Tries to execute compilation started actions. /// </summary> /// <returns> /// True, if successfully executed the actions for the given analysis scope OR no actions were required to be executed for the given analysis scope. /// False, otherwise. /// </returns> private bool TryProcessCompilationStarted(CompilationStartedEvent startedEvent, AnalysisScope analysisScope, AnalysisState analysisStateOpt, CancellationToken cancellationToken) { return TryExecuteCompilationActions(_compilationActionsMap, startedEvent, analysisScope, analysisStateOpt, cancellationToken); }
private void ExecuteSymbolActions(SymbolDeclaredCompilationEvent symbolEvent, AnalysisScope analysisScope, AnalysisState analysisStateOpt, CancellationToken cancellationToken) { var symbol = symbolEvent.Symbol; if (!analysisScope.ShouldAnalyze(symbol)) { return; } Action<Diagnostic> addDiagnosticForSymbol = GetDiagnosticSinkWithSuppression(DiagnosticQueue.Enqueue, symbolEvent.Compilation, symbol); Action<Diagnostic, DiagnosticAnalyzer, bool> addLocalDiagnosticForSymbol = analysisScope.CategorizeDiagnostics ? GetDiagnosticSinkWithSuppression(DiagnosticQueue.EnqueueLocal, symbolEvent.Compilation, symbol) : null; Action<Diagnostic, DiagnosticAnalyzer> addNonLocalDiagnosticForSymbol = analysisScope.CategorizeDiagnostics ? GetDiagnosticSinkWithSuppression(DiagnosticQueue.EnqueueNonLocal, symbolEvent.Compilation, symbol) : null; foreach (var analyzer in analysisScope.Analyzers) { // Invoke symbol analyzers only for source symbols. ImmutableArray<ImmutableArray<SymbolAnalyzerAction>> actionsByKind; if (_symbolActionsByKind.TryGetValue(analyzer, out actionsByKind) && (int)symbol.Kind < actionsByKind.Length) { analyzerExecutor.ExecuteSymbolActions(actionsByKind[(int)symbol.Kind], analyzer, symbol, addDiagnosticForSymbol, addLocalDiagnosticForSymbol, addNonLocalDiagnosticForSymbol, GetTopmostNodeForAnalysis, analysisScope, analysisStateOpt); } else { analysisStateOpt?.MarkSymbolComplete(symbol, analyzer); } } }
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 ProcessCompilationUnitCompleted(CompilationUnitCompletedEvent completedEvent, AnalysisScope analysisScope, AnalysisState analysisStateOpt, CancellationToken cancellationToken) { // When the compiler is finished with a compilation unit, we can run user diagnostics which // might want to ask the compiler for all the diagnostics in the source file, for example // to get information about unnecessary usings. var semanticModel = analysisStateOpt != null ? GetOrCreateCachedSemanticModel(completedEvent.CompilationUnit, completedEvent.Compilation, cancellationToken) : completedEvent.SemanticModel; if (!analysisScope.ShouldAnalyze(semanticModel.SyntaxTree)) { return; } try { foreach (var analyzer in analysisScope.Analyzers) { ImmutableArray<SemanticModelAnalyzerAction> semanticModelActions; if (_semanticModelActionsMap.TryGetValue(analyzer, out semanticModelActions)) { // Execute actions for a given analyzer sequentially. analyzerExecutor.ExecuteSemanticModelActions(semanticModelActions, analyzer, semanticModel, completedEvent, analysisScope, analysisStateOpt); } else { analysisStateOpt?.MarkEventComplete(completedEvent, analyzer); } } } finally { completedEvent.FlushCache(); } }
private static bool TryStartSyntaxAnalysis(SyntaxTree tree, DiagnosticAnalyzer analyzer, AnalysisScope analysisScope, AnalysisState analysisStateOpt, out AnalyzerStateData analyzerStateOpt) { Debug.Assert(analysisScope.Analyzers.Contains(analyzer)); analyzerStateOpt = null; return(analysisStateOpt == null || analysisStateOpt.TryStartSyntaxAnalysis(tree, analyzer, out analyzerStateOpt)); }
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(); } }
private static bool TryStartAnalyzingSymbol(ISymbol symbol, DiagnosticAnalyzer analyzer, AnalysisScope analysisScope, AnalysisState analysisStateOpt, out AnalyzerStateData analyzerStateOpt) { Debug.Assert(analysisScope.Analyzers.Contains(analyzer)); analyzerStateOpt = null; return(analysisStateOpt == null || analysisStateOpt.TryStartAnalyzingSymbol(symbol, analyzer, out analyzerStateOpt)); }