Example #1
0
    @Nullable
    PurityInferenceResult getResult() {
      if (calls.size() > 1 || !hasReturns) return null;

      int bodyStart = body.getStartOffset();
      return new PurityInferenceResult(
          ContainerUtil.map(mutatedRefs, node -> ExpressionRange.create(node, bodyStart)),
          calls.isEmpty() ? null : ExpressionRange.create(calls.get(0), bodyStart));
    }
  public static boolean parseAsTree(
      ErrorState state,
      final PsiBuilder builder,
      int level,
      final IElementType chunkType,
      boolean checkBraces,
      final Parser parser,
      final Parser eatMoreCondition) {
    final LinkedList<Pair<PsiBuilder.Marker, PsiBuilder.Marker>> parenList =
        new LinkedList<Pair<PsiBuilder.Marker, PsiBuilder.Marker>>();
    final LinkedList<Pair<PsiBuilder.Marker, Integer>> siblingList =
        new LinkedList<Pair<PsiBuilder.Marker, Integer>>();
    PsiBuilder.Marker marker = null;

    final Runnable checkSiblingsRunnable =
        new Runnable() {
          @Override
          public void run() {
            main:
            while (!siblingList.isEmpty()) {
              final Pair<PsiBuilder.Marker, PsiBuilder.Marker> parenPair = parenList.peek();
              final int rating = siblingList.getFirst().second;
              int count = 0;
              for (Pair<PsiBuilder.Marker, Integer> pair : siblingList) {
                if (pair.second != rating || parenPair != null && pair.first == parenPair.second)
                  break main;
                if (++count >= MAX_CHILDREN_IN_TREE) {
                  PsiBuilder.Marker parentMarker = pair.first.precede();
                  parentMarker.setCustomEdgeTokenBinders(
                      WhitespacesBinders.GREEDY_LEFT_BINDER, null);
                  while (count-- > 0) {
                    siblingList.removeFirst();
                  }
                  parentMarker.done(chunkType);
                  siblingList.addFirst(Pair.create(parentMarker, rating + 1));
                  continue main;
                }
              }
              break;
            }
          }
        };
    boolean checkParens = state.braces != null && checkBraces;
    int totalCount = 0;
    int tokenCount = 0;
    if (checkParens) {
      int tokenIdx = -1;
      while (builder.rawLookup(tokenIdx) == TokenType.WHITE_SPACE) tokenIdx--;
      LighterASTNode doneMarker =
          builder.rawLookup(tokenIdx) == state.braces[0].getLeftBraceType()
              ? builder.getLatestDoneMarker()
              : null;
      if (doneMarker != null
          && doneMarker.getStartOffset() == builder.rawTokenTypeStart(tokenIdx)
          && doneMarker.getTokenType() == TokenType.ERROR_ELEMENT) {
        parenList.add(
            Pair.create(((PsiBuilder.Marker) doneMarker).precede(), (PsiBuilder.Marker) null));
      }
    }
    while (true) {
      final IElementType tokenType = builder.getTokenType();
      if (checkParens
          && (tokenType == state.braces[0].getLeftBraceType()
              || tokenType == state.braces[0].getRightBraceType() && !parenList.isEmpty())) {
        if (marker != null) {
          marker.done(chunkType);
          siblingList.addFirst(Pair.create(marker, 1));
          marker = null;
          tokenCount = 0;
        }
        if (tokenType == state.braces[0].getLeftBraceType()) {
          final Pair<PsiBuilder.Marker, Integer> prev = siblingList.peek();
          parenList.addFirst(Pair.create(builder.mark(), prev == null ? null : prev.first));
        }
        checkSiblingsRunnable.run();
        builder.advanceLexer();
        if (tokenType == state.braces[0].getRightBraceType()) {
          final Pair<PsiBuilder.Marker, PsiBuilder.Marker> pair = parenList.removeFirst();
          pair.first.done(chunkType);
          // drop all markers inside parens
          while (!siblingList.isEmpty() && siblingList.getFirst().first != pair.second) {
            siblingList.removeFirst();
          }
          siblingList.addFirst(Pair.create(pair.first, 1));
          checkSiblingsRunnable.run();
        }
      } else {
        if (marker == null) {
          marker = builder.mark();
          marker.setCustomEdgeTokenBinders(WhitespacesBinders.GREEDY_LEFT_BINDER, null);
        }
        final boolean result =
            (!parenList.isEmpty() || eatMoreCondition.parse(builder, level + 1))
                && parser.parse(builder, level + 1);
        if (result) {
          tokenCount++;
          totalCount++;
        }
        if (!result) {
          break;
        }
      }

      if (tokenCount >= MAX_CHILDREN_IN_TREE && marker != null) {
        marker.done(chunkType);
        siblingList.addFirst(Pair.create(marker, 1));
        checkSiblingsRunnable.run();
        marker = null;
        tokenCount = 0;
      }
    }
    if (marker != null) {
      marker.drop();
    }
    for (Pair<PsiBuilder.Marker, PsiBuilder.Marker> pair : parenList) {
      pair.first.drop();
    }
    return totalCount != 0;
  }