Ejemplo n.º 1
0
        private static bool TryGetDescriptorCreateMethodAndArguments(
            IFieldInitializerOperation fieldInitializer,
            INamedTypeSymbol diagnosticDescriptorType,
            out IMethodSymbol creationMethod,
            out ImmutableArray <IArgumentOperation> creationArguments)
        {
            (creationMethod, creationArguments) = fieldInitializer.Value switch
            {
                IObjectCreationOperation objectCreation when IsDescriptorConstructor(objectCreation.Constructor)
                => (objectCreation.Constructor, objectCreation.Arguments),
                IInvocationOperation invocation when IsCreateHelper(invocation.TargetMethod)
                => (invocation.TargetMethod, invocation.Arguments),
                _ => default
            };

            return(creationMethod != null);

            bool IsDescriptorConstructor(IMethodSymbol method)
            => method.ContainingType.Equals(diagnosticDescriptorType);

            // Heuristic to identify helper methods to create DiagnosticDescriptor:
            //  "A method invocation that returns 'DiagnosticDescriptor' and has a first string parameter named 'id'"
            bool IsCreateHelper(IMethodSymbol method)
            => method.ReturnType.Equals(diagnosticDescriptorType) &&
            !method.Parameters.IsEmpty &&
            method.Parameters[0].Name == DiagnosticIdParameterName &&
            method.Parameters[0].Type.SpecialType == SpecialType.System_String;
        }
        public static void RegisterMemberAccess(this AnalysisContext context, Action <InvocationAnalysisContext> action)
        {
            var operationKinds = new[]
            {
                OperationKind.Invocation,
                OperationKind.SimpleAssignment,
                OperationKind.VariableDeclaration,
                OperationKind.ObjectCreation,
                OperationKind.FieldInitializer,
                OperationKind.FieldReference,
            };

            context.RegisterOperationAction(ctx =>
            {
                ISymbol?symbol = ctx.Operation switch
                {
                    IInvocationOperation invocation => invocation.TargetMethod,
                    IPropertyReferenceOperation property => property.Property.Type,
                    IObjectCreationOperation creation => creation.Type,
                    ISimpleAssignmentOperation assignment => assignment.Type,
                    IFieldInitializerOperation fieldInitializer => fieldInitializer.Type,
                    IFieldReferenceOperation fieldRef => fieldRef.Type,
                    IVariableDeclarationOperation variableDeclaration => variableDeclaration.Type,
                    _ => null,
                };

                if (symbol is null)
                {
                    return;
                }

                var location = ctx.Operation.Syntax.GetLocation();
                var newCtx   = new InvocationAnalysisContext(symbol, location, ctx.Compilation, ctx.Options, ctx.ReportDiagnostic, ctx.CancellationToken);

                action(newCtx);
            }, operationKinds);

            context.RegisterSymbolAction(ctx =>
            {
                var symbol = ctx.Symbol switch
                {
                    IPropertySymbol property => property.Type,
                    IParameterSymbol parameter => parameter.Type,
                    IMethodSymbol method => method.ReturnsVoid ? null : method.ReturnType,
                    IFieldSymbol field => field.Type,
                    _ => null,
                };

                if (symbol is null)
                {
                    return;
                }

                var location = ctx.Symbol.Locations[0];
                var newCtx   = new InvocationAnalysisContext(symbol, location, ctx.Compilation, ctx.Options, ctx.ReportDiagnostic, ctx.CancellationToken);

                action(newCtx);
            }, SymbolKind.Property, SymbolKind.Method, SymbolKind.Parameter, SymbolKind.Field);
        }
Ejemplo n.º 3
0
 public override void VisitFieldInitializer(IFieldInitializerOperation operation)
 {
     foreach (var field in operation.InitializedFields)
     {
         // empty loop body, just want to make sure it won't crash.
     }
     base.VisitFieldInitializer(operation);
 }
