예제 #1
0
        private static void AnalyzeNode(SyntaxNodeAnalysisContext context)
        {
            var invocation = (InvocationExpressionSyntax)context.Node;

            var symbolInfo = context.SemanticModel.GetSymbolInfo(invocation);

            var symbol = symbolInfo.Symbol as IMethodSymbol;

            // Are we an extension method?
            if (symbol?.MethodKind != MethodKind.ReducedExtension)
            {
                return;
            }

            // Are we extending IDbConnection
            if (!(symbol?.ReceiverType.Name.EndsWith("IDbConnection")).GetValueOrDefault())
            {
                return;
            }

            // Is our first argument a string aka SQL? Is the string a constant value (aka, does it contain anything besides string literals and const references)?
            var isNotConstant = false;
            var sqlLiteral    = SemanticStringHelpers.GetResolvedString(context, invocation.ArgumentList.Arguments.FirstOrDefault()?.Expression, ref isNotConstant);

            if (string.IsNullOrWhiteSpace(sqlLiteral))
            {
                return;
            }

            var secondArgument = invocation.ArgumentList.Arguments.Skip(1).FirstOrDefault()?.Expression;

            if (secondArgument == null)
            {
                return;
            }

            IReadOnlyList <string> availableProperties;

            if (secondArgument is AnonymousObjectCreationExpressionSyntax)
            {
                availableProperties = TypeHelpers.GetMembers(secondArgument as AnonymousObjectCreationExpressionSyntax);
            }
            else if (secondArgument is IdentifierNameSyntax)
            {
                availableProperties = TypeHelpers.GetMembers(context.SemanticModel.GetTypeInfo(secondArgument).Type).ToList();
            }
            else
            {
                return;
            }

            bool isValid;
            var  parameters = SqlHelpers.GetSqlParameters(sqlLiteral, out isValid);

            if (!isValid)
            {
                return;
            }

            if (!availableProperties.All(
                    availableProperty => parameters.Contains(availableProperty, StringComparer.CurrentCultureIgnoreCase)))
            {
                var diagnostic = Diagnostic.Create(
                    Rule,
                    secondArgument.GetLocation(),
                    string.Join(
                        ", ",
                        availableProperties.Where(
                            availableProperty =>
                            !parameters.Contains(availableProperty, StringComparer.CurrentCultureIgnoreCase))));

                context.ReportDiagnostic(diagnostic);
            }
        }