Search in sources :

Example 1 with DynamicVariable

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

the class TraitReceiverTransformer method transform.

@Override
public Expression transform(final Expression exp) {
    ClassNode weavedType = weaved.getOriginType();
    if (exp instanceof BinaryExpression) {
        return transformBinaryExpression((BinaryExpression) exp, weavedType);
    } else if (exp instanceof StaticMethodCallExpression) {
        StaticMethodCallExpression call = (StaticMethodCallExpression) exp;
        ClassNode ownerType = call.getOwnerType();
        if (traitClass.equals(ownerType)) {
            MethodCallExpression result = new MethodCallExpression(new VariableExpression(weaved), call.getMethod(), transform(call.getArguments()));
            result.setSafe(false);
            result.setImplicitThis(false);
            result.setSpreadSafe(false);
            result.setSourcePosition(call);
            return result;
        }
    } else if (exp instanceof MethodCallExpression) {
        MethodCallExpression call = (MethodCallExpression) exp;
        Expression obj = call.getObjectExpression();
        if (call.isImplicitThis() || "this".equals(obj.getText())) {
            return transformMethodCallOnThis(call);
        } else if ("super".equals(obj.getText())) {
            return transformSuperMethodCall(call);
        }
    } else if (exp instanceof FieldExpression) {
        return transformFieldExpression((FieldExpression) exp);
    } else if (exp instanceof VariableExpression) {
        VariableExpression vexp = (VariableExpression) exp;
        Variable accessedVariable = vexp.getAccessedVariable();
        if (accessedVariable instanceof FieldNode) {
            FieldNode fn = (FieldNode) accessedVariable;
            Expression receiver = createFieldHelperReceiver();
            MethodCallExpression mce;
            boolean isStatic = fn.isStatic();
            if (isStatic) {
                receiver = createStaticReceiver(receiver);
            }
            mce = new MethodCallExpression(receiver, Traits.helperGetterName(fn), ArgumentListExpression.EMPTY_ARGUMENTS);
            mce.setSourcePosition(exp);
            mce.setImplicitThis(false);
            markDynamicCall(mce, fn, isStatic);
            return mce;
        } else if (accessedVariable instanceof PropertyNode) {
            String propName = accessedVariable.getName();
            if (knownFields.contains(propName)) {
                String method = Traits.helperGetterName(new FieldNode(propName, 0, ClassHelper.OBJECT_TYPE, weavedType, null));
                MethodCallExpression mce = new MethodCallExpression(createFieldHelperReceiver(), method, ArgumentListExpression.EMPTY_ARGUMENTS);
                mce.setSourcePosition(exp);
                mce.setImplicitThis(false);
                return mce;
            } else {
                return new PropertyExpression(new VariableExpression(weaved), accessedVariable.getName());
            }
        } else if (accessedVariable instanceof DynamicVariable) {
            return new PropertyExpression(new VariableExpression(weaved), accessedVariable.getName());
        }
        if (vexp.isThisExpression()) {
            VariableExpression res = new VariableExpression(weaved);
            res.setSourcePosition(exp);
            return res;
        }
        if (vexp.isSuperExpression()) {
            throwSuperError(vexp);
        }
    } else if (exp instanceof PropertyExpression) {
        PropertyExpression pexp = (PropertyExpression) exp;
        Expression object = pexp.getObjectExpression();
        if (pexp.isImplicitThis() || "this".equals(object.getText())) {
            String propName = pexp.getPropertyAsString();
            if (knownFields.contains(propName)) {
                String method = Traits.helperGetterName(new FieldNode(propName, 0, ClassHelper.OBJECT_TYPE, weavedType, null));
                MethodCallExpression mce = new MethodCallExpression(createFieldHelperReceiver(), method, ArgumentListExpression.EMPTY_ARGUMENTS);
                mce.setSourcePosition(exp);
                mce.setImplicitThis(false);
                return mce;
            }
        }
    } else if (exp instanceof ClosureExpression) {
        MethodCallExpression mce = new MethodCallExpression(exp, "rehydrate", new ArgumentListExpression(new VariableExpression(weaved), new VariableExpression(weaved), new VariableExpression(weaved)));
        mce.setImplicitThis(false);
        mce.setSourcePosition(exp);
        ((ClosureExpression) exp).getCode().visit(this);
        // The rewrite we do is causing some troubles with type checking, which will
        // not be able to perform closure parameter type inference
        // so we store the replacement, which will be done *after* type checking.
        exp.putNodeMetaData(TraitASTTransformation.POST_TYPECHECKING_REPLACEMENT, mce);
        return exp;
    }
    // todo: unary expressions (field++, field+=, ...)
    return super.transform(exp);
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) Variable(org.codehaus.groovy.ast.Variable) DynamicVariable(org.codehaus.groovy.ast.DynamicVariable) FieldNode(org.codehaus.groovy.ast.FieldNode) StaticMethodCallExpression(org.codehaus.groovy.ast.expr.StaticMethodCallExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) FieldExpression(org.codehaus.groovy.ast.expr.FieldExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) StaticMethodCallExpression(org.codehaus.groovy.ast.expr.StaticMethodCallExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) BooleanExpression(org.codehaus.groovy.ast.expr.BooleanExpression) PropertyExpression(org.codehaus.groovy.ast.expr.PropertyExpression) StaticMethodCallExpression(org.codehaus.groovy.ast.expr.StaticMethodCallExpression) 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) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) DeclarationExpression(org.codehaus.groovy.ast.expr.DeclarationExpression) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) FieldExpression(org.codehaus.groovy.ast.expr.FieldExpression) TernaryExpression(org.codehaus.groovy.ast.expr.TernaryExpression) CastExpression(org.codehaus.groovy.ast.expr.CastExpression) DynamicVariable(org.codehaus.groovy.ast.DynamicVariable) PropertyNode(org.codehaus.groovy.ast.PropertyNode) PropertyExpression(org.codehaus.groovy.ast.expr.PropertyExpression) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression)

Example 2 with DynamicVariable

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

the class MarkupBuilderCodeTransformer method transform.

@Override
public Expression transform(final Expression exp) {
    if (exp instanceof BinaryExpression) {
        return transformBinaryExpression((BinaryExpression) exp);
    }
    if (exp instanceof MethodCallExpression) {
        return transformMethodCall((MethodCallExpression) exp);
    }
    if (exp instanceof ClosureExpression) {
        ClosureExpression cl = (ClosureExpression) exp;
        cl.getCode().visit(this);
        return cl;
    }
    if (exp instanceof VariableExpression) {
        VariableExpression var = (VariableExpression) exp;
        if (var.getAccessedVariable() instanceof DynamicVariable) {
            MethodCallExpression callGetModel = new MethodCallExpression(new VariableExpression("this"), "getModel", ArgumentListExpression.EMPTY_ARGUMENTS);
            callGetModel.setImplicitThis(true);
            callGetModel.setSourcePosition(exp);
            String varName = var.getName();
            if ("model".equals(varName) || "unescaped".equals(varName)) {
                return callGetModel;
            }
            MethodCallExpression mce = new MethodCallExpression(callGetModel, "get", new ArgumentListExpression(new ConstantExpression(varName)));
            mce.setSourcePosition(exp);
            mce.setImplicitThis(false);
            MethodCallExpression yield = new MethodCallExpression(new VariableExpression("this"), "tryEscape", new ArgumentListExpression(mce));
            yield.setImplicitThis(true);
            yield.setSourcePosition(exp);
            yield.putNodeMetaData(TARGET_VARIABLE, varName);
            return autoEscape ? yield : mce;
        }
    }
    return super.transform(exp);
}
Also used : BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) DynamicVariable(org.codehaus.groovy.ast.DynamicVariable) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression)

Example 3 with DynamicVariable

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

the class ResolveVisitor method transformVariableExpression.

protected Expression transformVariableExpression(final VariableExpression ve) {
    visitAnnotations(ve);
    Variable v = ve.getAccessedVariable();
    if (!(v instanceof DynamicVariable) && !checkingVariableTypeInDeclaration) {
        /*
             *  GROOVY-4009: when a normal variable is simply being used, there is no need to try to
             *  resolve its type. Variable type resolve should proceed only if the variable is being declared.
             */
        return ve;
    }
    if (v instanceof DynamicVariable) {
        String name = ve.getName();
        ClassNode t = ClassHelper.make(name);
        // asking isResolved here allows to check if a primitive
        // type name like "int" was used to make t. In such a case
        // we have nothing left to do.
        boolean isClass = t.isResolved();
        if (!isClass) {
            // compiler skip the resolving at several places in this class.
            if (Character.isLowerCase(name.charAt(0))) {
                t = new LowerCaseClass(name);
            }
            isClass = resolve(t);
        }
        if (isClass) {
            // for each parentscope too
            for (VariableScope scope = currentScope; scope != null && !scope.isRoot(); scope = scope.getParent()) {
                if (scope.removeReferencedClassVariable(ve.getName()) == null)
                    break;
            }
            return new ClassExpression(t);
        }
    }
    resolveOrFail(ve.getType(), ve);
    ClassNode origin = ve.getOriginType();
    if (origin != ve.getType())
        resolveOrFail(origin, ve);
    return ve;
}
Also used : InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) Variable(org.codehaus.groovy.ast.Variable) DynamicVariable(org.codehaus.groovy.ast.DynamicVariable) DynamicVariable(org.codehaus.groovy.ast.DynamicVariable) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) VariableScope(org.codehaus.groovy.ast.VariableScope)

Example 4 with DynamicVariable

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

the class VariableScopeVisitor method findVariableDeclaration.

private Variable findVariableDeclaration(final String name) {
    if ("super".equals(name) || "this".equals(name))
        return null;
    Variable variable = null;
    VariableScope scope = currentScope;
    boolean crossingStaticContext = false;
    // try to find a declaration of a variable
    while (true) {
        crossingStaticContext = (crossingStaticContext || scope.isInStaticContext());
        Variable var = scope.getDeclaredVariable(name);
        if (var != null) {
            variable = var;
            break;
        }
        var = scope.getReferencedLocalVariable(name);
        if (var != null) {
            variable = var;
            break;
        }
        var = scope.getReferencedClassVariable(name);
        if (var != null) {
            variable = var;
            break;
        }
        ClassNode node = scope.getClassScope();
        if (node != null) {
            Variable member = findClassMember(node, name);
            boolean requireStatic = (crossingStaticContext || inSpecialConstructorCall);
            while (member == null && node.getOuterClass() != null && !isAnonymous(node)) {
                requireStatic = requireStatic || isStatic(node.getModifiers());
                member = findClassMember((node = node.getOuterClass()), name);
            }
            if (member != null) {
                // prevent a static context (e.g. a static method) from accessing a non-static member (e.g. a non-static field)
                if (requireStatic ? member.isInStaticContext() : !node.isScript()) {
                    variable = member;
                }
            }
            // GROOVY-5961
            if (!isAnonymous(scope.getClassScope()))
                break;
        }
        scope = scope.getParent();
    }
    if (variable == null) {
        variable = new DynamicVariable(name, crossingStaticContext);
    }
    boolean isClassVariable = (scope.isClassScope() && !scope.isReferencedLocalVariable(name)) || (scope.isReferencedClassVariable(name) && scope.getDeclaredVariable(name) == null);
    VariableScope end = scope;
    scope = currentScope;
    while (scope != end) {
        if (isClassVariable) {
            scope.putReferencedClassVariable(variable);
        } else {
            scope.putReferencedLocalVariable(variable);
        }
        scope = scope.getParent();
    }
    return variable;
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) Variable(org.codehaus.groovy.ast.Variable) DynamicVariable(org.codehaus.groovy.ast.DynamicVariable) DynamicVariable(org.codehaus.groovy.ast.DynamicVariable) VariableScope(org.codehaus.groovy.ast.VariableScope)

Example 5 with DynamicVariable

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

the class LogASTTransformation method visit.

@Override
public void visit(final ASTNode[] nodes, final SourceUnit sourceUnit) {
    init(nodes, sourceUnit);
    AnnotatedNode targetClass = (AnnotatedNode) nodes[1];
    AnnotationNode logAnnotation = (AnnotationNode) nodes[0];
    final LoggingStrategy loggingStrategy = createLoggingStrategy(logAnnotation, sourceUnit.getClassLoader(), compilationUnit.getTransformLoader());
    if (loggingStrategy == null)
        return;
    final String logFieldName = lookupLogFieldName(logAnnotation);
    final String categoryName = lookupCategoryName(logAnnotation);
    final int logFieldModifiers = lookupLogFieldModifiers(targetClass, logAnnotation);
    if (!(targetClass instanceof ClassNode))
        throw new GroovyBugError("Class annotation " + logAnnotation.getClassNode().getName() + " annotated no Class, this must not happen.");
    final ClassNode classNode = (ClassNode) targetClass;
    ClassCodeExpressionTransformer transformer = new ClassCodeExpressionTransformer() {

        private FieldNode logNode;

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

        @Override
        public Expression transform(final Expression exp) {
            if (exp == null)
                return null;
            if (exp instanceof MethodCallExpression) {
                return transformMethodCallExpression(exp);
            }
            if (exp instanceof ClosureExpression) {
                return transformClosureExpression((ClosureExpression) exp);
            }
            return super.transform(exp);
        }

        @Override
        public void visitClass(final ClassNode node) {
            FieldNode logField = node.getField(logFieldName);
            if (logField != null && logField.getOwner().equals(node)) {
                addError("Class annotated with Log annotation cannot have log field declared", logField);
            } else if (logField != null && !Modifier.isPrivate(logField.getModifiers())) {
                addError("Class annotated with Log annotation cannot have log field declared because the field exists in the parent class: " + logField.getOwner().getName(), logField);
            } else {
                if (loggingStrategy instanceof LoggingStrategyV2) {
                    LoggingStrategyV2 loggingStrategyV2 = (LoggingStrategyV2) loggingStrategy;
                    logNode = loggingStrategyV2.addLoggerFieldToClass(node, logFieldName, categoryName, logFieldModifiers);
                } else {
                    // support the old style but they won't be as configurable
                    logNode = loggingStrategy.addLoggerFieldToClass(node, logFieldName, categoryName);
                }
            }
            super.visitClass(node);
        }

        private Expression transformClosureExpression(final ClosureExpression exp) {
            if (exp.getCode() instanceof BlockStatement) {
                BlockStatement code = (BlockStatement) exp.getCode();
                super.visitBlockStatement(code);
            }
            return exp;
        }

        private Expression transformMethodCallExpression(final Expression exp) {
            Expression modifiedCall = addGuard((MethodCallExpression) exp);
            return modifiedCall == null ? super.transform(exp) : modifiedCall;
        }

        private Expression addGuard(final MethodCallExpression mce) {
            // only add guard to methods of the form: logVar.logMethod(params)
            if (!(mce.getObjectExpression() instanceof VariableExpression)) {
                return null;
            }
            VariableExpression variableExpression = (VariableExpression) mce.getObjectExpression();
            if (!variableExpression.getName().equals(logFieldName) || !(variableExpression.getAccessedVariable() instanceof DynamicVariable)) {
                return null;
            }
            String methodName = mce.getMethodAsString();
            if (methodName == null)
                return null;
            if (!loggingStrategy.isLoggingMethod(methodName))
                return null;
            // since there is no saving
            if (usesSimpleMethodArgumentsOnly(mce))
                return null;
            variableExpression.setAccessedVariable(logNode);
            return loggingStrategy.wrapLoggingMethodCall(variableExpression, methodName, mce);
        }

        private boolean usesSimpleMethodArgumentsOnly(final MethodCallExpression mce) {
            Expression arguments = mce.getArguments();
            if (arguments instanceof TupleExpression) {
                TupleExpression tuple = (TupleExpression) arguments;
                for (Expression exp : tuple.getExpressions()) {
                    if (!isSimpleExpression(exp))
                        return false;
                }
                return true;
            }
            return !isSimpleExpression(arguments);
        }

        private boolean isSimpleExpression(final Expression exp) {
            if (exp instanceof ConstantExpression)
                return true;
            if (exp instanceof VariableExpression)
                return true;
            return false;
        }
    };
    transformer.visitClass(classNode);
    // GROOVY-6373: references to 'log' field are normally already FieldNodes by now, so revisit scoping
    new VariableScopeVisitor(sourceUnit, true).visitClass(classNode);
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) FieldNode(org.codehaus.groovy.ast.FieldNode) AnnotatedNode(org.codehaus.groovy.ast.AnnotatedNode) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) GroovyBugError(org.codehaus.groovy.GroovyBugError) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) AnnotationNode(org.codehaus.groovy.ast.AnnotationNode) 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) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) DynamicVariable(org.codehaus.groovy.ast.DynamicVariable) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression) VariableScopeVisitor(org.codehaus.groovy.classgen.VariableScopeVisitor) ClassCodeExpressionTransformer(org.codehaus.groovy.ast.ClassCodeExpressionTransformer)

Aggregations

DynamicVariable (org.codehaus.groovy.ast.DynamicVariable)22 VariableExpression (org.codehaus.groovy.ast.expr.VariableExpression)15 ClassNode (org.codehaus.groovy.ast.ClassNode)12 Variable (org.codehaus.groovy.ast.Variable)12 ClosureExpression (org.codehaus.groovy.ast.expr.ClosureExpression)10 MethodCallExpression (org.codehaus.groovy.ast.expr.MethodCallExpression)10 BinaryExpression (org.codehaus.groovy.ast.expr.BinaryExpression)9 ConstantExpression (org.codehaus.groovy.ast.expr.ConstantExpression)9 Expression (org.codehaus.groovy.ast.expr.Expression)9 FieldNode (org.codehaus.groovy.ast.FieldNode)6 InnerClassNode (org.codehaus.groovy.ast.InnerClassNode)6 ArgumentListExpression (org.codehaus.groovy.ast.expr.ArgumentListExpression)6 PropertyExpression (org.codehaus.groovy.ast.expr.PropertyExpression)6 TupleExpression (org.codehaus.groovy.ast.expr.TupleExpression)5 Parameter (org.codehaus.groovy.ast.Parameter)4 PropertyNode (org.codehaus.groovy.ast.PropertyNode)4 ClassExpression (org.codehaus.groovy.ast.expr.ClassExpression)4 DeclarationExpression (org.codehaus.groovy.ast.expr.DeclarationExpression)4 MapExpression (org.codehaus.groovy.ast.expr.MapExpression)4 GroovyBugError (org.codehaus.groovy.GroovyBugError)3