use of groovy.lang.Tuple3 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 groovy.lang.Tuple3 in project groovy by apache.
the class AstBuilder method visitCreator.
// } primary ---------------------------------------------------------------
@Override
public Expression visitCreator(final CreatorContext ctx) {
ClassNode classNode = this.visitCreatedName(ctx.createdName());
if (asBoolean(ctx.arguments())) {
// create instance of class
Expression arguments = this.visitArguments(ctx.arguments());
Expression enclosingInstanceExpression = ctx.getNodeMetaData(ENCLOSING_INSTANCE_EXPRESSION);
if (enclosingInstanceExpression != null) {
if (arguments instanceof ArgumentListExpression) {
((ArgumentListExpression) arguments).getExpressions().add(0, enclosingInstanceExpression);
} else if (arguments instanceof TupleExpression) {
throw createParsingFailedException("Creating instance of non-static class does not support named parameters", arguments);
} else if (arguments instanceof NamedArgumentListExpression) {
throw createParsingFailedException("Unexpected arguments", arguments);
} else {
// should never reach here
throw createParsingFailedException("Unsupported arguments", arguments);
}
if (enclosingInstanceExpression instanceof ConstructorCallExpression && classNode.getName().indexOf('.') < 0) {
// GROOVY-8947
classNode.setName(enclosingInstanceExpression.getType().getName() + '.' + classNode.getName());
}
}
if (asBoolean(ctx.anonymousInnerClassDeclaration())) {
ctx.anonymousInnerClassDeclaration().putNodeMetaData(ANONYMOUS_INNER_CLASS_SUPER_CLASS, classNode);
InnerClassNode anonymousInnerClassNode = this.visitAnonymousInnerClassDeclaration(ctx.anonymousInnerClassDeclaration());
List<InnerClassNode> anonymousInnerClassList = anonymousInnerClassesDefinedInMethodStack.peek();
if (anonymousInnerClassList != null) {
// if the anonymous class is created in a script, no anonymousInnerClassList is available.
anonymousInnerClassList.add(anonymousInnerClassNode);
}
ConstructorCallExpression constructorCallExpression = new ConstructorCallExpression(anonymousInnerClassNode, arguments);
constructorCallExpression.setUsingAnonymousInnerClass(true);
return configureAST(constructorCallExpression, ctx);
}
return configureAST(new ConstructorCallExpression(classNode, arguments), ctx);
}
if (asBoolean(ctx.dim())) {
// create array
ArrayExpression arrayExpression;
List<Tuple3<Expression, List<AnnotationNode>, TerminalNode>> dimList = ctx.dim().stream().map(this::visitDim).collect(Collectors.toList());
TerminalNode invalidDimLBrack = null;
Boolean exprEmpty = null;
List<Tuple3<Expression, List<AnnotationNode>, TerminalNode>> emptyDimList = new LinkedList<>();
List<Tuple3<Expression, List<AnnotationNode>, TerminalNode>> dimWithExprList = new LinkedList<>();
Tuple3<Expression, List<AnnotationNode>, TerminalNode> latestDim = null;
for (Tuple3<Expression, List<AnnotationNode>, TerminalNode> dim : dimList) {
if (null == dim.getV1()) {
emptyDimList.add(dim);
exprEmpty = Boolean.TRUE;
} else {
if (Boolean.TRUE.equals(exprEmpty)) {
invalidDimLBrack = latestDim.getV3();
}
dimWithExprList.add(dim);
exprEmpty = Boolean.FALSE;
}
latestDim = dim;
}
if (asBoolean(ctx.arrayInitializer())) {
if (!dimWithExprList.isEmpty()) {
throw createParsingFailedException("dimension should be empty", dimWithExprList.get(0).getV3());
}
ClassNode elementType = classNode;
for (int i = 0, n = emptyDimList.size() - 1; i < n; i += 1) {
elementType = this.createArrayType(elementType);
}
arrayExpression = new ArrayExpression(elementType, this.visitArrayInitializer(ctx.arrayInitializer()));
} else {
if (null != invalidDimLBrack) {
throw createParsingFailedException("dimension cannot be empty", invalidDimLBrack);
}
if (dimWithExprList.isEmpty() && !emptyDimList.isEmpty()) {
throw createParsingFailedException("dimensions cannot be all empty", emptyDimList.get(0).getV3());
}
Expression[] empties;
if (asBoolean(emptyDimList)) {
empties = new Expression[emptyDimList.size()];
Arrays.fill(empties, ConstantExpression.EMPTY_EXPRESSION);
} else {
empties = Expression.EMPTY_ARRAY;
}
arrayExpression = new ArrayExpression(classNode, null, Stream.concat(dimWithExprList.stream().map(Tuple3::getV1), Arrays.stream(empties)).collect(Collectors.toList()));
}
arrayExpression.setType(this.createArrayType(classNode, dimList.stream().map(Tuple3::getV2).collect(Collectors.toList())));
return configureAST(arrayExpression, ctx);
}
throw createParsingFailedException("Unsupported creator: " + ctx.getText(), ctx);
}
use of groovy.lang.Tuple3 in project groovy by apache.
the class SAXBuilder method getNameInfo.
private Tuple3<String, String, String> getNameInfo(Object name) {
String uri;
String localName;
String qualifiedName;
if (name instanceof QName) {
QName qname = (QName) name;
uri = qname.getNamespaceURI();
localName = qname.getLocalPart();
qualifiedName = qname.getQualifiedName();
} else {
uri = "";
localName = name.toString();
qualifiedName = localName;
}
return new Tuple3<>(uri, localName, qualifiedName);
}
use of groovy.lang.Tuple3 in project groovy by apache.
the class AstBuilder method visitSwitchExpression.
/**
* <pre>
* switch(a) {
* case 0, 1 -> 'a';
* case 2 -> 'b';
* default -> 'z';
* }
* </pre>
* the above code will be transformed to:
* <pre>
* {->
* switch(a) {
* case 0:
* case 1: return 'a';
* case 2: return 'b';
* default: return 'z';
* }
* }()
* </pre>
*
* @param ctx the parse tree
* @return {@link MethodCallExpression} instance
*/
@Override
public MethodCallExpression visitSwitchExpression(SwitchExpressionContext ctx) {
switchExpressionRuleContextStack.push(ctx);
try {
validateSwitchExpressionLabels(ctx);
List<Tuple3<List<Statement>, Boolean, Boolean>> statementInfoList = ctx.switchBlockStatementExpressionGroup().stream().map(e -> this.visitSwitchBlockStatementExpressionGroup(e)).collect(Collectors.toList());
if (statementInfoList.isEmpty()) {
throw createParsingFailedException("`case` or `default` branches are expected", ctx.LBRACE());
}
Boolean isArrow = statementInfoList.get(0).getV2();
if (!isArrow && statementInfoList.stream().noneMatch(e -> {
Boolean hasYieldOrThrowStatement = e.getV3();
return hasYieldOrThrowStatement;
})) {
throw createParsingFailedException("`yield` or `throw` is expected", ctx);
}
List<Statement> statementList = statementInfoList.stream().map(e -> e.getV1()).reduce(new LinkedList<>(), (r, e) -> {
r.addAll(e);
return r;
});
List<CaseStatement> caseStatementList = new LinkedList<>();
List<Statement> defaultStatementList = new LinkedList<>();
statementList.forEach(e -> {
if (e instanceof CaseStatement) {
caseStatementList.add((CaseStatement) e);
} else if (isTrue(e, IS_SWITCH_DEFAULT)) {
defaultStatementList.add(e);
}
});
int defaultStatementListSize = defaultStatementList.size();
if (defaultStatementListSize > 1) {
throw createParsingFailedException("switch expression should have only one default case, which should appear at last", defaultStatementList.get(0));
}
if (defaultStatementListSize > 0 && last(statementList) instanceof CaseStatement) {
throw createParsingFailedException("default case should appear at last", defaultStatementList.get(0));
}
String variableName = "__$$sev" + switchExpressionVariableSeq++;
Statement declarationStatement = declS(localVarX(variableName), this.visitExpressionInPar(ctx.expressionInPar()));
SwitchStatement switchStatement = configureAST(new SwitchStatement(varX(variableName), caseStatementList, defaultStatementListSize == 0 ? EmptyStatement.INSTANCE : defaultStatementList.get(0)), ctx);
MethodCallExpression callClosure = callX(configureAST(closureX(null, createBlockStatement(declarationStatement, switchStatement)), ctx), "call");
callClosure.setImplicitThis(false);
return configureAST(callClosure, ctx);
} finally {
switchExpressionRuleContextStack.pop();
}
}
Aggregations