use of org.codehaus.groovy.ast.CodeVisitorSupport in project groovy by apache.
the class ClosureWriter method correctAccessedVariable.
private static void correctAccessedVariable(final InnerClassNode closureClass, ClosureExpression ce) {
CodeVisitorSupport visitor = new CodeVisitorSupport() {
@Override
public void visitVariableExpression(VariableExpression expression) {
Variable v = expression.getAccessedVariable();
if (v == null)
return;
if (!(v instanceof FieldNode))
return;
String name = expression.getName();
FieldNode fn = closureClass.getDeclaredField(name);
if (fn != null) {
// only overwrite if we find something more specific
expression.setAccessedVariable(fn);
}
}
};
visitor.visitClosureExpression(ce);
}
use of org.codehaus.groovy.ast.CodeVisitorSupport in project groovy-core by groovy.
the class ClosureWriter method correctAccessedVariable.
private void correctAccessedVariable(final InnerClassNode closureClass, ClosureExpression ce) {
CodeVisitorSupport visitor = new CodeVisitorSupport() {
@Override
public void visitVariableExpression(VariableExpression expression) {
Variable v = expression.getAccessedVariable();
if (v == null)
return;
if (!(v instanceof FieldNode))
return;
String name = expression.getName();
FieldNode fn = closureClass.getDeclaredField(name);
if (fn != null) {
// only overwrite if we find something more specific
expression.setAccessedVariable(fn);
}
}
};
visitor.visitClosureExpression(ce);
}
use of org.codehaus.groovy.ast.CodeVisitorSupport 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.codehaus.groovy.ast.CodeVisitorSupport in project groovy by apache.
the class Verifier method addConstructor.
protected void addConstructor(final Parameter[] newParams, final ConstructorNode ctor, final Statement code, final ClassNode type) {
ConstructorNode newConstructor = type.addConstructor(ctor.getModifiers(), newParams, ctor.getExceptions(), code);
newConstructor.putNodeMetaData(DEFAULT_PARAMETER_GENERATED, Boolean.TRUE);
markAsGenerated(type, newConstructor);
// TODO: Copy annotations, etc.?
// set anon. inner enclosing method reference
code.visit(new CodeVisitorSupport() {
@Override
public void visitConstructorCallExpression(final ConstructorCallExpression call) {
if (call.isUsingAnonymousInnerClass()) {
call.getType().setEnclosingMethod(newConstructor);
}
super.visitConstructorCallExpression(call);
}
});
}
use of org.codehaus.groovy.ast.CodeVisitorSupport in project groovy by apache.
the class Verifier method addDefaultParameterConstructors.
/**
* Creates a new constructor for each combination of default parameter expressions.
*/
protected void addDefaultParameterConstructors(final ClassNode type) {
List<ConstructorNode> constructors = new ArrayList<>(type.getDeclaredConstructors());
addDefaultParameters(constructors, (arguments, params, method) -> {
// GROOVY-9151: check for references to parameters that have been removed
for (ListIterator<Expression> it = arguments.getExpressions().listIterator(); it.hasNext(); ) {
Expression argument = it.next();
if (argument instanceof CastExpression) {
argument = ((CastExpression) argument).getExpression();
}
if (argument instanceof VariableExpression) {
VariableExpression v = (VariableExpression) argument;
if (v.getAccessedVariable() instanceof Parameter) {
Parameter p = (Parameter) v.getAccessedVariable();
if (p.hasInitialExpression() && !Arrays.asList(params).contains(p) && p.getInitialExpression() instanceof ConstantExpression) {
// replace argument "(Type) param" with "(Type) <param's default>" for simple default value
it.set(castX(method.getParameters()[it.nextIndex() - 1].getType(), p.getInitialExpression()));
}
}
}
}
GroovyCodeVisitor visitor = new CodeVisitorSupport() {
@Override
public void visitVariableExpression(final VariableExpression e) {
if (e.getAccessedVariable() instanceof Parameter) {
Parameter p = (Parameter) e.getAccessedVariable();
if (p.hasInitialExpression() && !Arrays.asList(params).contains(p)) {
String error = String.format("The generated constructor \"%s(%s)\" references parameter '%s' which has been replaced by a default value expression.", type.getNameWithoutPackage(), Arrays.stream(params).map(Parameter::getType).map(ClassNodeUtils::formatTypeName).collect(joining(",")), p.getName());
throw new RuntimeParserException(error, sourceOf(method));
}
}
}
};
visitor.visitArgumentlistExpression(arguments);
// delegate to original constructor using arguments derived from defaults
Statement code = new ExpressionStatement(new ConstructorCallExpression(ClassNode.THIS, arguments));
addConstructor(params, (ConstructorNode) method, code, type);
});
}
Aggregations