public static void report_error_(PsiBuilder builder_) { ErrorState state = ErrorState.get(builder_); Frame frame = state.levelCheck.isEmpty() ? null : state.levelCheck.getLast(); if (frame == null) { LOG.error("Unbalanced error section: got null , expected " + frame); return; } int offset = builder_.getCurrentOffset(); if (frame.errorReportedAt < offset && getLastVariantOffset(state, builder_.getCurrentOffset()) <= offset) { if (reportError(state, builder_, true)) { frame.errorReportedAt = offset; } } }
public static boolean empty_element_parsed_guard_(PsiBuilder builder, String funcName, int pos) { if (pos == current_position_(builder)) { builder.error( "Empty element parsed in '" + funcName + "' at offset " + builder.getCurrentOffset()); return false; } return true; }
public String getExpectedText(PsiBuilder builder_) { int offset = builder_.getCurrentOffset(); StringBuilder sb = new StringBuilder(); if (addExpected(sb, offset, true)) { sb.append(" expected, "); } else if (addExpected(sb, offset, false)) sb.append(" unexpected, "); return sb.toString(); }
public static boolean replaceVariants(PsiBuilder builder_, int variantCount, String frameName) { ErrorState state = ErrorState.get(builder_); if (!state.suppressErrors && state.predicateCount < 2 && state.predicateSign) { state.clearVariants(true, state.variants.size() - variantCount); addVariantInner(state, builder_.getCurrentOffset(), frameName); } return true; }
private static void addVariant(ErrorState state, PsiBuilder builder_, Object o) { int offset = builder_.getCurrentOffset(); addVariantInner(state, offset, o); CompletionState completionState = state.completionState; if (completionState != null && state.predicateSign) { addCompletionVariant(state, completionState, builder_, o, offset); } }
public static boolean invalid_left_marker_guard_( PsiBuilder builder_, PsiBuilder.Marker marker_, String funcName_) { // builder_.error("Invalid left marker encountered in " + funcName_ +" at offset " + // builder_.getCurrentOffset()); boolean goodMarker = marker_ != null && ((LighterASTNode) marker_).getTokenType() != TokenType.ERROR_ELEMENT; if (!goodMarker) return false; ErrorState state = ErrorState.get(builder_); Frame frame = state.levelCheck.isEmpty() ? null : state.levelCheck.getLast(); return frame == null || frame.errorReportedAt <= builder_.getCurrentOffset(); }
public Frame init( PsiBuilder builder, ErrorState state, int level_, int modifiers_, String name_) { offset = builder.getCurrentOffset(); position = builder.rawTokenIndex(); level = level_; modifiers = modifiers_; name = name_; variantCount = state.variants.size(); errorReportedAt = -1; Frame prev = state.frameStack.peekLast(); errorReportedAtPrev = prev == null ? -1 : prev.errorReportedAt; leftMarker = null; return this; }
public static int nextTokenIsFast(PsiBuilder builder, String tokenText, boolean caseSensitive) { CharSequence sequence = builder.getOriginalText(); int offset = builder.getCurrentOffset(); int endOffset = offset + tokenText.length(); CharSequence subSequence = sequence.subSequence(offset, Math.min(endOffset, sequence.length())); if (!Comparing.equal(subSequence, tokenText, caseSensitive)) return 0; int count = 0; while (true) { int nextOffset = builder.rawTokenTypeStart(++count); if (nextOffset > endOffset) { return -count; } else if (nextOffset == endOffset) { break; } } return count; }
private static void addCompletionVariant( @NotNull PsiBuilder builder, @NotNull CompletionState completionState, Object o) { int offset = builder.getCurrentOffset(); if (!builder.eof() && offset == builder.rawTokenTypeStart(1)) return; // suppress for zero-length tokens boolean add = false; int diff = completionState.offset - offset; String text = completionState.convertItem(o); int length = text == null ? 0 : text.length(); if (length == 0) return; if (diff == 0) { add = true; } else if (diff > 0 && diff <= length) { CharSequence fragment = builder.getOriginalText().subSequence(offset, completionState.offset); add = completionState.prefixMatches(fragment.toString(), text); } else if (diff < 0) { for (int i = -1; ; i--) { IElementType type = builder.rawLookup(i); int tokenStart = builder.rawTokenTypeStart(i); if (isWhitespaceOrComment(builder, type)) { diff = completionState.offset - tokenStart; } else if (type != null && tokenStart < completionState.offset) { CharSequence fragment = builder.getOriginalText().subSequence(tokenStart, completionState.offset); if (completionState.prefixMatches(fragment.toString(), text)) { diff = completionState.offset - tokenStart; } break; } else break; } add = diff >= 0 && diff < length; } add = add && length > 1 && !(text.charAt(0) == '<' && text.charAt(length - 1) == '>') && !(text.charAt(0) == '\'' && text.charAt(length - 1) == '\'' && length < 5); if (add) { completionState.addItem(builder, text); } }
public Frame init( PsiBuilder builder, ErrorState state, int level_, int modifiers_, IElementType elementType_, String name_) { parentFrame = state.currentFrame; elementType = elementType_; offset = builder.getCurrentOffset(); position = builder.rawTokenIndex(); level = level_; modifiers = modifiers_; name = name_; variantCount = state.variants.size(); errorReportedAt = -1; leftMarker = null; return this; }
public static boolean consumeTokens(PsiBuilder builder_, int pin_, IElementType... tokens_) { ErrorState state = ErrorState.get(builder_); if (state.completionState != null && state.predicateSign) { addCompletionVariant( state, state.completionState, builder_, tokens_, builder_.getCurrentOffset()); } // suppress single token completion CompletionState completionState = state.completionState; state.completionState = null; boolean result_ = true; boolean pinned_ = false; for (int i = 0, tokensLength = tokens_.length; i < tokensLength; i++) { if (pin_ > 0 && i == pin_) pinned_ = result_; if ((result_ || pinned_) && !consumeToken(builder_, tokens_[i])) { result_ = false; if (pin_ < 0 || pinned_) report_error_(builder_); } } state.completionState = completionState; return pinned_ || result_; }
public static boolean consumeTokenInner(PsiBuilder builder_, String text, boolean caseSensitive) { final CharSequence sequence = builder_.getOriginalText(); final int offset = builder_.getCurrentOffset(); final int endOffset = offset + text.length(); CharSequence tokenText = sequence.subSequence(offset, Math.min(endOffset, sequence.length())); if (Comparing.equal(text, tokenText, caseSensitive)) { int count = 0; while (true) { final int nextOffset = builder_.rawTokenTypeStart(++count); if (nextOffset > endOffset) { return false; } else if (nextOffset == endOffset) { break; } } while (count-- > 0) builder_.advanceLexer(); return true; } return false; }
public static void enterErrorRecordingSection( PsiBuilder builder_, int level, @NotNull String sectionType, @Nullable String frameName) { ErrorState state = ErrorState.get(builder_); Frame frame = state .FRAMES .alloc() .init( builder_.getCurrentOffset(), level, sectionType, frameName, state.variants.size()); state.levelCheck.add(frame); if (sectionType == _SECTION_AND_) { if (state.predicateCount == 0 && !state.predicateSign) { throw new AssertionError("Incorrect false predicate sign"); } state.predicateCount++; } else if (sectionType == _SECTION_NOT_) { if (state.predicateCount == 0) { state.predicateSign = false; } else { state.predicateSign = !state.predicateSign; } state.predicateCount++; } }
protected int getCurrentOffset() { return myBuilder.getCurrentOffset(); }
// todo[r.sh] make 'this', 'super' and 'class' reference expressions @Nullable private PsiBuilder.Marker parsePrimary( final PsiBuilder builder, @Nullable final BreakPoint breakPoint, final int breakOffset) { PsiBuilder.Marker startMarker = builder.mark(); PsiBuilder.Marker expr = parsePrimaryExpressionStart(builder); if (expr == null) { startMarker.drop(); return null; } while (true) { final IElementType tokenType = builder.getTokenType(); if (tokenType == JavaTokenType.DOT) { final PsiBuilder.Marker dotPos = builder.mark(); final int dotOffset = builder.getCurrentOffset(); builder.advanceLexer(); IElementType dotTokenType = builder.getTokenType(); if (dotTokenType == JavaTokenType.AT) { myParser.getDeclarationParser().parseAnnotations(builder); dotTokenType = builder.getTokenType(); } if (dotTokenType == JavaTokenType.CLASS_KEYWORD && exprType(expr) == JavaElementType.REFERENCE_EXPRESSION) { if (breakPoint == BreakPoint.P1 && builder.getCurrentOffset() == breakOffset) { error(builder, JavaErrorMessages.message("expected.identifier")); PsiBuilderUtil.drop(startMarker, dotPos); return expr; } final PsiBuilder.Marker copy = startMarker.precede(); final int offset = builder.getCurrentOffset(); startMarker.rollbackTo(); final PsiBuilder.Marker classObjAccess = parseClassAccessOrMethodReference(builder); if (classObjAccess == null || builder.getCurrentOffset() < offset) { copy.rollbackTo(); return parsePrimary(builder, BreakPoint.P1, offset); } startMarker = copy; expr = classObjAccess; } else if (dotTokenType == JavaTokenType.NEW_KEYWORD) { dotPos.drop(); expr = parseNew(builder, expr); } else if (THIS_OR_SUPER.contains(dotTokenType) && exprType(expr) == JavaElementType.REFERENCE_EXPRESSION) { if (breakPoint == BreakPoint.P2 && builder.getCurrentOffset() == breakOffset) { dotPos.rollbackTo(); startMarker.drop(); return expr; } final PsiBuilder.Marker copy = startMarker.precede(); final int offset = builder.getCurrentOffset(); startMarker.rollbackTo(); final PsiBuilder.Marker ref = myParser .getReferenceParser() .parseJavaCodeReference(builder, false, true, false, false); if (ref == null || builder.getTokenType() != JavaTokenType.DOT || builder.getCurrentOffset() != dotOffset) { copy.rollbackTo(); return parsePrimary(builder, BreakPoint.P2, offset); } builder.advanceLexer(); if (builder.getTokenType() != dotTokenType) { copy.rollbackTo(); return parsePrimary(builder, BreakPoint.P2, offset); } builder.advanceLexer(); startMarker = copy; expr = ref.precede(); expr.done( dotTokenType == JavaTokenType.THIS_KEYWORD ? JavaElementType.THIS_EXPRESSION : JavaElementType.SUPER_EXPRESSION); } else if (dotTokenType == JavaTokenType.SUPER_KEYWORD) { dotPos.drop(); final PsiBuilder.Marker refExpr = expr.precede(); builder.advanceLexer(); refExpr.done(JavaElementType.REFERENCE_EXPRESSION); expr = refExpr; } else { dotPos.drop(); final PsiBuilder.Marker refExpr = expr.precede(); myParser.getReferenceParser().parseReferenceParameterList(builder, false, false); if (!expectOrError(builder, ID_OR_SUPER, "expected.identifier")) { refExpr.done(JavaElementType.REFERENCE_EXPRESSION); startMarker.drop(); return refExpr; } refExpr.done(JavaElementType.REFERENCE_EXPRESSION); expr = refExpr; } } else if (tokenType == JavaTokenType.LPARENTH) { if (exprType(expr) != JavaElementType.REFERENCE_EXPRESSION) { if (exprType(expr) == JavaElementType.SUPER_EXPRESSION) { if (breakPoint == BreakPoint.P3) { startMarker.drop(); return expr; } final PsiBuilder.Marker copy = startMarker.precede(); startMarker.rollbackTo(); final PsiBuilder.Marker qualifier = parsePrimaryExpressionStart(builder); if (qualifier != null) { final PsiBuilder.Marker refExpr = qualifier.precede(); if (builder.getTokenType() == JavaTokenType.DOT) { builder.advanceLexer(); if (builder.getTokenType() == JavaTokenType.SUPER_KEYWORD) { builder.advanceLexer(); refExpr.done(JavaElementType.REFERENCE_EXPRESSION); expr = refExpr; startMarker = copy; continue; } } } copy.rollbackTo(); return parsePrimary(builder, BreakPoint.P3, -1); } else { startMarker.drop(); return expr; } } final PsiBuilder.Marker callExpr = expr.precede(); parseArgumentList(builder); callExpr.done(JavaElementType.METHOD_CALL_EXPRESSION); expr = callExpr; } else if (tokenType == JavaTokenType.LBRACKET) { if (breakPoint == BreakPoint.P4) { startMarker.drop(); return expr; } builder.advanceLexer(); if (builder.getTokenType() == JavaTokenType.RBRACKET && exprType(expr) == JavaElementType.REFERENCE_EXPRESSION) { final int pos = builder.getCurrentOffset(); final PsiBuilder.Marker copy = startMarker.precede(); startMarker.rollbackTo(); final PsiBuilder.Marker classObjAccess = parseClassAccessOrMethodReference(builder); if (classObjAccess == null || builder.getCurrentOffset() <= pos) { copy.rollbackTo(); return parsePrimary(builder, BreakPoint.P4, -1); } startMarker = copy; expr = classObjAccess; } else { final PsiBuilder.Marker arrayAccess = expr.precede(); final PsiBuilder.Marker index = parse(builder); if (index == null) { error(builder, JavaErrorMessages.message("expected.expression")); arrayAccess.done(JavaElementType.ARRAY_ACCESS_EXPRESSION); startMarker.drop(); return arrayAccess; } if (builder.getTokenType() != JavaTokenType.RBRACKET) { error(builder, JavaErrorMessages.message("expected.rbracket")); arrayAccess.done(JavaElementType.ARRAY_ACCESS_EXPRESSION); startMarker.drop(); return arrayAccess; } builder.advanceLexer(); arrayAccess.done(JavaElementType.ARRAY_ACCESS_EXPRESSION); expr = arrayAccess; } } else if (tokenType == JavaTokenType.DOUBLE_COLON) { return parseMethodReference(builder, startMarker); } else { startMarker.drop(); return expr; } } }
public static boolean exitErrorRecordingSection( PsiBuilder builder_, int level, boolean result, boolean pinned, @NotNull String sectionType, @Nullable Parser eatMore) { ErrorState state = ErrorState.get(builder_); Frame frame = state.levelCheck.pollLast(); int initialOffset = builder_.getCurrentOffset(); if (frame == null || level != frame.level || !sectionType.equals(frame.section)) { LOG.error( "Unbalanced error section: got " + new Frame().init(initialOffset, level, sectionType, "", 0) + ", expected " + frame); if (frame != null) state.FRAMES.recycle(frame); return result; } if (sectionType == _SECTION_AND_ || sectionType == _SECTION_NOT_) { state.predicateCount--; if (sectionType == _SECTION_NOT_) state.predicateSign = !state.predicateSign; state.FRAMES.recycle(frame); return result; } if (!result && !pinned && initialOffset == frame.offset && state.lastExpectedVariantOffset == frame.offset && frame.name != null && state.variants.size() - frame.variantCount > 1) { state.clearVariants(true, frame.variantCount); addVariantInner(state, initialOffset, frame.name); } if (sectionType == _SECTION_RECOVER_ && !state.suppressErrors && eatMore != null) { state.suppressErrors = true; final boolean eatMoreFlagOnce = !builder_.eof() && eatMore.parse(builder_, frame.level + 1); final int lastErrorPos = getLastVariantOffset(state, initialOffset); boolean eatMoreFlag = eatMoreFlagOnce || frame.offset == initialOffset && lastErrorPos > frame.offset; final LighterASTNode latestDoneMarker = (pinned || result) && (state.altMode || lastErrorPos > initialOffset) && eatMoreFlagOnce ? builder_.getLatestDoneMarker() : null; PsiBuilder.Marker extensionMarker = null; IElementType extensionTokenType = null; if (latestDoneMarker instanceof PsiBuilder.Marker) { extensionMarker = ((PsiBuilder.Marker) latestDoneMarker).precede(); extensionTokenType = latestDoneMarker.getTokenType(); ((PsiBuilder.Marker) latestDoneMarker).drop(); } // advance to the last error pos // skip tokens until lastErrorPos. parseAsTree might look better here... int parenCount = 0; while (eatMoreFlag && builder_.getCurrentOffset() < lastErrorPos) { if (state.braces != null) { if (builder_.getTokenType() == state.braces[0].getLeftBraceType()) parenCount++; else if (builder_.getTokenType() == state.braces[0].getRightBraceType()) parenCount--; } builder_.advanceLexer(); eatMoreFlag = parenCount != 0 || eatMore.parse(builder_, frame.level + 1); } boolean errorReported = frame.errorReportedAt == initialOffset; if (errorReported) { if (eatMoreFlag) { builder_.advanceLexer(); parseAsTree(state, builder_, frame.level + 1, DUMMY_BLOCK, true, TOKEN_ADVANCER, eatMore); } } else if (eatMoreFlag) { String tokenText = builder_.getTokenText(); String expectedText = state.getExpectedText(builder_); PsiBuilder.Marker mark = builder_.mark(); builder_.advanceLexer(); final String gotText = !expectedText.isEmpty() ? "got '" + tokenText + "'" : "'" + tokenText + "' unexpected"; mark.error(expectedText + gotText); parseAsTree(state, builder_, frame.level + 1, DUMMY_BLOCK, true, TOKEN_ADVANCER, eatMore); errorReported = true; } else if (eatMoreFlagOnce || (!result && frame.offset != builder_.getCurrentOffset())) { reportError(state, builder_, true); errorReported = true; } if (extensionMarker != null) { extensionMarker.done(extensionTokenType); } state.suppressErrors = false; if (errorReported || result) { state.clearVariants(true, 0); state.clearVariants(false, 0); state.lastExpectedVariantOffset = -1; } if (!result && eatMoreFlagOnce && frame.offset != builder_.getCurrentOffset()) result = true; } else if (!result && pinned && frame.errorReportedAt < 0) { // do not report if there're errors after current offset if (getLastVariantOffset(state, initialOffset) == initialOffset) { // do not force, inner recoverRoot might have skipped some tokens if (reportError(state, builder_, false)) { frame.errorReportedAt = initialOffset; } } } // propagate errorReportedAt up the stack to avoid duplicate reporting Frame prevFrame = state.levelCheck.isEmpty() ? null : state.levelCheck.getLast(); if (prevFrame != null && prevFrame.errorReportedAt < frame.errorReportedAt) prevFrame.errorReportedAt = frame.errorReportedAt; state.FRAMES.recycle(frame); return result; }