20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.tools.javac.parser;
27
28 import java.util.*;
29 import java.util.function.Function;
30 import java.util.function.Predicate;
31 import java.util.stream.Collectors;
32
33 import javax.lang.model.SourceVersion;
34
35 import com.sun.source.tree.CaseTree;
36 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
37 import com.sun.source.tree.ModuleTree.ModuleKind;
38
39 import com.sun.tools.javac.code.*;
40 import com.sun.tools.javac.code.Source.Feature;
41 import com.sun.tools.javac.file.PathFileObject;
42 import com.sun.tools.javac.parser.Tokens.*;
43 import com.sun.tools.javac.resources.CompilerProperties.Errors;
44 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
45 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
46 import com.sun.tools.javac.tree.*;
47 import com.sun.tools.javac.tree.JCTree.*;
48 import com.sun.tools.javac.util.*;
49 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
50 import com.sun.tools.javac.util.JCDiagnostic.Error;
51 import com.sun.tools.javac.util.JCDiagnostic.Fragment;
52 import com.sun.tools.javac.util.List;
53
54 import static com.sun.tools.javac.parser.Tokens.TokenKind.*;
55 import static com.sun.tools.javac.parser.Tokens.TokenKind.ASSERT;
56 import static com.sun.tools.javac.parser.Tokens.TokenKind.CASE;
57 import static com.sun.tools.javac.parser.Tokens.TokenKind.CATCH;
58 import static com.sun.tools.javac.parser.Tokens.TokenKind.EQ;
59 import static com.sun.tools.javac.parser.Tokens.TokenKind.GT;
60 import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT;
61 import static com.sun.tools.javac.parser.Tokens.TokenKind.LT;
62 import static com.sun.tools.javac.tree.JCTree.Tag.*;
63 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.ImplicitAndExplicitNotAllowed;
64 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndExplicitNotAllowed;
65 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndImplicitNotAllowed;
66 import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
67
68 /**
69 * The parser maps a token sequence into an abstract syntax tree.
70 * The parser is a hand-written recursive-descent parser that
71 * implements the grammar described in the Java Language Specification.
72 * For efficiency reasons, an operator precedence scheme is used
73 * for parsing binary operation expressions.
74 *
75 * <p><b>This is NOT part of any supported API.
76 * If you write code that depends on this, you do so at your own risk.
77 * This code and its internal interfaces are subject to change or
78 * deletion without notice.</b>
79 */
80 public class JavacParser implements Parser {
81
174 boolean keepLineMap,
175 boolean keepEndPositions,
176 boolean parseModuleInfo) {
177 this.S = S;
178 nextToken(); // prime the pump
179 this.F = fac.F;
180 this.log = fac.log;
181 this.names = fac.names;
182 this.source = fac.source;
183 this.preview = fac.preview;
184 this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true);
185 this.keepDocComments = keepDocComments;
186 this.parseModuleInfo = parseModuleInfo;
187 this.docComments = newDocCommentTable(keepDocComments, fac);
188 this.keepLineMap = keepLineMap;
189 this.errorTree = F.Erroneous();
190 this.endPosTable = newEndPosTable(keepEndPositions);
191 this.allowYieldStatement = Feature.SWITCH_EXPRESSION.allowedInSource(source);
192 this.allowRecords = Feature.RECORDS.allowedInSource(source);
193 this.allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
194 }
195
196 /** Construct a parser from an existing parser, with minimal overhead.
197 */
198 @SuppressWarnings("this-escape")
199 protected JavacParser(JavacParser parser,
200 Lexer S) {
201 this.S = S;
202 this.token = parser.token;
203 this.F = parser.F;
204 this.log = parser.log;
205 this.names = parser.names;
206 this.source = parser.source;
207 this.preview = parser.preview;
208 this.allowStringFolding = parser.allowStringFolding;
209 this.keepDocComments = parser.keepDocComments;
210 this.parseModuleInfo = false;
211 this.docComments = parser.docComments;
212 this.errorTree = F.Erroneous();
213 this.endPosTable = newEndPosTable(false);
214 this.allowYieldStatement = Feature.SWITCH_EXPRESSION.allowedInSource(source);
215 this.allowRecords = Feature.RECORDS.allowedInSource(source);
216 this.allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
217 }
218
219 protected AbstractEndPosTable newEndPosTable(boolean keepEndPositions) {
220 return keepEndPositions
221 ? new SimpleEndPosTable(this)
222 : new EmptyEndPosTable(this);
223 }
224
225 protected DocCommentTable newDocCommentTable(boolean keepDocComments, ParserFactory fac) {
226 return keepDocComments ? new LazyDocCommentTable(fac) : null;
227 }
228
229 /** Switch: should we fold strings?
230 */
231 boolean allowStringFolding;
232
233 /** Switch: should we keep docComments?
234 */
235 boolean keepDocComments;
236
237 /** Switch: should we keep line table?
238 */
239 boolean keepLineMap;
240
241 /** Switch: is "this" allowed as an identifier?
242 * This is needed to parse receiver types.
243 */
244 boolean allowThisIdent;
245
246 /** Switch: is yield statement allowed in this source level?
247 */
248 boolean allowYieldStatement;
249
250 /** Switch: are records allowed in this source level?
251 */
252 boolean allowRecords;
253
254 /** Switch: are sealed types allowed in this source level?
255 */
256 boolean allowSealedTypes;
257
258 /** The type of the method receiver, as specified by a first "this" parameter.
259 */
260 JCVariableDecl receiverParam;
261
262 /** When terms are parsed, the mode determines which is expected:
263 * mode = EXPR : an expression
264 * mode = TYPE : a type
265 * mode = NOPARAMS : no parameters allowed for type
266 * mode = TYPEARG : type argument
267 * mode |= NOLAMBDA : lambdas are not allowed
268 */
269 protected static final int EXPR = 1 << 0;
270 protected static final int TYPE = 1 << 1;
271 protected static final int NOPARAMS = 1 << 2;
272 protected static final int TYPEARG = 1 << 3;
273 protected static final int DIAMOND = 1 << 4;
1579 token.kind == MONKEYS_AT) {
1580 //error recovery, case like:
1581 //int i = expr.<missing-ident>
1582 //@Deprecated
1583 if (typeArgs != null) illegal();
1584 return toP(t);
1585 }
1586 if (tyannos != null && tyannos.nonEmpty()) {
1587 t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
1588 }
1589 break;
1590 case ELLIPSIS:
1591 if (this.permitTypeAnnotationsPushBack) {
1592 this.typeAnnotationsPushedBack = annos;
1593 } else if (annos.nonEmpty()) {
1594 // Don't return here -- error recovery attempt
1595 illegal(annos.head.pos);
1596 }
1597 break loop;
1598 case LT:
1599 if (!isMode(TYPE) && isUnboundMemberRef()) {
1600 //this is an unbound method reference whose qualifier
1601 //is a generic type i.e. A<S>::m
1602 int pos1 = token.pos;
1603 accept(LT);
1604 ListBuffer<JCExpression> args = new ListBuffer<>();
1605 args.append(typeArgument());
1606 while (token.kind == COMMA) {
1607 nextToken();
1608 args.append(typeArgument());
1609 }
1610 accept(GT);
1611 t = toP(F.at(pos1).TypeApply(t, args.toList()));
1612 while (token.kind == DOT) {
1613 nextToken();
1614 selectTypeMode();
1615 t = toP(F.at(token.pos).Select(t, ident()));
1616 t = typeArgumentsOpt(t);
1617 }
1618 t = bracketsOpt(t);
1619 if (token.kind != COLCOL) {
1620 //method reference expected here
1828 return illegal(annos.head.pos);
1829 }
1830 break;
1831 }
1832 }
1833 while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && isMode(EXPR)) {
1834 selectExprMode();
1835 t = to(F.at(token.pos).Unary(
1836 token.kind == PLUSPLUS ? POSTINC : POSTDEC, t));
1837 nextToken();
1838 }
1839 return toP(t);
1840 }
1841
1842 /**
1843 * If we see an identifier followed by a '<' it could be an unbound
1844 * method reference or a binary expression. To disambiguate, look for a
1845 * matching '>' and see if the subsequent terminal is either '.' or '::'.
1846 */
1847 @SuppressWarnings("fallthrough")
1848 boolean isUnboundMemberRef() {
1849 int pos = 0, depth = 0;
1850 outer: for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
1851 switch (t.kind) {
1852 case IDENTIFIER: case UNDERSCORE: case QUES: case EXTENDS: case SUPER:
1853 case DOT: case RBRACKET: case LBRACKET: case COMMA:
1854 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
1855 case DOUBLE: case BOOLEAN: case CHAR:
1856 case MONKEYS_AT:
1857 break;
1858
1859 case LPAREN:
1860 // skip annotation values
1861 int nesting = 0;
1862 for (; ; pos++) {
1863 TokenKind tk2 = S.token(pos).kind;
1864 switch (tk2) {
1865 case EOF:
1866 return false;
1867 case LPAREN:
1868 nesting++;
2497 List<JCExpression> typeArgs = null;
2498 if (token.kind == LT) {
2499 typeArgs = typeArguments(false);
2500 }
2501 Name refName;
2502 ReferenceMode refMode;
2503 if (token.kind == NEW) {
2504 refMode = ReferenceMode.NEW;
2505 refName = names.init;
2506 nextToken();
2507 } else {
2508 refMode = ReferenceMode.INVOKE;
2509 refName = ident();
2510 }
2511 return toP(F.at(t.getStartPosition()).Reference(refMode, refName, t, typeArgs));
2512 }
2513
2514 /** Creator = [Annotations] Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
2515 */
2516 JCExpression creator(int newpos, List<JCExpression> typeArgs) {
2517 List<JCAnnotation> newAnnotations = typeAnnotationsOpt();
2518
2519 switch (token.kind) {
2520 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
2521 case DOUBLE: case BOOLEAN:
2522 if (typeArgs == null) {
2523 if (newAnnotations.isEmpty()) {
2524 return arrayCreatorRest(newpos, basicType());
2525 } else {
2526 return arrayCreatorRest(newpos, toP(F.at(newAnnotations.head.pos).AnnotatedType(newAnnotations, basicType())));
2527 }
2528 }
2529 break;
2530 default:
2531 }
2532 JCExpression t = qualident(true);
2533
2534 int prevmode = mode;
2535 selectTypeMode();
2536 boolean diamondFound = false;
2537 int lastTypeargsPos = -1;
2538 if (token.kind == LT) {
2539 lastTypeargsPos = token.pos;
2540 t = typeArguments(t, true);
2541 diamondFound = isMode(DIAMOND);
2574 }
2575 else if (typeArgs != null) {
2576 int pos = newpos;
2577 if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) {
2578 // note: this should always happen but we should
2579 // not rely on this as the parser is continuously
2580 // modified to improve error recovery.
2581 pos = typeArgs.head.pos;
2582 }
2583 setErrorEndPos(S.prevToken().endPos);
2584 JCErroneous err = F.at(pos).Erroneous(typeArgs.prepend(e));
2585 reportSyntaxError(err, Errors.CannotCreateArrayWithTypeArguments);
2586 return toP(err);
2587 }
2588 return e;
2589 } else if (token.kind == LPAREN) {
2590 // handle type annotations for instantiations and anonymous classes
2591 if (newAnnotations.nonEmpty()) {
2592 t = insertAnnotationsToMostInner(t, newAnnotations, false);
2593 }
2594 return classCreatorRest(newpos, null, typeArgs, t);
2595 } else {
2596 setErrorEndPos(token.pos);
2597 reportSyntaxError(token.pos, Errors.Expected2(LPAREN, LBRACKET));
2598 t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.nil(), null));
2599 return toP(F.at(newpos).Erroneous(List.<JCTree>of(t)));
2600 }
2601 }
2602
2603 /** InnerCreator = [Annotations] Ident [TypeArguments] ClassCreatorRest
2604 */
2605 JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) {
2606 List<JCAnnotation> newAnnotations = typeAnnotationsOpt();
2607
2608 JCExpression t = toP(F.at(token.pos).Ident(ident()));
2609
2610 if (newAnnotations.nonEmpty()) {
2611 t = toP(F.at(newAnnotations.head.pos).AnnotatedType(newAnnotations, t));
2612 }
2613
2614 if (token.kind == LT) {
2615 int prevmode = mode;
2616 t = typeArguments(t, true);
2617 setMode(prevmode);
2618 }
2619 return classCreatorRest(newpos, encl, typeArgs, t);
2620 }
2621
2622 /** ArrayCreatorRest = [Annotations] "[" ( "]" BracketsOpt ArrayInitializer
2623 * | Expression "]" {[Annotations] "[" Expression "]"} BracketsOpt )
2624 */
2625 JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
2626 List<JCAnnotation> annos = typeAnnotationsOpt();
2627
2628 accept(LBRACKET);
2629 if (token.kind == RBRACKET) {
2630 accept(RBRACKET);
2631 elemtype = bracketsOpt(elemtype, annos);
2632 if (token.kind == LBRACE) {
2633 JCNewArray na = (JCNewArray)arrayInitializer(newpos, elemtype);
2634 if (annos.nonEmpty()) {
2635 // when an array initializer is present then
2636 // the parsed annotations should target the
2637 // new array tree
2638 // bracketsOpt inserts the annotation in
2639 // elemtype, and it needs to be corrected
2677 if (token.kind == LBRACE) {
2678 elems = arrayInitializerElements(newpos, elemtype);
2679 }
2680
2681 JCNewArray na = toP(F.at(newpos).NewArray(elemtype, dims.toList(), elems));
2682 na.dimAnnotations = dimAnnotations.toList();
2683
2684 if (elems != null) {
2685 return syntaxError(errpos, List.of(na), Errors.IllegalArrayCreationBothDimensionAndInitialization);
2686 }
2687
2688 return na;
2689 }
2690 }
2691
2692 /** ClassCreatorRest = Arguments [ClassBody]
2693 */
2694 JCNewClass classCreatorRest(int newpos,
2695 JCExpression encl,
2696 List<JCExpression> typeArgs,
2697 JCExpression t)
2698 {
2699 List<JCExpression> args = arguments();
2700 JCClassDecl body = null;
2701 if (token.kind == LBRACE) {
2702 int pos = token.pos;
2703 List<JCTree> defs = classInterfaceOrRecordBody(names.empty, false, false);
2704 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
2705 body = toP(F.at(pos).AnonymousClassDef(mods, defs));
2706 }
2707 return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body));
2708 }
2709
2710 /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}"
2711 */
2712 JCExpression arrayInitializer(int newpos, JCExpression t) {
2713 List<JCExpression> elems = arrayInitializerElements(newpos, t);
2714 return toP(F.at(newpos).NewArray(t, List.nil(), elems));
2715 }
2716
2717 List<JCExpression> arrayInitializerElements(int newpos, JCExpression t) {
2718 accept(LBRACE);
2719 ListBuffer<JCExpression> elems = new ListBuffer<>();
2720 if (token.kind == COMMA) {
2721 nextToken();
2722 } else if (token.kind != RBRACE) {
2723 elems.append(variableInitializer());
2724 while (token.kind == COMMA) {
2919 accept(SEMI);
2920 return List.of(toP(F.at(pos).Yield(t)));
2921 }
2922
2923 //else intentional fall-through
2924 } else {
2925 if (isNonSealedClassStart(true)) {
2926 log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
2927 nextToken();
2928 nextToken();
2929 nextToken();
2930 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
2931 } else if (isSealedClassStart(true)) {
2932 checkSourceLevel(Feature.SEALED_CLASSES);
2933 log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
2934 nextToken();
2935 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
2936 }
2937 }
2938 }
2939 if (isRecordStart() && allowRecords) {
2940 dc = token.docComment();
2941 return List.of(recordDeclaration(F.at(pos).Modifiers(0), dc));
2942 } else {
2943 Token prevToken = token;
2944 JCExpression t = term(EXPR | TYPE);
2945 if (token.kind == COLON && t.hasTag(IDENT)) {
2946 nextToken();
2947 JCStatement stat = parseStatementAsBlock();
2948 return List.of(F.at(pos).Labelled(prevToken.name(), stat));
2949 } else if (wasTypeMode() && LAX_IDENTIFIER.test(token.kind)) {
2950 pos = token.pos;
2951 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
2952 F.at(pos);
2953 return localVariableDeclarations(mods, t);
2954 } else {
2955 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
2956 t = checkExprStat(t);
2957 accept(SEMI);
2958 JCExpressionStatement expr = toP(F.at(pos).Exec(t));
3414 nextToken();
3415 pos = token.pos;
3416 JCExpression t = parseExpression();
3417 // This Exec is a "StatementExpression"; it subsumes no terminating token
3418 stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
3419 }
3420 return stats;
3421 }
3422
3423 /** ForInit = StatementExpression MoreStatementExpressions
3424 * | { FINAL | '@' Annotation } Type VariableDeclarators
3425 */
3426 List<JCStatement> forInit() {
3427 ListBuffer<JCStatement> stats = new ListBuffer<>();
3428 int pos = token.pos;
3429 if (token.kind == FINAL || token.kind == MONKEYS_AT) {
3430 return variableDeclarators(optFinal(0), parseType(true), stats, true).toList();
3431 } else {
3432 JCExpression t = term(EXPR | TYPE);
3433 if (wasTypeMode() && LAX_IDENTIFIER.test(token.kind)) {
3434 return variableDeclarators(modifiersOpt(), t, stats, true).toList();
3435 } else if (wasTypeMode() && token.kind == COLON) {
3436 log.error(DiagnosticFlag.SYNTAX, pos, Errors.BadInitializer("for-loop"));
3437 return List.of((JCStatement)F.at(pos).VarDef(modifiersOpt(), names.error, t, null));
3438 } else {
3439 return moreStatementExpressions(pos, t, stats).toList();
3440 }
3441 }
3442 }
3443
3444 /** ForUpdate = StatementExpression MoreStatementExpressions
3445 */
3446 List<JCExpressionStatement> forUpdate() {
3447 return moreStatementExpressions(token.pos,
3448 parseExpression(),
3449 new ListBuffer<JCExpressionStatement>()).toList();
3450 }
3451
3452 /** AnnotationsOpt = { '@' Annotation }
3453 *
3454 * @param kind Whether to parse an ANNOTATION or TYPE_ANNOTATION
3511 case ABSTRACT : flag = Flags.ABSTRACT; break;
3512 case NATIVE : flag = Flags.NATIVE; break;
3513 case VOLATILE : flag = Flags.VOLATILE; break;
3514 case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
3515 case STRICTFP : flag = Flags.STRICTFP; break;
3516 case MONKEYS_AT : flag = Flags.ANNOTATION; break;
3517 case DEFAULT : flag = Flags.DEFAULT; break;
3518 case ERROR : flag = 0; nextToken(); break;
3519 case IDENTIFIER : {
3520 if (isNonSealedClassStart(false)) {
3521 flag = Flags.NON_SEALED;
3522 nextToken();
3523 nextToken();
3524 break;
3525 }
3526 if (isSealedClassStart(false)) {
3527 checkSourceLevel(Feature.SEALED_CLASSES);
3528 flag = Flags.SEALED;
3529 break;
3530 }
3531 break loop;
3532 }
3533 default: break loop;
3534 }
3535 if ((flags & flag) != 0) log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.RepeatedModifier);
3536 lastPos = token.pos;
3537 nextToken();
3538 if (flag == Flags.ANNOTATION) {
3539 if (token.kind != INTERFACE) {
3540 JCAnnotation ann = annotation(lastPos, Tag.ANNOTATION);
3541 // if first modifier is an annotation, set pos to annotation's.
3542 if (flags == 0 && annotations.isEmpty())
3543 pos = ann.pos;
3544 annotations.append(ann);
3545 flag = 0;
3546 }
3547 }
3548 flags |= flag;
3549 }
3550 switch (token.kind) {
3777 if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source)) {
3778 return Source.JDK10;
3779 } else if (shouldWarn) {
3780 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK10));
3781 }
3782 }
3783 if (name == names.yield) {
3784 if (allowYieldStatement) {
3785 return Source.JDK14;
3786 } else if (shouldWarn) {
3787 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK14));
3788 }
3789 }
3790 if (name == names.record) {
3791 if (allowRecords) {
3792 return Source.JDK14;
3793 } else if (shouldWarn) {
3794 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK14));
3795 }
3796 }
3797 if (name == names.sealed) {
3798 if (allowSealedTypes) {
3799 return Source.JDK15;
3800 } else if (shouldWarn) {
3801 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3802 }
3803 }
3804 if (name == names.permits) {
3805 if (allowSealedTypes) {
3806 return Source.JDK15;
3807 } else if (shouldWarn) {
3808 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3809 }
3810 }
3811 return null;
3812 }
3813
3814 /** VariableDeclaratorId = Ident BracketsOpt
3815 */
3816 JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean catchParameter, boolean lambdaParameter, boolean recordComponent) {
4843 Token next = S.token(3);
4844 return allowedAfterSealedOrNonSealed(next, local, true);
4845 }
4846 return false;
4847 }
4848
4849 protected boolean isNonSealedIdentifier(Token someToken, int lookAheadOffset) {
4850 if (someToken.name() == names.non && peekToken(lookAheadOffset, TokenKind.SUB, TokenKind.IDENTIFIER)) {
4851 Token tokenSub = S.token(lookAheadOffset + 1);
4852 Token tokenSealed = S.token(lookAheadOffset + 2);
4853 if (someToken.endPos == tokenSub.pos &&
4854 tokenSub.endPos == tokenSealed.pos &&
4855 tokenSealed.name() == names.sealed) {
4856 checkSourceLevel(Feature.SEALED_CLASSES);
4857 return true;
4858 }
4859 }
4860 return false;
4861 }
4862
4863 protected boolean isSealedClassStart(boolean local) {
4864 if (token.name() == names.sealed) {
4865 Token next = S.token(1);
4866 if (allowedAfterSealedOrNonSealed(next, local, false)) {
4867 checkSourceLevel(Feature.SEALED_CLASSES);
4868 return true;
4869 }
4870 }
4871 return false;
4872 }
4873
4874 private boolean allowedAfterSealedOrNonSealed(Token next, boolean local, boolean currentIsNonSealed) {
4875 return local ?
4876 switch (next.kind) {
4877 case MONKEYS_AT -> {
4878 Token afterNext = S.token(2);
4879 yield afterNext.kind != INTERFACE || currentIsNonSealed;
4880 }
4881 case ABSTRACT, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
4882 default -> false;
4883 } :
4884 switch (next.kind) {
4885 case MONKEYS_AT -> {
4886 Token afterNext = S.token(2);
4887 yield afterNext.kind != INTERFACE || currentIsNonSealed;
4888 }
4889 case PUBLIC, PROTECTED, PRIVATE, ABSTRACT, STATIC, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
4890 case IDENTIFIER -> isNonSealedIdentifier(next, currentIsNonSealed ? 3 : 1) || next.name() == names.sealed;
4891 default -> false;
4892 };
4893 }
4894
4895 /** MethodDeclaratorRest =
4896 * FormalParameters BracketsOpt [THROWS TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
4897 * VoidMethodDeclaratorRest =
4898 * FormalParameters [THROWS TypeList] ( MethodBody | ";")
4899 * ConstructorDeclaratorRest =
4900 * "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
4901 */
4902 protected JCTree methodDeclaratorRest(int pos,
4903 JCModifiers mods,
4904 JCExpression type,
4905 Name name,
4906 List<JCTypeParameter> typarams,
4907 boolean isInterface, boolean isVoid,
4908 boolean isRecord,
4909 Comment dc) {
4910 if (isInterface) {
|
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.tools.javac.parser;
27
28 import java.util.*;
29 import java.util.function.Function;
30 import java.util.function.Predicate;
31 import java.util.stream.Collectors;
32
33 import javax.lang.model.SourceVersion;
34
35 import com.sun.source.tree.CaseTree;
36 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
37 import com.sun.source.tree.ModuleTree.ModuleKind;
38
39 import com.sun.tools.javac.code.*;
40 import com.sun.tools.javac.code.Flags.Flag;
41 import com.sun.tools.javac.code.Source.Feature;
42 import com.sun.tools.javac.file.PathFileObject;
43 import com.sun.tools.javac.parser.Tokens.*;
44 import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
45 import com.sun.tools.javac.resources.CompilerProperties.Errors;
46 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
47 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
48 import com.sun.tools.javac.tree.*;
49 import com.sun.tools.javac.tree.JCTree.*;
50 import com.sun.tools.javac.util.*;
51 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
52 import com.sun.tools.javac.util.JCDiagnostic.Error;
53 import com.sun.tools.javac.util.JCDiagnostic.Fragment;
54 import com.sun.tools.javac.util.List;
55
56 import static com.sun.tools.javac.code.Flags.asFlagSet;
57 import static com.sun.tools.javac.parser.Tokens.TokenKind.*;
58 import static com.sun.tools.javac.parser.Tokens.TokenKind.ASSERT;
59 import static com.sun.tools.javac.parser.Tokens.TokenKind.CASE;
60 import static com.sun.tools.javac.parser.Tokens.TokenKind.CATCH;
61 import static com.sun.tools.javac.parser.Tokens.TokenKind.EQ;
62 import static com.sun.tools.javac.parser.Tokens.TokenKind.GT;
63 import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT;
64 import static com.sun.tools.javac.parser.Tokens.TokenKind.LT;
65 import static com.sun.tools.javac.parser.Tokens.TokenKind.SYNCHRONIZED;
66 import static com.sun.tools.javac.tree.JCTree.Tag.*;
67 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.ImplicitAndExplicitNotAllowed;
68 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndExplicitNotAllowed;
69 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndImplicitNotAllowed;
70 import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
71
72 /**
73 * The parser maps a token sequence into an abstract syntax tree.
74 * The parser is a hand-written recursive-descent parser that
75 * implements the grammar described in the Java Language Specification.
76 * For efficiency reasons, an operator precedence scheme is used
77 * for parsing binary operation expressions.
78 *
79 * <p><b>This is NOT part of any supported API.
80 * If you write code that depends on this, you do so at your own risk.
81 * This code and its internal interfaces are subject to change or
82 * deletion without notice.</b>
83 */
84 public class JavacParser implements Parser {
85
178 boolean keepLineMap,
179 boolean keepEndPositions,
180 boolean parseModuleInfo) {
181 this.S = S;
182 nextToken(); // prime the pump
183 this.F = fac.F;
184 this.log = fac.log;
185 this.names = fac.names;
186 this.source = fac.source;
187 this.preview = fac.preview;
188 this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true);
189 this.keepDocComments = keepDocComments;
190 this.parseModuleInfo = parseModuleInfo;
191 this.docComments = newDocCommentTable(keepDocComments, fac);
192 this.keepLineMap = keepLineMap;
193 this.errorTree = F.Erroneous();
194 this.endPosTable = newEndPosTable(keepEndPositions);
195 this.allowYieldStatement = Feature.SWITCH_EXPRESSION.allowedInSource(source);
196 this.allowRecords = Feature.RECORDS.allowedInSource(source);
197 this.allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
198 this.allowValueClasses = (!preview.isPreview(Feature.VALUE_CLASSES) || preview.isEnabled()) &&
199 Feature.VALUE_CLASSES.allowedInSource(source);
200 }
201
202 /** Construct a parser from an existing parser, with minimal overhead.
203 */
204 @SuppressWarnings("this-escape")
205 protected JavacParser(JavacParser parser,
206 Lexer S) {
207 this.S = S;
208 this.token = parser.token;
209 this.F = parser.F;
210 this.log = parser.log;
211 this.names = parser.names;
212 this.source = parser.source;
213 this.preview = parser.preview;
214 this.allowStringFolding = parser.allowStringFolding;
215 this.keepDocComments = parser.keepDocComments;
216 this.parseModuleInfo = false;
217 this.docComments = parser.docComments;
218 this.errorTree = F.Erroneous();
219 this.endPosTable = newEndPosTable(false);
220 this.allowYieldStatement = Feature.SWITCH_EXPRESSION.allowedInSource(source);
221 this.allowRecords = Feature.RECORDS.allowedInSource(source);
222 this.allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
223 this.allowValueClasses = (!preview.isPreview(Feature.VALUE_CLASSES) || preview.isEnabled()) &&
224 Feature.VALUE_CLASSES.allowedInSource(source);
225 }
226
227 protected AbstractEndPosTable newEndPosTable(boolean keepEndPositions) {
228 return keepEndPositions
229 ? new SimpleEndPosTable(this)
230 : new EmptyEndPosTable(this);
231 }
232
233 protected DocCommentTable newDocCommentTable(boolean keepDocComments, ParserFactory fac) {
234 return keepDocComments ? new LazyDocCommentTable(fac) : null;
235 }
236
237 /** Switch: should we fold strings?
238 */
239 boolean allowStringFolding;
240
241 /** Switch: should we keep docComments?
242 */
243 boolean keepDocComments;
244
245 /** Switch: should we keep line table?
246 */
247 boolean keepLineMap;
248
249 /** Switch: is "this" allowed as an identifier?
250 * This is needed to parse receiver types.
251 */
252 boolean allowThisIdent;
253
254 /** Switch: is yield statement allowed in this source level?
255 */
256 boolean allowYieldStatement;
257
258 /** Switch: are records allowed in this source level?
259 */
260 boolean allowRecords;
261
262 /** Switch: are value classes allowed in this source level?
263 */
264 boolean allowValueClasses;
265
266 /** Switch: are sealed types allowed in this source level?
267 */
268 boolean allowSealedTypes;
269
270 /** The type of the method receiver, as specified by a first "this" parameter.
271 */
272 JCVariableDecl receiverParam;
273
274 /** When terms are parsed, the mode determines which is expected:
275 * mode = EXPR : an expression
276 * mode = TYPE : a type
277 * mode = NOPARAMS : no parameters allowed for type
278 * mode = TYPEARG : type argument
279 * mode |= NOLAMBDA : lambdas are not allowed
280 */
281 protected static final int EXPR = 1 << 0;
282 protected static final int TYPE = 1 << 1;
283 protected static final int NOPARAMS = 1 << 2;
284 protected static final int TYPEARG = 1 << 3;
285 protected static final int DIAMOND = 1 << 4;
1591 token.kind == MONKEYS_AT) {
1592 //error recovery, case like:
1593 //int i = expr.<missing-ident>
1594 //@Deprecated
1595 if (typeArgs != null) illegal();
1596 return toP(t);
1597 }
1598 if (tyannos != null && tyannos.nonEmpty()) {
1599 t = toP(F.at(tyannos.head.pos).AnnotatedType(tyannos, t));
1600 }
1601 break;
1602 case ELLIPSIS:
1603 if (this.permitTypeAnnotationsPushBack) {
1604 this.typeAnnotationsPushedBack = annos;
1605 } else if (annos.nonEmpty()) {
1606 // Don't return here -- error recovery attempt
1607 illegal(annos.head.pos);
1608 }
1609 break loop;
1610 case LT:
1611 if (!isMode(TYPE) && isParameterizedTypePrefix()) {
1612 //this is either an unbound method reference whose qualifier
1613 //is a generic type i.e. A<S>::m
1614 int pos1 = token.pos;
1615 accept(LT);
1616 ListBuffer<JCExpression> args = new ListBuffer<>();
1617 args.append(typeArgument());
1618 while (token.kind == COMMA) {
1619 nextToken();
1620 args.append(typeArgument());
1621 }
1622 accept(GT);
1623 t = toP(F.at(pos1).TypeApply(t, args.toList()));
1624 while (token.kind == DOT) {
1625 nextToken();
1626 selectTypeMode();
1627 t = toP(F.at(token.pos).Select(t, ident()));
1628 t = typeArgumentsOpt(t);
1629 }
1630 t = bracketsOpt(t);
1631 if (token.kind != COLCOL) {
1632 //method reference expected here
1840 return illegal(annos.head.pos);
1841 }
1842 break;
1843 }
1844 }
1845 while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && isMode(EXPR)) {
1846 selectExprMode();
1847 t = to(F.at(token.pos).Unary(
1848 token.kind == PLUSPLUS ? POSTINC : POSTDEC, t));
1849 nextToken();
1850 }
1851 return toP(t);
1852 }
1853
1854 /**
1855 * If we see an identifier followed by a '<' it could be an unbound
1856 * method reference or a binary expression. To disambiguate, look for a
1857 * matching '>' and see if the subsequent terminal is either '.' or '::'.
1858 */
1859 @SuppressWarnings("fallthrough")
1860 boolean isParameterizedTypePrefix() {
1861 int pos = 0, depth = 0;
1862 outer: for (Token t = S.token(pos) ; ; t = S.token(++pos)) {
1863 switch (t.kind) {
1864 case IDENTIFIER: case UNDERSCORE: case QUES: case EXTENDS: case SUPER:
1865 case DOT: case RBRACKET: case LBRACKET: case COMMA:
1866 case BYTE: case SHORT: case INT: case LONG: case FLOAT:
1867 case DOUBLE: case BOOLEAN: case CHAR:
1868 case MONKEYS_AT:
1869 break;
1870
1871 case LPAREN:
1872 // skip annotation values
1873 int nesting = 0;
1874 for (; ; pos++) {
1875 TokenKind tk2 = S.token(pos).kind;
1876 switch (tk2) {
1877 case EOF:
1878 return false;
1879 case LPAREN:
1880 nesting++;
2509 List<JCExpression> typeArgs = null;
2510 if (token.kind == LT) {
2511 typeArgs = typeArguments(false);
2512 }
2513 Name refName;
2514 ReferenceMode refMode;
2515 if (token.kind == NEW) {
2516 refMode = ReferenceMode.NEW;
2517 refName = names.init;
2518 nextToken();
2519 } else {
2520 refMode = ReferenceMode.INVOKE;
2521 refName = ident();
2522 }
2523 return toP(F.at(t.getStartPosition()).Reference(refMode, refName, t, typeArgs));
2524 }
2525
2526 /** Creator = [Annotations] Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
2527 */
2528 JCExpression creator(int newpos, List<JCExpression> typeArgs) {
2529 final JCModifiers mods = modifiersOpt();
2530 List<JCAnnotation> newAnnotations = mods.annotations;
2531 switch (token.kind) {
2532 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
2533 case DOUBLE: case BOOLEAN:
2534 if (mods.flags != 0) {
2535 log.error(token.pos, Errors.ModNotAllowedHere(asFlagSet(mods.flags)));
2536 }
2537 if (typeArgs == null) {
2538 if (newAnnotations.isEmpty()) {
2539 return arrayCreatorRest(newpos, basicType());
2540 } else {
2541 return arrayCreatorRest(newpos, toP(F.at(newAnnotations.head.pos).AnnotatedType(newAnnotations, basicType())));
2542 }
2543 }
2544 break;
2545 default:
2546 }
2547 JCExpression t = qualident(true);
2548
2549 int prevmode = mode;
2550 selectTypeMode();
2551 boolean diamondFound = false;
2552 int lastTypeargsPos = -1;
2553 if (token.kind == LT) {
2554 lastTypeargsPos = token.pos;
2555 t = typeArguments(t, true);
2556 diamondFound = isMode(DIAMOND);
2589 }
2590 else if (typeArgs != null) {
2591 int pos = newpos;
2592 if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) {
2593 // note: this should always happen but we should
2594 // not rely on this as the parser is continuously
2595 // modified to improve error recovery.
2596 pos = typeArgs.head.pos;
2597 }
2598 setErrorEndPos(S.prevToken().endPos);
2599 JCErroneous err = F.at(pos).Erroneous(typeArgs.prepend(e));
2600 reportSyntaxError(err, Errors.CannotCreateArrayWithTypeArguments);
2601 return toP(err);
2602 }
2603 return e;
2604 } else if (token.kind == LPAREN) {
2605 // handle type annotations for instantiations and anonymous classes
2606 if (newAnnotations.nonEmpty()) {
2607 t = insertAnnotationsToMostInner(t, newAnnotations, false);
2608 }
2609 JCNewClass newClass = classCreatorRest(newpos, null, typeArgs, t, mods.flags);
2610 if ((newClass.def == null) && (mods.flags != 0)) {
2611 log.error(newClass.pos, Errors.ModNotAllowedHere(asFlagSet(mods.flags)));
2612 }
2613 return newClass;
2614 } else {
2615 setErrorEndPos(token.pos);
2616 reportSyntaxError(token.pos, Errors.Expected2(LPAREN, LBRACKET));
2617 t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.nil(), null));
2618 return toP(F.at(newpos).Erroneous(List.<JCTree>of(t)));
2619 }
2620 }
2621
2622 /** InnerCreator = [Annotations] Ident [TypeArguments] ClassCreatorRest
2623 */
2624 JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) {
2625 List<JCAnnotation> newAnnotations = typeAnnotationsOpt();
2626
2627 JCExpression t = toP(F.at(token.pos).Ident(ident()));
2628
2629 if (newAnnotations.nonEmpty()) {
2630 t = toP(F.at(newAnnotations.head.pos).AnnotatedType(newAnnotations, t));
2631 }
2632
2633 if (token.kind == LT) {
2634 int prevmode = mode;
2635 t = typeArguments(t, true);
2636 setMode(prevmode);
2637 }
2638 return classCreatorRest(newpos, encl, typeArgs, t, 0);
2639 }
2640
2641 /** ArrayCreatorRest = [Annotations] "[" ( "]" BracketsOpt ArrayInitializer
2642 * | Expression "]" {[Annotations] "[" Expression "]"} BracketsOpt )
2643 */
2644 JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
2645 List<JCAnnotation> annos = typeAnnotationsOpt();
2646
2647 accept(LBRACKET);
2648 if (token.kind == RBRACKET) {
2649 accept(RBRACKET);
2650 elemtype = bracketsOpt(elemtype, annos);
2651 if (token.kind == LBRACE) {
2652 JCNewArray na = (JCNewArray)arrayInitializer(newpos, elemtype);
2653 if (annos.nonEmpty()) {
2654 // when an array initializer is present then
2655 // the parsed annotations should target the
2656 // new array tree
2657 // bracketsOpt inserts the annotation in
2658 // elemtype, and it needs to be corrected
2696 if (token.kind == LBRACE) {
2697 elems = arrayInitializerElements(newpos, elemtype);
2698 }
2699
2700 JCNewArray na = toP(F.at(newpos).NewArray(elemtype, dims.toList(), elems));
2701 na.dimAnnotations = dimAnnotations.toList();
2702
2703 if (elems != null) {
2704 return syntaxError(errpos, List.of(na), Errors.IllegalArrayCreationBothDimensionAndInitialization);
2705 }
2706
2707 return na;
2708 }
2709 }
2710
2711 /** ClassCreatorRest = Arguments [ClassBody]
2712 */
2713 JCNewClass classCreatorRest(int newpos,
2714 JCExpression encl,
2715 List<JCExpression> typeArgs,
2716 JCExpression t,
2717 long flags)
2718 {
2719 List<JCExpression> args = arguments();
2720 JCClassDecl body = null;
2721 if (token.kind == LBRACE) {
2722 int pos = token.pos;
2723 List<JCTree> defs = classInterfaceOrRecordBody(names.empty, false, false);
2724 JCModifiers mods = F.at(Position.NOPOS).Modifiers(flags);
2725 body = toP(F.at(pos).AnonymousClassDef(mods, defs));
2726 }
2727 return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body));
2728 }
2729
2730 /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}"
2731 */
2732 JCExpression arrayInitializer(int newpos, JCExpression t) {
2733 List<JCExpression> elems = arrayInitializerElements(newpos, t);
2734 return toP(F.at(newpos).NewArray(t, List.nil(), elems));
2735 }
2736
2737 List<JCExpression> arrayInitializerElements(int newpos, JCExpression t) {
2738 accept(LBRACE);
2739 ListBuffer<JCExpression> elems = new ListBuffer<>();
2740 if (token.kind == COMMA) {
2741 nextToken();
2742 } else if (token.kind != RBRACE) {
2743 elems.append(variableInitializer());
2744 while (token.kind == COMMA) {
2939 accept(SEMI);
2940 return List.of(toP(F.at(pos).Yield(t)));
2941 }
2942
2943 //else intentional fall-through
2944 } else {
2945 if (isNonSealedClassStart(true)) {
2946 log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
2947 nextToken();
2948 nextToken();
2949 nextToken();
2950 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
2951 } else if (isSealedClassStart(true)) {
2952 checkSourceLevel(Feature.SEALED_CLASSES);
2953 log.error(token.pos, Errors.SealedOrNonSealedLocalClassesNotAllowed);
2954 nextToken();
2955 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), token.docComment()));
2956 }
2957 }
2958 }
2959 if ((isValueModifier()) && allowValueClasses) {
2960 checkSourceLevel(Feature.VALUE_CLASSES);
2961 dc = token.docComment();
2962 return List.of(classOrRecordOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
2963 }
2964 if (isRecordStart() && allowRecords) {
2965 dc = token.docComment();
2966 return List.of(recordDeclaration(F.at(pos).Modifiers(0), dc));
2967 } else {
2968 Token prevToken = token;
2969 JCExpression t = term(EXPR | TYPE);
2970 if (token.kind == COLON && t.hasTag(IDENT)) {
2971 nextToken();
2972 JCStatement stat = parseStatementAsBlock();
2973 return List.of(F.at(pos).Labelled(prevToken.name(), stat));
2974 } else if (wasTypeMode() && LAX_IDENTIFIER.test(token.kind)) {
2975 pos = token.pos;
2976 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
2977 F.at(pos);
2978 return localVariableDeclarations(mods, t);
2979 } else {
2980 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
2981 t = checkExprStat(t);
2982 accept(SEMI);
2983 JCExpressionStatement expr = toP(F.at(pos).Exec(t));
3439 nextToken();
3440 pos = token.pos;
3441 JCExpression t = parseExpression();
3442 // This Exec is a "StatementExpression"; it subsumes no terminating token
3443 stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
3444 }
3445 return stats;
3446 }
3447
3448 /** ForInit = StatementExpression MoreStatementExpressions
3449 * | { FINAL | '@' Annotation } Type VariableDeclarators
3450 */
3451 List<JCStatement> forInit() {
3452 ListBuffer<JCStatement> stats = new ListBuffer<>();
3453 int pos = token.pos;
3454 if (token.kind == FINAL || token.kind == MONKEYS_AT) {
3455 return variableDeclarators(optFinal(0), parseType(true), stats, true).toList();
3456 } else {
3457 JCExpression t = term(EXPR | TYPE);
3458 if (wasTypeMode() && LAX_IDENTIFIER.test(token.kind)) {
3459 pos = token.pos;
3460 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
3461 F.at(pos);
3462 return variableDeclarators(mods, t, stats, true).toList();
3463 } else if (wasTypeMode() && token.kind == COLON) {
3464 log.error(DiagnosticFlag.SYNTAX, pos, Errors.BadInitializer("for-loop"));
3465 return List.of((JCStatement)F.at(pos).VarDef(modifiersOpt(), names.error, t, null));
3466 } else {
3467 return moreStatementExpressions(pos, t, stats).toList();
3468 }
3469 }
3470 }
3471
3472 /** ForUpdate = StatementExpression MoreStatementExpressions
3473 */
3474 List<JCExpressionStatement> forUpdate() {
3475 return moreStatementExpressions(token.pos,
3476 parseExpression(),
3477 new ListBuffer<JCExpressionStatement>()).toList();
3478 }
3479
3480 /** AnnotationsOpt = { '@' Annotation }
3481 *
3482 * @param kind Whether to parse an ANNOTATION or TYPE_ANNOTATION
3539 case ABSTRACT : flag = Flags.ABSTRACT; break;
3540 case NATIVE : flag = Flags.NATIVE; break;
3541 case VOLATILE : flag = Flags.VOLATILE; break;
3542 case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
3543 case STRICTFP : flag = Flags.STRICTFP; break;
3544 case MONKEYS_AT : flag = Flags.ANNOTATION; break;
3545 case DEFAULT : flag = Flags.DEFAULT; break;
3546 case ERROR : flag = 0; nextToken(); break;
3547 case IDENTIFIER : {
3548 if (isNonSealedClassStart(false)) {
3549 flag = Flags.NON_SEALED;
3550 nextToken();
3551 nextToken();
3552 break;
3553 }
3554 if (isSealedClassStart(false)) {
3555 checkSourceLevel(Feature.SEALED_CLASSES);
3556 flag = Flags.SEALED;
3557 break;
3558 }
3559 if (isValueModifier()) {
3560 checkSourceLevel(Feature.VALUE_CLASSES);
3561 flag = Flags.VALUE_CLASS;
3562 break;
3563 }
3564 break loop;
3565 }
3566 default: break loop;
3567 }
3568 if ((flags & flag) != 0) log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.RepeatedModifier);
3569 lastPos = token.pos;
3570 nextToken();
3571 if (flag == Flags.ANNOTATION) {
3572 if (token.kind != INTERFACE) {
3573 JCAnnotation ann = annotation(lastPos, Tag.ANNOTATION);
3574 // if first modifier is an annotation, set pos to annotation's.
3575 if (flags == 0 && annotations.isEmpty())
3576 pos = ann.pos;
3577 annotations.append(ann);
3578 flag = 0;
3579 }
3580 }
3581 flags |= flag;
3582 }
3583 switch (token.kind) {
3810 if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source)) {
3811 return Source.JDK10;
3812 } else if (shouldWarn) {
3813 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK10));
3814 }
3815 }
3816 if (name == names.yield) {
3817 if (allowYieldStatement) {
3818 return Source.JDK14;
3819 } else if (shouldWarn) {
3820 log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK14));
3821 }
3822 }
3823 if (name == names.record) {
3824 if (allowRecords) {
3825 return Source.JDK14;
3826 } else if (shouldWarn) {
3827 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK14));
3828 }
3829 }
3830 if (name == names.value) {
3831 if (allowValueClasses) {
3832 return Source.JDK23;
3833 } else if (shouldWarn) {
3834 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK23));
3835 }
3836 }
3837 if (name == names.sealed) {
3838 if (allowSealedTypes) {
3839 return Source.JDK15;
3840 } else if (shouldWarn) {
3841 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3842 }
3843 }
3844 if (name == names.permits) {
3845 if (allowSealedTypes) {
3846 return Source.JDK15;
3847 } else if (shouldWarn) {
3848 log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK15));
3849 }
3850 }
3851 return null;
3852 }
3853
3854 /** VariableDeclaratorId = Ident BracketsOpt
3855 */
3856 JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean catchParameter, boolean lambdaParameter, boolean recordComponent) {
4883 Token next = S.token(3);
4884 return allowedAfterSealedOrNonSealed(next, local, true);
4885 }
4886 return false;
4887 }
4888
4889 protected boolean isNonSealedIdentifier(Token someToken, int lookAheadOffset) {
4890 if (someToken.name() == names.non && peekToken(lookAheadOffset, TokenKind.SUB, TokenKind.IDENTIFIER)) {
4891 Token tokenSub = S.token(lookAheadOffset + 1);
4892 Token tokenSealed = S.token(lookAheadOffset + 2);
4893 if (someToken.endPos == tokenSub.pos &&
4894 tokenSub.endPos == tokenSealed.pos &&
4895 tokenSealed.name() == names.sealed) {
4896 checkSourceLevel(Feature.SEALED_CLASSES);
4897 return true;
4898 }
4899 }
4900 return false;
4901 }
4902
4903 protected boolean isValueModifier() {
4904 if (token.kind == IDENTIFIER && token.name() == names.value) {
4905 boolean isValueModifier = false;
4906 Token next = S.token(1);
4907 switch (next.kind) {
4908 case PRIVATE: case PROTECTED: case PUBLIC: case STATIC: case TRANSIENT:
4909 case FINAL: case ABSTRACT: case NATIVE: case VOLATILE: case SYNCHRONIZED:
4910 case STRICTFP: case MONKEYS_AT: case DEFAULT: case BYTE: case SHORT:
4911 case CHAR: case INT: case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
4912 case CLASS: case INTERFACE: case ENUM:
4913 isValueModifier = true;
4914 break;
4915 case IDENTIFIER: // value record R || value value || new value Comparable() {} ??
4916 if (next.name() == names.record || next.name() == names.value
4917 || (mode & EXPR) != 0)
4918 isValueModifier = true;
4919 break;
4920 }
4921 if (isValueModifier) {
4922 checkSourceLevel(Feature.VALUE_CLASSES);
4923 return true;
4924 }
4925 }
4926 return false;
4927 }
4928
4929 protected boolean isSealedClassStart(boolean local) {
4930 if (token.name() == names.sealed) {
4931 Token next = S.token(1);
4932 if (allowedAfterSealedOrNonSealed(next, local, false)) {
4933 checkSourceLevel(Feature.SEALED_CLASSES);
4934 return true;
4935 }
4936 }
4937 return false;
4938 }
4939
4940 private boolean allowedAfterSealedOrNonSealed(Token next, boolean local, boolean currentIsNonSealed) {
4941 return local ?
4942 switch (next.kind) {
4943 case MONKEYS_AT -> {
4944 Token afterNext = S.token(2);
4945 yield afterNext.kind != INTERFACE || currentIsNonSealed;
4946 }
4947 case ABSTRACT, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
4948 default -> false;
4949 } :
4950 switch (next.kind) {
4951 case MONKEYS_AT -> {
4952 Token afterNext = S.token(2);
4953 yield afterNext.kind != INTERFACE || currentIsNonSealed;
4954 }
4955 case PUBLIC, PROTECTED, PRIVATE, ABSTRACT, STATIC, FINAL, STRICTFP, CLASS, INTERFACE, ENUM -> true;
4956 case IDENTIFIER -> isNonSealedIdentifier(next, currentIsNonSealed ? 3 : 1) ||
4957 next.name() == names.sealed ||
4958 allowValueClasses && next.name() == names.value;
4959 default -> false;
4960 };
4961 }
4962
4963 /** MethodDeclaratorRest =
4964 * FormalParameters BracketsOpt [THROWS TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
4965 * VoidMethodDeclaratorRest =
4966 * FormalParameters [THROWS TypeList] ( MethodBody | ";")
4967 * ConstructorDeclaratorRest =
4968 * "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
4969 */
4970 protected JCTree methodDeclaratorRest(int pos,
4971 JCModifiers mods,
4972 JCExpression type,
4973 Name name,
4974 List<JCTypeParameter> typarams,
4975 boolean isInterface, boolean isVoid,
4976 boolean isRecord,
4977 Comment dc) {
4978 if (isInterface) {
|