Search in sources :

Example 46 with InnerClassNode

use of org.codehaus.groovy.ast.InnerClassNode in project groovy by apache.

the class TraitComposer method applyTrait.

private static void applyTrait(final ClassNode trait, final ClassNode cNode, final TraitHelpersTuple helpers) {
    ClassNode helperClassNode = helpers.getHelper();
    ClassNode fieldHelperClassNode = helpers.getFieldHelper();
    Map<String, ClassNode> genericsSpec = GenericsUtils.createGenericsSpec(cNode);
    genericsSpec = GenericsUtils.createGenericsSpec(trait, genericsSpec);
    for (MethodNode methodNode : helperClassNode.getAllDeclaredMethods()) {
        String name = methodNode.getName();
        Parameter[] helperMethodParams = methodNode.getParameters();
        boolean isAbstract = methodNode.isAbstract();
        if (!isAbstract && helperMethodParams.length > 0 && ((methodNode.getModifiers() & Opcodes.ACC_STATIC) == Opcodes.ACC_STATIC) && (!name.contains("$") || (methodNode.getModifiers() & Opcodes.ACC_SYNTHETIC) == 0)) {
            ArgumentListExpression argList = new ArgumentListExpression();
            argList.addExpression(new VariableExpression("this"));
            Parameter[] origParams = new Parameter[helperMethodParams.length - 1];
            Parameter[] params = new Parameter[helperMethodParams.length - 1];
            System.arraycopy(methodNode.getParameters(), 1, params, 0, params.length);
            Map<String, ClassNode> methodGenericsSpec = new LinkedHashMap<String, ClassNode>(genericsSpec);
            MethodNode originalMethod = trait.getMethod(name, params);
            // Original method may be null for the case of private or static methods
            if (originalMethod != null) {
                methodGenericsSpec = GenericsUtils.addMethodGenerics(originalMethod, methodGenericsSpec);
            }
            for (int i = 1; i < helperMethodParams.length; i++) {
                Parameter parameter = helperMethodParams[i];
                ClassNode originType = parameter.getOriginType();
                ClassNode fixedType = correctToGenericsSpecRecurse(methodGenericsSpec, originType);
                Parameter newParam = new Parameter(fixedType, "arg" + i);
                List<AnnotationNode> copied = new LinkedList<AnnotationNode>();
                List<AnnotationNode> notCopied = new LinkedList<AnnotationNode>();
                GeneralUtils.copyAnnotatedNodeAnnotations(parameter, copied, notCopied);
                newParam.addAnnotations(copied);
                params[i - 1] = newParam;
                origParams[i - 1] = parameter;
                argList.addExpression(new VariableExpression(params[i - 1]));
            }
            createForwarderMethod(trait, cNode, methodNode, originalMethod, helperClassNode, methodGenericsSpec, helperMethodParams, origParams, params, argList);
        }
    }
    cNode.addObjectInitializerStatements(new ExpressionStatement(new MethodCallExpression(new ClassExpression(helperClassNode), Traits.INIT_METHOD, new ArgumentListExpression(new VariableExpression("this")))));
    MethodCallExpression staticInitCall = new MethodCallExpression(new ClassExpression(helperClassNode), Traits.STATIC_INIT_METHOD, new ArgumentListExpression(new ClassExpression(cNode)));
    MethodNode staticInitMethod = new MethodNode(Traits.STATIC_INIT_METHOD, Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC, ClassHelper.VOID_TYPE, new Parameter[] { new Parameter(ClassHelper.CLASS_Type, "clazz") }, ClassNode.EMPTY_ARRAY, EmptyStatement.INSTANCE);
    staticInitMethod.setDeclaringClass(helperClassNode);
    staticInitCall.setMethodTarget(staticInitMethod);
    cNode.addStaticInitializerStatements(Collections.<Statement>singletonList(new ExpressionStatement(staticInitCall)), false);
    if (fieldHelperClassNode != null && !cNode.declaresInterface(fieldHelperClassNode)) {
        // we should implement the field helper interface too
        cNode.addInterface(fieldHelperClassNode);
        // implementation of methods
        List<MethodNode> declaredMethods = new LinkedList<MethodNode>();
        for (MethodNode declaredMethod : fieldHelperClassNode.getAllDeclaredMethods()) {
            if (declaredMethod.getName().endsWith(Traits.DIRECT_GETTER_SUFFIX)) {
                declaredMethods.add(0, declaredMethod);
            } else {
                declaredMethods.add(declaredMethod);
            }
        }
        for (MethodNode methodNode : declaredMethods) {
            String fieldName = methodNode.getName();
            if (fieldName.endsWith(Traits.DIRECT_GETTER_SUFFIX) || fieldName.endsWith(Traits.DIRECT_SETTER_SUFFIX)) {
                int suffixIdx = fieldName.lastIndexOf("$");
                fieldName = fieldName.substring(0, suffixIdx);
                String operation = methodNode.getName().substring(suffixIdx + 1);
                boolean getter = "get".equals(operation);
                ClassNode returnType = correctToGenericsSpecRecurse(genericsSpec, methodNode.getReturnType());
                int fieldMods = 0;
                int isStatic = 0;
                boolean publicField = true;
                FieldNode helperField = null;
                fieldMods = 0;
                isStatic = 0;
                // look first for field with encoded modifier information
                for (Integer mod : Traits.FIELD_PREFIXES) {
                    helperField = fieldHelperClassNode.getField(String.format("$0x%04x", mod) + fieldName);
                    if (helperField != null) {
                        if ((mod & Opcodes.ACC_STATIC) != 0)
                            isStatic = Opcodes.ACC_STATIC;
                        fieldMods = fieldMods | mod;
                        break;
                    }
                }
                if (helperField == null) {
                    // look for possible legacy fields (trait compiled pre 2.4.8)
                    helperField = fieldHelperClassNode.getField(Traits.FIELD_PREFIX + Traits.PUBLIC_FIELD_PREFIX + fieldName);
                    if (helperField == null) {
                        publicField = false;
                        helperField = fieldHelperClassNode.getField(Traits.FIELD_PREFIX + Traits.PRIVATE_FIELD_PREFIX + fieldName);
                    }
                    if (helperField == null) {
                        publicField = true;
                        // try to find a static one
                        helperField = fieldHelperClassNode.getField(Traits.STATIC_FIELD_PREFIX + Traits.PUBLIC_FIELD_PREFIX + fieldName);
                        if (helperField == null) {
                            publicField = false;
                            helperField = fieldHelperClassNode.getField(Traits.STATIC_FIELD_PREFIX + Traits.PRIVATE_FIELD_PREFIX + fieldName);
                        }
                        fieldMods = fieldMods | Opcodes.ACC_STATIC;
                        isStatic = Opcodes.ACC_STATIC;
                    }
                    fieldMods = fieldMods | (publicField ? Opcodes.ACC_PUBLIC : Opcodes.ACC_PRIVATE);
                }
                if (getter) {
                    // add field
                    if (helperField != null) {
                        List<AnnotationNode> copied = new LinkedList<AnnotationNode>();
                        List<AnnotationNode> notCopied = new LinkedList<AnnotationNode>();
                        GeneralUtils.copyAnnotatedNodeAnnotations(helperField, copied, notCopied);
                        FieldNode fieldNode = cNode.addField(fieldName, fieldMods, returnType, (fieldMods & Opcodes.ACC_FINAL) == 0 ? null : helperField.getInitialExpression());
                        fieldNode.addAnnotations(copied);
                        // so instead set within (static) initializer
                        if (fieldNode.isFinal() && !(helperClassNode instanceof InnerClassNode)) {
                            String baseName = fieldNode.isStatic() ? Traits.STATIC_INIT_METHOD : Traits.INIT_METHOD;
                            Expression mce = callX(helperClassNode, baseName + fieldNode.getName());
                            Statement stmt = stmt(assignX(varX(fieldNode.getName(), fieldNode.getType()), mce));
                            if (isStatic == 0) {
                                cNode.addObjectInitializerStatements(stmt);
                            } else {
                                cNode.addStaticInitializerStatements(Collections.<Statement>singletonList(stmt), false);
                            }
                        }
                    }
                }
                Parameter[] newParams;
                if (getter) {
                    newParams = Parameter.EMPTY_ARRAY;
                } else {
                    ClassNode originType = methodNode.getParameters()[0].getOriginType();
                    ClassNode fixedType = originType.isGenericsPlaceHolder() ? ClassHelper.OBJECT_TYPE : correctToGenericsSpecRecurse(genericsSpec, originType);
                    newParams = new Parameter[] { new Parameter(fixedType, "val") };
                }
                Expression fieldExpr = varX(cNode.getField(fieldName));
                boolean finalSetter = !getter && (fieldMods & Opcodes.ACC_FINAL) != 0;
                Statement body = getter ? returnS(fieldExpr) : (finalSetter ? null : stmt(new BinaryExpression(fieldExpr, Token.newSymbol(Types.EQUAL, 0, 0), varX(newParams[0]))));
                // add getter/setter even though setter not strictly needed for final fields
                // but add empty body for setter for legacy compatibility
                MethodNode impl = new MethodNode(methodNode.getName(), Opcodes.ACC_PUBLIC | isStatic, returnType, newParams, ClassNode.EMPTY_ARRAY, body);
                AnnotationNode an = new AnnotationNode(COMPILESTATIC_CLASSNODE);
                impl.addAnnotation(an);
                cNode.addTransform(StaticCompileTransformation.class, an);
                cNode.addMethod(impl);
            }
        }
    }
}
Also used : InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) FieldNode(org.codehaus.groovy.ast.FieldNode) IfStatement(org.codehaus.groovy.ast.stmt.IfStatement) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) Statement(org.codehaus.groovy.ast.stmt.Statement) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) ReturnStatement(org.codehaus.groovy.ast.stmt.ReturnStatement) EmptyStatement(org.codehaus.groovy.ast.stmt.EmptyStatement) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) LinkedList(java.util.LinkedList) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) LinkedHashMap(java.util.LinkedHashMap) MethodNode(org.codehaus.groovy.ast.MethodNode) StaticMethodCallExpression(org.codehaus.groovy.ast.expr.StaticMethodCallExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) AnnotationNode(org.codehaus.groovy.ast.AnnotationNode) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ArrayExpression(org.codehaus.groovy.ast.expr.ArrayExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) CastExpression(org.codehaus.groovy.ast.expr.CastExpression) BooleanExpression(org.codehaus.groovy.ast.expr.BooleanExpression) StaticMethodCallExpression(org.codehaus.groovy.ast.expr.StaticMethodCallExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) Expression(org.codehaus.groovy.ast.expr.Expression) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) Parameter(org.codehaus.groovy.ast.Parameter)

