package fi.evident.dalesbred.plugin.idea;

import com.intellij.codeInspection.BaseJavaLocalInspectionTool;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.patterns.PsiMethodCallPattern;
import com.intellij.psi.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import static fi.evident.dalesbred.plugin.idea.DalesbredPatterns.psiDalesbredFindMethodCall;
import static fi.evident.dalesbred.plugin.idea.DalesbredPatterns.psiDalesbredSqlQueryMethodCall;
import static fi.evident.dalesbred.plugin.idea.SqlUtils.countQueryParametersPlaceholders;

public class DalesbredIncorrectParameterCountInspection extends BaseJavaLocalInspectionTool {

    private static final PsiMethodCallPattern FIND_METHOD_CALL = psiDalesbredFindMethodCall();
    private static final PsiMethodCallPattern SQL_QUERY_METHOD_CALL = psiDalesbredSqlQueryMethodCall();

    @NotNull
    @Override
    public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
        return new JavaElementVisitor() {

            @Override
            public void visitMethodCallExpression(PsiMethodCallExpression expression) {
                if (FIND_METHOD_CALL.accepts(expression)) {
                    String methodName = expression.getMethodExpression().getReferenceName();
                    PsiExpression[] parameters = expression.getArgumentList().getExpressions();

                    if ("findMap".equals(methodName))
                        verifyQueryParameterCount(parameters, 2, holder);
                    else
                        verifyQueryParameterCount(parameters, 1, holder);

                } else if (SQL_QUERY_METHOD_CALL.accepts(expression)) {
                    PsiExpression[] parameters = expression.getArgumentList().getExpressions();
                    verifyQueryParameterCount(parameters, 0, holder);
                }
            }
        };
    }

    private static void verifyQueryParameterCount(@NotNull PsiExpression[] parameters, int queryIndex, @NotNull ProblemsHolder holder) {
        PsiExpression queryParameter = parameters[queryIndex];
        String sql = resolveQueryString(queryParameter);
        if (sql != null) {
            int expected = countQueryParametersPlaceholders(sql);

            int actual = parameters.length - (queryIndex+1);
            if (actual != expected)
                holder.registerProblem(queryParameter, "Expected " + expected + " query parameters, but got " + actual + '.');
        }
    }

    @Nullable
    private static String resolveQueryString(@NotNull PsiExpression parameter) {
        if (parameter instanceof PsiLiteralExpression) {
            PsiLiteralExpression literal = (PsiLiteralExpression) parameter;
            Object value = literal.getValue();
            if (value instanceof String)
                return (String) value;
        }
        return null;
    }
}

@@ -230,96 +230,339 @@
 psi.
-*;%0Aimport org.jetbrains.annotations.NotNull;%0Aimport org.jetbrains.annotations.Nullable;%0A
+JavaElementVisitor;%0Aimport com.intellij.psi.PsiElementVisitor;%0Aimport com.intellij.psi.PsiExpression;%0Aimport com.intellij.psi.PsiMethodCallExpression;%0Aimport org.jetbrains.annotations.NotNull;%0Aimport org.jetbrains.annotations.Nullable;%0A%0Aimport static com.intellij.psi.impl.JavaConstantExpressionEvaluator.computeConstantExpression;
 %0Aimp
@@ -2881,111 +2881,38 @@
     
-if (parameter instanceof PsiLiteralExpression) %7B%0A            PsiLiteralExpression literal = (PsiLiteral
+Object value = computeConstant
 Expr
@@ -2917,18 +2917,17 @@
 pression
-) 
+(
 paramete
@@ -2931,54 +2931,15 @@
 eter
-;%0A            Object value = literal.getValue(
+, false
 );%0A 
@@ -2945,22 +2945,22 @@
         
-    if
+return
  (value 
@@ -2981,72 +2981,27 @@
 ing)
-%0A                return (String) value;%0A        %7D%0A        return
+ ? (String) value :
  nul

Support constant expressions when resolving query-parameters.