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); } }