use of org.codehaus.groovy.ast.expr.ListExpression in project groovy by apache.
the class AsmClassGenerator method visitListExpression.
@Override
public void visitListExpression(final ListExpression expression) {
onLineNumber(expression, "ListExpression");
int size = expression.getExpressions().size();
boolean containsSpreadExpression = containsSpreadExpression(expression);
boolean containsOnlyConstants = !containsSpreadExpression && containsOnlyConstants(expression);
OperandStack operandStack = controller.getOperandStack();
if (!containsSpreadExpression) {
MethodVisitor mv = controller.getMethodVisitor();
BytecodeHelper.pushConstant(mv, size);
mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
int maxInit = 1000;
if (size < maxInit || !containsOnlyConstants) {
for (int i = 0; i < size; i += 1) {
mv.visitInsn(DUP);
BytecodeHelper.pushConstant(mv, i);
expression.getExpression(i).visit(this);
operandStack.box();
mv.visitInsn(AASTORE);
}
operandStack.remove(size);
} else {
List<Expression> expressions = expression.getExpressions();
List<String> methods = new ArrayList<>();
MethodVisitor oldMv = mv;
int index = 0;
while (index < size) {
String methodName = "$createListEntry_" + controller.getNextHelperMethodIndex();
methods.add(methodName);
mv = controller.getClassVisitor().visitMethod(ACC_PRIVATE + ACC_STATIC + ACC_SYNTHETIC, methodName, "([Ljava/lang/Object;)V", null, null);
controller.setMethodVisitor(mv);
mv.visitCode();
int methodBlockSize = Math.min(size - index, maxInit);
int methodBlockEnd = index + methodBlockSize;
for (; index < methodBlockEnd; index += 1) {
mv.visitVarInsn(ALOAD, 0);
mv.visitLdcInsn(index);
expressions.get(index).visit(this);
operandStack.box();
mv.visitInsn(AASTORE);
}
operandStack.remove(methodBlockSize);
mv.visitInsn(RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
mv = oldMv;
controller.setMethodVisitor(mv);
for (String methodName : methods) {
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKESTATIC, controller.getInternalClassName(), methodName, "([Ljava/lang/Object;)V", false);
}
}
} else {
despreadList(expression.getExpressions(), false);
}
createListMethod.call(controller.getMethodVisitor());
operandStack.push(ClassHelper.LIST_TYPE);
}
use of org.codehaus.groovy.ast.expr.ListExpression in project groovy by apache.
the class ExtendedVerifier method processDuplicateAnnotationContainers.
private void processDuplicateAnnotationContainers(AnnotatedNode node, Map<String, List<AnnotationNode>> nonSourceAnnotations) {
for (Map.Entry<String, List<AnnotationNode>> next : nonSourceAnnotations.entrySet()) {
if (next.getValue().size() > 1) {
ClassNode repeatable = null;
AnnotationNode repeatee = next.getValue().get(0);
for (AnnotationNode anno : repeatee.getClassNode().getAnnotations()) {
if (anno.getClassNode().getName().equals("java.lang.annotation.Repeatable")) {
Expression value = anno.getMember("value");
if (value instanceof ClassExpression && value.getType().isAnnotationDefinition()) {
repeatable = value.getType();
break;
}
}
}
if (repeatable != null) {
if (nonSourceAnnotations.containsKey(repeatable.getName())) {
addError("Cannot specify duplicate annotation on the same member. Explicit " + repeatable.getName() + " found when creating implicit container for " + next.getKey(), node);
}
AnnotationNode collector = new AnnotationNode(repeatable);
if (repeatee.hasRuntimeRetention()) {
collector.setRuntimeRetention(true);
} else if (repeatable.isResolved()) {
Class<?> repeatableType = repeatable.getTypeClass();
Retention retention = repeatableType.getAnnotation(Retention.class);
collector.setRuntimeRetention(retention != null && retention.value().equals(RetentionPolicy.RUNTIME));
} else {
for (AnnotationNode annotation : repeatable.getAnnotations()) {
if (annotation.getClassNode().getName().equals("java.lang.annotation.Retention")) {
Expression value = annotation.getMember("value");
assert value != null;
Object retention = evaluateExpression(value, source.getConfiguration());
collector.setRuntimeRetention(retention != null && retention.toString().equals("RUNTIME"));
break;
}
}
}
collector.addMember("value", new ListExpression(next.getValue().stream().map(AnnotationConstantExpression::new).collect(Collectors.toList())));
node.getAnnotations().removeAll(next.getValue());
node.addAnnotation(collector);
}
}
}
}
use of org.codehaus.groovy.ast.expr.ListExpression 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.expr.ListExpression in project groovy by apache.
the class Java8 method configureAnnotationNodeFromDefinition.
@Override
public void configureAnnotationNodeFromDefinition(final AnnotationNode definition, final AnnotationNode root) {
ClassNode type = definition.getClassNode();
final String typeName = type.getName();
if ("java.lang.annotation.Retention".equals(typeName)) {
Expression exp = definition.getMember("value");
if (!(exp instanceof PropertyExpression))
return;
PropertyExpression pe = (PropertyExpression) exp;
String name = pe.getPropertyAsString();
RetentionPolicy policy = RetentionPolicy.valueOf(name);
setRetentionPolicy(policy, root);
} else if ("java.lang.annotation.Target".equals(typeName)) {
Expression exp = definition.getMember("value");
if (!(exp instanceof ListExpression))
return;
ListExpression le = (ListExpression) exp;
int bitmap = 0;
for (Expression e : le.getExpressions()) {
if (!(e instanceof PropertyExpression))
return;
PropertyExpression element = (PropertyExpression) e;
String name = element.getPropertyAsString();
ElementType value = ElementType.valueOf(name);
bitmap |= getElementCode(value);
}
root.setAllowedTargets(bitmap);
}
}
use of org.codehaus.groovy.ast.expr.ListExpression in project groovy by apache.
the class AstBuilder method visitPathElement.
@Override
public Expression visitPathElement(final PathElementContext ctx) {
Expression baseExpr = ctx.getNodeMetaData(PATH_EXPRESSION_BASE_EXPR);
Objects.requireNonNull(baseExpr, "baseExpr is required!");
if (asBoolean(ctx.namePart())) {
Expression namePartExpr = this.visitNamePart(ctx.namePart());
GenericsType[] genericsTypes = this.visitNonWildcardTypeArguments(ctx.nonWildcardTypeArguments());
if (asBoolean(ctx.DOT())) {
boolean isSafeChain = this.isTrue(baseExpr, PATH_EXPRESSION_BASE_EXPR_SAFE_CHAIN);
return this.createDotExpression(ctx, baseExpr, namePartExpr, genericsTypes, isSafeChain);
} else if (asBoolean(ctx.SAFE_DOT())) {
return this.createDotExpression(ctx, baseExpr, namePartExpr, genericsTypes, true);
} else if (asBoolean(ctx.SAFE_CHAIN_DOT())) {
// e.g. obj??.a OR obj??.@a
Expression expression = createDotExpression(ctx, baseExpr, namePartExpr, genericsTypes, true);
expression.putNodeMetaData(PATH_EXPRESSION_BASE_EXPR_SAFE_CHAIN, true);
return expression;
} else if (asBoolean(ctx.METHOD_POINTER())) {
// e.g. obj.&m
return configureAST(new MethodPointerExpression(baseExpr, namePartExpr), ctx);
} else if (asBoolean(ctx.METHOD_REFERENCE())) {
// e.g. obj::m
return configureAST(new MethodReferenceExpression(baseExpr, namePartExpr), ctx);
} else if (asBoolean(ctx.SPREAD_DOT())) {
if (asBoolean(ctx.AT())) {
// e.g. obj*.@a
AttributeExpression attributeExpression = new AttributeExpression(baseExpr, namePartExpr, true);
attributeExpression.setSpreadSafe(true);
return configureAST(attributeExpression, ctx);
} else {
// e.g. obj*.p
PropertyExpression propertyExpression = new PropertyExpression(baseExpr, namePartExpr, true);
propertyExpression.putNodeMetaData(PATH_EXPRESSION_BASE_EXPR_GENERICS_TYPES, genericsTypes);
propertyExpression.setSpreadSafe(true);
return configureAST(propertyExpression, ctx);
}
}
} else if (asBoolean(ctx.creator())) {
CreatorContext creatorContext = ctx.creator();
creatorContext.putNodeMetaData(ENCLOSING_INSTANCE_EXPRESSION, baseExpr);
return configureAST(this.visitCreator(creatorContext), ctx);
} else if (asBoolean(ctx.indexPropertyArgs())) {
// e.g. list[1, 3, 5]
Tuple2<Token, Expression> tuple = this.visitIndexPropertyArgs(ctx.indexPropertyArgs());
boolean isSafeChain = this.isTrue(baseExpr, PATH_EXPRESSION_BASE_EXPR_SAFE_CHAIN);
return configureAST(new BinaryExpression(baseExpr, createGroovyToken(tuple.getV1()), tuple.getV2(), isSafeChain || asBoolean(ctx.indexPropertyArgs().SAFE_INDEX())), ctx);
} else if (asBoolean(ctx.namedPropertyArgs())) {
// this is a special way to signify a cast, e.g. Person[name: 'Daniel.Sun', location: 'Shanghai']
List<MapEntryExpression> mapEntryExpressionList = this.visitNamedPropertyArgs(ctx.namedPropertyArgs());
Expression right;
Expression firstKeyExpression;
int mapEntryExpressionListSize = mapEntryExpressionList.size();
if (mapEntryExpressionListSize == 0) {
// expecting list of MapEntryExpressions later so use SpreadMap to smuggle empty MapExpression to later stages
right = configureAST(new SpreadMapExpression(configureAST(new MapExpression(), ctx.namedPropertyArgs())), ctx.namedPropertyArgs());
} else if (mapEntryExpressionListSize == 1 && (firstKeyExpression = mapEntryExpressionList.get(0).getKeyExpression()) instanceof SpreadMapExpression) {
right = firstKeyExpression;
} else {
ListExpression listExpression = configureAST(new ListExpression(mapEntryExpressionList.stream().map(e -> {
if (e.getKeyExpression() instanceof SpreadMapExpression) {
return e.getKeyExpression();
}
return e;
}).collect(Collectors.toList())), ctx.namedPropertyArgs());
listExpression.setWrapped(true);
right = listExpression;
}
NamedPropertyArgsContext namedPropertyArgsContext = ctx.namedPropertyArgs();
Token token = (namedPropertyArgsContext.LBRACK() == null ? namedPropertyArgsContext.SAFE_INDEX() : namedPropertyArgsContext.LBRACK()).getSymbol();
return configureAST(new BinaryExpression(baseExpr, createGroovyToken(token), right), ctx);
} else if (asBoolean(ctx.arguments())) {
Expression argumentsExpr = this.visitArguments(ctx.arguments());
configureAST(argumentsExpr, ctx);
if (isInsideParentheses(baseExpr)) {
// e.g. (obj.x)(), (obj.@x)()
return configureAST(createCallMethodCallExpression(baseExpr, argumentsExpr), ctx);
}
if (baseExpr instanceof AttributeExpression) {
// e.g. obj.@a(1, 2)
AttributeExpression attributeExpression = (AttributeExpression) baseExpr;
// whether attributeExpression is spread safe or not, we must reset it as false
attributeExpression.setSpreadSafe(false);
return configureAST(createCallMethodCallExpression(attributeExpression, argumentsExpr, true), ctx);
}
if (baseExpr instanceof PropertyExpression) {
// e.g. obj.a(1, 2)
MethodCallExpression methodCallExpression = this.createMethodCallExpression((PropertyExpression) baseExpr, argumentsExpr);
return configureAST(methodCallExpression, ctx);
}
if (baseExpr instanceof VariableExpression) {
// void and primitive type AST node must be an instance of VariableExpression
String baseExprText = baseExpr.getText();
if (VOID_STR.equals(baseExprText)) {
// e.g. void()
return configureAST(this.createCallMethodCallExpression(this.createConstantExpression(baseExpr), argumentsExpr), ctx);
} else if (isPrimitiveType(baseExprText)) {
// e.g. int(), long(), float(), etc.
throw this.createParsingFailedException("Primitive type literal: " + baseExprText + " cannot be used as a method name", ctx);
}
}
if (// e.g. m()
baseExpr instanceof VariableExpression || // e.g. "$m"()
baseExpr instanceof GStringExpression || (baseExpr instanceof ConstantExpression && this.isTrue(baseExpr, IS_STRING))) {
// e.g. "m"()
String baseExprText = baseExpr.getText();
if (THIS_STR.equals(baseExprText) || SUPER_STR.equals(baseExprText)) {
// @MapConstructor(pre={ super(args?.first, args?.last); args = args ?: [:] }, post = { first = first?.toUpperCase() })
if (visitingClosureCount > 0) {
return configureAST(new MethodCallExpression(baseExpr, baseExprText, argumentsExpr), ctx);
}
return configureAST(new ConstructorCallExpression(SUPER_STR.equals(baseExprText) ? ClassNode.SUPER : ClassNode.THIS, argumentsExpr), ctx);
}
MethodCallExpression methodCallExpression = this.createMethodCallExpression(baseExpr, argumentsExpr);
return configureAST(methodCallExpression, ctx);
}
// e.g. 1(), 1.1(), ((int) 1 / 2)(1, 2), {a, b -> a + b }(1, 2), m()()
return configureAST(this.createCallMethodCallExpression(baseExpr, argumentsExpr), ctx);
} else if (asBoolean(ctx.closureOrLambdaExpression())) {
ClosureExpression closureExpression = this.visitClosureOrLambdaExpression(ctx.closureOrLambdaExpression());
if (baseExpr instanceof MethodCallExpression) {
MethodCallExpression methodCallExpression = (MethodCallExpression) baseExpr;
Expression argumentsExpression = methodCallExpression.getArguments();
if (argumentsExpression instanceof ArgumentListExpression) {
// normal arguments, e.g. 1, 2
ArgumentListExpression argumentListExpression = (ArgumentListExpression) argumentsExpression;
argumentListExpression.getExpressions().add(closureExpression);
return configureAST(methodCallExpression, ctx);
}
if (argumentsExpression instanceof TupleExpression) {
// named arguments, e.g. x: 1, y: 2
TupleExpression tupleExpression = (TupleExpression) argumentsExpression;
NamedArgumentListExpression namedArgumentListExpression = (NamedArgumentListExpression) tupleExpression.getExpression(0);
if (asBoolean(tupleExpression.getExpressions())) {
methodCallExpression.setArguments(configureAST(new ArgumentListExpression(configureAST(new MapExpression(namedArgumentListExpression.getMapEntryExpressions()), namedArgumentListExpression), closureExpression), tupleExpression));
} else {
// the branch should never reach, because named arguments must not be empty
methodCallExpression.setArguments(configureAST(new ArgumentListExpression(closureExpression), tupleExpression));
}
return configureAST(methodCallExpression, ctx);
}
}
if (baseExpr instanceof PropertyExpression) {
// e.g. obj.m { }
MethodCallExpression methodCallExpression = this.createMethodCallExpression((PropertyExpression) baseExpr, configureAST(new ArgumentListExpression(closureExpression), closureExpression));
return configureAST(methodCallExpression, ctx);
}
if (// e.g. m { }
baseExpr instanceof VariableExpression || // e.g. "$m" { }
baseExpr instanceof GStringExpression || (baseExpr instanceof ConstantExpression && this.isTrue(baseExpr, IS_STRING))) {
// e.g. "m" { }
MethodCallExpression methodCallExpression = this.createMethodCallExpression(baseExpr, configureAST(new ArgumentListExpression(closureExpression), closureExpression));
return configureAST(methodCallExpression, ctx);
}
// e.g. 1 { }, 1.1 { }, (1 / 2) { }, m() { }, { -> ... } { }
MethodCallExpression methodCallExpression = this.createCallMethodCallExpression(baseExpr, configureAST(new ArgumentListExpression(closureExpression), closureExpression));
return configureAST(methodCallExpression, ctx);
}
throw createParsingFailedException("Unsupported path element: " + ctx.getText(), ctx);
}
Aggregations