Example 47 with InnerClassNode

use of org.codehaus.groovy.ast.InnerClassNode in project groovy by apache.

the class SortableASTTransformation method createComparatorFor.

private static void createComparatorFor(ClassNode classNode, PropertyNode property) {
    String propName = property.getName();
    String className = classNode.getName() + "$" + StringGroovyMethods.capitalize(propName) + "Comparator";
    ClassNode superClass = makeClassSafeWithGenerics(AbstractComparator.class, classNode);
    InnerClassNode cmpClass = new InnerClassNode(classNode, className, ACC_PRIVATE | ACC_STATIC, superClass);
    classNode.getModule().addClass(cmpClass);
    cmpClass.addMethod(new MethodNode("compare", ACC_PUBLIC, ClassHelper.int_TYPE, params(param(newClass(classNode), ARG0), param(newClass(classNode), ARG1)), ClassNode.EMPTY_ARRAY, createCompareMethodBody(property)));
    String fieldName = "this$" + StringGroovyMethods.capitalize(propName) + "Comparator";
    // private final Comparator this$<property>Comparator = new <type>$<property>Comparator();
    FieldNode cmpField = classNode.addField(fieldName, ACC_STATIC | ACC_FINAL | ACC_PRIVATE | ACC_SYNTHETIC, COMPARATOR_TYPE, ctorX(cmpClass));
    classNode.addMethod(new MethodNode("comparatorBy" + StringGroovyMethods.capitalize(propName), ACC_PUBLIC | ACC_STATIC, COMPARATOR_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, returnS(fieldX(cmpField))));
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) MethodNode(org.codehaus.groovy.ast.MethodNode) FieldNode(org.codehaus.groovy.ast.FieldNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode)

Example 48 with InnerClassNode

use of org.codehaus.groovy.ast.InnerClassNode in project groovity by disney.

the class GroovityASTTransformation method visit.

public void visit(ASTNode[] nodes, final SourceUnit sourceUnit) {
    ModuleNode mn = sourceUnit.getAST();
    try {
        if (mn != null) {
            ClassNode scriptClassNode = mn.getScriptClassDummy();
            LoadFieldVisitor loadFieldVisitor = new LoadFieldVisitor(sourceUnit);
            loadFieldVisitor.visitClass(scriptClassNode);
            if (mn.getStatementBlock().isEmpty()) {
                // System.out.println("Adding dummy statement to force script");
                mn.getStatementBlock().addStatement(new ExpressionStatement(new DeclarationExpression(new VariableExpression("___groovy__run__stub___"), Token.newSymbol(Types.EQUAL, 1, 1), new ConstantExpression(null))));
            } else {
                // check whether script body really does anything, if so add ScriptBody marker API
                final AtomicBoolean runnable = new AtomicBoolean(false);
                mn.getStatementBlock().visit(new CodeVisitorSupport() {

                    public void visitExpressionStatement(ExpressionStatement statement) {
                        Expression expression = statement.getExpression();
                        if (expression instanceof DeclarationExpression) {
                            List<AnnotationNode> fa = expression.getAnnotations();
                            for (AnnotationNode n : fa) {
                                if ("Field".equals(n.getClassNode().getName()) || Field.class.equals(n.getClassNode().getTypeClass())) {
                                    // short-circuit and ignore the field declaration
                                    return;
                                }
                            }
                            DeclarationExpression de = (DeclarationExpression) expression;
                            if ((de.getVariableExpression().getModifiers() & ACC_STATIC) != 0) {
                                // static declarations are implied fields
                                return;
                            }
                        }
                        runnable.set(true);
                    }

                    public void visitReturnStatement(ReturnStatement statement) {
                        runnable.set(true);
                    }

                    public void visitAssertStatement(AssertStatement statement) {
                        runnable.set(true);
                    }
                });
                if (runnable.get()) {
                    scriptClassNode.addInterface(new ClassNode(ScriptBody.class));
                }
            }
            LoadFinder loadFinder = new LoadFinder(sourceUnit);
            loadFinder.visitClass(scriptClassNode);
            if (loadFinder.loadMethod != null) {
                scriptClassNode.addInterface(new ClassNode(Loadable.class));
            }
            LineNumberVisitor lineNumberVisitor = null;
            if (sourceLineNumbers != null) {
                lineNumberVisitor = new LineNumberVisitor(sourceUnit);
            }
            boolean isLibrary = false;
            ArgVisitor argVisitor = new ArgVisitor(sourceUnit);
            InitDependencyVisitor initVisitor = new InitDependencyVisitor(sourceUnit);
            TagFinder tagFinder = new TagFinder(sourceUnit);
            TagCallFinder tagCallFinder = new TagCallFinder(sourceUnit, scriptClassNode, factory.getTaggables());
            StaticBindingTransformer staticBindingTransformer = new StaticBindingTransformer(sourceUnit);
            StaticFieldVisitor staticFieldVisitor = new StaticFieldVisitor(sourceUnit);
            staticFieldVisitor.visitClass(scriptClassNode);
            List<MethodNode> methods = mn.getMethods();
            if (methods != null) {
                for (MethodNode method : methods) {
                    boolean isFunction = false;
                    for (AnnotationNode annotation : method.getAnnotations()) {
                        if ("Function".equals(annotation.getClassNode().getName())) {
                            // If this script contains at least one Function declaration, mark it as a library
                            isFunction = true;
                            break;
                        }
                    }
                    if (isFunction) {
                        isLibrary = true;
                        break;
                    }
                }
            }
            List<ClassNode> cnodes = mn.getClasses();
            iterateClassNodes: for (final ClassNode cn : cnodes) {
                // remap GSP line numbers so they match up with original source
                if (lineNumberVisitor != null) {
                    lineNumberVisitor.visitClass(cn);
                }
                tagCallFinder.visitClass(cn);
                // add arg annotations to methods to preserve parameter names
                argVisitor.visitClass(cn);
                if (cn.isInterface()) {
                    continue;
                }
                // Skip further processing for Traits as they don't handle static things well yet ...
                if (cn.getAnnotations() != null) {
                    for (AnnotationNode anno : cn.getAnnotations()) {
                        if (anno.getClassNode().getName().equals("groovy.transform.Trait")) {
                            // System.out.println("SKIPPING TRAIT "+cn.getName());
                            continue iterateClassNodes;
                        }
                    }
                }
                staticBindingTransformer.visitClass(cn);
                // add statistics gathering to methods and closures
                initVisitor.visitClass(cn);
                tagFinder.visitClass(cn);
                final String internalClassName = BytecodeHelper.getClassInternalName(cn);
                // add static missing property support to all classes
                BytecodeExpression staticGetPropertyMissingExpression = new BytecodeExpression() {

                    @Override
                    public void visit(MethodVisitor mv) {
                        mv.visitFieldInsn(GETSTATIC, internalClassName, GROOVITY_SCRIPT_HELPER_FIELD, BytecodeHelper.getTypeDescription(ScriptHelper.class));
                        // BytecodeHelper.visitClassLiteral(mv, cn);
                        mv.visitVarInsn(ALOAD, 0);
                        mv.visitMethodInsn(INVOKEVIRTUAL, BytecodeHelper.getClassInternalName(ScriptHelper.class), "staticPropertyMissing", BytecodeHelper.getMethodDescriptor(Object.class, new Class[] { String.class }), false);
                        mv.visitInsn(ARETURN);
                    }
                };
                MethodNode staticGetPropMethod = new MethodNode("$static_propertyMissing", ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC, new ClassNode(Object.class), new Parameter[] { new Parameter(ClassHelper.make(String.class), "propertyName") }, new ClassNode[] {}, new BlockStatement(new Statement[] { new ReturnStatement(staticGetPropertyMissingExpression) }, new VariableScope()));
                staticGetPropMethod.setSynthetic(true);
                staticGetPropMethod.putNodeMetaData(StaticCompilationMetadataKeys.STATIC_COMPILE_NODE, true);
                cn.addMethod(staticGetPropMethod);
                // add static missing method support to all classes
                BytecodeExpression staticGetMethodMissingExpression = new BytecodeExpression() {

                    @Override
                    public void visit(MethodVisitor mv) {
                        mv.visitFieldInsn(GETSTATIC, internalClassName, GROOVITY_SCRIPT_HELPER_FIELD, BytecodeHelper.getTypeDescription(ScriptHelper.class));
                        // BytecodeHelper.visitClassLiteral(mv, cn);
                        mv.visitVarInsn(ALOAD, 0);
                        mv.visitVarInsn(ALOAD, 1);
                        mv.visitMethodInsn(INVOKEVIRTUAL, BytecodeHelper.getClassInternalName(ScriptHelper.class), "invokeMethod", BytecodeHelper.getMethodDescriptor(Object.class, new Class[] { String.class, Object.class }), false);
                        mv.visitInsn(ARETURN);
                    }
                };
                MethodNode staticGetMissingMethod = new MethodNode("$static_methodMissing", ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC, new ClassNode(Object.class), new Parameter[] { new Parameter(ClassHelper.make(String.class), "methodName"), new Parameter(ClassHelper.make(Object.class), "methodArgs") }, new ClassNode[] {}, new BlockStatement(new Statement[] { new ReturnStatement(staticGetMethodMissingExpression) }, new VariableScope()));
                staticGetMissingMethod.setSynthetic(true);
                staticGetMissingMethod.putNodeMetaData(StaticCompilationMetadataKeys.STATIC_COMPILE_NODE, true);
                cn.addMethod(staticGetMissingMethod);
                if (!(cn instanceof InnerClassNode) || cn.isStaticClass()) {
                    FieldNode gsfNode = new FieldNode(GROOVITY_SCRIPT_HELPER_FIELD, ACC_PROTECTED | ACC_STATIC, new ClassNode(ScriptHelper.class), cn, ConstantExpression.NULL);
                    cn.addField(gsfNode);
                    // add missing method support to all classes
                    BytecodeExpression getMethodMissingExpression = new BytecodeExpression() {

                        @Override
                        public void visit(MethodVisitor mv) {
                            mv.visitFieldInsn(GETSTATIC, internalClassName, GROOVITY_SCRIPT_HELPER_FIELD, BytecodeHelper.getTypeDescription(ScriptHelper.class));
                            // BytecodeHelper.visitClassLiteral(mv, cn);
                            mv.visitVarInsn(ALOAD, 1);
                            mv.visitVarInsn(ALOAD, 2);
                            mv.visitMethodInsn(INVOKEVIRTUAL, BytecodeHelper.getClassInternalName(ScriptHelper.class), "invokeMethod", BytecodeHelper.getMethodDescriptor(Object.class, new Class[] { String.class, Object.class }), false);
                            mv.visitInsn(ARETURN);
                        }
                    };
                    MethodNode getMissingMethod = new MethodNode("methodMissing", ACC_PUBLIC | ACC_SYNTHETIC, new ClassNode(Object.class), new Parameter[] { new Parameter(ClassHelper.make(String.class), "methodName"), new Parameter(ClassHelper.make(Object.class), "methodArgs") }, new ClassNode[] { new ClassNode(Exception.class) }, new BlockStatement(new Statement[] { new ReturnStatement(getMethodMissingExpression) }, new VariableScope()));
                    getMissingMethod.setSynthetic(true);
                    getMissingMethod.putNodeMetaData(StaticCompilationMetadataKeys.STATIC_COMPILE_NODE, true);
                    cn.addMethod(getMissingMethod);
                    // add missing property lookup to top-level classes
                    BytecodeExpression instanceGetPropertyMissingExpression = new BytecodeExpression() {

                        @Override
                        public void visit(MethodVisitor mv) {
                            mv.visitFieldInsn(GETSTATIC, internalClassName, GROOVITY_SCRIPT_HELPER_FIELD, BytecodeHelper.getTypeDescription(ScriptHelper.class));
                            mv.visitVarInsn(ALOAD, 1);
                            mv.visitMethodInsn(INVOKEVIRTUAL, BytecodeHelper.getClassInternalName(ScriptHelper.class), "getProperty", BytecodeHelper.getMethodDescriptor(Object.class, new Class[] { String.class }), false);
                            mv.visitInsn(ARETURN);
                        }
                    };
                    MethodNode instanceGetMethod = new MethodNode("propertyMissing", ACC_PUBLIC | ACC_SYNTHETIC, new ClassNode(Object.class), new Parameter[] { new Parameter(ClassHelper.make(String.class), "propertyName") }, new ClassNode[] {}, new BlockStatement(new Statement[] { new ReturnStatement(instanceGetPropertyMissingExpression) }, new VariableScope()));
                    instanceGetMethod.setSynthetic(true);
                    instanceGetMethod.putNodeMetaData(StaticCompilationMetadataKeys.STATIC_COMPILE_NODE, true);
                    cn.addMethod(instanceGetMethod);
                    BytecodeExpression instanceSetPropertyMissingExpression = new BytecodeExpression() {

                        @Override
                        public void visit(MethodVisitor mv) {
                            mv.visitFieldInsn(GETSTATIC, internalClassName, GROOVITY_SCRIPT_HELPER_FIELD, BytecodeHelper.getTypeDescription(ScriptHelper.class));
                            mv.visitVarInsn(ALOAD, 1);
                            mv.visitVarInsn(ALOAD, 2);
                            mv.visitMethodInsn(INVOKEVIRTUAL, BytecodeHelper.getClassInternalName(ScriptHelper.class), "setProperty", Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(String.class), Type.getType(Object.class)), false);
                            mv.visitInsn(RETURN);
                        }
                    };
                    MethodNode setMethod = new MethodNode("propertyMissing", ACC_PUBLIC | ACC_SYNTHETIC, ClassHelper.VOID_TYPE, new Parameter[] { new Parameter(ClassHelper.make(String.class), "propertyName"), new Parameter(new ClassNode(Object.class), "newValue") }, new ClassNode[] {}, new BlockStatement(new Statement[] { new ExpressionStatement(instanceSetPropertyMissingExpression) }, new VariableScope()));
                    setMethod.setSynthetic(true);
                    setMethod.putNodeMetaData(StaticCompilationMetadataKeys.STATIC_COMPILE_NODE, true);
                    cn.addMethod(setMethod);
                    if (cn != scriptClassNode) {
                        // add getBinding to other classes
                        BytecodeExpression getFactoryCall = new BytecodeExpression() {

                            @Override
                            public void visit(MethodVisitor mv) {
                                mv.visitFieldInsn(GETSTATIC, internalClassName, GROOVITY_SCRIPT_HELPER_FIELD, BytecodeHelper.getTypeDescription(ScriptHelper.class));
                                mv.visitMethodInsn(INVOKEVIRTUAL, BytecodeHelper.getClassInternalName(ScriptHelper.class), "getBinding", BytecodeHelper.getMethodDescriptor(Binding.class, new Class[] {}), false);
                                mv.visitInsn(ARETURN);
                            }
                        };
                        MethodNode getMethod = new MethodNode("getBinding", ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC, new ClassNode(Binding.class), new Parameter[] {}, new ClassNode[] {}, new BlockStatement(new Statement[] { new ReturnStatement(getFactoryCall) }, new VariableScope()));
                        getMethod.setSynthetic(true);
                        getMethod.putNodeMetaData(StaticCompilationMetadataKeys.STATIC_COMPILE_NODE, true);
                        cn.addMethod(getMethod);
                    }
                    // add load, run and tag methods to all top level classes
                    BytecodeExpression loadFactoryCall = new BytecodeExpression() {

                        @Override
                        public void visit(MethodVisitor mv) {
                            mv.visitFieldInsn(GETSTATIC, internalClassName, GROOVITY_SCRIPT_HELPER_FIELD, BytecodeHelper.getTypeDescription(ScriptHelper.class));
                            mv.visitVarInsn(ALOAD, 0);
                            mv.visitMethodInsn(INVOKEVIRTUAL, BytecodeHelper.getClassInternalName(ScriptHelper.class), LOAD, BytecodeHelper.getMethodDescriptor(Script.class, new Class[] { String.class }), false);
                            mv.visitInsn(ARETURN);
                        }
                    };
                    MethodNode loadMethod = new MethodNode(LOAD, ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC, new ClassNode(Script.class), new Parameter[] { new Parameter(new ClassNode(String.class), "path") }, new ClassNode[] { new ClassNode(InstantiationException.class), new ClassNode(IllegalAccessException.class), new ClassNode(ClassNotFoundException.class) }, new BlockStatement(new Statement[] { new ReturnStatement(loadFactoryCall) }, new VariableScope()));
                    loadMethod.setSynthetic(true);
                    loadMethod.putNodeMetaData(StaticCompilationMetadataKeys.STATIC_COMPILE_NODE, true);
                    cn.addMethod(loadMethod);
                    BytecodeExpression runFactoryCall = new BytecodeExpression() {

                        @Override
                        public void visit(MethodVisitor mv) {
                            mv.visitFieldInsn(GETSTATIC, internalClassName, GROOVITY_SCRIPT_HELPER_FIELD, BytecodeHelper.getTypeDescription(ScriptHelper.class));
                            mv.visitVarInsn(ALOAD, 0);
                            mv.visitMethodInsn(INVOKEVIRTUAL, BytecodeHelper.getClassInternalName(ScriptHelper.class), RUN, BytecodeHelper.getMethodDescriptor(Object.class, new Class[] { String.class }), false);
                            mv.visitInsn(ARETURN);
                        }
                    };
                    MethodNode runMethod = new MethodNode(RUN, ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC, ClassHelper.OBJECT_TYPE, new Parameter[] { new Parameter(new ClassNode(String.class), "path") }, new ClassNode[] { new ClassNode(InstantiationException.class), new ClassNode(IllegalAccessException.class), new ClassNode(ClassNotFoundException.class), new ClassNode(IOException.class) }, new BlockStatement(new Statement[] { new ReturnStatement(runFactoryCall) }, new VariableScope()));
                    runMethod.setSynthetic(true);
                    runMethod.putNodeMetaData(StaticCompilationMetadataKeys.STATIC_COMPILE_NODE, true);
                    cn.addMethod(runMethod);
                    BytecodeExpression doStreamCall = new BytecodeExpression() {

                        @Override
                        public void visit(MethodVisitor mv) {
                            mv.visitFieldInsn(GETSTATIC, internalClassName, GROOVITY_SCRIPT_HELPER_FIELD, BytecodeHelper.getTypeDescription(ScriptHelper.class));
                            mv.visitVarInsn(ALOAD, 0);
                            mv.visitMethodInsn(INVOKEVIRTUAL, BytecodeHelper.getClassInternalName(ScriptHelper.class), STREAM, Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(Object.class)), false);
                            mv.visitInsn(RETURN);
                        }
                    };
                    MethodNode doStreamMethod = new MethodNode(STREAM, ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC, ClassHelper.VOID_TYPE, new Parameter[] { new Parameter(ClassHelper.make(Object.class), "obj") }, new ClassNode[] {}, new BlockStatement(new Statement[] { new ExpressionStatement(doStreamCall) }, new VariableScope()));
                    doStreamMethod.setSynthetic(true);
                    doStreamMethod.putNodeMetaData(StaticCompilationMetadataKeys.STATIC_COMPILE_NODE, true);
                    cn.addMethod(doStreamMethod);
                    BytecodeExpression doTagFullFactoryCall = new BytecodeExpression() {

                        @Override
                        public void visit(MethodVisitor mv) {
                            mv.visitFieldInsn(GETSTATIC, internalClassName, GROOVITY_SCRIPT_HELPER_FIELD, BytecodeHelper.getTypeDescription(ScriptHelper.class));
                            mv.visitVarInsn(ALOAD, 0);
                            mv.visitVarInsn(ALOAD, 1);
                            mv.visitVarInsn(ALOAD, 2);
                            mv.visitMethodInsn(INVOKEVIRTUAL, BytecodeHelper.getClassInternalName(ScriptHelper.class), TAG, BytecodeHelper.getMethodDescriptor(Object.class, new Class[] { String.class, Map.class, Closure.class }), false);
                            mv.visitInsn(ARETURN);
                        }
                    };
                    MethodNode doTagFullMethod = new MethodNode(TAG, ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC, ClassHelper.OBJECT_TYPE, new Parameter[] { new Parameter(ClassHelper.make(String.class), "tagName"), new Parameter(new ClassNode(Map.class), "attributes"), new Parameter(new ClassNode(Closure.class), "body") }, new ClassNode[] { new ClassNode(Exception.class) }, new BlockStatement(new Statement[] { new ReturnStatement(doTagFullFactoryCall) }, new VariableScope()));
                    doTagFullMethod.setSynthetic(true);
                    doTagFullMethod.putNodeMetaData(StaticCompilationMetadataKeys.STATIC_COMPILE_NODE, true);
                    cn.addMethod(doTagFullMethod);
                    BytecodeExpression doTagShortBodyFactoryCall = new BytecodeExpression() {

                        @Override
                        public void visit(MethodVisitor mv) {
                            mv.visitFieldInsn(GETSTATIC, internalClassName, GROOVITY_SCRIPT_HELPER_FIELD, BytecodeHelper.getTypeDescription(ScriptHelper.class));
                            mv.visitVarInsn(ALOAD, 0);
                            mv.visitVarInsn(ALOAD, 1);
                            mv.visitMethodInsn(INVOKEVIRTUAL, BytecodeHelper.getClassInternalName(ScriptHelper.class), TAG, BytecodeHelper.getMethodDescriptor(Object.class, new Class[] { String.class, Closure.class }), false);
                            mv.visitInsn(ARETURN);
                        }
                    };
                    MethodNode doTagShortBodyMethod = new MethodNode(TAG, ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC, ClassHelper.OBJECT_TYPE, new Parameter[] { new Parameter(ClassHelper.make(String.class), "tagName"), new Parameter(new ClassNode(Closure.class), "body") }, new ClassNode[] { new ClassNode(Exception.class) }, new BlockStatement(new Statement[] { new ReturnStatement(doTagShortBodyFactoryCall) }, new VariableScope()));
                    doTagShortBodyMethod.setSynthetic(true);
                    doTagShortBodyMethod.putNodeMetaData(StaticCompilationMetadataKeys.STATIC_COMPILE_NODE, true);
                    cn.addMethod(doTagShortBodyMethod);
                }
            }
            // Record whether the class is a library with @Functions in a static final boolean.
            final FieldNode isLibraryFieldNode = new FieldNode("isGroovyLibrary", ACC_PUBLIC | ACC_STATIC | ACC_FINAL, new ClassNode(Boolean.class), scriptClassNode, new ConstantExpression(isLibrary));
            scriptClassNode.addField(isLibraryFieldNode);
            ListExpression dependencyExpression = new ListExpression();
            for (String dep : initDependencies) {
                dependencyExpression.addExpression(new ConstantExpression(dep));
            }
            // Store pointers to all dependencies to help control load order
            final FieldNode initDependenciesFieldNode = new FieldNode("initDependencies", ACC_PUBLIC | ACC_STATIC | ACC_FINAL, new ClassNode(new ArrayList<String>().getClass()), scriptClassNode, dependencyExpression);
            scriptClassNode.addField(initDependenciesFieldNode);
        }
    } catch (Exception e) {
        log.error("Error generating stats AST: ", e);
    }
}
Also used : Loadable(com.disney.groovity.Loadable) Closure(groovy.lang.Closure) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) MethodVisitor(groovyjarjarasm.asm.MethodVisitor) MethodNode(org.codehaus.groovy.ast.MethodNode) AnnotationNode(org.codehaus.groovy.ast.AnnotationNode) ReturnStatement(org.codehaus.groovy.ast.stmt.ReturnStatement) ArrayList(java.util.ArrayList) List(java.util.List) BytecodeExpression(org.codehaus.groovy.classgen.BytecodeExpression) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) ModuleNode(org.codehaus.groovy.ast.ModuleNode) ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) FieldNode(org.codehaus.groovy.ast.FieldNode) DeclarationExpression(org.codehaus.groovy.ast.expr.DeclarationExpression) ClosureListExpression(org.codehaus.groovy.ast.expr.ClosureListExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) ListExpression(org.codehaus.groovy.ast.expr.ListExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) IOException(java.io.IOException) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) CodeVisitorSupport(org.codehaus.groovy.ast.CodeVisitorSupport) ClassCodeVisitorSupport(org.codehaus.groovy.ast.ClassCodeVisitorSupport) UnaryMinusExpression(org.codehaus.groovy.ast.expr.UnaryMinusExpression) ClosureListExpression(org.codehaus.groovy.ast.expr.ClosureListExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) TernaryExpression(org.codehaus.groovy.ast.expr.TernaryExpression) CastExpression(org.codehaus.groovy.ast.expr.CastExpression) BooleanExpression(org.codehaus.groovy.ast.expr.BooleanExpression) PropertyExpression(org.codehaus.groovy.ast.expr.PropertyExpression) StaticMethodCallExpression(org.codehaus.groovy.ast.expr.StaticMethodCallExpression) PrefixExpression(org.codehaus.groovy.ast.expr.PrefixExpression) PostfixExpression(org.codehaus.groovy.ast.expr.PostfixExpression) Expression(org.codehaus.groovy.ast.expr.Expression) UnaryPlusExpression(org.codehaus.groovy.ast.expr.UnaryPlusExpression) BitwiseNegationExpression(org.codehaus.groovy.ast.expr.BitwiseNegationExpression) GStringExpression(org.codehaus.groovy.ast.expr.GStringExpression) ListExpression(org.codehaus.groovy.ast.expr.ListExpression) MapExpression(org.codehaus.groovy.ast.expr.MapExpression) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) RangeExpression(org.codehaus.groovy.ast.expr.RangeExpression) BytecodeExpression(org.codehaus.groovy.classgen.BytecodeExpression) SpreadExpression(org.codehaus.groovy.ast.expr.SpreadExpression) ArrayExpression(org.codehaus.groovy.ast.expr.ArrayExpression) NotExpression(org.codehaus.groovy.ast.expr.NotExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) FieldExpression(org.codehaus.groovy.ast.expr.FieldExpression) ElvisOperatorExpression(org.codehaus.groovy.ast.expr.ElvisOperatorExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) SpreadMapExpression(org.codehaus.groovy.ast.expr.SpreadMapExpression) ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) DeclarationExpression(org.codehaus.groovy.ast.expr.DeclarationExpression) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) AttributeExpression(org.codehaus.groovy.ast.expr.AttributeExpression) MethodPointerExpression(org.codehaus.groovy.ast.expr.MethodPointerExpression) MapEntryExpression(org.codehaus.groovy.ast.expr.MapEntryExpression) ScriptBody(com.disney.groovity.ScriptBody) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) AssertStatement(org.codehaus.groovy.ast.stmt.AssertStatement) Parameter(org.codehaus.groovy.ast.Parameter) Map(java.util.Map) VariableScope(org.codehaus.groovy.ast.VariableScope)

Example 49 with InnerClassNode

use of org.codehaus.groovy.ast.InnerClassNode in project groovy-core by groovy.

the class LazyASTTransformation method addHolderClassIdiomBody.

private static void addHolderClassIdiomBody(BlockStatement body, FieldNode fieldNode, Expression initExpr) {
    final ClassNode declaringClass = fieldNode.getDeclaringClass();
    final ClassNode fieldType = fieldNode.getType();
    final int visibility = ACC_PRIVATE | ACC_STATIC;
    final String fullName = declaringClass.getName() + "$" + fieldType.getNameWithoutPackage() + "Holder_" + fieldNode.getName().substring(1);
    final InnerClassNode holderClass = new InnerClassNode(declaringClass, fullName, visibility, ClassHelper.OBJECT_TYPE);
    final String innerFieldName = "INSTANCE";
    holderClass.addField(innerFieldName, ACC_PRIVATE | ACC_STATIC | ACC_FINAL, fieldType, initExpr);
    final Expression innerField = propX(classX(holderClass), innerFieldName);
    declaringClass.getModule().addClass(holderClass);
    body.addStatement(returnS(innerField));
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) Expression(org.codehaus.groovy.ast.expr.Expression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode)

Example 50 with InnerClassNode

use of org.codehaus.groovy.ast.InnerClassNode in project groovy-core by groovy.

the class StaticTypeCheckingVisitor method existsProperty.

/**
 * Checks whether a property exists on the receiver, or on any of the possible receiver classes (found in the
 * temporary type information table)
 *
 * @param pexp             a property expression
 * @param readMode         if true, look for property read, else for property set
 * @param visitor          if not null, when the property node is found, visit it with the provided visitor
 * @return true if the property is defined in any of the possible receiver classes
 */
protected boolean existsProperty(final PropertyExpression pexp, final boolean readMode, final ClassCodeVisitorSupport visitor) {
    super.visitPropertyExpression(pexp);
    String propertyName = pexp.getPropertyAsString();
    if (propertyName == null)
        return false;
    Expression objectExpression = pexp.getObjectExpression();
    final ClassNode objectExpressionType = getType(objectExpression);
    boolean staticOnlyAccess = isClassClassNodeWrappingConcreteType(objectExpressionType);
    if ("this".equals(propertyName) && staticOnlyAccess) {
        // Outer.this
        ClassNode outerNode = objectExpressionType.getGenericsTypes()[0].getType();
        ClassNode current = typeCheckingContext.getEnclosingClassNode();
        if (!current.isStaticClass() && current instanceof InnerClassNode) {
            InnerClassNode icn = (InnerClassNode) current;
            if (outerNode.equals(icn.getOuterClass())) {
                storeType(pexp, outerNode);
                return true;
            }
        }
    }
    if (objectExpressionType.isArray() && "length".equals(pexp.getPropertyAsString())) {
        storeType(pexp, int_TYPE);
        if (visitor != null) {
            PropertyNode node = new PropertyNode("length", Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, int_TYPE, objectExpressionType, null, null, null);
            visitor.visitProperty(node);
        }
        return true;
    }
    boolean foundGetterOrSetter = false;
    List<Receiver<String>> receivers = new LinkedList<Receiver<String>>();
    List<Receiver<String>> owners = makeOwnerList(objectExpression);
    addReceivers(receivers, owners, pexp.isImplicitThis());
    String capName = MetaClassHelper.capitalize(propertyName);
    boolean isAttributeExpression = pexp instanceof AttributeExpression;
    HashSet<ClassNode> handledNodes = new HashSet<ClassNode>();
    for (Receiver<String> receiver : receivers) {
        ClassNode testClass = receiver.getType();
        LinkedList<ClassNode> queue = new LinkedList<ClassNode>();
        queue.add(testClass);
        if (isPrimitiveType(testClass)) {
            queue.add(getWrapper(testClass));
        }
        while (!queue.isEmpty()) {
            ClassNode current = queue.removeFirst();
            if (handledNodes.contains(current))
                continue;
            handledNodes.add(current);
            Set<ClassNode> allInterfaces = current.getAllInterfaces();
            for (ClassNode intf : allInterfaces) {
                // TODO: apply right generics here!
                queue.add(GenericsUtils.parameterizeType(current, intf));
            }
            // in case of a lookup on Class we look for instance methods on Class
            // as well, since in case of a static property access we have the class
            // itself in the list of receivers already;
            boolean staticOnly;
            if (isClassClassNodeWrappingConcreteType(current)) {
                staticOnly = false;
            } else {
                staticOnly = staticOnlyAccess;
            }
            FieldNode field = current.getDeclaredField(propertyName);
            field = allowStaticAccessToMember(field, staticOnly);
            if (storeField(field, isAttributeExpression, pexp, current, visitor, receiver.getData()))
                return true;
            PropertyNode propertyNode = current.getProperty(propertyName);
            propertyNode = allowStaticAccessToMember(propertyNode, staticOnly);
            if (storeProperty(propertyNode, pexp, current, visitor, receiver.getData()))
                return true;
            boolean isThisExpression = objectExpression instanceof VariableExpression && ((VariableExpression) objectExpression).isThisExpression();
            if (storeField(field, isThisExpression, pexp, receiver.getType(), visitor, receiver.getData()))
                return true;
            MethodNode getter = current.getGetterMethod("get" + capName);
            getter = allowStaticAccessToMember(getter, staticOnly);
            if (getter == null)
                getter = current.getGetterMethod("is" + capName);
            getter = allowStaticAccessToMember(getter, staticOnly);
            final String setterName = "set" + capName;
            List<MethodNode> setters = findSetters(current, setterName, false);
            setters = allowStaticAccessToMember(setters, staticOnly);
            // need to visit even if we only look for a setters for compatibility
            if (visitor != null && getter != null)
                visitor.visitMethod(getter);
            if (readMode) {
                if (getter != null) {
                    ClassNode cn = inferReturnTypeGenerics(current, getter, ArgumentListExpression.EMPTY_ARGUMENTS);
                    storeInferredTypeForPropertyExpression(pexp, cn);
                    pexp.removeNodeMetaData(StaticTypesMarker.READONLY_PROPERTY);
                    String delegationData = receiver.getData();
                    if (delegationData != null)
                        pexp.putNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER, delegationData);
                    return true;
                }
            } else {
                if (!setters.isEmpty()) {
                    if (visitor != null) {
                        if (field != null) {
                            visitor.visitField(field);
                        } else {
                            for (MethodNode setter : setters) {
                                ClassNode setterType = setter.getParameters()[0].getOriginType();
                                FieldNode virtual = new FieldNode(propertyName, 0, setterType, current, EmptyExpression.INSTANCE);
                                visitor.visitField(virtual);
                            }
                        }
                    }
                    // TODO: apply generics on parameter[0]?
                    // storeType(pexp, setter.getParameters()[0].getType());
                    SetterInfo info = new SetterInfo(current, setterName, setters);
                    BinaryExpression enclosingBinaryExpression = typeCheckingContext.getEnclosingBinaryExpression();
                    if (enclosingBinaryExpression != null) {
                        putSetterInfo(enclosingBinaryExpression.getLeftExpression(), info);
                    }
                    String delegationData = receiver.getData();
                    if (delegationData != null) {
                        pexp.putNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER, delegationData);
                    }
                    return true;
                } else if (getter != null) {
                    pexp.putNodeMetaData(StaticTypesMarker.READONLY_PROPERTY, true);
                }
            }
            foundGetterOrSetter = foundGetterOrSetter || !setters.isEmpty() || getter != null;
            if (storeField(field, true, pexp, current, visitor, receiver.getData()))
                return true;
            // we stop now, otherwise we must check the parent class
            if (/*!isAttributeExpression && */
            current.getSuperClass() != null) {
                queue.add(current.getUnresolvedSuperClass());
            }
        }
        // GROOVY-5568, the property may be defined by DGM
        List<MethodNode> methods = findDGMMethodsByNameAndArguments(getTransformLoader(), testClass, "get" + capName, ClassNode.EMPTY_ARRAY);
        if (!methods.isEmpty()) {
            List<MethodNode> methodNodes = chooseBestMethod(testClass, methods, ClassNode.EMPTY_ARRAY);
            if (methodNodes.size() == 1) {
                MethodNode getter = methodNodes.get(0);
                if (visitor != null) {
                    visitor.visitMethod(getter);
                }
                ClassNode cn = inferReturnTypeGenerics(testClass, getter, ArgumentListExpression.EMPTY_ARGUMENTS);
                storeInferredTypeForPropertyExpression(pexp, cn);
                return true;
            }
        }
    }
    for (Receiver<String> receiver : receivers) {
        ClassNode testClass = receiver.getType();
        ClassNode propertyType = getTypeForMapPropertyExpression(testClass, objectExpressionType, pexp);
        if (propertyType == null)
            propertyType = getTypeForListPropertyExpression(testClass, objectExpressionType, pexp);
        if (propertyType == null)
            propertyType = getTypeForSpreadExpression(testClass, objectExpressionType, pexp);
        if (propertyType == null)
            continue;
        if (visitor != null) {
            // todo : type inference on maps and lists, if possible
            PropertyNode node = new PropertyNode(propertyName, Opcodes.ACC_PUBLIC, propertyType, receiver.getType(), null, null, null);
            node.setDeclaringClass(receiver.getType());
            visitor.visitProperty(node);
        }
        storeType(pexp, propertyType);
        String delegationData = receiver.getData();
        if (delegationData != null)
            pexp.putNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER, delegationData);
        return true;
    }
    return foundGetterOrSetter;
}
Also used : LowestUpperBoundClassNode(org.codehaus.groovy.ast.tools.WideningCategories.LowestUpperBoundClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) FieldNode(org.codehaus.groovy.ast.FieldNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) LinkedList(java.util.LinkedList) MethodNode(org.codehaus.groovy.ast.MethodNode) PropertyNode(org.codehaus.groovy.ast.PropertyNode) LinkedHashSet(java.util.LinkedHashSet) HashSet(java.util.HashSet)

Aggregations

InnerClassNode (org.codehaus.groovy.ast.InnerClassNode)78 ClassNode (org.codehaus.groovy.ast.ClassNode)67 MethodNode (org.codehaus.groovy.ast.MethodNode)33 FieldNode (org.codehaus.groovy.ast.FieldNode)20 Parameter (org.codehaus.groovy.ast.Parameter)20 BlockStatement (org.codehaus.groovy.ast.stmt.BlockStatement)20 ArrayList (java.util.ArrayList)17 MethodCallExpression (org.codehaus.groovy.ast.expr.MethodCallExpression)16 ClassExpression (org.codehaus.groovy.ast.expr.ClassExpression)15 ConstructorCallExpression (org.codehaus.groovy.ast.expr.ConstructorCallExpression)15 Expression (org.codehaus.groovy.ast.expr.Expression)15 ExpressionStatement (org.codehaus.groovy.ast.stmt.ExpressionStatement)14 VariableExpression (org.codehaus.groovy.ast.expr.VariableExpression)13 Statement (org.codehaus.groovy.ast.stmt.Statement)13 ConstructorNode (org.codehaus.groovy.ast.ConstructorNode)12 ClosureExpression (org.codehaus.groovy.ast.expr.ClosureExpression)12 ConstantExpression (org.codehaus.groovy.ast.expr.ConstantExpression)11 EnumConstantClassNode (org.codehaus.groovy.ast.EnumConstantClassNode)10 GenericsType (org.codehaus.groovy.ast.GenericsType)10 ArgumentListExpression (org.codehaus.groovy.ast.expr.ArgumentListExpression)9