use of org.codehaus.groovy.ast.stmt.ReturnStatement in project groovy by apache.
the class ReturnAdder method adjustSwitchCaseCode.
private Statement adjustSwitchCaseCode(final Statement statement, final VariableScope scope, final boolean lastCase) {
if (!statement.isEmpty() && statement instanceof BlockStatement) {
BlockStatement block = (BlockStatement) statement;
int breakIndex = block.getStatements().size() - 1;
if (block.getStatements().get(breakIndex) instanceof BreakStatement) {
if (doAdd) {
Statement breakStatement = block.getStatements().remove(breakIndex);
if (breakIndex == 0)
block.addStatement(EmptyStatement.INSTANCE);
addReturnsIfNeeded(block, scope);
// GROOVY-9880: some code structures will fall through
Statement lastStatement = last(block.getStatements());
if (!(lastStatement instanceof ReturnStatement || lastStatement instanceof ThrowStatement)) {
block.addStatement(breakStatement);
}
} else {
addReturnsIfNeeded(new BlockStatement(block.getStatements().subList(0, breakIndex), null), scope);
}
} else if (lastCase) {
return addReturnsIfNeeded(statement, scope);
}
}
return statement;
}
use of org.codehaus.groovy.ast.stmt.ReturnStatement in project groovy by apache.
the class Verifier method addDefaultParameterMethods.
/**
* Creates a new method for each combination of default parameter expressions.
*/
protected void addDefaultParameterMethods(final ClassNode type) {
List<MethodNode> methods = new ArrayList<>(type.getMethods());
addDefaultParameters(methods, (arguments, params, method) -> {
BlockStatement code = new BlockStatement();
MethodNode newMethod = new MethodNode(method.getName(), method.getModifiers(), method.getReturnType(), params, method.getExceptions(), code);
MethodNode oldMethod = type.getDeclaredMethod(method.getName(), params);
if (oldMethod != null) {
throw new RuntimeParserException("The method with default parameters \"" + method.getTypeDescriptor() + "\" defines a method \"" + newMethod.getTypeDescriptor() + "\" that is already defined.", sourceOf(method));
}
List<AnnotationNode> annotations = method.getAnnotations();
if (annotations != null && !annotations.isEmpty()) {
newMethod.addAnnotations(annotations);
}
newMethod.setGenericsTypes(method.getGenericsTypes());
// GROOVY-5632, GROOVY-9151: check for references to parameters that have been removed
GroovyCodeVisitor visitor = new CodeVisitorSupport() {
private boolean inClosure;
@Override
public void visitClosureExpression(final ClosureExpression e) {
boolean prev = inClosure;
inClosure = true;
super.visitClosureExpression(e);
inClosure = prev;
}
@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)) {
VariableScope blockScope = code.getVariableScope();
VariableExpression localVariable = (VariableExpression) blockScope.getDeclaredVariable(p.getName());
if (localVariable == null) {
// create a variable declaration so that the name can be found in the new method
localVariable = localVarX(p.getName(), p.getType());
localVariable.setModifiers(p.getModifiers());
blockScope.putDeclaredVariable(localVariable);
localVariable.setInStaticContext(blockScope.isInStaticContext());
code.addStatement(declS(localVariable, p.getInitialExpression()));
}
if (!localVariable.isClosureSharedVariable()) {
localVariable.setClosureSharedVariable(inClosure);
}
}
}
}
};
visitor.visitArgumentlistExpression(arguments);
// if variable was created to capture an initial value expression, reference it in arguments as well
for (ListIterator<Expression> it = arguments.getExpressions().listIterator(); it.hasNext(); ) {
Expression argument = it.next();
if (argument instanceof CastExpression) {
argument = ((CastExpression) argument).getExpression();
}
for (Parameter p : method.getParameters()) {
if (p.hasInitialExpression() && p.getInitialExpression() == argument) {
if (code.getVariableScope().getDeclaredVariable(p.getName()) != null) {
it.set(varX(p.getName()));
}
break;
}
}
}
// delegate to original method using arguments derived from defaults
MethodCallExpression call = callThisX(method.getName(), arguments);
call.setMethodTarget(method);
call.setImplicitThis(true);
if (method.isVoidMethod()) {
code.addStatement(new ExpressionStatement(call));
} else {
code.addStatement(new ReturnStatement(call));
}
// GROOVY-5681: set anon. inner enclosing method reference
visitor = new CodeVisitorSupport() {
@Override
public void visitConstructorCallExpression(final ConstructorCallExpression call) {
if (call.isUsingAnonymousInnerClass()) {
call.getType().setEnclosingMethod(newMethod);
}
super.visitConstructorCallExpression(call);
}
};
visitor.visitBlockStatement(code);
addPropertyMethod(newMethod);
newMethod.putNodeMetaData(DEFAULT_PARAMETER_GENERATED, Boolean.TRUE);
});
}
use of org.codehaus.groovy.ast.stmt.ReturnStatement in project groovy by apache.
the class ExtendedVerifier method visitConstructorOrMethod.
private void visitConstructorOrMethod(MethodNode node, int methodTarget) {
visitAnnotations(node, methodTarget);
for (Parameter parameter : node.getParameters()) {
visitAnnotations(parameter, PARAMETER_TARGET);
visitTypeAnnotations(parameter.getType());
extractTypeUseAnnotations(parameter.getAnnotations(), parameter.getType(), PARAMETER_TARGET);
}
if (node.getExceptions() != null) {
for (ClassNode t : node.getExceptions()) {
visitTypeAnnotations(t);
}
}
if (this.currentClass.isAnnotationDefinition() && !node.isStaticConstructor()) {
ErrorCollector errorCollector = new ErrorCollector(this.source.getConfiguration());
AnnotationVisitor visitor = new AnnotationVisitor(this.source, errorCollector);
visitor.setReportClass(this.currentClass);
visitor.checkReturnType(node.getReturnType(), node);
if (node.getParameters().length > 0) {
addError("Annotation members may not have parameters.", node.getParameters()[0]);
}
if (node.getExceptions().length > 0) {
addError("Annotation members may not have a throws clause.", node.getExceptions()[0]);
}
ReturnStatement code = (ReturnStatement) node.getCode();
if (code != null) {
visitor.visitExpression(node.getName(), code.getExpression(), node.getReturnType());
visitor.checkCircularReference(this.currentClass, node.getReturnType(), code.getExpression());
}
this.source.getErrorCollector().addCollectorContents(errorCollector);
}
Statement code = node.getCode();
if (code != null) {
code.visit(this);
}
}
use of org.codehaus.groovy.ast.stmt.ReturnStatement in project groovy by apache.
the class EnumVisitor method addInit.
private void addInit(final ClassNode enumClass, final FieldNode minValue, final FieldNode maxValue, final FieldNode values, final boolean isAIC) {
// constructor helper
// This method is used instead of calling the constructor as
// calling the constructor may require a table with MetaClass
// selecting the constructor for each enum value. So instead we
// use this method to have a central point for constructor selection
// and only one table. The whole construction is needed because
// Reflection forbids access to the enum constructor.
// code:
// def $INIT(Object[] para) {
// return this(*para)
// }
ClassNode enumRef = enumClass.getPlainNodeReference();
Parameter[] parameter = new Parameter[] { new Parameter(ClassHelper.OBJECT_TYPE.makeArray(), "para") };
MethodNode initMethod = new MethodNode("$INIT", ACC_FINAL | ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC, enumRef, parameter, ClassNode.EMPTY_ARRAY, null);
initMethod.setSynthetic(true);
ConstructorCallExpression cce = new ConstructorCallExpression(ClassNode.THIS, new ArgumentListExpression(new SpreadExpression(new VariableExpression("para"))));
BlockStatement code = new BlockStatement();
code.addStatement(new ReturnStatement(cce));
initMethod.setCode(code);
addGeneratedMethod(enumClass, initMethod);
// static init
List<FieldNode> fields = enumClass.getFields();
List<Expression> arrayInit = new ArrayList<>();
int value = -1;
Token assign = Token.newSymbol(Types.ASSIGN, -1, -1);
List<Statement> block = new ArrayList<>();
FieldNode tempMin = null;
FieldNode tempMax = null;
for (FieldNode field : fields) {
if (!field.isEnum())
continue;
value += 1;
if (tempMin == null)
tempMin = field;
tempMax = field;
ClassNode enumBase = enumClass;
ArgumentListExpression args = new ArgumentListExpression();
args.addExpression(new ConstantExpression(field.getName()));
args.addExpression(new ConstantExpression(value));
if (field.getInitialExpression() == null) {
if (enumClass.isAbstract()) {
addError(field, "The enum constant " + field.getName() + " must override abstract methods from " + enumBase.getName() + ".");
continue;
}
} else {
ListExpression oldArgs = (ListExpression) field.getInitialExpression();
List<MapEntryExpression> savedMapEntries = new ArrayList<>();
for (Expression exp : oldArgs.getExpressions()) {
if (exp instanceof MapEntryExpression) {
savedMapEntries.add((MapEntryExpression) exp);
continue;
}
InnerClassNode inner = null;
if (exp instanceof ClassExpression) {
ClassExpression clazzExp = (ClassExpression) exp;
ClassNode ref = clazzExp.getType();
if (ref instanceof EnumConstantClassNode) {
inner = (InnerClassNode) ref;
}
}
if (inner != null) {
List<MethodNode> baseMethods = enumBase.getMethods();
for (MethodNode methodNode : baseMethods) {
if (!methodNode.isAbstract())
continue;
MethodNode enumConstMethod = inner.getMethod(methodNode.getName(), methodNode.getParameters());
if (enumConstMethod == null || enumConstMethod.isAbstract()) {
addError(field, "Can't have an abstract method in enum constant " + field.getName() + ". Implement method '" + methodNode.getTypeDescriptor() + "'.");
}
}
if (inner.getVariableScope() == null) {
enumBase = inner;
/*
* GROOVY-3985: Remove the final modifier from $INIT method in this case
* so that subclasses of enum generated for enum constants (aic) can provide
* their own $INIT method
*/
initMethod.setModifiers(initMethod.getModifiers() & ~ACC_FINAL);
continue;
}
}
args.addExpression(exp);
}
if (!savedMapEntries.isEmpty()) {
args.getExpressions().add(2, new MapExpression(savedMapEntries));
}
}
field.setInitialValueExpression(null);
block.add(new ExpressionStatement(new BinaryExpression(new FieldExpression(field), assign, new StaticMethodCallExpression(enumBase, "$INIT", args))));
arrayInit.add(new FieldExpression(field));
}
if (!isAIC) {
if (tempMin != null) {
block.add(new ExpressionStatement(new BinaryExpression(new FieldExpression(minValue), assign, new FieldExpression(tempMin))));
block.add(new ExpressionStatement(new BinaryExpression(new FieldExpression(maxValue), assign, new FieldExpression(tempMax))));
enumClass.addField(minValue);
enumClass.addField(maxValue);
}
block.add(new ExpressionStatement(new BinaryExpression(new FieldExpression(values), assign, new ArrayExpression(enumClass, arrayInit))));
enumClass.addField(values);
}
enumClass.addStaticInitializerStatements(block, true);
}
use of org.codehaus.groovy.ast.stmt.ReturnStatement in project groovy by apache.
the class EnumVisitor method addMethods.
private static void addMethods(final ClassNode enumClass, final FieldNode values) {
List<MethodNode> methods = enumClass.getMethods();
boolean hasNext = false;
boolean hasPrevious = false;
for (MethodNode m : methods) {
if (m.getName().equals("next") && m.getParameters().length == 0)
hasNext = true;
if (m.getName().equals("previous") && m.getParameters().length == 0)
hasPrevious = true;
if (hasNext && hasPrevious)
break;
}
ClassNode enumRef = enumClass.getPlainNodeReference();
{
// create values() method
MethodNode valuesMethod = new MethodNode("values", ACC_FINAL | ACC_PUBLIC | ACC_STATIC, enumRef.makeArray(), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, null);
valuesMethod.setSynthetic(true);
BlockStatement code = new BlockStatement();
MethodCallExpression cloneCall = new MethodCallExpression(new FieldExpression(values), "clone", MethodCallExpression.NO_ARGUMENTS);
cloneCall.setMethodTarget(values.getType().getMethod("clone", Parameter.EMPTY_ARRAY));
code.addStatement(new ReturnStatement(cloneCall));
valuesMethod.setCode(code);
addGeneratedMethod(enumClass, valuesMethod);
}
if (!hasNext) {
// create next() method, code:
// Day next() {
// int ordinal = ordinal().next()
// if (ordinal >= values().size()) ordinal = 0
// return values()[ordinal]
// }
Token assign = Token.newSymbol(Types.ASSIGN, -1, -1);
Token ge = Token.newSymbol(Types.COMPARE_GREATER_THAN_EQUAL, -1, -1);
MethodNode nextMethod = new MethodNode("next", ACC_PUBLIC, enumRef, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, null);
nextMethod.setSynthetic(true);
BlockStatement code = new BlockStatement();
BlockStatement ifStatement = new BlockStatement();
ifStatement.addStatement(new ExpressionStatement(new BinaryExpression(new VariableExpression("ordinal"), assign, new ConstantExpression(0))));
code.addStatement(new ExpressionStatement(new DeclarationExpression(localVarX("ordinal"), assign, new MethodCallExpression(new MethodCallExpression(VariableExpression.THIS_EXPRESSION, "ordinal", MethodCallExpression.NO_ARGUMENTS), "next", MethodCallExpression.NO_ARGUMENTS))));
code.addStatement(new IfStatement(new BooleanExpression(new BinaryExpression(new VariableExpression("ordinal"), ge, new MethodCallExpression(new FieldExpression(values), "size", MethodCallExpression.NO_ARGUMENTS))), ifStatement, EmptyStatement.INSTANCE));
code.addStatement(new ReturnStatement(new MethodCallExpression(new FieldExpression(values), "getAt", new VariableExpression("ordinal"))));
nextMethod.setCode(code);
addGeneratedMethod(enumClass, nextMethod);
}
if (!hasPrevious) {
// create previous() method, code:
// Day previous() {
// int ordinal = ordinal().previous()
// if (ordinal < 0) ordinal = values().size() - 1
// return values()[ordinal]
// }
Token assign = Token.newSymbol(Types.ASSIGN, -1, -1);
Token lt = Token.newSymbol(Types.COMPARE_LESS_THAN, -1, -1);
MethodNode prevMethod = new MethodNode("previous", ACC_PUBLIC, enumRef, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, null);
prevMethod.setSynthetic(true);
BlockStatement code = new BlockStatement();
BlockStatement ifStatement = new BlockStatement();
ifStatement.addStatement(new ExpressionStatement(new BinaryExpression(new VariableExpression("ordinal"), assign, new MethodCallExpression(new MethodCallExpression(new FieldExpression(values), "size", MethodCallExpression.NO_ARGUMENTS), "minus", new ConstantExpression(1)))));
code.addStatement(new ExpressionStatement(new DeclarationExpression(localVarX("ordinal"), assign, new MethodCallExpression(new MethodCallExpression(VariableExpression.THIS_EXPRESSION, "ordinal", MethodCallExpression.NO_ARGUMENTS), "previous", MethodCallExpression.NO_ARGUMENTS))));
code.addStatement(new IfStatement(new BooleanExpression(new BinaryExpression(new VariableExpression("ordinal"), lt, new ConstantExpression(0))), ifStatement, EmptyStatement.INSTANCE));
code.addStatement(new ReturnStatement(new MethodCallExpression(new FieldExpression(values), "getAt", new VariableExpression("ordinal"))));
prevMethod.setCode(code);
addGeneratedMethod(enumClass, prevMethod);
}
{
// create valueOf
Parameter stringParameter = new Parameter(ClassHelper.STRING_TYPE, "name");
MethodNode valueOfMethod = new MethodNode("valueOf", ACC_PUBLIC | ACC_STATIC, enumRef, new Parameter[] { stringParameter }, ClassNode.EMPTY_ARRAY, null);
ArgumentListExpression callArguments = new ArgumentListExpression();
callArguments.addExpression(new ClassExpression(enumClass));
callArguments.addExpression(new VariableExpression("name"));
BlockStatement code = new BlockStatement();
code.addStatement(new ReturnStatement(new MethodCallExpression(new ClassExpression(ClassHelper.Enum_Type), "valueOf", callArguments)));
valueOfMethod.setCode(code);
valueOfMethod.setSynthetic(true);
addGeneratedMethod(enumClass, valueOfMethod);
}
}
Aggregations