use of org.codehaus.groovy.ast.ClassHelper.OBJECT_TYPE in project groovy by apache.
the class StaticTypesCallSiteWriter method writeListDotProperty.
private void writeListDotProperty(final Expression receiver, final String propertyName, final boolean safe) {
// for lists, replace list.foo with:
// def result = new ArrayList(list.size())
// for (item in list) result.add(item.foo)
// result
ClassNode componentType = receiver.getNodeMetaData(StaticCompilationMetadataKeys.COMPONENT_TYPE);
if (componentType == null) {
componentType = OBJECT_TYPE;
}
CompileStack compileStack = controller.getCompileStack();
MethodVisitor mv = controller.getMethodVisitor();
Label exit = new Label();
if (safe) {
receiver.visit(controller.getAcg());
Label doGet = new Label();
mv.visitJumpInsn(IFNONNULL, doGet);
controller.getOperandStack().remove(1);
mv.visitInsn(ACONST_NULL);
mv.visitJumpInsn(GOTO, exit);
mv.visitLabel(doGet);
}
Variable tmpList = varX("tmpList", ClassHelper.make(ArrayList.class));
int var = compileStack.defineTemporaryVariable(tmpList, false);
Variable iterator = varX("iterator", Iterator_TYPE);
int it = compileStack.defineTemporaryVariable(iterator, false);
Variable nextVar = varX("next", componentType);
final int next = compileStack.defineTemporaryVariable(nextVar, false);
mv.visitTypeInsn(NEW, "java/util/ArrayList");
mv.visitInsn(DUP);
receiver.visit(controller.getAcg());
mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "size", "()I", true);
controller.getOperandStack().remove(1);
mv.visitMethodInsn(INVOKESPECIAL, "java/util/ArrayList", "<init>", "(I)V", false);
mv.visitVarInsn(ASTORE, var);
Label l1 = new Label();
mv.visitLabel(l1);
receiver.visit(controller.getAcg());
mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "iterator", "()Ljava/util/Iterator;", true);
controller.getOperandStack().remove(1);
mv.visitVarInsn(ASTORE, it);
Label l2 = new Label();
mv.visitLabel(l2);
mv.visitVarInsn(ALOAD, it);
mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Iterator", "hasNext", "()Z", true);
Label l3 = new Label();
mv.visitJumpInsn(IFEQ, l3);
mv.visitVarInsn(ALOAD, it);
mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Iterator", "next", "()Ljava/lang/Object;", true);
mv.visitTypeInsn(CHECKCAST, BytecodeHelper.getClassInternalName(componentType));
mv.visitVarInsn(ASTORE, next);
Label l4 = new Label();
mv.visitLabel(l4);
mv.visitVarInsn(ALOAD, var);
PropertyExpression pexp = propX(bytecodeX(componentType, v -> v.visitVarInsn(ALOAD, next)), propertyName);
pexp.visit(controller.getAcg());
controller.getOperandStack().box();
controller.getOperandStack().remove(1);
mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "add", "(Ljava/lang/Object;)Z", true);
mv.visitInsn(POP);
Label l5 = new Label();
mv.visitLabel(l5);
mv.visitJumpInsn(GOTO, l2);
mv.visitLabel(l3);
mv.visitVarInsn(ALOAD, var);
if (safe) {
mv.visitLabel(exit);
}
controller.getOperandStack().push(ClassHelper.make(ArrayList.class));
controller.getCompileStack().removeVar(next);
controller.getCompileStack().removeVar(it);
controller.getCompileStack().removeVar(var);
}
use of org.codehaus.groovy.ast.ClassHelper.OBJECT_TYPE in project groovy by apache.
the class StaticTypeCheckingSupport method evaluateExpression.
/**
* A helper method that can be used to evaluate expressions as found in annotation
* parameters. For example, it will evaluate a constant, be it referenced directly as
* an integer or as a reference to a field.
* <p>
* If this method throws an exception, then the expression cannot be evaluated on its own.
*
* @param expr the expression to be evaluated
* @param config the compiler configuration
* @return the result of the expression
*/
public static Object evaluateExpression(final Expression expr, final CompilerConfiguration config) {
Expression ce = expr instanceof CastExpression ? ((CastExpression) expr).getExpression() : expr;
if (ce instanceof ConstantExpression) {
if (expr.getType().equals(ce.getType()))
return ((ConstantExpression) ce).getValue();
} else if (ce instanceof ListExpression) {
if (expr.getType().isArray() && expr.getType().getComponentType().equals(STRING_TYPE))
return ((ListExpression) ce).getExpressions().stream().map(e -> evaluateExpression(e, config)).toArray(String[]::new);
}
String className = "Expression$" + UUID.randomUUID().toString().replace('-', '$');
ClassNode simpleClass = new ClassNode(className, Opcodes.ACC_PUBLIC, OBJECT_TYPE);
addGeneratedMethod(simpleClass, "eval", Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, OBJECT_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, new ReturnStatement(expr));
// adjust configuration so class can be inspected by this JVM
CompilerConfiguration cc = new CompilerConfiguration(config);
// unlikely to be required by expression
cc.setPreviewFeatures(false);
cc.setTargetBytecode(CompilerConfiguration.DEFAULT.getTargetBytecode());
CompilationUnit cu = new CompilationUnit(cc);
try {
cu.addClassNode(simpleClass);
cu.compile(Phases.CLASS_GENERATION);
List<GroovyClass> classes = cu.getClasses();
Class<?> aClass = cu.getClassLoader().defineClass(className, classes.get(0).getBytes());
try {
return aClass.getMethod("eval").invoke(null);
} catch (ReflectiveOperationException e) {
throw new GroovyBugError(e);
}
} finally {
closeQuietly(cu.getClassLoader());
}
}
use of org.codehaus.groovy.ast.ClassHelper.OBJECT_TYPE in project groovy by apache.
the class StaticTypeCheckingVisitor method findMethodsWithGenerated.
/**
* Returns methods defined for the specified receiver and adds "non-existing"
* methods that will be generated afterwards by the compiler; for example if
* a method is using default values and the class node isn't compiled yet.
*
* @param receiver the receiver where to find methods
* @param name the name of the methods to return
* @return the methods that are defined on the receiver completed with stubs for future methods
*/
protected List<MethodNode> findMethodsWithGenerated(final ClassNode receiver, final String name) {
if (receiver.isArray()) {
if (name.equals("clone")) {
// GROOVY-10319: array clone -- <https://docs.oracle.com/javase/specs/jls/se8/html/jls-10.html#jls-10.7>
MethodNode clone = new MethodNode("clone", Opcodes.ACC_PUBLIC, OBJECT_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, null);
// retain Object for declaringClass and returnType
clone.setDeclaringClass(OBJECT_TYPE);
clone.setNodeMetaData(INFERRED_RETURN_TYPE, receiver);
return Collections.singletonList(clone);
} else {
return OBJECT_TYPE.getMethods(name);
}
}
List<MethodNode> methods = receiver.getMethods(name);
if (receiver.isAbstract()) {
collectAllInterfaceMethodsByName(receiver, name, methods);
} else {
// GROOVY-9890: always search for default methods
List<MethodNode> interfaceMethods = new ArrayList<>();
collectAllInterfaceMethodsByName(receiver, name, interfaceMethods);
interfaceMethods.stream().filter(mn -> mn.isDefault() || (mn.isPublic() && !mn.isStatic() && !mn.isAbstract() && Traits.isTrait(mn.getDeclaringClass()))).forEach(methods::add);
}
if (receiver.isInterface()) {
methods.addAll(OBJECT_TYPE.getMethods(name));
}
if (methods.isEmpty() || receiver.isResolved()) {
return methods;
}
return addGeneratedMethods(receiver, methods);
}
Aggregations