private void ReportUnusedParameterDiagnostic(
                IParameterSymbol parameter,
                bool hasReference,
                Action <Diagnostic> reportDiagnostic,
                AnalyzerOptions analyzerOptions)
            {
                if (!IsUnusedParameterCandidate(parameter))
                {
                    return;
                }

                var location = parameter.Locations[0];
                var option   = analyzerOptions.GetAnalyzerOptions(location.SourceTree).UnusedParameters;

                if (option.Notification.Severity == ReportDiagnostic.Suppress ||
                    !ShouldReportUnusedParameters(parameter.ContainingSymbol, option.Value, option.Notification.Severity))
                {
                    return;
                }

                var message = GetMessageForUnusedParameterDiagnostic(
                    parameter.Name,
                    hasReference,
                    isPublicApiParameter: parameter.ContainingSymbol.HasPublicResultantVisibility(),
                    isLocalFunctionParameter: parameter.ContainingSymbol.IsLocalFunction());

                var diagnostic = DiagnosticHelper.CreateWithMessage(s_unusedParameterRule, location,
                                                                    option.Notification.Severity, additionalLocations: null, properties: null, message);

                reportDiagnostic(diagnostic);
            }
        private bool TryGetOptions(SyntaxTree syntaxTree, AnalyzerOptions analyzerOptions, out Options options)
        {
            options = null;

            var optionsProvider = analyzerOptions.GetAnalyzerOptions(syntaxTree);

            var unusedParametersOption = optionsProvider.UnusedParameters;

            var(unusedValueExpressionStatementPreference, unusedValueExpressionStatementSeverity) = GetPreferenceAndSeverity(GetUnusedValueExpressionStatementOption(optionsProvider));
            var(unusedValueAssignmentPreference, unusedValueAssignmentSeverity) = GetPreferenceAndSeverity(GetUnusedValueAssignmentOption(optionsProvider));

            if (unusedParametersOption.Notification.Severity == ReportDiagnostic.Suppress &&
                unusedValueExpressionStatementSeverity == ReportDiagnostic.Suppress &&
                unusedValueAssignmentSeverity == ReportDiagnostic.Suppress)
            {
                return(false);
            }

            options = new Options(unusedValueExpressionStatementPreference, unusedValueExpressionStatementSeverity,
                                  unusedValueAssignmentPreference, unusedValueAssignmentSeverity,
                                  unusedParametersOption.Value, unusedParametersOption.Notification.Severity);
            return(true);

            // Local functions.
            (UnusedValuePreference preference, ReportDiagnostic severity) GetPreferenceAndSeverity(CodeStyleOption2 <UnusedValuePreference> option)
            {
                var preferenceOpt = option?.Value;

                if (preferenceOpt == null ||
                    option.Notification.Severity == ReportDiagnostic.Suppress)
                {
                    // Prefer does not matter as the severity is suppressed - we will never report this diagnostic.
                    return(default(UnusedValuePreference), ReportDiagnostic.Suppress);
                }

                // If language or language version does not support discard, fall back to prefer unused local variable.
                if (preferenceOpt.Value == UnusedValuePreference.DiscardVariable &&
                    !SupportsDiscard(syntaxTree))
                {
                    preferenceOpt = UnusedValuePreference.UnusedLocalVariable;
                }

                return(preferenceOpt.Value, option.Notification.Severity);
            }
        }
Example #3
0
            private static void AnalyzeIfEnabled <TContext>(
                TCodeStyleProvider provider, TContext context, Action <TContext, CodeStyleOption2 <TOptionValue> > analyze,
                AnalyzerOptions analyzerOptions, SyntaxTree syntaxTree)
            {
                var optionValue = provider.GetCodeStyleOption(analyzerOptions.GetAnalyzerOptions(syntaxTree));
                var severity    = GetOptionSeverity(optionValue);

                switch (severity)
                {
                case ReportDiagnostic.Error:
                case ReportDiagnostic.Warn:
                case ReportDiagnostic.Info:
                    break;

                default:
                    // don't analyze if it's any other value.
                    return;
                }

                analyze(context, optionValue);
            }
Example #4
0
        private Diagnostic?TryGetDiagnostic(
            Compilation compilation,
            ISymbol symbol,
            AnalyzerOptions options,
            ConcurrentDictionary <Guid, ConcurrentDictionary <string, string?> > idToCachedResult,
            CancellationToken cancellationToken)
        {
            if (string.IsNullOrEmpty(symbol.Name))
            {
                return(null);
            }

            if (symbol is IMethodSymbol methodSymbol && methodSymbol.IsEntryPoint(compilation.TaskType(), compilation.TaskOfTType()))
            {
                return(null);
            }

            if (ShouldIgnore(symbol))
            {
                return(null);
            }

            if (symbol.IsSymbolWithSpecialDiscardName())
            {
                return(null);
            }

            var sourceTree = symbol.Locations.FirstOrDefault()?.SourceTree;

            if (sourceTree == null)
            {
                return(null);
            }

            var namingPreferences = options.GetAnalyzerOptions(sourceTree).NamingPreferences;
            var namingStyleRules  = namingPreferences.Rules;

            if (!namingStyleRules.TryGetApplicableRule(symbol, out var applicableRule) ||
                applicableRule.EnforcementLevel == ReportDiagnostic.Suppress)
            {
                return(null);
            }

            var cache = idToCachedResult.GetOrAdd(applicableRule.NamingStyle.ID, s_createCache);

            if (!cache.TryGetValue(symbol.Name, out var failureReason))
            {
                if (applicableRule.NamingStyle.IsNameCompliant(symbol.Name, out failureReason))
                {
                    failureReason = null;
                }

                cache.TryAdd(symbol.Name, failureReason);
            }

            if (failureReason == null)
            {
                return(null);
            }

            var builder = ImmutableDictionary.CreateBuilder <string, string?>();

            builder[nameof(NamingStyle)] = applicableRule.NamingStyle.CreateXElement().ToString();
            builder["OptionName"]        = nameof(NamingStyleOptions.NamingPreferences);
            builder["OptionLanguage"]    = compilation.Language;

            return(DiagnosticHelper.Create(Descriptor, symbol.Locations.First(), applicableRule.EnforcementLevel, additionalLocations: null, builder.ToImmutable(), failureReason));
        }