public override void Initialize(AnalysisContext analysisContext)
        {
            analysisContext.EnableConcurrentExecution();
            analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);

            analysisContext.RegisterCompilationStartAction(compilationContext =>
            {
                INamedTypeSymbol conditionalAttributeSymbol = WellKnownTypes.ConditionalAttribute(compilationContext.Compilation);

                compilationContext.RegisterOperationBlockActionInternal(context =>
                {
                    var method = context.OwningSymbol as IMethodSymbol;
                    if (method == null)
                    {
                        return;
                    }

                    if (!method.IsFinalizer())
                    {
                        return;
                    }

                    if (IsEmptyFinalizer(context.OperationBlocks, conditionalAttributeSymbol))
                    {
                        context.ReportDiagnostic(context.OwningSymbol.CreateDiagnostic(Rule));
                    }
                });
            });
        }
Пример #2
0
        private static bool IsConditionalInvocation(InvocationExpressionSyntax invocationExpr, SemanticModel semanticModel)
        {
            if (!(semanticModel.GetSymbolInfo(invocationExpr).Symbol is IMethodSymbol invocationSymbol))
            {
                // Presumably, if the user has typed something but it doesn't have a symbol yet, the body won't be empty
                // once all compile errors are corrected, so we return false here.
                return(false);
            }

            var conditionalAttributeSymbol = WellKnownTypes.ConditionalAttribute(semanticModel.Compilation);

            return(InvocationIsConditional(invocationSymbol, conditionalAttributeSymbol));
        }
        protected override bool IsEmptyFinalizer(SyntaxNode methodBody, CodeBlockAnalysisContext analysisContext)
        {
            var destructorDeclaration = (DestructorDeclarationSyntax)methodBody;

            if ((destructorDeclaration?.Body?.Statements.Count ?? 0) == 0)
            {
                return(true);
            }

            if (destructorDeclaration.Body.Statements.Count == 1)
            {
                var body = destructorDeclaration.Body.Statements[0];

                if (body.Kind() == CodeAnalysis.CSharp.SyntaxKind.ThrowStatement)
                {
                    return(true);
                }

                if (body.Kind() == CodeAnalysis.CSharp.SyntaxKind.ExpressionStatement &&
                    body is ExpressionStatementSyntax expr &&
                    expr.Expression.Kind() == CodeAnalysis.CSharp.SyntaxKind.InvocationExpression)
                {
                    if (!(analysisContext.SemanticModel.GetSymbolInfo(expr.Expression).Symbol is IMethodSymbol invocationSymbol))
                    {
                        // Presumably, if the user has typed something but it doesn't have a symbol yet, the body won't be empty
                        // once all compile errors are corrected, so we return false here.
                        return(false);
                    }

                    var conditionalAttributeSymbol = WellKnownTypes.ConditionalAttribute(analysisContext.SemanticModel.Compilation);
                    return(InvocationIsConditional(invocationSymbol, conditionalAttributeSymbol));
                }
            }

            return(false);
        }
