protected PsiType processParameterDeclaration(PsiElement parentDeclarationScope) {
   PsiType result = null;
   if (parentDeclarationScope instanceof PsiForeachStatement) {
     final PsiForeachStatement foreachStatement = (PsiForeachStatement) parentDeclarationScope;
     final PsiExpression iteratedValue = foreachStatement.getIteratedValue();
     if (iteratedValue != null) {
       result = JavaGenericsUtil.getCollectionItemType(iteratedValue);
     }
   }
   return result;
 }
  @NotNull
  static ElementFilter getReferenceFilter(PsiElement element, boolean allowRecursion) {
    // throw foo
    if (psiElement()
        .withParent(psiElement(PsiReferenceExpression.class).withParent(PsiThrowStatement.class))
        .accepts(element)) {
      return TrueFilter.INSTANCE;
    }

    if (psiElement()
        .inside(
            StandardPatterns.or(
                psiElement(PsiAnnotationParameterList.class),
                psiElement(PsiSwitchLabelStatement.class)))
        .accepts(element)) {
      return new ElementExtractorFilter(
          new AndFilter(
              new ClassFilter(PsiField.class),
              new ModifierFilter(PsiKeyword.STATIC, PsiKeyword.FINAL)));
    }

    final PsiForeachStatement foreach =
        PsiTreeUtil.getParentOfType(element, PsiForeachStatement.class);
    if (foreach != null && !PsiTreeUtil.isAncestor(foreach.getBody(), element, false)) {
      return new ElementExtractorFilter(
          new ElementFilter() {
            @Override
            public boolean isAcceptable(Object element, @Nullable PsiElement context) {
              return element != foreach.getIterationParameter();
            }

            @Override
            public boolean isClassAcceptable(Class hintClass) {
              return true;
            }
          });
    }

    if (!allowRecursion) {
      final ElementFilter filter = RecursionWeigher.recursionFilter(element);
      if (filter != null) {
        return new ElementExtractorFilter(filter);
      }
    }

    return TrueFilter.INSTANCE;
  }
 private static boolean isAddAllCall(PsiForeachStatement statement, PsiStatement body) {
   final PsiIfStatement ifStatement = extractIfStatement(body);
   if (ifStatement == null) {
     final PsiParameter parameter = statement.getIterationParameter();
     final PsiMethodCallExpression methodCallExpression = extractAddCall(body, null);
     LOG.assertTrue(methodCallExpression != null);
     return isIdentityMapping(
         parameter, methodCallExpression.getArgumentList().getExpressions()[0]);
   }
   return false;
 }
 private static boolean forEachStatementsAreEquivalent(
     @NotNull PsiForeachStatement statement1, @NotNull PsiForeachStatement statement2) {
   final PsiExpression value1 = statement1.getIteratedValue();
   final PsiExpression value2 = statement2.getIteratedValue();
   if (!expressionsAreEquivalent(value1, value2)) {
     return false;
   }
   final PsiParameter parameter1 = statement1.getIterationParameter();
   final PsiParameter parameter2 = statement1.getIterationParameter();
   final String name1 = parameter1.getName();
   final String name2 = parameter2.getName();
   if (!name1.equals(name2)) {
     return false;
   }
   final PsiType type1 = parameter1.getType();
   if (!type1.equals(parameter2.getType())) {
     return false;
   }
   final PsiStatement body1 = statement1.getBody();
   final PsiStatement body2 = statement2.getBody();
   return statementsAreEquivalent(body1, body2);
 }
 @Override
 public void visitForeachStatement(PsiForeachStatement statement) {
   super.visitForeachStatement(statement);
   final PsiExpression iteratedValue = statement.getIteratedValue();
   if (iteratedValue == null) {
     return;
   }
   final PsiType type = iteratedValue.getType();
   if (!(type instanceof PsiArrayType)) {
     return;
   }
   final PsiArrayType arrayType = (PsiArrayType) type;
   final PsiType componentType = arrayType.getComponentType();
   if (componentType instanceof PsiPrimitiveType) {
     return;
   }
   final PsiParameter parameter = statement.getIterationParameter();
   final PsiStatement body = statement.getBody();
   if (!bodyIsArrayToCollectionCopy(body, parameter, false)) {
     return;
   }
   registerStatementError(statement);
 }
 @Nullable
 private static String getCollectionsAddAllText(PsiForeachStatement foreachStatement)
     throws IncorrectOperationException {
   final PsiStatement body = getBody(foreachStatement);
   if (!(body instanceof PsiExpressionStatement)) {
     return null;
   }
   final PsiExpressionStatement expressionStatement = (PsiExpressionStatement) body;
   final PsiMethodCallExpression methodCallExpression =
       (PsiMethodCallExpression) expressionStatement.getExpression();
   final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
   final PsiElement collection = methodExpression.getQualifier();
   if (collection == null) {
     // fixme for when the array is added to 'this'
     return null;
   }
   final String collectionText = collection.getText();
   final PsiExpression iteratedValue = foreachStatement.getIteratedValue();
   if (iteratedValue == null) {
     return null;
   }
   final String arrayText = iteratedValue.getText();
   @NonNls final StringBuilder buffer = new StringBuilder();
   if (PsiUtil.isLanguageLevel5OrHigher(foreachStatement)) {
     buffer.append("java.util.Collections.addAll(");
     buffer.append(collectionText);
     buffer.append(',');
     buffer.append(arrayText);
     buffer.append(");");
   } else {
     buffer.append(collectionText);
     buffer.append(".addAll(java.util.Arrays.asList(");
     buffer.append(arrayText);
     buffer.append("));");
   }
   return buffer.toString();
 }
 @Override
 public void visitReferenceExpression(PsiReferenceExpression expression) {
   if (myWritten && myRead) {
     return;
   }
   super.visitReferenceExpression(expression);
   final PsiElement target = expression.resolve();
   if (target != myVariable) {
     return;
   }
   if (PsiUtil.isAccessedForWriting(expression)) {
     final PsiElement parent =
         PsiTreeUtil.skipParentsOfType(expression, PsiParenthesizedExpression.class);
     if (parent instanceof PsiAssignmentExpression) {
       final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression) parent;
       final PsiExpression rhs = assignmentExpression.getRExpression();
       if (isComplexArrayExpression(rhs)) {
         myWritten = true;
         myRead = true;
       } else if (!isSimpleArrayExpression(rhs)) {
         myWritten = true;
       }
     }
     return;
   }
   myIsReferenced = true;
   PsiElement parent = getParent(expression);
   if (parent instanceof PsiArrayAccessExpression) {
     PsiArrayAccessExpression arrayAccessExpression = (PsiArrayAccessExpression) parent;
     parent = getParent(parent);
     while (parent instanceof PsiArrayAccessExpression) {
       arrayAccessExpression = (PsiArrayAccessExpression) parent;
       parent = getParent(parent);
     }
     final PsiType type = arrayAccessExpression.getType();
     if (type != null) {
       final int dimensions = type.getArrayDimensions();
       if (dimensions > 0 && dimensions != myVariable.getType().getArrayDimensions()) {
         myWritten = true;
       }
     }
     if (PsiUtil.isAccessedForWriting(arrayAccessExpression)) {
       myWritten = true;
     }
     if (PsiUtil.isAccessedForReading(arrayAccessExpression)) {
       myRead = true;
     }
   } else if (parent instanceof PsiReferenceExpression) {
     final PsiReferenceExpression referenceExpression = (PsiReferenceExpression) parent;
     final String name = referenceExpression.getReferenceName();
     if ("length".equals(name)
         || ("clone".equals(name)
             && referenceExpression.getParent() instanceof PsiMethodCallExpression)) {
       myRead = true;
     }
   } else if (parent instanceof PsiForeachStatement) {
     final PsiForeachStatement foreachStatement = (PsiForeachStatement) parent;
     final PsiExpression iteratedValue = foreachStatement.getIteratedValue();
     if (PsiTreeUtil.isAncestor(iteratedValue, expression, false)) {
       myRead = true;
     }
   } else if (parent instanceof PsiExpressionList) {
     final PsiExpressionList expressionList = (PsiExpressionList) parent;
     parent = parent.getParent();
     if (parent instanceof PsiMethodCallExpression) {
       final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression) parent;
       final PsiMethod method = methodCallExpression.resolveMethod();
       if (method != null) {
         final PsiClass aClass = method.getContainingClass();
         if (aClass != null) {
           final String methodName = method.getName();
           final String qualifiedName = aClass.getQualifiedName();
           if ("java.lang.System".equals(qualifiedName)) {
             if ("arraycopy".equals(methodName)) {
               final PsiExpression[] expressions = expressionList.getExpressions();
               if (expressions.length == 5) {
                 if (PsiTreeUtil.isAncestor(expressions[0], expression, false)) {
                   myRead = true;
                   return;
                 } else if (PsiTreeUtil.isAncestor(expressions[2], expression, false)) {
                   myWritten = true;
                   return;
                 }
               }
             }
           } else if (CommonClassNames.JAVA_UTIL_ARRAYS.equals(qualifiedName)) {
             if ("fill".equals(methodName)
                 || "parallelPrefix".equals(methodName)
                 || "parallelSetAll".equals(methodName)
                 || "parallelSort".equals(methodName)
                 || "setAll".equals(methodName)
                 || "sort".equals(methodName)) {
               myWritten = true;
             } else {
               myRead = true;
             }
             return;
           }
         }
       }
     }
     myRead = true;
     myWritten = true;
   } else {
     myWritten = true;
     myRead = true;
   }
 }
 private static void restoreComments(PsiForeachStatement foreachStatement, PsiStatement body) {
   final PsiElement parent = foreachStatement.getParent();
   for (PsiElement comment : PsiTreeUtil.findChildrenOfType(body, PsiComment.class)) {
     parent.addBefore(comment, foreachStatement);
   }
 }
    @Override
    public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
      final PsiForeachStatement foreachStatement =
          PsiTreeUtil.getParentOfType(descriptor.getPsiElement(), PsiForeachStatement.class);
      if (foreachStatement != null) {
        if (!FileModificationService.getInstance().preparePsiElementForWrite(foreachStatement))
          return;
        final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
        PsiStatement body = foreachStatement.getBody();
        final PsiExpression iteratedValue = foreachStatement.getIteratedValue();
        if (body != null && iteratedValue != null) {
          final PsiParameter parameter = foreachStatement.getIterationParameter();
          final PsiIfStatement ifStatement = extractIfStatement(body);
          final PsiMethodCallExpression methodCallExpression = extractAddCall(body, ifStatement);

          if (methodCallExpression == null) return;

          if (isAddAllCall(foreachStatement, body)) {
            restoreComments(foreachStatement, body);
            final PsiExpression qualifierExpression =
                methodCallExpression.getMethodExpression().getQualifierExpression();
            final String qualifierText =
                qualifierExpression != null ? qualifierExpression.getText() : "";
            final String callText =
                StringUtil.getQualifiedName(
                    qualifierText, "addAll(" + getIteratedValueText(iteratedValue) + ");");
            PsiElement result =
                foreachStatement.replace(
                    elementFactory.createStatementFromText(callText, foreachStatement));
            reformatWhenNeeded(project, result);
            return;
          }
          final StringBuilder builder =
              new StringBuilder(getIteratedValueText(iteratedValue) + ".stream()");

          builder.append(createFiltersChainText(body, parameter, ifStatement));
          builder.append(
              createMapperFunctionalExpressionText(
                  parameter, methodCallExpression.getArgumentList().getExpressions()[0]));

          builder.append(".collect(java.util.stream.Collectors.");
          PsiElement result = null;
          try {
            final PsiExpression qualifierExpression =
                methodCallExpression.getMethodExpression().getQualifierExpression();
            if (qualifierExpression instanceof PsiReferenceExpression) {
              final PsiElement resolve = ((PsiReferenceExpression) qualifierExpression).resolve();
              if (resolve instanceof PsiVariable) {
                if (resolve instanceof PsiLocalVariable
                    && foreachStatement.equals(
                        PsiTreeUtil.skipSiblingsForward(
                            resolve.getParent(), PsiWhiteSpace.class))) {
                  final PsiExpression initializer = ((PsiVariable) resolve).getInitializer();
                  if (initializer instanceof PsiNewExpression) {
                    final PsiExpressionList argumentList =
                        ((PsiNewExpression) initializer).getArgumentList();
                    if (argumentList != null && argumentList.getExpressions().length == 0) {
                      restoreComments(foreachStatement, body);
                      final String callText =
                          builder.toString()
                              + createInitializerReplacementText(
                                  ((PsiVariable) resolve).getType(), initializer)
                              + ")";
                      result =
                          initializer.replace(
                              elementFactory.createExpressionFromText(callText, null));
                      simplifyRedundantCast(result);
                      foreachStatement.delete();
                      return;
                    }
                  }
                }
              }
            }
            restoreComments(foreachStatement, body);
            final String qualifierText =
                qualifierExpression != null ? qualifierExpression.getText() : "";
            final String callText =
                StringUtil.getQualifiedName(
                    qualifierText, "addAll(" + builder.toString() + "toList()));");
            result =
                foreachStatement.replace(
                    elementFactory.createStatementFromText(callText, foreachStatement));
            simplifyRedundantCast(result);
          } finally {
            reformatWhenNeeded(project, result);
          }
        }
      }
    }
    @Override
    public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
      final PsiForeachStatement foreachStatement =
          PsiTreeUtil.getParentOfType(descriptor.getPsiElement(), PsiForeachStatement.class);
      if (foreachStatement != null) {
        if (!FileModificationService.getInstance().preparePsiElementForWrite(foreachStatement))
          return;
        PsiStatement body = foreachStatement.getBody();
        final PsiExpression iteratedValue = foreachStatement.getIteratedValue();
        if (body != null && iteratedValue != null) {
          restoreComments(foreachStatement, body);

          final PsiParameter parameter = foreachStatement.getIterationParameter();
          final PsiIfStatement ifStmt = extractIfStatement(body);

          StringBuilder buffer = new StringBuilder(getIteratedValueText(iteratedValue));
          if (ifStmt != null) {
            final PsiStatement thenBranch = ifStmt.getThenBranch();
            LOG.assertTrue(thenBranch != null);
            buffer.append(".stream()");
            buffer.append(createFiltersChainText(body, parameter, ifStmt));
            body = thenBranch;
          }

          buffer.append(".").append(getForEachMethodName()).append("(");

          final String functionalExpressionText =
              createForEachFunctionalExpressionText(project, body, parameter);
          final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
          PsiExpressionStatement callStatement =
              (PsiExpressionStatement)
                  elementFactory.createStatementFromText(
                      buffer.toString() + functionalExpressionText + ");", foreachStatement);
          callStatement = (PsiExpressionStatement) foreachStatement.replace(callStatement);

          final PsiExpressionList argumentList =
              ((PsiCallExpression) callStatement.getExpression()).getArgumentList();
          LOG.assertTrue(argumentList != null, callStatement.getText());
          final PsiExpression[] expressions = argumentList.getExpressions();
          LOG.assertTrue(expressions.length == 1);

          if (expressions[0] instanceof PsiFunctionalExpression
              && ((PsiFunctionalExpression) expressions[0]).getFunctionalInterfaceType() == null) {
            callStatement =
                (PsiExpressionStatement)
                    callStatement.replace(
                        elementFactory.createStatementFromText(
                            buffer.toString()
                                + "("
                                + parameter.getText()
                                + ") -> "
                                + wrapInBlock(body)
                                + ");",
                            callStatement));
          }

          simplifyRedundantCast(callStatement);

          CodeStyleManager.getInstance(project)
              .reformat(
                  JavaCodeStyleManager.getInstance(project).shortenClassReferences(callStatement));
        }
      }
    }