@NotNull public static PsiBuilder.Marker parseArgumentList(final PsiBuilder builder) { final PsiBuilder.Marker list = builder.mark(); builder.advanceLexer(); boolean first = true; while (true) { final IElementType tokenType = builder.getTokenType(); if (first && (ARGS_LIST_END.contains(tokenType) || builder.eof())) break; if (!first && !ARGS_LIST_CONTINUE.contains(tokenType)) break; boolean hasError = false; if (!first) { if (builder.getTokenType() == JavaTokenType.COMMA) { builder.advanceLexer(); } else { hasError = true; error(builder, JavaErrorMessages.message("expected.comma.or.rparen")); emptyExpression(builder); } } first = false; final PsiBuilder.Marker arg = parse(builder); if (arg == null) { if (!hasError) { error(builder, JavaErrorMessages.message("expected.expression")); emptyExpression(builder); } if (!ARGS_LIST_CONTINUE.contains(builder.getTokenType())) break; if (builder.getTokenType() != JavaTokenType.COMMA && !builder.eof()) { builder.advanceLexer(); } } } final boolean closed = JavaParserUtil.expectOrError( builder, JavaTokenType.RPARENTH, JavaErrorMessages.message("expected.rparen")); list.done(JavaElementType.EXPRESSION_LIST); if (!closed) { list.setCustomEdgeTokenBinders(null, GREEDY_RIGHT_EDGE_PROCESSOR); } return list; }
@NotNull private static PsiBuilder.Marker parseNew( final PsiBuilder builder, final PsiBuilder.Marker start) { final PsiBuilder.Marker newExpr = (start != null ? start.precede() : builder.mark()); builder.advanceLexer(); final boolean parseDiamonds = areDiamondsSupported(builder); ReferenceParser.parseReferenceParameterList(builder, false, parseDiamonds); final PsiBuilder.Marker refOrType; final boolean parseAnnotations = areTypeAnnotationsSupported(builder) && builder.getTokenType() == JavaTokenType.AT; final IElementType tokenType = builder.getTokenType(); if (tokenType == JavaTokenType.IDENTIFIER || parseAnnotations) { refOrType = ReferenceParser.parseJavaCodeReference( builder, true, true, parseAnnotations, true, parseDiamonds); if (refOrType == null) { error(builder, JavaErrorMessages.message("expected.identifier")); newExpr.done(JavaElementType.NEW_EXPRESSION); return newExpr; } } else if (ElementType.PRIMITIVE_TYPE_BIT_SET.contains(tokenType)) { refOrType = null; builder.advanceLexer(); } else { error(builder, JavaErrorMessages.message("expected.identifier")); newExpr.done(JavaElementType.NEW_EXPRESSION); return newExpr; } if (refOrType != null && builder.getTokenType() == JavaTokenType.LPARENTH) { parseArgumentList(builder); if (builder.getTokenType() == JavaTokenType.LBRACE) { final PsiBuilder.Marker classElement = refOrType.precede(); DeclarationParser.parseClassBodyWithBraces(builder, false, false); classElement.done(JavaElementType.ANONYMOUS_CLASS); } } else { if (builder.getTokenType() != JavaTokenType.LBRACKET) { error( builder, refOrType == null ? JavaErrorMessages.message("expected.lbracket") : JavaErrorMessages.message("expected.lparen.or.lbracket")); newExpr.done(JavaElementType.NEW_EXPRESSION); return newExpr; } int bracketCount = 0; int dimCount = 0; while (true) { if (builder.getTokenType() != JavaTokenType.LBRACKET) break; builder.advanceLexer(); if (bracketCount == dimCount) { final PsiBuilder.Marker dimExpr = parse(builder); if (dimExpr != null) { dimCount++; } } bracketCount++; if (!JavaParserUtil.expectOrError( builder, JavaTokenType.RBRACKET, JavaErrorMessages.message("expected.rbracket"))) { newExpr.done(JavaElementType.NEW_EXPRESSION); return newExpr; } } if (dimCount == 0) { if (builder.getTokenType() == JavaTokenType.LBRACE) { parseArrayInitializer(builder); } else { error(builder, JavaErrorMessages.message("expected.array.initializer")); } } } newExpr.done(JavaElementType.NEW_EXPRESSION); return newExpr; }
@Nullable private static PsiBuilder.Marker parsePrimary( final PsiBuilder builder, 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(); final IElementType 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 = parseClassObjectAccess(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 ((dotTokenType == JavaTokenType.THIS_KEYWORD || dotTokenType == JavaTokenType.SUPER_KEYWORD) && 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 = ReferenceParser.parseJavaCodeReference(builder, false, true, false, 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(); ReferenceParser.parseReferenceParameterList(builder, false, false); if (!JavaParserUtil.expectOrError( builder, JavaTokenType.IDENTIFIER, JavaErrorMessages.message("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 = parseClassObjectAccess(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 { startMarker.drop(); return expr; } } }