Пример #4
0
        public override void Initialize(AnalysisContext context)
        {
            // TODO: Consider making this analyzer thread-safe.
            //context.EnableConcurrentExecution();

            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);

            context.RegisterCompilationStartAction(compilationStartContext =>
            {
                INamedTypeSymbol eventsArgSymbol = compilationStartContext.Compilation.GetTypeByMetadataName("System.EventArgs");

                // Ignore conditional methods (FxCop compat - One conditional will often call another conditional method as its only use of a parameter)
                INamedTypeSymbol conditionalAttributeSymbol = WellKnownTypes.ConditionalAttribute(compilationStartContext.Compilation);

                // Ignore methods with special serialization attributes (FxCop compat - All serialization methods need to take 'StreamingContext')
                INamedTypeSymbol onDeserializingAttribute = WellKnownTypes.OnDeserializingAttribute(compilationStartContext.Compilation);
                INamedTypeSymbol onDeserializedAttribute  = WellKnownTypes.OnDeserializedAttribute(compilationStartContext.Compilation);
                INamedTypeSymbol onSerializingAttribute   = WellKnownTypes.OnSerializingAttribute(compilationStartContext.Compilation);
                INamedTypeSymbol onSerializedAttribute    = WellKnownTypes.OnSerializedAttribute(compilationStartContext.Compilation);
                INamedTypeSymbol obsoleteAttribute        = WellKnownTypes.ObsoleteAttribute(compilationStartContext.Compilation);

                ImmutableHashSet <INamedTypeSymbol> attributeSetForMethodsToIgnore = ImmutableHashSet.Create(
                    conditionalAttributeSymbol,
                    onDeserializedAttribute,
                    onDeserializingAttribute,
                    onSerializedAttribute,
                    onSerializingAttribute,
                    obsoleteAttribute);

                UnusedParameterDictionary unusedMethodParameters = new ConcurrentDictionary <IMethodSymbol, ISet <IParameterSymbol> >();
                ISet <IMethodSymbol> methodsUsedAsDelegates      = new HashSet <IMethodSymbol>();

                // Create a list of functions to exclude from analysis. We assume that any function that is used in an IMethodBindingExpression
                // cannot have its signature changed, and add it to the list of methods to be excluded from analysis.
                compilationStartContext.RegisterOperationActionInternal(operationContext =>
                {
                    var methodBinding = (IMethodBindingExpression)operationContext.Operation;
                    methodsUsedAsDelegates.Add(methodBinding.Method.OriginalDefinition);
                }, OperationKind.MethodBindingExpression);

                compilationStartContext.RegisterOperationBlockStartActionInternal(startOperationBlockContext =>
                {
                    // We only care about methods.
                    if (startOperationBlockContext.OwningSymbol.Kind != SymbolKind.Method)
                    {
                        return;
                    }

                    // We only care about methods with parameters.
                    var method = (IMethodSymbol)startOperationBlockContext.OwningSymbol;
                    if (method.Parameters.IsEmpty)
                    {
                        return;
                    }

                    // Ignore implicitly declared methods, abstract methods, virtual methods, interface implementations and finalizers (FxCop compat).
                    if (method.IsImplicitlyDeclared ||
                        method.IsAbstract ||
                        method.IsVirtual ||
                        method.IsOverride ||
                        method.IsImplementationOfAnyInterfaceMember() ||
                        method.IsFinalizer())
                    {
                        return;
                    }

                    // Ignore event handler methods "Handler(object, MyEventArgs)"
                    if (eventsArgSymbol != null &&
                        method.Parameters.Length == 2 &&
                        method.Parameters[0].Type.SpecialType == SpecialType.System_Object &&
                        method.Parameters[1].Type.Inherits(eventsArgSymbol))
                    {
                        return;
                    }

                    // Ignore methods with any attributes in 'attributeSetForMethodsToIgnore'.
                    if (method.GetAttributes().Any(a => a.AttributeClass != null && attributeSetForMethodsToIgnore.Contains(a.AttributeClass)))
                    {
                        return;
                    }

                    // Ignore methods that were used as delegates
                    if (methodsUsedAsDelegates.Contains(method))
                    {
                        return;
                    }

                    // Initialize local mutable state in the start action.
                    var analyzer = new UnusedParametersAnalyzer(method, unusedMethodParameters);

                    // Register an intermediate non-end action that accesses and modifies the state.
                    startOperationBlockContext.RegisterOperationActionInternal(analyzer.AnalyzeOperation, OperationKind.ParameterReferenceExpression);

                    // Register an end action to add unused parameters to the unusedMethodParameters dictionary
                    startOperationBlockContext.RegisterOperationBlockEndAction(analyzer.OperationBlockEndAction);
                });

                // Register a compilation end action to filter all methods used as delegates and report any diagnostics
                compilationStartContext.RegisterCompilationEndAction(compilationAnalysisContext =>
                {
                    // Report diagnostics for unused parameters.
                    var unusedParameters = unusedMethodParameters.Where(kvp => !methodsUsedAsDelegates.Contains(kvp.Key)).SelectMany(kvp => kvp.Value);
                    foreach (var parameter in unusedParameters)
                    {
                        var diagnostic = Diagnostic.Create(Rule, parameter.Locations[0], parameter.Name, parameter.ContainingSymbol.Name);
                        compilationAnalysisContext.ReportDiagnostic(diagnostic);
                    }
                });
            });
        }
