use of org.apache.groovy.parser.antlr4.GroovyLexer.THROW in project groovy by apache.
the class AstBuilder method visitSwitchBlockStatementExpressionGroup.
@Override
@SuppressWarnings("unchecked")
public Tuple3<List<Statement>, Boolean, Boolean> visitSwitchBlockStatementExpressionGroup(SwitchBlockStatementExpressionGroupContext ctx) {
int labelCnt = ctx.switchExpressionLabel().size();
List<Token> firstLabelHolder = new ArrayList<>(1);
final int[] arrowCntHolder = new int[1];
boolean[] isArrowHolder = new boolean[1];
boolean[] hasResultStmtHolder = new boolean[1];
List<Statement> result = (List<Statement>) ctx.switchExpressionLabel().stream().map(e -> (Object) this.visitSwitchExpressionLabel(e)).reduce(new ArrayList<Statement>(4), (r, e) -> {
List<Statement> statementList = (List<Statement>) r;
Tuple3<Token, List<Expression>, Integer> tuple = (Tuple3<Token, List<Expression>, Integer>) e;
boolean isArrow = ARROW == tuple.getV3();
isArrowHolder[0] = isArrow;
if (isArrow) {
if (++arrowCntHolder[0] > 1 && !firstLabelHolder.isEmpty()) {
throw createParsingFailedException("`case ... ->` does not support falling through cases", firstLabelHolder.get(0));
}
}
boolean isLast = labelCnt - 1 == statementList.size();
BlockStatement codeBlock = this.visitBlockStatements(ctx.blockStatements());
List<Statement> statements = codeBlock.getStatements();
int statementsCnt = statements.size();
if (0 == statementsCnt) {
throw createParsingFailedException("`yield` is expected", ctx.blockStatements());
}
if (isArrow && statementsCnt > 1) {
throw createParsingFailedException("Expect only 1 statement, but " + statementsCnt + " statements found", ctx.blockStatements());
}
if (!isArrow) {
boolean[] hasYieldHolder = new boolean[1];
boolean[] hasThrowHolder = new boolean[1];
codeBlock.visit(new CodeVisitorSupport() {
@Override
public void visitReturnStatement(ReturnStatement statement) {
if (isTrue(statement, IS_YIELD_STATEMENT)) {
hasYieldHolder[0] = true;
return;
}
super.visitReturnStatement(statement);
}
@Override
public void visitThrowStatement(ThrowStatement statement) {
hasThrowHolder[0] = true;
}
});
if (hasYieldHolder[0] || hasThrowHolder[0]) {
hasResultStmtHolder[0] = true;
}
}
Statement exprOrBlockStatement = statements.get(0);
if (exprOrBlockStatement instanceof BlockStatement) {
BlockStatement blockStatement = (BlockStatement) exprOrBlockStatement;
List<Statement> branchStatementList = blockStatement.getStatements();
if (1 == branchStatementList.size()) {
exprOrBlockStatement = branchStatementList.get(0);
}
}
if (!(exprOrBlockStatement instanceof ReturnStatement || exprOrBlockStatement instanceof ThrowStatement)) {
if (isArrow) {
MethodCallExpression callClosure = callX(configureAST(closureX(null, exprOrBlockStatement), exprOrBlockStatement), "call");
callClosure.setImplicitThis(false);
Expression resultExpr = exprOrBlockStatement instanceof ExpressionStatement ? ((ExpressionStatement) exprOrBlockStatement).getExpression() : callClosure;
codeBlock = configureAST(createBlockStatement(configureAST(returnS(resultExpr), exprOrBlockStatement)), exprOrBlockStatement);
}
}
switch(tuple.getV1().getType()) {
case CASE:
{
if (!asBoolean(statementList)) {
firstLabelHolder.add(tuple.getV1());
}
for (int i = 0, n = tuple.getV2().size(); i < n; i++) {
Expression expr = tuple.getV2().get(i);
statementList.add(configureAST(new CaseStatement(expr, // check whether processing the last label. if yes, block statement should be attached.
(isLast && i == n - 1) ? codeBlock : EmptyStatement.INSTANCE), firstLabelHolder.get(0)));
}
break;
}
case DEFAULT:
{
codeBlock.putNodeMetaData(IS_SWITCH_DEFAULT, true);
statementList.add(// this.configureAST(codeBlock, tuple.getKey())
codeBlock);
break;
}
}
return statementList;
});
return tuple(result, isArrowHolder[0], hasResultStmtHolder[0]);
}
use of org.apache.groovy.parser.antlr4.GroovyLexer.THROW in project groovy by apache.
the class AstBuilder method visitUnaryAddExprAlt.
@Override
public Expression visitUnaryAddExprAlt(final UnaryAddExprAltContext ctx) {
ExpressionContext expressionCtx = ctx.expression();
Expression expression = (Expression) this.visit(expressionCtx);
switch(ctx.op.getType()) {
case ADD:
{
if (isNonStringConstantOutsideParentheses(expression)) {
return configureAST(expression, ctx);
}
return configureAST(new UnaryPlusExpression(expression), ctx);
}
case SUB:
{
if (isNonStringConstantOutsideParentheses(expression)) {
ConstantExpression constantExpression = (ConstantExpression) expression;
try {
String integerLiteralText = constantExpression.getNodeMetaData(INTEGER_LITERAL_TEXT);
if (null != integerLiteralText) {
ConstantExpression result = new ConstantExpression(Numbers.parseInteger(SUB_STR + integerLiteralText));
// reset the numberFormatError
this.numberFormatError = null;
return configureAST(result, ctx);
}
String floatingPointLiteralText = constantExpression.getNodeMetaData(FLOATING_POINT_LITERAL_TEXT);
if (null != floatingPointLiteralText) {
ConstantExpression result = new ConstantExpression(Numbers.parseDecimal(SUB_STR + floatingPointLiteralText));
// reset the numberFormatError
this.numberFormatError = null;
return configureAST(result, ctx);
}
} catch (Exception e) {
throw createParsingFailedException(e.getMessage(), ctx);
}
throw new GroovyBugError("Failed to find the original number literal text: " + constantExpression.getText());
}
return configureAST(new UnaryMinusExpression(expression), ctx);
}
case INC:
case DEC:
return configureAST(new PrefixExpression(this.createGroovyToken(ctx.op), expression), ctx);
default:
throw createParsingFailedException("Unsupported unary operation: " + ctx.getText(), ctx);
}
}
use of org.apache.groovy.parser.antlr4.GroovyLexer.THROW in project groovy by apache.
the class SemanticPredicates method isFollowingArgumentsOrClosure.
/**
* Check whether following a method name of command expression.
* Method name should not end with "2: arguments" and "3: closure"
*
* @param context the preceding expression
*/
public static boolean isFollowingArgumentsOrClosure(ExpressionContext context) {
if (context instanceof PostfixExprAltContext) {
List<ParseTree> peacChildren = ((PostfixExprAltContext) context).children;
try {
ParseTree peacChild = peacChildren.get(0);
List<ParseTree> pecChildren = ((PostfixExpressionContext) peacChild).children;
ParseTree pecChild = pecChildren.get(0);
PathExpressionContext pec = (PathExpressionContext) pecChild;
int t = pec.t;
return (2 == t || 3 == t);
} catch (IndexOutOfBoundsException | ClassCastException e) {
throw new GroovyBugError("Unexpected structure of expression context: " + context, e);
}
}
return false;
}
use of org.apache.groovy.parser.antlr4.GroovyLexer.THROW in project groovy by apache.
the class AstBuilder method visitClassDeclaration.
@Override
public ClassNode visitClassDeclaration(final ClassDeclarationContext ctx) {
String packageName = Optional.ofNullable(moduleNode.getPackageName()).orElse("");
String className = this.visitIdentifier(ctx.identifier());
if (VAR_STR.equals(className)) {
throw createParsingFailedException("var cannot be used for type declarations", ctx.identifier());
}
boolean isAnnotation = asBoolean(ctx.AT());
if (isAnnotation) {
if (asBoolean(ctx.typeParameters())) {
throw createParsingFailedException("annotation declaration cannot have type parameters", ctx.typeParameters());
}
if (asBoolean(ctx.EXTENDS())) {
throw createParsingFailedException("No extends clause allowed for annotation declaration", ctx.EXTENDS());
}
if (asBoolean(ctx.IMPLEMENTS())) {
throw createParsingFailedException("No implements clause allowed for annotation declaration", ctx.IMPLEMENTS());
}
}
boolean isEnum = asBoolean(ctx.ENUM());
if (isEnum) {
if (asBoolean(ctx.typeParameters())) {
throw createParsingFailedException("enum declaration cannot have type parameters", ctx.typeParameters());
}
if (asBoolean(ctx.EXTENDS())) {
throw createParsingFailedException("No extends clause allowed for enum declaration", ctx.EXTENDS());
}
}
boolean isInterface = (asBoolean(ctx.INTERFACE()) && !isAnnotation);
if (isInterface) {
if (asBoolean(ctx.IMPLEMENTS())) {
throw createParsingFailedException("No implements clause allowed for interface declaration", ctx.IMPLEMENTS());
}
}
List<ModifierNode> modifierNodeList = ctx.getNodeMetaData(TYPE_DECLARATION_MODIFIERS);
Objects.requireNonNull(modifierNodeList, "modifierNodeList should not be null");
ModifierManager modifierManager = new ModifierManager(this, modifierNodeList);
Optional<ModifierNode> finalModifierNodeOptional = modifierManager.get(FINAL);
Optional<ModifierNode> sealedModifierNodeOptional = modifierManager.get(SEALED);
Optional<ModifierNode> nonSealedModifierNodeOptional = modifierManager.get(NON_SEALED);
boolean isFinal = finalModifierNodeOptional.isPresent();
boolean isSealed = sealedModifierNodeOptional.isPresent();
boolean isNonSealed = nonSealedModifierNodeOptional.isPresent();
boolean isRecord = asBoolean(ctx.RECORD());
boolean hasRecordHeader = asBoolean(ctx.formalParameters());
if (isRecord) {
if (asBoolean(ctx.EXTENDS())) {
throw createParsingFailedException("No extends clause allowed for record declaration", ctx.EXTENDS());
}
if (!hasRecordHeader) {
throw createParsingFailedException("header declaration of record is expected", ctx.identifier());
}
if (isSealed) {
throw createParsingFailedException("`sealed` is not allowed for record declaration", sealedModifierNodeOptional.get());
}
if (isNonSealed) {
throw createParsingFailedException("`non-sealed` is not allowed for record declaration", nonSealedModifierNodeOptional.get());
}
} else {
if (hasRecordHeader) {
throw createParsingFailedException("header declaration is only allowed for record declaration", ctx.formalParameters());
}
}
if (isSealed && isNonSealed) {
throw createParsingFailedException("type cannot be defined with both `sealed` and `non-sealed`", nonSealedModifierNodeOptional.get());
}
if (isFinal && (isSealed || isNonSealed)) {
throw createParsingFailedException("type cannot be defined with both " + (isSealed ? "`sealed`" : "`non-sealed`") + " and `final`", finalModifierNodeOptional.get());
}
if ((isAnnotation || isEnum) && (isSealed || isNonSealed)) {
ModifierNode mn = isSealed ? sealedModifierNodeOptional.get() : nonSealedModifierNodeOptional.get();
throw createParsingFailedException("modifier `" + mn.getText() + "` is not allowed for " + (isEnum ? "enum" : "annotation definition"), mn);
}
boolean hasPermits = asBoolean(ctx.PERMITS());
if (!isSealed && hasPermits) {
throw createParsingFailedException("only sealed type declarations should have `permits` clause", ctx);
}
int modifiers = modifierManager.getClassModifiersOpValue();
boolean syntheticPublic = ((modifiers & Opcodes.ACC_SYNTHETIC) != 0);
modifiers &= ~Opcodes.ACC_SYNTHETIC;
ClassNode classNode, outerClass = classNodeStack.peek();
if (isEnum) {
classNode = EnumHelper.makeEnumNode(asBoolean(outerClass) ? className : packageName + className, modifiers, null, outerClass);
} else if (asBoolean(outerClass)) {
if (outerClass.isInterface())
modifiers |= Opcodes.ACC_STATIC;
classNode = new InnerClassNode(outerClass, outerClass.getName() + "$" + className, modifiers, ClassHelper.OBJECT_TYPE.getPlainNodeReference());
} else {
classNode = new ClassNode(packageName + className, modifiers, ClassHelper.OBJECT_TYPE.getPlainNodeReference());
}
configureAST(classNode, ctx);
classNode.setSyntheticPublic(syntheticPublic);
classNode.setGenericsTypes(this.visitTypeParameters(ctx.typeParameters()));
boolean isInterfaceWithDefaultMethods = (isInterface && this.containsDefaultMethods(ctx));
if (isSealed) {
AnnotationNode sealedAnnotationNode = new AnnotationNode(ClassHelper.makeCached(Sealed.class));
if (asBoolean(ctx.ps)) {
ListExpression permittedSubclassesListExpression = listX(Arrays.stream(this.visitTypeList(ctx.ps)).map(ClassExpression::new).collect(Collectors.toList()));
sealedAnnotationNode.setMember("permittedSubclasses", permittedSubclassesListExpression);
configureAST(sealedAnnotationNode, ctx.PERMITS());
sealedAnnotationNode.setNodeMetaData("permits", true);
}
classNode.addAnnotation(sealedAnnotationNode);
} else if (isNonSealed) {
classNode.addAnnotation(new AnnotationNode(ClassHelper.makeCached(NonSealed.class)));
}
if (isInterfaceWithDefaultMethods || asBoolean(ctx.TRAIT())) {
classNode.addAnnotation(new AnnotationNode(ClassHelper.makeCached(Trait.class)));
}
if (isRecord) {
classNode.addAnnotation(new AnnotationNode(RECORD_TYPE_CLASS));
}
classNode.addAnnotations(modifierManager.getAnnotations());
if (isInterfaceWithDefaultMethods) {
classNode.putNodeMetaData(IS_INTERFACE_WITH_DEFAULT_METHODS, Boolean.TRUE);
}
classNode.putNodeMetaData(CLASS_NAME, className);
if (asBoolean(ctx.CLASS()) || asBoolean(ctx.TRAIT())) {
if (asBoolean(ctx.scs)) {
ClassNode[] scs = this.visitTypeList(ctx.scs);
if (scs.length > 1) {
throw createParsingFailedException("Cannot extend multiple classes", ctx.EXTENDS());
}
classNode.setSuperClass(scs[0]);
}
classNode.setInterfaces(this.visitTypeList(ctx.is));
this.initUsingGenerics(classNode);
} else if (isInterfaceWithDefaultMethods) {
// GROOVY-9259
classNode.setInterfaces(this.visitTypeList(ctx.scs));
this.initUsingGenerics(classNode);
} else if (isInterface) {
classNode.setModifiers(classNode.getModifiers() | Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT);
classNode.setInterfaces(this.visitTypeList(ctx.scs));
this.initUsingGenerics(classNode);
this.hackMixins(classNode);
} else if (isEnum || isRecord) {
classNode.setInterfaces(this.visitTypeList(ctx.is));
this.initUsingGenerics(classNode);
if (isRecord) {
transformRecordHeaderToProperties(ctx, classNode);
}
} else if (isAnnotation) {
classNode.setModifiers(classNode.getModifiers() | Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT | Opcodes.ACC_ANNOTATION);
classNode.addInterface(ClassHelper.Annotation_TYPE);
this.hackMixins(classNode);
} else {
throw createParsingFailedException("Unsupported class declaration: " + ctx.getText(), ctx);
}
// have here to ensure it won't be the inner class
if (asBoolean(ctx.CLASS()) || asBoolean(ctx.TRAIT())) {
classNodeList.add(classNode);
}
classNodeStack.push(classNode);
ctx.classBody().putNodeMetaData(CLASS_DECLARATION_CLASS_NODE, classNode);
this.visitClassBody(ctx.classBody());
if (isRecord) {
Optional<FieldNode> fieldNodeOptional = classNode.getFields().stream().filter(f -> !isTrue(f, IS_RECORD_GENERATED) && !f.isStatic()).findFirst();
if (fieldNodeOptional.isPresent()) {
createParsingFailedException("Instance field is not allowed in `record`", fieldNodeOptional.get());
}
}
classNodeStack.pop();
if (!(asBoolean(ctx.CLASS()) || asBoolean(ctx.TRAIT()))) {
classNodeList.add(classNode);
}
groovydocManager.handle(classNode, ctx);
return classNode;
}
use of org.apache.groovy.parser.antlr4.GroovyLexer.THROW in project groovy by apache.
the class AstBuilder method visitContinueStatement.
@Override
public ContinueStatement visitContinueStatement(final ContinueStatementContext ctx) {
if (visitingLoopStatementCount == 0) {
throw createParsingFailedException("continue statement is only allowed inside loops", ctx);
}
GroovyParserRuleContext gprc = switchExpressionRuleContextStack.peek();
if (gprc instanceof SwitchExpressionContext) {
throw createParsingFailedException("switch expression does not support `continue`", ctx);
}
String label = asBoolean(ctx.identifier()) ? this.visitIdentifier(ctx.identifier()) : null;
return configureAST(new ContinueStatement(label), ctx);
}
Aggregations