@Override
  public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
    return new JavaElementVisitor() {
      void handleIteratorLoop(PsiLoopStatement statement, PsiJavaToken endToken, IteratorDeclaration declaration) {
        if (endToken == null || declaration == null || !declaration.isCollection()) return;
        PsiStatement[] statements = ControlFlowUtils.unwrapBlock(statement.getBody());
        if (statements.length == 2 && statements[1] instanceof PsiIfStatement ifStatement) {
          PsiVariable element = declaration.getNextElementVariable(statements[0]);
          if (element == null) return;
          if(checkAndExtractCondition(declaration, ifStatement) == null) return;
          registerProblem(statement);
        }
        else if (statements.length == 1 && statements[0] instanceof PsiIfStatement ifStatement){
          PsiExpression condition = checkAndExtractCondition(declaration, ifStatement);
          if (condition == null) return;
          PsiElement ref = declaration.findOnlyIteratorRef(condition);
          if (ref != null && declaration.isIteratorMethodCall(ref.getParent().getParent(), "next") && isAlwaysExecuted(condition, ref)) {
            registerProblem(statement);
          }
        }
      }

      private static boolean isAlwaysExecuted(PsiExpression condition, PsiElement ref) {
        while(ref != condition) {
          PsiElement parent = ref.getParent();
          if(parent instanceof PsiPolyadicExpression polyadicExpression) {
            IElementType type = polyadicExpression.getOperationTokenType();
            if ((type.equals(JavaTokenType.ANDAND) || type.equals(JavaTokenType.OROR)) && polyadicExpression.getOperands()[0] != ref) {
              return false;
            }
          }
          if(parent instanceof PsiConditionalExpression && ((PsiConditionalExpression)parent).getCondition() != ref) {
            return false;
          }
          ref = parent;
        }
        return true;
      }

      private void registerProblem(PsiLoopStatement statement) {
        holder.registerProblem(statement.getFirstChild(),
                               QuickFixBundle.message("java.8.collection.removeif.inspection.description"),
                               new ReplaceWithRemoveIfQuickFix());
      }

      @Nullable
      private static PsiExpression checkAndExtractCondition(IterableTraversal traversal, PsiIfStatement ifStatement) {
        PsiExpression condition = ifStatement.getCondition();
        if (condition == null || ifStatement.getElseBranch() != null) return null;
        PsiStatement thenStatement = ControlFlowUtils.stripBraces(ifStatement.getThenBranch());
        if (!(thenStatement instanceof PsiExpressionStatement)) return null;
        if (!traversal.isRemoveCall(((PsiExpressionStatement)thenStatement).getExpression())) return null;
        if (!LambdaGenerationUtil.canBeUncheckedLambda(condition)) return null;
        PsiReferenceExpression iterable = tryCast(PsiUtil.skipParenthesizedExprDown(traversal.getIterable()), PsiReferenceExpression.class);
        PsiVariable iterableVariable = iterable != null ? tryCast(iterable.resolve(), PsiVariable.class) : null;
        if (iterableVariable != null && VariableAccessUtils.variableIsUsed(iterableVariable, condition)) return null;
        return condition;
      }

      @Override
      public void visitForStatement(@NotNull PsiForStatement statement) {
        super.visitForStatement(statement);
        IteratorDeclaration declaration = IteratorDeclaration.fromLoop(statement);
        handleIteratorLoop(statement, statement.getRParenth(), declaration);
      }

      @Override
      public void visitWhileStatement(@NotNull PsiWhileStatement statement) {
        super.visitWhileStatement(statement);
        IteratorDeclaration declaration = IteratorDeclaration.fromLoop(statement);
        handleIteratorLoop(statement, statement.getRParenth(), declaration);
      }

      @Override
      public void visitForeachStatement(@NotNull PsiForeachStatement statement) {
        super.visitForeachStatement(statement);
        ForEachCollectionTraversal traversal = ForEachCollectionTraversal.fromLoop(statement);
        if (traversal == null) return;
        PsiIfStatement ifStatement = tryCast(ControlFlowUtils.stripBraces(statement.getBody()), PsiIfStatement.class);
        if (ifStatement == null) return;
        PsiExpression condition = checkAndExtractCondition(traversal, ifStatement);
        if (condition == null) return;
        PsiJavaToken endToken = statement.getRParenth();
        if (endToken == null) return;
        registerProblem(statement);
      }
    };
  }
@Override
  public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly)