Search in sources :

Example 11 with CodeVisitorSupport

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

the class StaticTypesLambdaWriter method isAccessingInstanceMembersOfEnclosingClass.

private static boolean isAccessingInstanceMembersOfEnclosingClass(final MethodNode lambdaMethod) {
    boolean[] result = new boolean[1];
    ClassNode enclosingClass = lambdaMethod.getDeclaringClass().getOuterClass();
    lambdaMethod.getCode().visit(new CodeVisitorSupport() {

        @Override
        public void visitVariableExpression(final VariableExpression expression) {
            if (expression.isThisExpression() || enclosingClass.equals(expression.getNodeMetaData(StaticCompilationMetadataKeys.PROPERTY_OWNER))) {
                result[0] = true;
            }
        }
    });
    return result[0];
}
Also used : InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) CodeVisitorSupport(org.codehaus.groovy.ast.CodeVisitorSupport) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression)

Example 12 with CodeVisitorSupport

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

the class Verifier method visitConstructor.

@Override
public void visitConstructor(final ConstructorNode node) {
    Statement stmt = node.getCode();
    if (stmt != null) {
        stmt.visit(new VerifierCodeVisitor(getClassNode()));
        // check for uninitialized-this references
        stmt.visit(new CodeVisitorSupport() {

            @Override
            public void visitClosureExpression(final ClosureExpression ce) {
                boolean oldInClosure = inClosure;
                inClosure = true;
                super.visitClosureExpression(ce);
                inClosure = oldInClosure;
            }

            @Override
            public void visitConstructorCallExpression(final ConstructorCallExpression cce) {
                boolean oldIsSpecialConstructorCall = inSpecialConstructorCall;
                inSpecialConstructorCall |= cce.isSpecialCall();
                super.visitConstructorCallExpression(cce);
                inSpecialConstructorCall = oldIsSpecialConstructorCall;
            }

            @Override
            public void visitMethodCallExpression(final MethodCallExpression mce) {
                if (inSpecialConstructorCall && isThisObjectExpression(mce)) {
                    MethodNode methodTarget = mce.getMethodTarget();
                    if (methodTarget == null || !(methodTarget.isStatic() || classNode.getOuterClasses().contains(methodTarget.getDeclaringClass()))) {
                        if (!mce.isImplicitThis()) {
                            throw newVariableError(mce.getObjectExpression().getText(), mce.getObjectExpression());
                        } else {
                            throw newVariableError(mce.getMethodAsString(), mce.getMethod());
                        }
                    }
                    mce.getMethod().visit(this);
                    mce.getArguments().visit(this);
                } else {
                    super.visitMethodCallExpression(mce);
                }
            }

            @Override
            public void visitVariableExpression(final VariableExpression ve) {
                // before this/super ctor call completes, only params and static or outer members are accessible
                if (inSpecialConstructorCall && (ve.isThisExpression() || ve.isSuperExpression() || isNonStaticMemberAccess(ve))) {
                    // TODO: context for default argument
                    throw newVariableError(ve.getName(), ve.getLineNumber() > 0 ? ve : node);
                }
            }

            // 
            private boolean inClosure, inSpecialConstructorCall;

            private boolean isNonStaticMemberAccess(final VariableExpression ve) {
                Variable variable = ve.getAccessedVariable();
                return !inClosure && variable != null && !isStatic(variable.getModifiers()) && !(variable instanceof DynamicVariable) && !(variable instanceof Parameter);
            }

            private boolean isThisObjectExpression(final MethodCallExpression mce) {
                if (mce.isImplicitThis()) {
                    return true;
                } else if (mce.getObjectExpression() instanceof VariableExpression) {
                    VariableExpression var = (VariableExpression) mce.getObjectExpression();
                    return var.isThisExpression() || var.isSuperExpression();
                } else {
                    return false;
                }
            }

            private GroovyRuntimeException newVariableError(final String name, final ASTNode node) {
                RuntimeParserException rpe = new RuntimeParserException("Cannot reference '" + name + "' before supertype constructor has been called. Possible causes:\n" + "You attempted to access an instance field, method, or property.\n" + "You attempted to construct a non-static inner class.", node);
                rpe.setModule(getClassNode().getModule());
                return rpe;
            }
        });
    }
}
Also used : Variable(org.codehaus.groovy.ast.Variable) DynamicVariable(org.codehaus.groovy.ast.DynamicVariable) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) ReturnStatement(org.codehaus.groovy.ast.stmt.ReturnStatement) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) Statement(org.codehaus.groovy.ast.stmt.Statement) ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) GroovyRuntimeException(groovy.lang.GroovyRuntimeException) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) CodeVisitorSupport(org.codehaus.groovy.ast.CodeVisitorSupport) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) MethodNode(org.codehaus.groovy.ast.MethodNode) DynamicVariable(org.codehaus.groovy.ast.DynamicVariable) ASTNode(org.codehaus.groovy.ast.ASTNode) Parameter(org.codehaus.groovy.ast.Parameter) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression) RuntimeParserException(org.codehaus.groovy.syntax.RuntimeParserException)

Example 13 with CodeVisitorSupport

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

the class Verifier method addDefaultParameterMethods.

/**
 * Creates a new method for each combination of default parameter expressions.
 */
protected void addDefaultParameterMethods(final ClassNode type) {
    List<MethodNode> methods = new ArrayList<>(type.getMethods());
    addDefaultParameters(methods, (arguments, params, method) -> {
        BlockStatement code = new BlockStatement();
        MethodNode newMethod = new MethodNode(method.getName(), method.getModifiers(), method.getReturnType(), params, method.getExceptions(), code);
        MethodNode oldMethod = type.getDeclaredMethod(method.getName(), params);
        if (oldMethod != null) {
            throw new RuntimeParserException("The method with default parameters \"" + method.getTypeDescriptor() + "\" defines a method \"" + newMethod.getTypeDescriptor() + "\" that is already defined.", sourceOf(method));
        }
        List<AnnotationNode> annotations = method.getAnnotations();
        if (annotations != null && !annotations.isEmpty()) {
            newMethod.addAnnotations(annotations);
        }
        newMethod.setGenericsTypes(method.getGenericsTypes());
        // GROOVY-5632, GROOVY-9151: check for references to parameters that have been removed
        GroovyCodeVisitor visitor = new CodeVisitorSupport() {

            private boolean inClosure;

            @Override
            public void visitClosureExpression(final ClosureExpression e) {
                boolean prev = inClosure;
                inClosure = true;
                super.visitClosureExpression(e);
                inClosure = prev;
            }

            @Override
            public void visitVariableExpression(final VariableExpression e) {
                if (e.getAccessedVariable() instanceof Parameter) {
                    Parameter p = (Parameter) e.getAccessedVariable();
                    if (p.hasInitialExpression() && !Arrays.asList(params).contains(p)) {
                        VariableScope blockScope = code.getVariableScope();
                        VariableExpression localVariable = (VariableExpression) blockScope.getDeclaredVariable(p.getName());
                        if (localVariable == null) {
                            // create a variable declaration so that the name can be found in the new method
                            localVariable = localVarX(p.getName(), p.getType());
                            localVariable.setModifiers(p.getModifiers());
                            blockScope.putDeclaredVariable(localVariable);
                            localVariable.setInStaticContext(blockScope.isInStaticContext());
                            code.addStatement(declS(localVariable, p.getInitialExpression()));
                        }
                        if (!localVariable.isClosureSharedVariable()) {
                            localVariable.setClosureSharedVariable(inClosure);
                        }
                    }
                }
            }
        };
        visitor.visitArgumentlistExpression(arguments);
        // if variable was created to capture an initial value expression, reference it in arguments as well
        for (ListIterator<Expression> it = arguments.getExpressions().listIterator(); it.hasNext(); ) {
            Expression argument = it.next();
            if (argument instanceof CastExpression) {
                argument = ((CastExpression) argument).getExpression();
            }
            for (Parameter p : method.getParameters()) {
                if (p.hasInitialExpression() && p.getInitialExpression() == argument) {
                    if (code.getVariableScope().getDeclaredVariable(p.getName()) != null) {
                        it.set(varX(p.getName()));
                    }
                    break;
                }
            }
        }
        // delegate to original method using arguments derived from defaults
        MethodCallExpression call = callThisX(method.getName(), arguments);
        call.setMethodTarget(method);
        call.setImplicitThis(true);
        if (method.isVoidMethod()) {
            code.addStatement(new ExpressionStatement(call));
        } else {
            code.addStatement(new ReturnStatement(call));
        }
        // GROOVY-5681: set anon. inner enclosing method reference
        visitor = new CodeVisitorSupport() {

            @Override
            public void visitConstructorCallExpression(final ConstructorCallExpression call) {
                if (call.isUsingAnonymousInnerClass()) {
                    call.getType().setEnclosingMethod(newMethod);
                }
                super.visitConstructorCallExpression(call);
            }
        };
        visitor.visitBlockStatement(code);
        addPropertyMethod(newMethod);
        newMethod.putNodeMetaData(DEFAULT_PARAMETER_GENERATED, Boolean.TRUE);
    });
}
Also used : ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) ArrayList(java.util.ArrayList) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) CodeVisitorSupport(org.codehaus.groovy.ast.CodeVisitorSupport) MethodNode(org.codehaus.groovy.ast.MethodNode) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) AnnotationNode(org.codehaus.groovy.ast.AnnotationNode) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) CastExpression(org.codehaus.groovy.ast.expr.CastExpression) Expression(org.codehaus.groovy.ast.expr.Expression) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) FieldExpression(org.codehaus.groovy.ast.expr.FieldExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) ReturnStatement(org.codehaus.groovy.ast.stmt.ReturnStatement) GroovyCodeVisitor(org.codehaus.groovy.ast.GroovyCodeVisitor) Parameter(org.codehaus.groovy.ast.Parameter) RuntimeParserException(org.codehaus.groovy.syntax.RuntimeParserException) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression) CastExpression(org.codehaus.groovy.ast.expr.CastExpression) VariableScope(org.codehaus.groovy.ast.VariableScope)

Example 14 with CodeVisitorSupport

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

the class InnerClassVisitor method isStatic.

private boolean isStatic(final ClassNode innerClass, final VariableScope scope, final ConstructorCallExpression call) {
    boolean isStatic = innerClass.isStaticClass();
    if (!isStatic) {
        if (currentMethod != null) {
            if (currentMethod instanceof ConstructorNode) {
                boolean[] precedesSuperOrThisCall = new boolean[1];
                ConstructorNode ctor = (ConstructorNode) currentMethod;
                GroovyCodeVisitor visitor = new CodeVisitorSupport() {

                    @Override
                    public void visitConstructorCallExpression(ConstructorCallExpression cce) {
                        if (cce == call) {
                            precedesSuperOrThisCall[0] = true;
                        } else {
                            super.visitConstructorCallExpression(cce);
                        }
                    }
                };
                if (ctor.firstStatementIsSpecialConstructorCall())
                    currentMethod.getFirstStatement().visit(visitor);
                Arrays.stream(ctor.getParameters()).filter(Parameter::hasInitialExpression).forEach(p -> p.getInitialExpression().visit(visitor));
                isStatic = precedesSuperOrThisCall[0];
            } else {
                isStatic = currentMethod.isStatic();
            }
        } else if (currentField != null) {
            isStatic = currentField.isStatic();
        }
    }
    // GROOVY-8433: Category transform implies static method
    isStatic = isStatic || innerClass.getOuterClass().getAnnotations().stream().anyMatch(a -> a.getClassNode().getName().equals("groovy.lang.Category"));
    return isStatic;
}
Also used : CodeVisitorSupport(org.codehaus.groovy.ast.CodeVisitorSupport) ConstructorNode(org.codehaus.groovy.ast.ConstructorNode) ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) GroovyCodeVisitor(org.codehaus.groovy.ast.GroovyCodeVisitor)

Example 15 with CodeVisitorSupport

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

the class EnumCompletionVisitor method getUniqueVariableName.

private String getUniqueVariableName(final String name, final Statement code) {
    if (code == null)
        return name;
    final Object[] found = new Object[1];
    CodeVisitorSupport cv = new CodeVisitorSupport() {

        @Override
        public void visitVariableExpression(VariableExpression expression) {
            if (expression.getName().equals(name))
                found[0] = Boolean.TRUE;
        }
    };
    code.visit(cv);
    if (found[0] != null)
        return getUniqueVariableName("_" + name, code);
    return name;
}
Also used : CodeVisitorSupport(org.codehaus.groovy.ast.CodeVisitorSupport) ClassCodeVisitorSupport(org.codehaus.groovy.ast.ClassCodeVisitorSupport) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression)

Aggregations

CodeVisitorSupport (org.codehaus.groovy.ast.CodeVisitorSupport)16 VariableExpression (org.codehaus.groovy.ast.expr.VariableExpression)12 Parameter (org.codehaus.groovy.ast.Parameter)9 ConstructorCallExpression (org.codehaus.groovy.ast.expr.ConstructorCallExpression)8 BlockStatement (org.codehaus.groovy.ast.stmt.BlockStatement)8 MethodCallExpression (org.codehaus.groovy.ast.expr.MethodCallExpression)7 ExpressionStatement (org.codehaus.groovy.ast.stmt.ExpressionStatement)7 ReturnStatement (org.codehaus.groovy.ast.stmt.ReturnStatement)7 BinaryExpression (org.codehaus.groovy.ast.expr.BinaryExpression)6 ClosureExpression (org.codehaus.groovy.ast.expr.ClosureExpression)6 ConstantExpression (org.codehaus.groovy.ast.expr.ConstantExpression)6 Expression (org.codehaus.groovy.ast.expr.Expression)6 ArrayList (java.util.ArrayList)5 ConstructorNode (org.codehaus.groovy.ast.ConstructorNode)5 FieldNode (org.codehaus.groovy.ast.FieldNode)5 Variable (org.codehaus.groovy.ast.Variable)5 ArgumentListExpression (org.codehaus.groovy.ast.expr.ArgumentListExpression)5 CastExpression (org.codehaus.groovy.ast.expr.CastExpression)5 Statement (org.codehaus.groovy.ast.stmt.Statement)5 ClassNode (org.codehaus.groovy.ast.ClassNode)4