/// <summary> /// Executes the <see cref="DiagnosticAnalyzer.Initialize(AnalysisContext)"/> for the given analyzer and returns the set of registered sessions. /// </summary> /// <param name="analyzer">Analyzer to get session wide analyzer actions.</param> /// <param name="addDiagnostic">Delegate to add diagnostics.</param> /// <param name="continueOnAnalyzerException">Predicate to decide if exceptions from the action should be handled or not.</param> /// <param name="cancellationToken">Cancellation token.</param> /// <remarks> /// Note that this API doesn't execute any <see cref="CompilationStartAnalyzerAction"/> registered by the Initialize invocation. /// Use <see cref="ExecuteCompilationStartActions(AnalyzerActions, DiagnosticAnalyzer, Compilation, AnalyzerOptions, Action{Diagnostic}, Func{Exception, DiagnosticAnalyzer, bool}, CancellationToken)"/> API /// to get execute these actions to get the per-compilation analyzer actions. /// </remarks> public static AnalyzerActions GetSessionAnalyzerActions( DiagnosticAnalyzer analyzer, Action <Diagnostic> addDiagnostic, Func <Exception, DiagnosticAnalyzer, bool> continueOnAnalyzerException, CancellationToken cancellationToken) { VerifyArguments(analyzer, addDiagnostic, continueOnAnalyzerException); HostSessionStartAnalysisScope sessionScope = new HostSessionStartAnalysisScope(); ExecuteAndCatchIfThrows(analyzer, addDiagnostic, continueOnAnalyzerException, () => { // The Initialize method should be run asynchronously in case it is not well behaved, e.g. does not terminate. analyzer.Initialize(new AnalyzerAnalysisContext(analyzer, sessionScope)); }, cancellationToken); return(sessionScope.GetAnalyzerActions(analyzer)); }
private static bool?GetOrComputeIsCompilationEndAnalyzer( DiagnosticAnalyzer analyzer, AnalyzerOptions analyzerOptions, Compilation compilation, ConcurrentDictionary <DiagnosticAnalyzer, bool?> endAnalyzerMap) { return(endAnalyzerMap.AddOrUpdate( analyzer, addValueFactory: ComputeIsCompilationEndAnalyzer, updateValueFactory: (a, currentValue) => currentValue != null ? currentValue : ComputeIsCompilationEndAnalyzer(a))); // Local functions bool?ComputeIsCompilationEndAnalyzer(DiagnosticAnalyzer analyzer) { Contract.ThrowIfNull(compilation); try { // currently, this is only way to see whether analyzer has compilation end analysis or not. // also, analyzer being compilation end analyzer or not is dynamic. so this can return different value based on // given compilation or options. // // but for now, this is what we decided in design meeting until we decide how to deal with compilation end analyzer // long term var context = new CollectCompilationActionsContext(compilation, analyzerOptions); analyzer.Initialize(context); return(context.IsCompilationEndAnalyzer); } catch { // analyzer.initialize can throw. when that happens, we will try again next time. // we are not logging anything here since it will be logged by CompilationWithAnalyzer later // in the error list return(null); } } }
/// <summary> /// Executes the <see cref="DiagnosticAnalyzer.Initialize(AnalysisContext)"/> for the given analyzer. /// </summary> /// <param name="analyzer">Analyzer to get session wide analyzer actions.</param> /// <param name="sessionScope">Session scope to store register session wide analyzer actions.</param> /// <remarks> /// Note that this API doesn't execute any <see cref="CompilationStartAnalyzerAction"/> registered by the Initialize invocation. /// Use <see cref="ExecuteCompilationStartActions(ImmutableArray{CompilationStartAnalyzerAction}, HostCompilationStartAnalysisScope)"/> API /// to get execute these actions to get the per-compilation analyzer actions. /// </remarks> public void ExecuteInitializeMethod(DiagnosticAnalyzer analyzer, HostSessionStartAnalysisScope sessionScope) { // The Initialize method should be run asynchronously in case it is not well behaved, e.g. does not terminate. ExecuteAndCatchIfThrows(analyzer, () => analyzer.Initialize(new AnalyzerAnalysisContext(analyzer, sessionScope))); }