Example #1
0
        protected override void AnalyzeNode(SyntaxNodeAnalysisContext context, EnabledRules rules)
        {
            var node          = context.Node;
            var semanticModel = context.SemanticModel;
            Action <Diagnostic> reportDiagnostic = context.ReportDiagnostic;
            var    cancellationToken             = context.CancellationToken;
            string filePath = node.SyntaxTree.FilePath;

            var invocationExpression = node as InvocationExpressionSyntax;

            if (semanticModel.GetSymbolInfo(invocationExpression, cancellationToken).Symbol is IMethodSymbol methodInfo)
            {
                if (rules.IsEnabled(AllocationRules.ValueTypeNonOverridenCallRule.Id))
                {
                    if (methodInfo.IsOverride)
                    {
                        var rule = rules.Get(AllocationRules.ValueTypeNonOverridenCallRule.Id);
                        CheckNonOverridenMethodOnStruct(rule, methodInfo, reportDiagnostic, invocationExpression, filePath);
                    }
                }

                if (rules.IsEnabled(AllocationRules.ParamsParameterRule.Id))
                {
                    if (methodInfo.Parameters.Length > 0 && invocationExpression.ArgumentList != null)
                    {
                        var lastParam = methodInfo.Parameters[methodInfo.Parameters.Length - 1];
                        if (lastParam.IsParams)
                        {
                            var rule = rules.Get(AllocationRules.ParamsParameterRule.Id);
                            CheckParam(rule, invocationExpression, methodInfo, semanticModel, reportDiagnostic, filePath, cancellationToken);
                        }
                    }
                }
            }
        }
        protected override void AnalyzeNode(SyntaxNodeAnalysisContext context, EnabledRules rules)
        {
            var node          = context.Node;
            var semanticModel = context.SemanticModel;
            Action <Diagnostic> reportDiagnostic = context.ReportDiagnostic;
            var    cancellationToken             = context.CancellationToken;
            string filePath          = node.SyntaxTree.FilePath;
            var    binaryExpressions = node.DescendantNodesAndSelf().OfType <BinaryExpressionSyntax>().Reverse(); // need inner most expressions

            int stringConcatenationCount = 0;

            foreach (var binaryExpression in binaryExpressions)
            {
                if (binaryExpression.Left == null || binaryExpression.Right == null)
                {
                    continue;
                }

                bool isConstant = semanticModel.GetConstantValue(binaryExpression, cancellationToken).HasValue;
                if (isConstant)
                {
                    continue;
                }
                // TODO: TryGetEnabled()
                var left  = semanticModel.GetTypeInfo(binaryExpression.Left, cancellationToken);
                var right = semanticModel.GetTypeInfo(binaryExpression.Right, cancellationToken);

                if (rules.TryGet(AllocationRules.ValueTypeToReferenceTypeInAStringConcatenationRule.Id, out var rule))
                {
                    var leftConversion  = semanticModel.GetConversion(binaryExpression.Left, cancellationToken);
                    var rightConversion = semanticModel.GetConversion(binaryExpression.Right, cancellationToken);
                    CheckTypeConversion(rule, left, leftConversion, reportDiagnostic, binaryExpression.Left.GetLocation(), filePath);
                    CheckTypeConversion(rule, right, rightConversion, reportDiagnostic, binaryExpression.Right.GetLocation(), filePath);
                }

                // regular string allocation
                if (rules.IsEnabled(AllocationRules.StringConcatenationAllocationRule.Id))
                {
                    if (left.Type?.SpecialType == SpecialType.System_String || right.Type?.SpecialType == SpecialType.System_String)
                    {
                        stringConcatenationCount++;
                    }
                }
            }

            if (stringConcatenationCount > 3)
            {
                var rule = rules.Get(AllocationRules.StringConcatenationAllocationRule.Id);
                reportDiagnostic(Diagnostic.Create(rule, node.GetLocation(), EmptyMessageArgs));
            }
        }
Example #3
0
        private static void ArgumentSyntaxCheck(EnabledRules rules, SyntaxNode node, SemanticModel semanticModel, bool isAssignmentToReadonly, Action <Diagnostic> reportDiagnostic, string filePath, CancellationToken cancellationToken)
        {
            var argument = node as ArgumentSyntax;

            if (argument.Expression != null)
            {
                if (rules.IsEnabled(AllocationRules.ValueTypeToReferenceTypeConversionRule.Id))
                {
                    var argumentTypeInfo       = semanticModel.GetTypeInfo(argument.Expression, cancellationToken);
                    var argumentConversionInfo = semanticModel.GetConversion(argument.Expression, cancellationToken);
                    CheckTypeConversion(rules.Get(AllocationRules.ValueTypeToReferenceTypeConversionRule.Id), argumentConversionInfo, reportDiagnostic, argument.Expression.GetLocation(), filePath);
                    CheckDelegateCreation(rules, argument.Expression, argumentTypeInfo, semanticModel, isAssignmentToReadonly, reportDiagnostic, argument.Expression.GetLocation(), filePath, cancellationToken);
                }
            }
        }
Example #4
0
        private static void CheckDelegateCreation(EnabledRules rules, SyntaxNode node, TypeInfo typeInfo, SemanticModel semanticModel, bool isAssignmentToReadonly, Action <Diagnostic> reportDiagnostic, Location location, string filePath, CancellationToken cancellationToken)
        {
            if (typeInfo.ConvertedType?.TypeKind != TypeKind.Delegate)
            {
                return;
            }

            if (rules.TryGet(AllocationRules.DelegateOnStructInstanceRule.Id, out var delegateOnStructRule))
            {
                var symbolInfo = semanticModel.GetSymbolInfo(node, cancellationToken).Symbol;
                if (symbolInfo?.ContainingType?.IsValueType == true && symbolInfo.GetType().Name == "SourceMemberMethodSymbol")
                {
                    reportDiagnostic(Diagnostic.Create(delegateOnStructRule, location, EmptyMessageArgs));
                }
            }

            // new Action<Foo>(MethodGroup); should skip this one
            var insideObjectCreation = node?.Parent?.Parent?.Parent?.Kind() == SyntaxKind.ObjectCreationExpression;

            if (node is ParenthesizedLambdaExpressionSyntax || node is SimpleLambdaExpressionSyntax ||
                node is AnonymousMethodExpressionSyntax || node is ObjectCreationExpressionSyntax ||
                insideObjectCreation)
            {
                // skip this, because it's intended.
                return;
            }

            if (rules.IsEnabled(AllocationRules.MethodGroupAllocationRule.Id) && node.IsKind(SyntaxKind.IdentifierName))
            {
                if (semanticModel.GetSymbolInfo(node, cancellationToken).Symbol is IMethodSymbol)
                {
                    reportDiagnostic(Diagnostic.Create(rules.Get(AllocationRules.MethodGroupAllocationRule.Id), location, EmptyMessageArgs));
                }
            }
            else if (node.IsKind(SyntaxKind.SimpleMemberAccessExpression))
            {
                var memberAccess = node as MemberAccessExpressionSyntax;
                if (semanticModel.GetSymbolInfo(memberAccess.Name, cancellationToken).Symbol is IMethodSymbol)
                {
                    if (isAssignmentToReadonly && rules.TryGet(AllocationRules.ReadonlyMethodGroupAllocationRule.Id, out var readonlyMethodGroupAllocationRule))
                    {
                        reportDiagnostic(Diagnostic.Create(readonlyMethodGroupAllocationRule, location, EmptyMessageArgs));
                    }
                    else if (rules.TryGet(AllocationRules.MethodGroupAllocationRule.Id, out var methodGroupAllocationRule))
                    {
                        reportDiagnostic(Diagnostic.Create(methodGroupAllocationRule, location, EmptyMessageArgs));
                    }
                }
            }
            else if (node is ArrowExpressionClauseSyntax)
            {
                if (rules.TryGet(AllocationRules.MethodGroupAllocationRule.Id, out var methodGroupAllocationRule))
                {
                    var arrowClause = node as ArrowExpressionClauseSyntax;
                    if (semanticModel.GetSymbolInfo(arrowClause.Expression, cancellationToken).Symbol is IMethodSymbol)
                    {
                        reportDiagnostic(Diagnostic.Create(methodGroupAllocationRule, location, EmptyMessageArgs));
                    }
                }
            }
        }