private static void AnalyzeIfEnabled <TContext>(
                TCodeStyleProvider provider, TContext context, Action <TContext, CodeStyleOption <TOptionKind> > analyze,
                AnalyzerOptions options, SyntaxTree syntaxTree, CancellationToken cancellationToken)
            {
                var optionSet = options.GetDocumentOptionSetAsync(syntaxTree, cancellationToken).GetAwaiter().GetResult();

                if (optionSet == null)
                {
                    return;
                }

                var optionValue = optionSet.GetOption(provider._option);
                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);
            }
        private bool TryGetOptions(
            SyntaxTree syntaxTree,
            string language,
            AnalyzerOptions analyzerOptions,
            CancellationToken cancellationToken,
            out Options options)
        {
            options = null;
            var optionSet = analyzerOptions.GetDocumentOptionSetAsync(syntaxTree, cancellationToken).GetAwaiter().GetResult();

            if (optionSet == null)
            {
                return(false);
            }

            var unusedParametersOption = optionSet.GetOption(CodeStyleOptions.UnusedParameters, language);

            var(unusedValueExpressionStatementPreference, unusedValueExpressionStatementSeverity) = GetPreferenceAndSeverity(UnusedValueExpressionStatementOption);
            var(unusedValueAssignmentPreference, unusedValueAssignmentSeverity) = GetPreferenceAndSeverity(UnusedValueAssignmentOption);
            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(
                Option <CodeStyleOption <UnusedValuePreference> > codeStyleOption)
            {
                var option        = optionSet.GetOption(codeStyleOption);
                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);
            }
        }
        private static async ValueTask <NamingStylePreferences> GetNamingStylePreferencesAsync(
            Compilation compilation,
            ISymbol symbol,
            AnalyzerOptions options,
            CancellationToken cancellationToken)
        {
            var sourceTree = symbol.Locations.FirstOrDefault()?.SourceTree;

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

            var optionSet = await options.GetDocumentOptionSetAsync(sourceTree, cancellationToken).ConfigureAwait(false);

            return(optionSet?.GetOption(SimplificationOptions.NamingPreferences, compilation.Language));
        }
            private void ReportUnusedParameterDiagnostic(
                IParameterSymbol parameter,
                bool hasReference,
                Action <Diagnostic> reportDiagnostic,
                AnalyzerOptions analyzerOptions,
                CancellationToken cancellationToken)
            {
                if (!IsUnusedParameterCandidate(parameter))
                {
                    return;
                }

                var location  = parameter.Locations[0];
                var optionSet = analyzerOptions.GetDocumentOptionSetAsync(location.SourceTree, cancellationToken).GetAwaiter().GetResult();

                if (optionSet == null)
                {
                    return;
                }

                var option = optionSet.GetOption(CodeStyleOptions.UnusedParameters, parameter.Language);

                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);
            }
