/*
 * Copyright 2003-2011 Bas Leijdekkers
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.siyeh.ig.psiutils;

import com.intellij.psi.*;
import com.siyeh.HardcodedMethodConstants;
import org.jetbrains.annotations.NotNull;

import java.util.regex.Pattern;

public class IteratorUtils {

    private IteratorUtils() {}

    /**
     * @param context  the context iterator.next() may be called in.
     * @param target  the target variable iterator.next() is called on. Specify
     *                null to check for "this"  as target variable.
     * @return true, if iterator.next() is called, false otherwise
     */
    public static boolean containsCallToIteratorNext(PsiElement context,
                                                     PsiVariable target,
                                                     boolean checkTarget) {
        final CallsIteratorNextVisitor visitor =
                new CallsIteratorNextVisitor(target, checkTarget, false);
        context.accept(visitor);
        return visitor.callsIteratorNext();
    }

    public static boolean containsCallToScannerNext(PsiElement context,
                                                    PsiVariable target,
                                                    boolean checkTarget) {
        final CallsIteratorNextVisitor visitor =
                new CallsIteratorNextVisitor(target, checkTarget, true);
        context.accept(visitor);
        return visitor.callsIteratorNext();
    }

    public static boolean isCallToHasNext(
            PsiMethodCallExpression methodCallExpression) {
        return MethodCallUtils.isCallToMethod(methodCallExpression,
                CommonClassNames.JAVA_UTIL_ITERATOR, PsiType.BOOLEAN, "hasNext");
    }

    private static class CallsIteratorNextVisitor
            extends JavaRecursiveElementVisitor {

        private static final Pattern SCANNER_PATTERN = Pattern.compile("next.*");

        private final boolean checkTarget;
        private final boolean checkScanner;
        private final PsiVariable target;
        private boolean doesCallIteratorNext = false;

        CallsIteratorNextVisitor(PsiVariable target, boolean checkTarget,
                                 boolean checkScanner) {
            this.checkTarget = checkTarget;
            this.target = target;
            this.checkScanner = checkScanner;
        }

        @Override public void visitElement(@NotNull PsiElement element){
            if (doesCallIteratorNext) {
                return;
            }
            super.visitElement(element);
        }

        @Override public void visitMethodCallExpression(
                @NotNull PsiMethodCallExpression expression){
            if(doesCallIteratorNext){
                return;
            }
            super.visitMethodCallExpression(expression);
            if (checkScanner) {
                if (!MethodCallUtils.isCallToMethod(expression,
                        CommonClassNames.JAVA_UTIL_ITERATOR, null,
                        SCANNER_PATTERN)) {
                    return;
                }
            } else {
                if (!MethodCallUtils.isCallToMethod(expression,
                        CommonClassNames.JAVA_UTIL_ITERATOR, null,
                        HardcodedMethodConstants.NEXT)) {
                    return;
                }
            }
            if (checkTarget) {
                final PsiReferenceExpression methodExpression =
                        expression.getMethodExpression();
                final PsiExpression qualifier =
                        methodExpression.getQualifierExpression();
                if (!(qualifier instanceof PsiReferenceExpression)) {
                    if (target != null) {
                        return;
                    }
                    if (qualifier != null &&
                            !(qualifier instanceof PsiThisExpression) &&
                            !(qualifier instanceof PsiSuperExpression)) {
                        return;
                    }
                } else {
                    final PsiReferenceExpression referenceExpression =
                            (PsiReferenceExpression) qualifier;
                    final PsiElement element = referenceExpression.resolve();
                    if (!target.equals(element)) {
                        return;
                    }
                }
            }
            doesCallIteratorNext = true;
        }

        public boolean callsIteratorNext(){
            return doesCallIteratorNext;
        }
    }
}
@@ -4801,16 +4801,34 @@
     if (
+target == null %7C%7C 
 !target.
@@ -5086,8 +5086,9 @@
 %0A    %7D%0A%7D
+%0A

fix NPE EA-26530