Search in sources :

Example 1 with Reference

use of groovy.lang.Reference in project groovy by apache.

the class BindPathSnooper method createBinding.

public FullBinding createBinding(SourceBinding source, TargetBinding target) {
    if (source != this) {
        throw new RuntimeException("Source binding must the Trigger Binding as well");
    }
    final BindPathSnooper delegate = new BindPathSnooper();
    try {
        // create our own local copy of the closure
        final Class closureClass = closure.getClass();
        // do in privileged block since we may be looking at private stuff
        Closure closureLocalCopy = java.security.AccessController.doPrivileged(new PrivilegedAction<Closure>() {

            public Closure run() {
                // assume closures have only 1 constructor, of the form (Object, Reference*)
                Constructor constructor = closureClass.getConstructors()[0];
                int paramCount = constructor.getParameterTypes().length;
                Object[] args = new Object[paramCount];
                args[0] = delegate;
                for (int i = 1; i < paramCount; i++) {
                    args[i] = new Reference(new BindPathSnooper());
                }
                try {
                    boolean acc = constructor.isAccessible();
                    constructor.setAccessible(true);
                    Closure localCopy = (Closure) constructor.newInstance(args);
                    if (!acc) {
                        constructor.setAccessible(false);
                    }
                    localCopy.setResolveStrategy(Closure.DELEGATE_ONLY);
                    for (Field f : closureClass.getDeclaredFields()) {
                        acc = f.isAccessible();
                        f.setAccessible(true);
                        if (f.getType() == Reference.class) {
                            delegate.fields.put(f.getName(), (BindPathSnooper) ((Reference) f.get(localCopy)).get());
                        }
                        if (!acc) {
                            f.setAccessible(false);
                        }
                    }
                    return localCopy;
                } catch (Exception e) {
                    throw new RuntimeException("Error snooping closure", e);
                }
            }
        });
        try {
            closureLocalCopy.call();
        } catch (DeadEndException e) {
            // we want this exception exposed.
            throw e;
        } catch (Exception e) {
        //LOGME
        // ignore it, likely failing because we are faking out properties
        // such as a call to Math.min(int, BindPathSnooper)
        }
    } catch (Exception e) {
        e.printStackTrace(System.out);
        throw new RuntimeException("A closure expression binding could not be created because of " + e.getClass().getName() + ":\n\t" + e.getMessage());
    }
    List<BindPath> rootPaths = new ArrayList<BindPath>();
    for (Map.Entry<String, BindPathSnooper> entry : delegate.fields.entrySet()) {
        BindPath bp = createBindPath(entry.getKey(), entry.getValue());
        bp.currentObject = closure;
        rootPaths.add(bp);
    }
    PropertyPathFullBinding fb = new PropertyPathFullBinding();
    fb.setSourceBinding(new ClosureSourceBinding(closure));
    fb.setTargetBinding(target);
    fb.bindPaths = rootPaths.toArray(new BindPath[rootPaths.size()]);
    return fb;
}
Also used : Closure(groovy.lang.Closure) Constructor(java.lang.reflect.Constructor) Reference(groovy.lang.Reference) ArrayList(java.util.ArrayList) Field(java.lang.reflect.Field) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map)

Example 2 with Reference

use of groovy.lang.Reference in project groovy by apache.

the class StaticCompilationVisitor method existsProperty.

@Override
protected boolean existsProperty(final PropertyExpression pexp, final boolean checkForReadOnly, final ClassCodeVisitorSupport visitor) {
    Expression objectExpression = pexp.getObjectExpression();
    ClassNode objectExpressionType = getType(objectExpression);
    Reference<ClassNode> rType = new Reference<>(objectExpressionType);
    ClassCodeVisitorSupport receiverMemoizer = new ClassCodeVisitorSupport() {

        @Override
        protected SourceUnit getSourceUnit() {
            return null;
        }

        @Override
        public void visitField(final FieldNode node) {
            if (visitor != null)
                visitor.visitField(node);
            ClassNode declaringClass = node.getDeclaringClass();
            if (declaringClass != null) {
                if (StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(declaringClass, LIST_TYPE)) {
                    boolean spread = declaringClass.getDeclaredField(node.getName()) != node;
                    pexp.setSpreadSafe(spread);
                }
                rType.set(declaringClass);
            }
        }

        @Override
        public void visitMethod(final MethodNode node) {
            if (visitor != null)
                visitor.visitMethod(node);
            ClassNode declaringClass = node.getDeclaringClass();
            if (declaringClass != null) {
                if (StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(declaringClass, LIST_TYPE)) {
                    List<MethodNode> properties = declaringClass.getDeclaredMethods(node.getName());
                    boolean spread = true;
                    for (MethodNode mn : properties) {
                        if (node == mn) {
                            spread = false;
                            break;
                        }
                    }
                    // it's no real property but a property of the component
                    pexp.setSpreadSafe(spread);
                }
                rType.set(declaringClass);
            }
        }

        @Override
        public void visitProperty(final PropertyNode node) {
            if (visitor != null)
                visitor.visitProperty(node);
            ClassNode declaringClass = node.getDeclaringClass();
            if (declaringClass != null) {
                if (StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(declaringClass, LIST_TYPE)) {
                    List<PropertyNode> properties = declaringClass.getProperties();
                    boolean spread = true;
                    for (PropertyNode propertyNode : properties) {
                        if (propertyNode == node) {
                            spread = false;
                            break;
                        }
                    }
                    // it's no real property but a property of the component
                    pexp.setSpreadSafe(spread);
                }
                rType.set(declaringClass);
            }
        }
    };
    boolean exists = super.existsProperty(pexp, checkForReadOnly, receiverMemoizer);
    if (exists) {
        objectExpressionType = rType.get();
        if (objectExpression.getNodeMetaData(PROPERTY_OWNER) == null) {
            objectExpression.putNodeMetaData(PROPERTY_OWNER, objectExpressionType);
        }
        if (StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(objectExpressionType, LIST_TYPE)) {
            objectExpression.putNodeMetaData(COMPONENT_TYPE, inferComponentType(objectExpressionType, int_TYPE));
        }
    }
    return exists;
}
Also used : InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) ClassCodeVisitorSupport(org.codehaus.groovy.ast.ClassCodeVisitorSupport) FieldNode(org.codehaus.groovy.ast.FieldNode) MethodNode(org.codehaus.groovy.ast.MethodNode) SpreadExpression(org.codehaus.groovy.ast.expr.SpreadExpression) ClosureListExpression(org.codehaus.groovy.ast.expr.ClosureListExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) PropertyExpression(org.codehaus.groovy.ast.expr.PropertyExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) Expression(org.codehaus.groovy.ast.expr.Expression) ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) Reference(groovy.lang.Reference) PropertyNode(org.codehaus.groovy.ast.PropertyNode)

Example 3 with Reference

use of groovy.lang.Reference in project groovy by apache.

the class CategoryASTTransformation method transformReferencesToThis.

// --------------------------------------------------------------------------
private void transformReferencesToThis(final ClassNode targetClass, final ClassNode sourceClass, final SourceUnit sourceUnit) {
    final Reference<Parameter> selfParameter = new Reference<>();
    final LinkedList<Set<String>> varStack = new LinkedList<>();
    Set<String> names = new HashSet<>();
    for (FieldNode fn : sourceClass.getFields()) names.add(fn.getName());
    for (PropertyNode pn : sourceClass.getProperties()) names.add(pn.getName());
    varStack.add(names);
    ClassCodeExpressionTransformer transformer = new ClassCodeExpressionTransformer() {

        // GROOVY-6510: track closure containment
        private boolean inClosure;

        private void addVariablesToStack(final Parameter[] parameter) {
            Set<String> names = new HashSet<>(varStack.getLast());
            for (Parameter p : parameter) names.add(p.getName());
            varStack.add(names);
        }

        private Expression createThisExpression() {
            VariableExpression ve = new VariableExpression("$this", targetClass);
            ve.setClosureSharedVariable(true);
            return ve;
        }

        @Override
        protected SourceUnit getSourceUnit() {
            return sourceUnit;
        }

        @Override
        public Expression transform(final Expression expression) {
            if (expression instanceof VariableExpression) {
                VariableExpression ve = (VariableExpression) expression;
                if (ve.isThisExpression()) {
                    Expression thisExpression = createThisExpression();
                    thisExpression.setSourcePosition(ve);
                    return thisExpression;
                } else if (!inClosure && !ve.isSuperExpression() && !varStack.getLast().contains(ve.getName())) {
                    PropertyExpression pe = new PropertyExpression(createThisExpression(), ve.getName());
                    pe.setSourcePosition(ve);
                    return pe;
                }
            } else if (expression instanceof MethodCallExpression) {
                MethodCallExpression mce = (MethodCallExpression) expression;
                if (inClosure && mce.isImplicitThis() && isThisExpression(mce.getObjectExpression())) {
                    // GROOVY-6510: preserve implicit-this semantics
                    mce.setArguments(transform(mce.getArguments()));
                    mce.setMethod(transform(mce.getMethod()));
                    return mce;
                }
            } else if (expression instanceof ClosureExpression) {
                ClosureExpression ce = (ClosureExpression) expression;
                addVariablesToStack(hasImplicitParameter(ce) ? params(param(ClassHelper.OBJECT_TYPE, "it")) : getParametersSafe(ce));
                ce.getVariableScope().putReferencedLocalVariable(selfParameter.get());
                addAll(varStack.getLast(), "owner", "delegate", "thisObject");
                boolean closure = inClosure;
                inClosure = true;
                ce.getCode().visit(this);
                varStack.removeLast();
                inClosure = closure;
            }
            return super.transform(expression);
        }

        @Override
        public void visitBlockStatement(final BlockStatement statement) {
            Set<String> names = new HashSet<>(varStack.getLast());
            varStack.add(names);
            super.visitBlockStatement(statement);
            varStack.remove(names);
        }

        @Override
        public void visitCatchStatement(final CatchStatement statement) {
            varStack.getLast().add(statement.getVariable().getName());
            super.visitCatchStatement(statement);
            varStack.getLast().remove(statement.getVariable().getName());
        }

        @Override
        public void visitClosureExpression(final ClosureExpression expression) {
        }

        @Override
        public void visitDeclarationExpression(final DeclarationExpression expression) {
            if (expression.isMultipleAssignmentDeclaration()) {
                for (Expression e : expression.getTupleExpression().getExpressions()) {
                    VariableExpression ve = (VariableExpression) e;
                    varStack.getLast().add(ve.getName());
                }
            } else {
                VariableExpression ve = expression.getVariableExpression();
                varStack.getLast().add(ve.getName());
            }
            super.visitDeclarationExpression(expression);
        }

        @Override
        public void visitExpressionStatement(final ExpressionStatement statement) {
            // GROOVY-3543: visit the declaration expressions so that declaration variables get added on the varStack
            if (statement.getExpression() instanceof DeclarationExpression) {
                statement.getExpression().visit(this);
            }
            super.visitExpressionStatement(statement);
        }

        @Override
        public void visitForLoop(final ForStatement statement) {
            Expression exp = statement.getCollectionExpression();
            exp.visit(this);
            Parameter loopParam = statement.getVariable();
            if (loopParam != null) {
                varStack.getLast().add(loopParam.getName());
            }
            super.visitForLoop(statement);
        }

        @Override
        public void visitMethod(final MethodNode node) {
            addVariablesToStack(node.getParameters());
            super.visitMethod(node);
            varStack.removeLast();
        }
    };
    for (MethodNode method : sourceClass.getMethods()) {
        if (!method.isStatic()) {
            Parameter p = new Parameter(targetClass, "$this");
            p.setClosureSharedVariable(true);
            selfParameter.set(p);
            Parameter[] oldParams = method.getParameters();
            Parameter[] newParams = new Parameter[oldParams.length + 1];
            newParams[0] = p;
            System.arraycopy(oldParams, 0, newParams, 1, oldParams.length);
            method.setModifiers(method.getModifiers() | Opcodes.ACC_STATIC);
            method.setParameters(newParams);
            transformer.visitMethod(method);
        }
    }
}
Also used : HashSet(java.util.HashSet) Set(java.util.Set) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) MethodNode(org.codehaus.groovy.ast.MethodNode) PropertyNode(org.codehaus.groovy.ast.PropertyNode) PropertyExpression(org.codehaus.groovy.ast.expr.PropertyExpression) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression) ForStatement(org.codehaus.groovy.ast.stmt.ForStatement) HashSet(java.util.HashSet) ClassCodeExpressionTransformer(org.codehaus.groovy.ast.ClassCodeExpressionTransformer) FieldNode(org.codehaus.groovy.ast.FieldNode) Reference(groovy.lang.Reference) DeclarationExpression(org.codehaus.groovy.ast.expr.DeclarationExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) LinkedList(java.util.LinkedList) CatchStatement(org.codehaus.groovy.ast.stmt.CatchStatement) PropertyExpression(org.codehaus.groovy.ast.expr.PropertyExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) Expression(org.codehaus.groovy.ast.expr.Expression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) DeclarationExpression(org.codehaus.groovy.ast.expr.DeclarationExpression) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) ExpressionUtils.isThisExpression(org.apache.groovy.ast.tools.ExpressionUtils.isThisExpression) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) Parameter(org.codehaus.groovy.ast.Parameter) ClosureUtils.hasImplicitParameter(org.codehaus.groovy.ast.tools.ClosureUtils.hasImplicitParameter)

Example 4 with Reference

use of groovy.lang.Reference in project groovy by apache.

the class DelegateASTTransformation method addGetterIfNeeded.

private static void addGetterIfNeeded(final DelegateDescription delegate, final PropertyNode prop, final String name, final boolean allNames) {
    boolean isPrimBool = isPrimitiveBoolean(prop.getOriginType());
    // do a little bit of pre-work since Groovy compiler hasn't added property accessors yet
    boolean willHaveGetAccessor = true;
    boolean willHaveIsAccessor = isPrimBool;
    String getterName = getGetterName(name);
    String isserName = getPredicateName(name);
    if (isPrimBool) {
        ClassNode cNode = prop.getDeclaringClass();
        if (cNode.getGetterMethod(isserName) != null && cNode.getGetterMethod(getterName) == null)
            willHaveGetAccessor = false;
        if (cNode.getGetterMethod(getterName) != null && cNode.getGetterMethod(isserName) == null)
            willHaveIsAccessor = false;
    }
    Reference<Boolean> ownerWillHaveGetAccessor = new Reference<Boolean>();
    Reference<Boolean> ownerWillHaveIsAccessor = new Reference<Boolean>();
    extractAccessorInfo(delegate.owner, name, ownerWillHaveGetAccessor, ownerWillHaveIsAccessor);
    if (willHaveGetAccessor && !ownerWillHaveGetAccessor.get() && !shouldSkipPropertyMethod(name, getterName, delegate.excludes, delegate.includes, allNames)) {
        addGeneratedMethod(delegate.owner, getterName, ACC_PUBLIC, nonGeneric(prop.getType()), Parameter.EMPTY_ARRAY, null, returnS(propX(delegate.getOp, name)));
    }
    if (willHaveIsAccessor && !ownerWillHaveIsAccessor.get() && !shouldSkipPropertyMethod(name, getterName, delegate.excludes, delegate.includes, allNames)) {
        addGeneratedMethod(delegate.owner, isserName, ACC_PUBLIC, nonGeneric(prop.getType()), Parameter.EMPTY_ARRAY, null, returnS(propX(delegate.getOp, name)));
    }
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) Reference(groovy.lang.Reference) ClassHelper.isPrimitiveBoolean(org.codehaus.groovy.ast.ClassHelper.isPrimitiveBoolean)

Example 5 with Reference

use of groovy.lang.Reference in project groovy by apache.

the class BindPathSnooper method createBinding.

@Override
public FullBinding createBinding(SourceBinding source, TargetBinding target) {
    if (source != this) {
        throw new RuntimeException("Source binding must the Trigger Binding as well");
    }
    final BindPathSnooper delegate = new BindPathSnooper();
    try {
        // create our own local copy of the closure
        final Class closureClass = closure.getClass();
        // do in privileged block since we may be looking at private stuff
        Closure closureLocalCopy = VMPluginFactory.getPlugin().doPrivileged(new PrivilegedAction<Closure>() {

            @Override
            public Closure run() {
                // assume closures have only 1 constructor, of the form (Object, Reference*)
                Constructor constructor = closureClass.getConstructors()[0];
                int paramCount = constructor.getParameterTypes().length;
                Object[] args = new Object[paramCount];
                args[0] = delegate;
                for (int i = 1; i < paramCount; i++) {
                    args[i] = new Reference<Object>(new BindPathSnooper());
                }
                try {
                    boolean acc = isAccessible(constructor);
                    ReflectionUtils.trySetAccessible(constructor);
                    Closure localCopy = (Closure) constructor.newInstance(args);
                    if (!acc) {
                        constructor.setAccessible(false);
                    }
                    localCopy.setResolveStrategy(Closure.DELEGATE_ONLY);
                    for (Field f : closureClass.getDeclaredFields()) {
                        acc = isAccessible(f);
                        ReflectionUtils.trySetAccessible(f);
                        if (f.getType() == Reference.class) {
                            delegate.fields.put(f.getName(), (BindPathSnooper) ((Reference) f.get(localCopy)).get());
                        }
                        if (!acc) {
                            f.setAccessible(false);
                        }
                    }
                    return localCopy;
                } catch (Exception e) {
                    throw new RuntimeException("Error snooping closure", e);
                }
            }
        });
        try {
            closureLocalCopy.call();
        } catch (DeadEndException e) {
            // we want this exception exposed.
            throw e;
        } catch (Exception e) {
        // LOGME
        // ignore it, likely failing because we are faking out properties
        // such as a call to Math.min(int, BindPathSnooper)
        }
    } catch (Exception e) {
        e.printStackTrace(System.out);
        throw new RuntimeException("A closure expression binding could not be created because of " + e.getClass().getName() + ":\n\t" + e.getMessage());
    }
    List<BindPath> rootPaths = new ArrayList<BindPath>();
    for (Map.Entry<String, BindPathSnooper> entry : delegate.fields.entrySet()) {
        BindPath bp = createBindPath(entry.getKey(), entry.getValue());
        bp.currentObject = closure;
        rootPaths.add(bp);
    }
    PropertyPathFullBinding fb = new PropertyPathFullBinding();
    fb.setSourceBinding(new ClosureSourceBinding(closure));
    fb.setTargetBinding(target);
    fb.bindPaths = rootPaths.toArray(EMPTY_BINDPATH_ARRAY);
    return fb;
}
Also used : Closure(groovy.lang.Closure) Constructor(java.lang.reflect.Constructor) Reference(groovy.lang.Reference) ArrayList(java.util.ArrayList) Field(java.lang.reflect.Field) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map)

Aggregations

Reference (groovy.lang.Reference)8 Closure (groovy.lang.Closure)3 Constructor (java.lang.reflect.Constructor)3 Field (java.lang.reflect.Field)3 ArrayList (java.util.ArrayList)3 LinkedHashMap (java.util.LinkedHashMap)3 Map (java.util.Map)3 ClassNode (org.codehaus.groovy.ast.ClassNode)3 FieldNode (org.codehaus.groovy.ast.FieldNode)3 MethodNode (org.codehaus.groovy.ast.MethodNode)3 PropertyNode (org.codehaus.groovy.ast.PropertyNode)3 Expression (org.codehaus.groovy.ast.expr.Expression)3 PropertyExpression (org.codehaus.groovy.ast.expr.PropertyExpression)3 HashSet (java.util.HashSet)2 LinkedList (java.util.LinkedList)2 Set (java.util.Set)2 ClassCodeExpressionTransformer (org.codehaus.groovy.ast.ClassCodeExpressionTransformer)2 Parameter (org.codehaus.groovy.ast.Parameter)2 ClassExpression (org.codehaus.groovy.ast.expr.ClassExpression)2 ClosureExpression (org.codehaus.groovy.ast.expr.ClosureExpression)2