示例#5
0
        protected bool TrySimplifyTypeNameExpression(SemanticModel model, SyntaxNode node, AnalyzerOptions analyzerOptions, out Diagnostic diagnostic, CancellationToken cancellationToken)
        {
            diagnostic = default;

            var syntaxTree = node.SyntaxTree;
            var optionSet  = analyzerOptions.GetDocumentOptionSetAsync(syntaxTree, cancellationToken).GetAwaiter().GetResult();

            if (optionSet == null)
            {
                return(false);
            }

            if (!CanSimplifyTypeNameExpressionCore(
                    model, node, optionSet,
                    out var issueSpan, out var diagnosticId, out var inDeclaration,
                    cancellationToken))
            {
                return(false);
            }

            if (model.SyntaxTree.OverlapsHiddenPosition(issueSpan, cancellationToken))
            {
                return(false);
            }

            PerLanguageOption <CodeStyleOption <bool> > option;
            DiagnosticDescriptor descriptor;
            ReportDiagnostic     severity;

            switch (diagnosticId)
            {
            case IDEDiagnosticIds.SimplifyNamesDiagnosticId:
                descriptor = s_descriptorSimplifyNames;
                severity   = descriptor.DefaultSeverity.ToReportDiagnostic();
                break;

            case IDEDiagnosticIds.SimplifyMemberAccessDiagnosticId:
                descriptor = s_descriptorSimplifyMemberAccess;
                severity   = descriptor.DefaultSeverity.ToReportDiagnostic();
                break;

            case IDEDiagnosticIds.PreferBuiltInOrFrameworkTypeDiagnosticId:
                option = inDeclaration
                        ? CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInDeclaration
                        : CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInMemberAccess;
                descriptor = s_descriptorPreferBuiltinOrFrameworkType;

                var optionValue = optionSet.GetOption(option, GetLanguageName());
                severity = optionValue.Notification.Severity;
                break;

            default:
                throw ExceptionUtilities.UnexpectedValue(diagnosticId);
            }

            if (descriptor == null)
            {
                return(false);
            }

            var tree    = model.SyntaxTree;
            var builder = ImmutableDictionary.CreateBuilder <string, string>();

            builder["OptionName"]     = nameof(CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInMemberAccess); // TODO: need the actual one
            builder["OptionLanguage"] = model.Language;
            diagnostic = DiagnosticHelper.Create(descriptor, tree.GetLocation(issueSpan), severity, additionalLocations: null, builder.ToImmutable());
            return(true);
        }
        protected bool TrySimplifyTypeNameExpression(SemanticModel model, SyntaxNode node, AnalyzerOptions analyzerOptions, out Diagnostic diagnostic, CancellationToken cancellationToken)
        {
            diagnostic = default;

            var syntaxTree = node.SyntaxTree;
            var optionSet  = analyzerOptions.GetDocumentOptionSetAsync(syntaxTree, cancellationToken).GetAwaiter().GetResult();

            if (optionSet == null)
            {
                return(false);
            }

            if (!CanSimplifyTypeNameExpressionCore(
                    model, node, optionSet,
                    out var issueSpan, out var diagnosticId, out var inDeclaration,
                    cancellationToken))
            {
                return(false);
            }

            if (model.SyntaxTree.OverlapsHiddenPosition(issueSpan, cancellationToken))
            {
                return(false);
            }

            PerLanguageOption <CodeStyleOption <bool> > option;
            DiagnosticDescriptor descriptor;
            ReportDiagnostic     severity;

            switch (diagnosticId)
            {
            case IDEDiagnosticIds.SimplifyNamesDiagnosticId:
                descriptor = s_descriptorSimplifyNames;
                severity   = descriptor.DefaultSeverity.ToReportDiagnostic();
                break;

            case IDEDiagnosticIds.SimplifyMemberAccessDiagnosticId:
                descriptor = s_descriptorSimplifyMemberAccess;
                severity   = descriptor.DefaultSeverity.ToReportDiagnostic();
                break;

            case IDEDiagnosticIds.PreferBuiltInOrFrameworkTypeDiagnosticId:
                option = inDeclaration
                        ? CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInDeclaration
                        : CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInMemberAccess;
                descriptor = s_descriptorPreferBuiltinOrFrameworkType;

                var optionValue = optionSet.GetOption(option, GetLanguageName());
                severity = optionValue.Notification.Severity;
                break;

            default:
                throw ExceptionUtilities.UnexpectedValue(diagnosticId);
            }

            if (descriptor == null)
            {
                return(false);
            }

            var tree    = model.SyntaxTree;
            var builder = ImmutableDictionary.CreateBuilder <string, string>();

            builder["OptionName"]     = nameof(CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInMemberAccess); // TODO: need the actual one
            builder["OptionLanguage"] = model.Language;
            diagnostic = DiagnosticHelper.Create(descriptor, tree.GetLocation(issueSpan), severity, additionalLocations: null, builder.ToImmutable());

#if LOG
            var sourceText = tree.GetText(cancellationToken);
            sourceText.GetLineAndOffset(issueSpan.Start, out var startLineNumber, out var startOffset);
            sourceText.GetLineAndOffset(issueSpan.End, out var endLineNumber, out var endOffset);
            var logLine = tree.FilePath + "," + startLineNumber + "\t" + diagnosticId + "\t" + inDeclaration + "\t";

            var leading = sourceText.ToString(TextSpan.FromBounds(
                                                  sourceText.Lines[startLineNumber].Start, issueSpan.Start));
            var mid      = sourceText.ToString(issueSpan);
            var trailing = sourceText.ToString(TextSpan.FromBounds(
                                                   issueSpan.End, sourceText.Lines[endLineNumber].End));

            var contents = leading + "[|" + s_newlinePattern.Replace(mid, " ") + "|]" + trailing;
            logLine += contents + "\r\n";

            lock (_logGate)
            {
                File.AppendAllText(_logFile, logLine);
            }
#endif

            return(true);
        }
        protected bool TrySimplifyTypeNameExpression(SemanticModel model, SyntaxNode node, AnalyzerOptions analyzerOptions, out Diagnostic diagnostic, CancellationToken cancellationToken)
        {
            diagnostic = default(Diagnostic);

            var syntaxTree = node.SyntaxTree;
            var optionSet  = analyzerOptions.GetDocumentOptionSetAsync(syntaxTree, cancellationToken).GetAwaiter().GetResult();

            if (optionSet == null)
            {
                return(false);
            }

            if (!CanSimplifyTypeNameExpressionCore(model, node, optionSet, out var issueSpan, out string diagnosticId, cancellationToken))
            {
                return(false);
            }

            if (model.SyntaxTree.OverlapsHiddenPosition(issueSpan, cancellationToken))
            {
                return(false);
            }

            PerLanguageOption <CodeStyleOption <bool> > option;
            DiagnosticDescriptor descriptor;

            switch (diagnosticId)
            {
            case IDEDiagnosticIds.SimplifyNamesDiagnosticId:
                descriptor = s_descriptorSimplifyNames;
                break;

            case IDEDiagnosticIds.SimplifyMemberAccessDiagnosticId:
                descriptor = s_descriptorSimplifyMemberAccess;
                break;

            case IDEDiagnosticIds.RemoveQualificationDiagnosticId:
                descriptor = GetRemoveQualificationDiagnosticDescriptor(model, node, optionSet, cancellationToken);
                break;

            case IDEDiagnosticIds.PreferIntrinsicPredefinedTypeInDeclarationsDiagnosticId:
                option     = CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInDeclaration;
                descriptor = GetApplicablePredefinedTypeDiagnosticDescriptor(
                    IDEDiagnosticIds.PreferIntrinsicPredefinedTypeInDeclarationsDiagnosticId, option, optionSet);
                break;

            case IDEDiagnosticIds.PreferIntrinsicPredefinedTypeInMemberAccessDiagnosticId:
                option     = CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInMemberAccess;
                descriptor = GetApplicablePredefinedTypeDiagnosticDescriptor(
                    IDEDiagnosticIds.PreferIntrinsicPredefinedTypeInMemberAccessDiagnosticId, option, optionSet);
                break;

            default:
                throw ExceptionUtilities.Unreachable;
            }

            if (descriptor == null)
            {
                return(false);
            }

            var tree    = model.SyntaxTree;
            var builder = ImmutableDictionary.CreateBuilder <string, string>();

            builder["OptionName"]     = nameof(CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInMemberAccess); // TODO: need the actual one
            builder["OptionLanguage"] = model.Language;
            diagnostic = Diagnostic.Create(descriptor, tree.GetLocation(issueSpan), builder.ToImmutable());
            return(true);
        }