예제 #1
0
        /// <summary>
        /// Returns true if the given analyzer has enabled concurrent execution by invoking <see cref="AnalysisContext.EnableConcurrentExecution"/>.
        /// </summary>
        public async Task <bool> IsConcurrentAnalyzerAsync(DiagnosticAnalyzer analyzer, AnalyzerExecutor analyzerExecutor)
        {
            var sessionScope = await GetSessionAnalysisScopeAsync(analyzer, analyzerExecutor).ConfigureAwait(false);

            return(sessionScope.IsConcurrentAnalyzer(analyzer));
        }
예제 #2
0
        public async ValueTask <AnalyzerActions> GetAnalyzerActionsAsync(DiagnosticAnalyzer analyzer, AnalyzerExecutor analyzerExecutor)
        {
            var sessionScope = await GetSessionAnalysisScopeAsync(analyzer, analyzerExecutor).ConfigureAwait(false);

            if (sessionScope.GetAnalyzerActions(analyzer).CompilationStartActionsCount > 0 && analyzerExecutor.Compilation != null)
            {
                var compilationScope = await GetCompilationAnalysisScopeAsync(analyzer, sessionScope, analyzerExecutor).ConfigureAwait(false);

                return(compilationScope.GetAnalyzerActions(analyzer));
            }

            return(sessionScope.GetAnalyzerActions(analyzer));
        }
예제 #3
0
        public async ValueTask <AnalyzerActions> GetPerSymbolAnalyzerActionsAsync(ISymbol symbol, DiagnosticAnalyzer analyzer, AnalyzerExecutor analyzerExecutor)
        {
            var analyzerActions = await GetAnalyzerActionsAsync(analyzer, analyzerExecutor).ConfigureAwait(false);

            if (analyzerActions.SymbolStartActionsCount > 0)
            {
                var filteredSymbolStartActions = getFilteredActionsByKind(analyzerActions.SymbolStartActions);
                if (filteredSymbolStartActions.Length > 0)
                {
                    var symbolScope = await GetSymbolAnalysisScopeAsync(symbol, analyzer, filteredSymbolStartActions, analyzerExecutor).ConfigureAwait(false);

                    return(symbolScope.GetAnalyzerActions(analyzer));
                }
            }

            return(AnalyzerActions.Empty);

            ImmutableArray <SymbolStartAnalyzerAction> getFilteredActionsByKind(ImmutableArray <SymbolStartAnalyzerAction> symbolStartActions)
            {
                ArrayBuilder <SymbolStartAnalyzerAction> filteredActionsBuilderOpt = null;

                for (int i = 0; i < symbolStartActions.Length; i++)
                {
                    var symbolStartAction = symbolStartActions[i];
                    if (symbolStartAction.Kind != symbol.Kind)
                    {
                        if (filteredActionsBuilderOpt == null)
                        {
                            filteredActionsBuilderOpt = ArrayBuilder <SymbolStartAnalyzerAction> .GetInstance();

                            filteredActionsBuilderOpt.AddRange(symbolStartActions, i);
                        }
                    }
                    else if (filteredActionsBuilderOpt != null)
                    {
                        filteredActionsBuilderOpt.Add(symbolStartAction);
                    }
                }

                return(filteredActionsBuilderOpt != null?filteredActionsBuilderOpt.ToImmutableAndFree() : symbolStartActions);
            }
        }
예제 #4
0
        /// <summary>
        /// Returns true if all the diagnostics that can be produced by this analyzer are suppressed through options.
        /// </summary>
        internal bool IsDiagnosticAnalyzerSuppressed(
            DiagnosticAnalyzer analyzer,
            CompilationOptions options,
            Func <DiagnosticAnalyzer, bool> isCompilerAnalyzer,
            AnalyzerExecutor analyzerExecutor)
        {
            if (isCompilerAnalyzer(analyzer))
            {
                // Compiler analyzer must always be executed for compiler errors, which cannot be suppressed or filtered.
                return(false);
            }

            var supportedDiagnostics = GetSupportedDiagnosticDescriptors(analyzer, analyzerExecutor);
            var diagnosticOptions    = options.SpecificDiagnosticOptions;

            foreach (var diag in supportedDiagnostics)
            {
                if (HasNotConfigurableTag(diag.CustomTags))
                {
                    if (diag.IsEnabledByDefault)
                    {
                        // Diagnostic descriptor is not configurable, so the diagnostics created through it cannot be suppressed.
                        return(false);
                    }
                    else
                    {
                        // NotConfigurable disabled diagnostic can be ignored as it is never reported.
                        continue;
                    }
                }

                // Is this diagnostic suppressed by default (as written by the rule author)
                var isSuppressed = !diag.IsEnabledByDefault;

                // Compilation wide user settings from ruleset/nowarn/warnaserror overrides the analyzer author.
                if (diagnosticOptions.TryGetValue(diag.Id, out var severity))
                {
                    isSuppressed = severity == ReportDiagnostic.Suppress;
                }

                // Editorconfig user settings override compilation wide settings.
                if (isSuppressed &&
                    isEnabledWithAnalyzerConfigOptions(diag.Id, analyzerExecutor.Compilation))
                {
                    isSuppressed = false;
                }

                if (!isSuppressed)
                {
                    return(false);
                }
            }

            if (analyzer is DiagnosticSuppressor suppressor)
            {
                foreach (var suppressionDescriptor in GetSupportedSuppressionDescriptors(suppressor, analyzerExecutor))
                {
                    if (!suppressionDescriptor.IsDisabled(options))
                    {
                        return(false);
                    }
                }
            }

            return(true);
예제 #5
0
 static Task <HostSessionStartAnalysisScope> getSessionAnalysisScopeTaskSlow(AnalyzerExecutionContext context, AnalyzerExecutor executor)
 {
     return(Task.Run(() =>
     {
         var sessionScope = new HostSessionStartAnalysisScope();
         executor.ExecuteInitializeMethod(context._analyzer, sessionScope);
         return sessionScope;
     }, executor.CancellationToken));
 }
예제 #6
0
        internal bool IsSupportedDiagnostic(DiagnosticAnalyzer analyzer, Diagnostic diagnostic, Func <DiagnosticAnalyzer, bool> isCompilerAnalyzer, AnalyzerExecutor analyzerExecutor)
        {
            // Avoid realizing all the descriptors for all compiler diagnostics by assuming that compiler analyzer doesn't report unsupported diagnostics.
            if (isCompilerAnalyzer(analyzer))
            {
                return(true);
            }

            // Get all the supported diagnostics and scan them linearly to see if the reported diagnostic is supported by the analyzer.
            // The linear scan is okay, given that this runs only if a diagnostic is being reported and a given analyzer is quite unlikely to have hundreds of thousands of supported diagnostics.
            var supportedDescriptors = GetSupportedDiagnosticDescriptors(analyzer, analyzerExecutor);

            foreach (var descriptor in supportedDescriptors)
            {
                if (descriptor.Id.Equals(diagnostic.Id, StringComparison.OrdinalIgnoreCase))
                {
                    return(true);
                }
            }

            return(false);
        }
예제 #7
0
        /// <summary>
        /// Returns <see cref="GeneratedCodeAnalysisFlags"/> for the given analyzer.
        /// If an analyzer hasn't configured generated code analysis, returns <see cref="AnalyzerDriver.DefaultGeneratedCodeAnalysisFlags"/>.
        /// </summary>
        public async Task <GeneratedCodeAnalysisFlags> GetGeneratedCodeAnalysisFlagsAsync(DiagnosticAnalyzer analyzer, AnalyzerExecutor analyzerExecutor)
        {
            var sessionScope = await GetSessionAnalysisScopeAsync(analyzer, analyzerExecutor).ConfigureAwait(false);

            return(sessionScope.GetGeneratedCodeAnalysisFlags(analyzer));
        }
예제 #8
0
        /// <summary>
        /// Returns true if analyzer registered a compilation start action during <see cref="DiagnosticAnalyzer.Initialize(AnalysisContext)"/>
        /// which registered a compilation end action and at least one other analyzer action, that the end action depends upon.
        /// </summary>
        public async Task <bool> GetAnalyzerHasDependentCompilationEndAsync(DiagnosticAnalyzer analyzer, AnalyzerExecutor analyzerExecutor)
        {
            var sessionScope = await GetSessionAnalysisScopeAsync(analyzer, analyzerExecutor).ConfigureAwait(false);

            if (sessionScope.CompilationStartActions.Length > 0 && analyzerExecutor.Compilation != null)
            {
                var compilationScope = await GetCompilationAnalysisScopeAsync(analyzer, sessionScope, analyzerExecutor).ConfigureAwait(false);

                var compilationActions = compilationScope.GetCompilationOnlyAnalyzerActions(analyzer);
                return(compilationActions != null &&
                       compilationActions.CompilationEndActionsCount > 0 &&
                       (compilationActions.CodeBlockEndActionsCount > 0 ||
                        compilationActions.CodeBlockStartActionsCount > 0 ||
                        compilationActions.SemanticModelActionsCount > 0 ||
                        compilationActions.SymbolActionsCount > 0 ||
                        compilationActions.SyntaxNodeActionsCount > 0 ||
                        compilationActions.SyntaxTreeActionsCount > 0));
            }

            return(false);
        }
            public Task <HostSessionStartAnalysisScope> GetSessionAnalysisScopeTask(DiagnosticAnalyzer analyzer, AnalyzerExecutor analyzerExecutor)
            {
                lock (_gate)
                {
                    Task <HostSessionStartAnalysisScope> task;
                    if (_lazySessionScopeTask != null)
                    {
                        return(_lazySessionScopeTask);
                    }

                    task = Task.Run(() =>
                    {
                        HostSessionStartAnalysisScope sessionScope = new HostSessionStartAnalysisScope();
                        analyzerExecutor.ExecuteInitializeMethod(analyzer, sessionScope);
                        return(sessionScope);
                    }, analyzerExecutor.CancellationToken);

                    _lazySessionScopeTask = task;
                    return(task);
                }
            }
            public ImmutableArray <DiagnosticDescriptor> GetOrComputeDescriptors(DiagnosticAnalyzer analyzer, AnalyzerExecutor analyzerExecutor)
            {
                lock (_gate)
                {
                    if (!_lazyDescriptors.IsDefault)
                    {
                        return(_lazyDescriptors);
                    }
                }

                // Otherwise, compute the value.
                // We do so outside the lock statement as we are calling into user code, which may be a long running operation.
                ImmutableArray <DiagnosticDescriptor> descriptors = ComputeDescriptors(analyzer, analyzerExecutor);

                lock (_gate)
                {
                    // Check if another thread already stored the computed value.
                    if (!_lazyDescriptors.IsDefault)
                    {
                        // If so, we return the stored value.
                        descriptors = _lazyDescriptors;
                    }
                    else
                    {
                        // Otherwise, store the value computed here.
                        _lazyDescriptors = descriptors;
                    }
                }

                return(descriptors);
            }