Ejemplo n.º 4
0
 public override void VisitFieldInitializer(IFieldInitializerOperation operation)
 {
     Assert.Equal(OperationKind.FieldInitializer, operation.Kind);
     foreach (var field in operation.InitializedFields)
     {
         Assert.NotNull(field);
     }
     VisitSymbolInitializer(operation);
 }
Ejemplo n.º 5
0
        private static void AnalyzeTitle(IMethodSymbol descriptorCreationMethod, IFieldInitializerOperation creation, Action <Diagnostic> reportDiagnostic)
        {
            IParameterSymbol title = descriptorCreationMethod.Parameters.FirstOrDefault(p => p.Name == "title");

            if (title != null &&
                title.Type != null &&
                title.Type.SpecialType == SpecialType.System_String)
            {
                Diagnostic diagnostic = creation.Value.CreateDiagnostic(UseLocalizableStringsInDescriptorRule, WellKnownTypeNames.MicrosoftCodeAnalysisLocalizableString);
                reportDiagnostic(diagnostic);
            }
        }
 override public void VisitFieldInitializer(IFieldInitializerOperation operation)
 {
     Graph = ControlFlowGraph.Create(operation);
 }
Ejemplo n.º 7
0
 public override IOperation VisitFieldInitializer(IFieldInitializerOperation operation, object argument)
 {
     return(new FieldInitializer(operation.Locals, operation.InitializedFields, Visit(operation.Value), operation.Kind, ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit));
 }
Ejemplo n.º 8
0
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterCompilationStartAction(
                (compilationContext) =>
            {
                Dictionary <IFieldSymbol, HashSet <INamedTypeSymbol> > fieldsSourceTypes = new Dictionary <IFieldSymbol, HashSet <INamedTypeSymbol> >();

                compilationContext.RegisterOperationBlockStartAction(
                    (operationBlockContext) =>
                {
                    if (operationBlockContext.OwningSymbol is IMethodSymbol containingMethod)
                    {
                        Dictionary <ILocalSymbol, HashSet <INamedTypeSymbol> > localsSourceTypes = new Dictionary <ILocalSymbol, HashSet <INamedTypeSymbol> >();

                        // Track explicit assignments.
                        operationBlockContext.RegisterOperationAction(
                            (operationContext) =>
                        {
                            if (operationContext.Operation is IAssignmentOperation assignment)
                            {
                                AssignTo(assignment.Target, localsSourceTypes, fieldsSourceTypes, assignment.Value);
                            }
                            else if (operationContext.Operation is IIncrementOrDecrementOperation increment)
                            {
                                SyntaxNode syntax = increment.Syntax;
                                ITypeSymbol type  = increment.Type;
                                Optional <object> constantValue = new Optional <object>(1);
                                bool isImplicit = increment.IsImplicit;
                                var value       = new LiteralExpression(operationContext.Compilation.GetSemanticModel(syntax.SyntaxTree), syntax, type, constantValue, isImplicit);

                                AssignTo(increment.Target, localsSourceTypes, fieldsSourceTypes, value);
                            }
                            else
                            {
                                throw TestExceptionUtilities.UnexpectedValue(operationContext.Operation);
                            }
                        },
                            OperationKind.SimpleAssignment,
                            OperationKind.CompoundAssignment,
                            OperationKind.Increment);

                        // Track arguments that match out or ref parameters.
                        operationBlockContext.RegisterOperationAction(
                            (operationContext) =>
                        {
                            IInvocationOperation invocation = (IInvocationOperation)operationContext.Operation;
                            foreach (IArgumentOperation argument in invocation.Arguments)
                            {
                                if (argument.Parameter.RefKind == RefKind.Out || argument.Parameter.RefKind == RefKind.Ref)
                                {
                                    AssignTo(argument.Value, localsSourceTypes, fieldsSourceTypes, argument.Parameter.Type);
                                }
                            }
                        },
                            OperationKind.Invocation);

                        // Track local variable initializations.
                        operationBlockContext.RegisterOperationAction(
                            (operationContext) =>
                        {
                            IVariableInitializerOperation initializer = (IVariableInitializerOperation)operationContext.Operation;
                            if (initializer.Parent is IVariableDeclarationOperation variableDeclaration)
                            {
                                foreach (ILocalSymbol local in variableDeclaration.Variables)
                                {
                                    AssignTo(local, local.Type, localsSourceTypes, initializer.Value);
                                }
                            }
                        },
                            OperationKind.VariableInitializer);

                        // Report locals that could have more specific types.
                        operationBlockContext.RegisterOperationBlockEndAction(
                            (operationBlockEndContext) =>
                        {
                            foreach (ILocalSymbol local in localsSourceTypes.Keys)
                            {
                                if (HasMoreSpecificSourceType(local, local.Type, localsSourceTypes, out var mostSpecificSourceType))
                                {
                                    Report(operationBlockEndContext, local, mostSpecificSourceType, LocalCouldHaveMoreSpecificTypeDescriptor);
                                }
                            }
                        });
                    }
                });

                // Track field initializations.
                compilationContext.RegisterOperationAction(
                    (operationContext) =>
                {
                    IFieldInitializerOperation initializer = (IFieldInitializerOperation)operationContext.Operation;
                    foreach (IFieldSymbol initializedField in initializer.InitializedFields)
                    {
                        AssignTo(initializedField, initializedField.Type, fieldsSourceTypes, initializer.Value);
                    }
                },
                    OperationKind.FieldInitializer);

                // Report fields that could have more specific types.
                compilationContext.RegisterCompilationEndAction(
                    (compilationEndContext) =>
                {
                    foreach (IFieldSymbol field in fieldsSourceTypes.Keys)
                    {
                        if (HasMoreSpecificSourceType(field, field.Type, fieldsSourceTypes, out var mostSpecificSourceType))
                        {
                            Report(compilationEndContext, field, mostSpecificSourceType, FieldCouldHaveMoreSpecificTypeDescriptor);
                        }
                    }
                });
            });
        }
Ejemplo n.º 9
0
 public virtual void VisitFieldInitializer(IFieldInitializerOperation operation)
 {
     DefaultVisit(operation);
 }
Ejemplo n.º 10
0
 public override void VisitFieldInitializer([NotNull] IFieldInitializerOperation operation)
 {
     base.VisitFieldInitializer(operation);
 }
 public override TAbstractAnalysisValue VisitFieldInitializer(IFieldInitializerOperation operation, object argument)
 {
     return(VisitSymbolInitializer(operation, operation.InitializedFields, argument));
 }
Ejemplo n.º 12
0
        private static void AnalyzeTitle(OperationAnalysisContext operationAnalysisContext, ImmutableArray <IArgumentOperation> creationArguments, IFieldInitializerOperation creation)
        {
            IArgumentOperation titleArgument = creationArguments.FirstOrDefault(a => a.Parameter.Name.Equals("title", StringComparison.OrdinalIgnoreCase));

            if (titleArgument?.Parameter.Type.SpecialType != SpecialType.System_String)
            {
                return;
            }

            operationAnalysisContext.ReportDiagnostic(creation.Value.CreateDiagnostic(UseLocalizableStringsInDescriptorRule, WellKnownTypeNames.MicrosoftCodeAnalysisLocalizableString));

            if (!TryGetNonEmptyConstantStringValue(titleArgument, out var title))
            {
                return;
            }

            if (IsMultiSentences(title) || EndsWithPeriod(title) || ContainsLineReturn(title))
            {
                operationAnalysisContext.ReportDiagnostic(titleArgument.CreateDiagnostic(DefineDiagnosticTitleCorrectlyRule));
            }
        }
Ejemplo n.º 13
0
 public override bool VisitFieldInitializer([NotNull] IFieldInitializerOperation operation1,
                                            [CanBeNull] IOperation argument)
 {
     return(argument is IFieldInitializerOperation operation2 && AreBaseOperationsEqual(operation1, operation2) &&
            AreSymbolSequencesEqual(operation1.InitializedFields, operation2.InitializedFields));
 }