Пример #5
0
        public override void Initialize(AnalysisContext context)
        {
            context.EnableConcurrentExecution();
            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);

            context.RegisterCompilationStartAction(compilationContext =>
            {
                INamedTypeSymbol localizableStateAttributeSymbol  = WellKnownTypes.LocalizableAttribute(compilationContext.Compilation);
                INamedTypeSymbol conditionalAttributeSymbol       = WellKnownTypes.ConditionalAttribute(compilationContext.Compilation);
                INamedTypeSymbol systemConsoleSymbol              = WellKnownTypes.Console(compilationContext.Compilation);
                ImmutableHashSet <INamedTypeSymbol> typesToIgnore = GetTypesToIgnore(compilationContext.Compilation);

                compilationContext.RegisterOperationBlockStartAction(operationBlockStartContext =>
                {
                    if (!(operationBlockStartContext.OwningSymbol is IMethodSymbol containingMethod))
                    {
                        return;
                    }

                    var lazyValueContentResult = new Lazy <DataFlowAnalysisResult <ValueContentBlockAnalysisResult, ValueContentAbstractValue> >(
                        valueFactory: ComputeValueContentAnalysisResult, isThreadSafe: false);

                    operationBlockStartContext.RegisterOperationAction(operationContext =>
                    {
                        var argument = (IArgumentOperation)operationContext.Operation;
                        IMethodSymbol targetMethod = null;
                        switch (argument.Parent)
                        {
                        case IInvocationOperation invocation:
                            targetMethod = invocation.TargetMethod;
                            break;

                        case IObjectCreationOperation objectCreation:
                            targetMethod = objectCreation.Constructor;
                            break;
                        }

                        if (ShouldAnalyze(targetMethod))
                        {
                            AnalyzeArgument(argument.Parameter, containingPropertySymbolOpt: null, operation: argument, reportDiagnostic: operationContext.ReportDiagnostic);
                        }
                    }, OperationKind.Argument);

                    operationBlockStartContext.RegisterOperationAction(operationContext =>
                    {
                        var propertyReference = (IPropertyReferenceOperation)operationContext.Operation;
                        if (propertyReference.Parent is IAssignmentOperation assignment &&
                            assignment.Target == propertyReference &&
                            !propertyReference.Property.IsIndexer &&
                            propertyReference.Property.SetMethod?.Parameters.Length == 1 &&
                            ShouldAnalyze(propertyReference.Property))
                        {
                            IParameterSymbol valueSetterParam = propertyReference.Property.SetMethod.Parameters[0];
                            AnalyzeArgument(valueSetterParam, propertyReference.Property, assignment, operationContext.ReportDiagnostic);
                        }
                    }, OperationKind.PropertyReference);

                    return;

                    // Local functions
                    bool ShouldAnalyze(ISymbol symbol)
                    => symbol != null && !symbol.IsConfiguredToSkipAnalysis(operationBlockStartContext.Options, Rule, operationBlockStartContext.Compilation, operationBlockStartContext.CancellationToken);

                    void AnalyzeArgument(IParameterSymbol parameter, IPropertySymbol containingPropertySymbolOpt, IOperation operation, Action <Diagnostic> reportDiagnostic)
                    {
                        if (ShouldBeLocalized(parameter.OriginalDefinition, containingPropertySymbolOpt?.OriginalDefinition, localizableStateAttributeSymbol, conditionalAttributeSymbol, systemConsoleSymbol, typesToIgnore) &&
                            lazyValueContentResult.Value != null)
                        {
                            ValueContentAbstractValue stringContentValue = lazyValueContentResult.Value[operation.Kind, operation.Syntax];
                            if (stringContentValue.IsLiteralState)
                            {
                                Debug.Assert(stringContentValue.LiteralValues.Count > 0);

                                if (stringContentValue.LiteralValues.Any(l => !(l is string)))
                                {
                                    return;
                                }

                                var stringLiteralValues = stringContentValue.LiteralValues.Select(l => (string)l);

                                // FxCop compat: Do not fire if the literal value came from a default parameter value
                                if (stringContentValue.LiteralValues.Count == 1 &&
                                    parameter.IsOptional &&
                                    parameter.ExplicitDefaultValue is string defaultValue &&
                                    defaultValue == stringLiteralValues.Single())
                                {
                                    return;
                                }

                                // FxCop compat: Do not fire if none of the string literals have any non-control character.
                                if (!LiteralValuesHaveNonControlCharacters(stringLiteralValues))
                                {
                                    return;
                                }

                                // FxCop compat: Filter out xml string literals.
                                var filteredStrings = stringLiteralValues.Where(literal => !LooksLikeXmlTag(literal));
                                if (filteredStrings.Any())
                                {
                                    // Method '{0}' passes a literal string as parameter '{1}' of a call to '{2}'. Retrieve the following string(s) from a resource table instead: "{3}".
                                    var arg1       = containingMethod.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat);
                                    var arg2       = parameter.Name;
                                    var arg3       = parameter.ContainingSymbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat);
                                    var arg4       = FormatLiteralValues(filteredStrings);
                                    var diagnostic = operation.CreateDiagnostic(Rule, arg1, arg2, arg3, arg4);
                                    reportDiagnostic(diagnostic);
                                }
                            }
                        }
                    }

                    DataFlowAnalysisResult <ValueContentBlockAnalysisResult, ValueContentAbstractValue> ComputeValueContentAnalysisResult()
                    {
                        var cfg = operationBlockStartContext.OperationBlocks.GetControlFlowGraph();
                        if (cfg != null)
                        {
                            var wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(operationBlockStartContext.Compilation);
                            return(ValueContentAnalysis.TryGetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider,
                                                                              operationBlockStartContext.Options, Rule, operationBlockStartContext.CancellationToken));
                        }

                        return(null);
                    }
                });
            });
        }
        public override void Initialize(AnalysisContext context)
        {
            context.RegisterCompilationStartAction(compilationStartContext =>
            {
                INamedTypeSymbol eventsArgSymbol = compilationStartContext.Compilation.GetTypeByMetadataName("System.EventArgs");

                // Ignore conditional methods (FxCop compat - One conditional will often call another conditional method as its only use of a parameter)
                INamedTypeSymbol conditionalAttributeSymbol = WellKnownTypes.ConditionalAttribute(compilationStartContext.Compilation);

                // Ignore methods with special serialization attributes (FxCop compat - All serialization methods need to take 'StreamingContext')
                INamedTypeSymbol onDeserializingAttribute = WellKnownTypes.OnDeserializingAttribute(compilationStartContext.Compilation);
                INamedTypeSymbol onDeserializedAttribute  = WellKnownTypes.OnDeserializedAttribute(compilationStartContext.Compilation);
                INamedTypeSymbol onSerializingAttribute   = WellKnownTypes.OnSerializingAttribute(compilationStartContext.Compilation);
                INamedTypeSymbol onSerializedAttribute    = WellKnownTypes.OnSerializedAttribute(compilationStartContext.Compilation);

                ImmutableHashSet <INamedTypeSymbol> attributeSetForMethodsToIgnore = ImmutableHashSet.Create(conditionalAttributeSymbol, onDeserializedAttribute, onDeserializingAttribute, onSerializedAttribute, onSerializingAttribute);

                compilationStartContext.RegisterOperationBlockStartAction(startOperationBlockContext =>
                {
                    // We only care about methods.
                    if (startOperationBlockContext.OwningSymbol.Kind != SymbolKind.Method)
                    {
                        return;
                    }

                    // We only care about methods with parameters.
                    var method = (IMethodSymbol)startOperationBlockContext.OwningSymbol;
                    if (method.Parameters.IsEmpty)
                    {
                        return;
                    }

                    // Ignore implicitly declared methods, abstract methods, virtual methods, interface implementations and finalizers (FxCop compat).
                    if (method.IsImplicitlyDeclared ||
                        method.IsAbstract ||
                        method.IsVirtual ||
                        method.IsOverride ||
                        method.IsImplementationOfAnyInterfaceMethod() ||
                        method.IsFinalizer())
                    {
                        return;
                    }

                    // Ignore event handler methods "Handler(object, MyEventArgs)"
                    if (eventsArgSymbol != null &&
                        method.Parameters.Length == 2 &&
                        method.Parameters[0].Type.SpecialType == SpecialType.System_Object &&
                        method.Parameters[1].Type.Inherits(eventsArgSymbol))
                    {
                        return;
                    }

                    // Ignore methods with any attributes in 'attributeSetForMethodsToIgnore'.
                    if (method.GetAttributes().Any(a => a.AttributeClass != null && attributeSetForMethodsToIgnore.Contains(a.AttributeClass)))
                    {
                        return;
                    }

                    // Initialize local mutable state in the start action.
                    var analyzer = new UnusedParametersAnalyzer(method);

                    // Register an intermediate non-end action that accesses and modifies the state.
                    startOperationBlockContext.RegisterOperationAction(analyzer.AnalyzeOperation, OperationKind.ParameterReferenceExpression);

                    // Register an end action to report diagnostics based on the final state.
                    startOperationBlockContext.RegisterOperationBlockEndAction(analyzer.OperationBlockEndAction);
                });
            });
        }
Пример #7
0
#pragma warning disable RS1026 // Enable concurrent execution
        public override void Initialize(AnalysisContext context)
#pragma warning restore RS1026 // Enable concurrent execution
        {
            // TODO: Consider making this analyzer thread-safe.
            //context.EnableConcurrentExecution();

            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);

            context.RegisterCompilationStartAction(compilationStartContext =>
            {
                INamedTypeSymbol eventsArgSymbol = compilationStartContext.Compilation.GetTypeByMetadataName("System.EventArgs");

                // Ignore conditional methods (FxCop compat - One conditional will often call another conditional method as its only use of a parameter)
                INamedTypeSymbol conditionalAttributeSymbol = WellKnownTypes.ConditionalAttribute(compilationStartContext.Compilation);

                // Ignore methods with special serialization attributes (FxCop compat - All serialization methods need to take 'StreamingContext')
                INamedTypeSymbol onDeserializingAttribute = WellKnownTypes.OnDeserializingAttribute(compilationStartContext.Compilation);
                INamedTypeSymbol onDeserializedAttribute  = WellKnownTypes.OnDeserializedAttribute(compilationStartContext.Compilation);
                INamedTypeSymbol onSerializingAttribute   = WellKnownTypes.OnSerializingAttribute(compilationStartContext.Compilation);
                INamedTypeSymbol onSerializedAttribute    = WellKnownTypes.OnSerializedAttribute(compilationStartContext.Compilation);
                INamedTypeSymbol obsoleteAttribute        = WellKnownTypes.ObsoleteAttribute(compilationStartContext.Compilation);

                ImmutableHashSet <INamedTypeSymbol> attributeSetForMethodsToIgnore = ImmutableHashSet.Create(
                    conditionalAttributeSymbol,
                    onDeserializedAttribute,
                    onDeserializingAttribute,
                    onSerializedAttribute,
                    onSerializingAttribute,
                    obsoleteAttribute);

                UnusedParameterDictionary unusedMethodParameters = new ConcurrentDictionary <IMethodSymbol, ISet <IParameterSymbol> >();
                ISet <IMethodSymbol> methodsUsedAsDelegates      = new HashSet <IMethodSymbol>();

                // Create a list of functions to exclude from analysis. We assume that any function that is used in an IMethodBindingExpression
                // cannot have its signature changed, and add it to the list of methods to be excluded from analysis.
                compilationStartContext.RegisterOperationAction(operationContext =>
                {
                    var methodBinding = (IMethodReferenceOperation)operationContext.Operation;
                    methodsUsedAsDelegates.Add(methodBinding.Method.OriginalDefinition);
                }, OperationKind.MethodReference);

                compilationStartContext.RegisterOperationBlockStartAction(startOperationBlockContext =>
                {
                    // We only care about methods.
                    if (!(startOperationBlockContext.OwningSymbol is IMethodSymbol method))
                    {
                        return;
                    }

                    AnalyzeMethod(method, startOperationBlockContext, unusedMethodParameters,
                                  eventsArgSymbol, methodsUsedAsDelegates, attributeSetForMethodsToIgnore);

                    foreach (var localFunctionOperation in startOperationBlockContext.OperationBlocks.SelectMany(o => o.Descendants()).OfType <ILocalFunctionOperation>())
                    {
                        AnalyzeMethod(localFunctionOperation.Symbol, startOperationBlockContext, unusedMethodParameters,
                                      eventsArgSymbol, methodsUsedAsDelegates, attributeSetForMethodsToIgnore);
                    }
                });

                // Register a compilation end action to filter all methods used as delegates and report any diagnostics
                compilationStartContext.RegisterCompilationEndAction(compilationAnalysisContext =>
                {
                    // Report diagnostics for unused parameters.
                    var unusedParameters = unusedMethodParameters.Where(kvp => !methodsUsedAsDelegates.Contains(kvp.Key)).SelectMany(kvp => kvp.Value);
                    foreach (var parameter in unusedParameters)
                    {
                        var diagnostic = Diagnostic.Create(Rule, parameter.Locations[0], parameter.Name, parameter.ContainingSymbol.Name);
                        compilationAnalysisContext.ReportDiagnostic(diagnostic);
                    }
                });
            });
        }
        public override void Initialize(AnalysisContext context)
        {
            context.EnableConcurrentExecution();
            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);

            context.RegisterCompilationStartAction(compilationContext =>
            {
                INamedTypeSymbol localizableStateAttributeSymbol  = WellKnownTypes.LocalizableAttribute(compilationContext.Compilation);
                INamedTypeSymbol conditionalAttributeSymbol       = WellKnownTypes.ConditionalAttribute(compilationContext.Compilation);
                INamedTypeSymbol systemConsoleSymbol              = WellKnownTypes.Console(compilationContext.Compilation);
                ImmutableHashSet <INamedTypeSymbol> typesToIgnore = GetTypesToIgnore(compilationContext.Compilation);

                compilationContext.RegisterOperationBlockStartAction(operationBlockStartContext =>
                {
                    if (!(operationBlockStartContext.OwningSymbol is IMethodSymbol containingMethod))
                    {
                        return;
                    }

                    var lazyStringContentResult = new Lazy <DataFlowAnalysisResult <StringContentBlockAnalysisResult, StringContentAbstractValue> >(
                        valueFactory: ComputeStringContentAnalysisResult, isThreadSafe: false);

                    operationBlockStartContext.RegisterOperationAction(operationContext =>
                    {
                        var argument = (IArgumentOperation)operationContext.Operation;
                        switch (argument.Parent?.Kind)
                        {
                        case OperationKind.Invocation:
                        case OperationKind.ObjectCreation:
                            AnalyzeArgument(argument.Parameter, containingPropertySymbolOpt: null, operation: argument, reportDiagnostic: operationContext.ReportDiagnostic);
                            return;
                        }
                    }, OperationKind.Argument);

                    operationBlockStartContext.RegisterOperationAction(operationContext =>
                    {
                        var propertyReference = (IPropertyReferenceOperation)operationContext.Operation;
                        if (propertyReference.Parent is IAssignmentOperation assignment &&
                            assignment.Target == propertyReference &&
                            !propertyReference.Property.IsIndexer &&
                            propertyReference.Property.SetMethod?.Parameters.Length == 1)
                        {
                            IParameterSymbol valueSetterParam = propertyReference.Property.SetMethod.Parameters[0];
                            AnalyzeArgument(valueSetterParam, propertyReference.Property, assignment, operationContext.ReportDiagnostic);
                        }
                    }, OperationKind.PropertyReference);

                    void AnalyzeArgument(IParameterSymbol parameter, IPropertySymbol containingPropertySymbolOpt, IOperation operation, Action <Diagnostic> reportDiagnostic)
                    {
                        if (ShouldBeLocalized(parameter, containingPropertySymbolOpt, localizableStateAttributeSymbol, conditionalAttributeSymbol, systemConsoleSymbol, typesToIgnore))
                        {
                            StringContentAbstractValue stringContentValue = lazyStringContentResult.Value[operation];
                            if (stringContentValue.IsLiteralState)
                            {
                                Debug.Assert(stringContentValue.LiteralValues.Count > 0);

                                // FxCop compat: Do not fire if the literal value came from a default parameter value
                                if (stringContentValue.LiteralValues.Count == 1 &&
                                    parameter.IsOptional &&
                                    parameter.ExplicitDefaultValue is string defaultValue &&
                                    defaultValue == stringContentValue.LiteralValues.Single())
                                {
                                    return;
                                }

                                // FxCop compat: Do not fire if none of the string literals have any non-control character.
                                if (!LiteralValuesHaveNonControlCharacters(stringContentValue.LiteralValues))
                                {
                                    return;
                                }

                                // FxCop compat: Filter out xml string literals.
                                var filteredStrings = stringContentValue.LiteralValues.Where(literal => !LooksLikeXmlTag(literal));
                                if (filteredStrings.Any())
                                {
                                    // Method '{0}' passes a literal string as parameter '{1}' of a call to '{2}'. Retrieve the following string(s) from a resource table instead: "{3}".
                                    var arg1       = containingMethod.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat);
                                    var arg2       = parameter.Name;
                                    var arg3       = parameter.ContainingSymbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat);
                                    var arg4       = FormatLiteralValues(filteredStrings);
                                    var diagnostic = operation.CreateDiagnostic(Rule, arg1, arg2, arg3, arg4);
                                    reportDiagnostic(diagnostic);
                                }
                            }
                        }
                    }

                    DataFlowAnalysisResult <StringContentBlockAnalysisResult, StringContentAbstractValue> ComputeStringContentAnalysisResult()
                    {
                        foreach (var operationRoot in operationBlockStartContext.OperationBlocks)
                        {
                            IBlockOperation topmostBlock = operationRoot.GetTopmostParentBlock();
                            if (topmostBlock != null)
                            {
                                var cfg = ControlFlowGraph.Create(topmostBlock);
                                var wellKnownTypeProvider  = WellKnownTypeProvider.GetOrCreate(operationBlockStartContext.Compilation);
                                var pointsToAnalysisResult = PointsToAnalysis.GetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider);
                                var copyAnalysisResult     = CopyAnalysis.GetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider, pointsToAnalysisResultOpt: pointsToAnalysisResult);
                                // Do another analysis pass to improve the results from PointsTo and Copy analysis.
                                pointsToAnalysisResult = PointsToAnalysis.GetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider, pointsToAnalysisResult, copyAnalysisResult);
                                return(StringContentAnalysis.GetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider, copyAnalysisResult, pointsToAnalysisResult));
                            }
                        }

                        return(null);
                    }
                });
            });
        }
Пример #9
0
        private bool HasConditionalAttribute(SyntaxNode root, SemanticModel model)
        {
            var node = root as InvocationExpressionSyntax;

            if (node != null)
            {
                var exp = node.Expression as MemberAccessExpressionSyntax;
                if (exp != null)
                {
                    var symbol = model.GetSymbolInfo(exp.Name).Symbol;
                    if (symbol != null && symbol.GetAttributes().Any(n => n.AttributeClass.Equals(WellKnownTypes.ConditionalAttribute(model.Compilation))))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }