@Nullable
  static List<OperationRecord> extractIterableForEach(PsiMethodCallExpression terminalCall) {
    if (!ITERABLE_FOREACH.test(terminalCall) || !ExpressionUtils.isVoidContext(terminalCall)) return null;
    PsiExpression qualifier = ExpressionUtils.getEffectiveQualifier(terminalCall.getMethodExpression());
    if (qualifier == null) return null;
    // Do not visit this path if some class implements both Iterable and Stream
    PsiType type = qualifier.getType();
    if (InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_UTIL_STREAM_BASE_STREAM)) return null;
    PsiExpression arg = terminalCall.getArgumentList().getExpressions()[0];
    FunctionHelper fn = FunctionHelper.create(arg, 1, true);
    if (fn == null) return null;
    PsiType elementType = PsiUtil.substituteTypeParameter(type, CommonClassNames.JAVA_LANG_ITERABLE, 0, false);
    if (!isValidElementType(elementType, terminalCall, true)) return null;
    elementType = GenericsUtil.getVariableTypeByExpressionType(elementType);
    TerminalOperation terminal = new TerminalOperation.ForEachTerminalOperation(fn);
    SourceOperation source = new SourceOperation.ForEachSource(qualifier);
    OperationRecord terminalRecord = new OperationRecord();
    OperationRecord sourceRecord = new OperationRecord();
    terminalRecord.myOperation = terminal;
    sourceRecord.myOperation = source;
    sourceRecord.myOutVar = terminalRecord.myInVar = new ChainVariable(elementType);
    sourceRecord.myInVar = terminalRecord.myOutVar = ChainVariable.STUB;
    return Arrays.asList(sourceRecord, terminalRecord);
  }
@Nullable
  static List<OperationRecord> extractIterableForEach(PsiMethodCallExpression terminalCall)