예제 #1
0
        private Diagnostic AnalyzeSyntax(
            SemanticModel semanticModel, CodeStyleOption <ExpressionBodyPreference> option,
            LambdaExpressionSyntax declaration, CancellationToken cancellationToken)
        {
            if (CanOfferUseExpressionBody(option.Value, declaration))
            {
                var location = GetDiagnosticLocation(declaration);

                var additionalLocations = ImmutableArray.Create(declaration.GetLocation());
                var properties          = ImmutableDictionary <string, string> .Empty;
                return(DiagnosticHelper.Create(
                           CreateDescriptorWithId(UseExpressionBodyTitle, UseExpressionBodyTitle),
                           location, option.Notification.Severity, additionalLocations, properties));
            }

            if (CanOfferUseBlockBody(semanticModel, option.Value, declaration, cancellationToken))
            {
                // They have an expression body.  Create a diagnostic to convert it to a block
                // if they don't want expression bodies for this member.
                var location = GetDiagnosticLocation(declaration);

                var properties          = ImmutableDictionary <string, string> .Empty;
                var additionalLocations = ImmutableArray.Create(declaration.GetLocation());
                return(DiagnosticHelper.Create(
                           CreateDescriptorWithId(UseBlockBodyTitle, UseBlockBodyTitle),
                           location, option.Notification.Severity, additionalLocations, properties));
            }

            return(null);
        }
예제 #2
0
        private Diagnostic AnalyzeSyntax(
            SemanticModel semanticModel, OptionSet optionSet,
            LambdaExpressionSyntax declaration, CancellationToken cancellationToken)
        {
            var preferExpressionBodiedOption = optionSet.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedLambdas);
            var severity = preferExpressionBodiedOption.Notification.Severity;

            if (CanOfferUseExpressionBody(optionSet, declaration, forAnalyzer: true))
            {
                var location = GetDiagnosticLocation(declaration);

                var additionalLocations = ImmutableArray.Create(declaration.GetLocation());
                var properties          = ImmutableDictionary <string, string> .Empty.Add(nameof(UseExpressionBody), "");

                return(DiagnosticHelper.Create(
                           CreateDescriptorWithId(DescriptorId, UseExpressionBodyTitle, UseExpressionBodyTitle),
                           location, severity, additionalLocations, properties));
            }

            var(canOffer, fixesError) = CanOfferUseBlockBody(
                semanticModel, optionSet, declaration, forAnalyzer: true, cancellationToken);
            if (canOffer)
            {
                // They have an expression body.  Create a diagnostic to convert it to a block
                // if they don't want expression bodies for this member.
                var location = GetDiagnosticLocation(declaration);

                var properties = ImmutableDictionary <string, string> .Empty;
                if (fixesError)
                {
                    properties = properties.Add(FixesError, "");
                }

                var additionalLocations = ImmutableArray.Create(declaration.GetLocation());
                return(DiagnosticHelper.Create(
                           CreateDescriptorWithId(DescriptorId, UseBlockBodyTitle, UseBlockBodyTitle),
                           location, severity, additionalLocations, properties));
            }

            return(null);
        }
        private void AnalyzeLambda(SyntaxNodeAnalysisContext context)
        {
            LambdaExpressionSyntax lambdaExpressionSyntax = (LambdaExpressionSyntax)context.Node;

            if (lambdaExpressionSyntax.AsyncKeyword.Kind() != SyntaxKind.AsyncKeyword)
            {
                return;
            }

            var retValType = context.SemanticModel.GetSymbolInfo(lambdaExpressionSyntax);

            if (retValType.Symbol is null)
            {
                return;
            }

            if (retValType.Symbol is IMethodSymbol method && method.ReturnType.SpecialType == SpecialType.System_Void)
            {
                context.ReportDiagnostic(Diagnostic.Create(Rule, lambdaExpressionSyntax.GetLocation()));
            }
        }
            private void AnalyzePredicate(SyntaxNodeAnalysisContext context, SyntaxToken methodName, LambdaExpressionSyntax lambdaExpression)
            {
                if (GetParameters(lambdaExpression) is var parameters &&
                    parameters.Length == 1 &&
                    lambdaExpression.ExpressionBody is ExpressionSyntax body)
                {
                    var parameterName = parameters[0].Identifier.ValueText;

                    var operands = GetBinaryExpressionOperands(body, SyntaxKind.LogicalAndExpression)
                                   .Select(operand =>
                    {
                        var propertyName = GetEqualParameterPropertyExpression(operand, parameterName);
                        IPropertySymbol?propertySymbol = null;

                        if (propertyName != null)
                        {
                            var propertyInfo = context.SemanticModel.GetSymbolInfo(propertyName, context.CancellationToken);
                            propertySymbol   = propertyInfo.Symbol as IPropertySymbol;
                        }

                        return(new BinaryOperatorOperand(operand, propertySymbol));
                    })
                                   .ToList();

                    if (operands.Count == 0)
                    {
                        return;
                    }

                    var columns = operands
                                  .Where(c => c.ColumnSymbol != null)
                                  .Select(c => c.ColumnSymbol !)
                                  .ToList();

                    // TODO(jpg): check if this is true for inherited properties
                    Debug.Assert(
                        columns.Select(c => c.ContainingType).Distinct().Count() <= 1,
                        "All properties must be contained in the same type."
                        );

                    var type = columns[0].ContainingType;
                    var declaredPrimaryKeys = type.GetMembers().OfType <IPropertySymbol>().Where(IsPrimaryKey);
                    var usedPrimaryKeys     = columns.Where(IsPrimaryKey);

                    // TODO(jpg): check if this is true for inherited properties
                    Debug.Assert(
                        !usedPrimaryKeys.Except(declaredPrimaryKeys).Any(),
                        "usedPrimaryKeys ⊆ declaredPrimaryKeys"
                        );

                    var unusedPrimaryKeys = declaredPrimaryKeys.Except(usedPrimaryKeys);
                    if (unusedPrimaryKeys.Any())
                    {
                        return;
                    }

                    var usedNonPrimaryKeys = operands
                                             .Where(c => c.ColumnSymbol == null || !IsPrimaryKey(c.ColumnSymbol))
                                             .ToList();

                    if (usedNonPrimaryKeys.Count == 0)
                    {
                        return;
                    }

                    var diagnostic = Diagnostic.Create(
                        descriptor: DiagnosticDescriptors.RemoveUnnecessaryConditionsFromPredicate,
                        location: methodName.GetLocation(),
                        additionalLocations: new[] { lambdaExpression.GetLocation() }.Concat(usedNonPrimaryKeys.Select(c => c.Expression.GetLocation()))
                        );

                    context.ReportDiagnostic(diagnostic);
                }
            }