Search in sources :

Example 86 with Parameter

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

the class EnumCompletionVisitor method transformConstructor.

/**
 * If constructor does not define a call to super, then transform constructor
 * to get String,int parameters at beginning and add call super(String,int).
 */
private void transformConstructor(final ConstructorNode ctor) {
    boolean chainedThisConstructorCall = false;
    ConstructorCallExpression cce = null;
    if (ctor.firstStatementIsSpecialConstructorCall()) {
        Statement code = ctor.getFirstStatement();
        cce = (ConstructorCallExpression) ((ExpressionStatement) code).getExpression();
        if (cce.isSuperCall())
            return;
        // must be call to this(...)
        chainedThisConstructorCall = true;
    }
    // we need to add parameters
    Parameter[] oldP = ctor.getParameters();
    Parameter[] newP = new Parameter[oldP.length + 2];
    String stringParameterName = getUniqueVariableName("__str", ctor.getCode());
    newP[0] = new Parameter(ClassHelper.STRING_TYPE, stringParameterName);
    String intParameterName = getUniqueVariableName("__int", ctor.getCode());
    newP[1] = new Parameter(ClassHelper.int_TYPE, intParameterName);
    System.arraycopy(oldP, 0, newP, 2, oldP.length);
    ctor.setParameters(newP);
    VariableExpression stringVariable = new VariableExpression(newP[0]);
    VariableExpression intVariable = new VariableExpression(newP[1]);
    if (chainedThisConstructorCall) {
        TupleExpression args = (TupleExpression) cce.getArguments();
        List<Expression> argsExprs = args.getExpressions();
        argsExprs.add(0, stringVariable);
        argsExprs.add(1, intVariable);
    } else {
        // add a super call
        List<Expression> args = new ArrayList<>();
        args.add(stringVariable);
        args.add(intVariable);
        if (EnumVisitor.isAnonymousInnerClass(ctor.getDeclaringClass())) {
            for (Parameter parameter : oldP) {
                args.add(new VariableExpression(parameter));
            }
            ClassNode enumClass = ctor.getDeclaringClass().getSuperClass();
            // GROOVY-6747: bridge enum's private constructor
            makeBridgeConstructor(enumClass, newP);
            args.add(new CastExpression(enumClass.getPlainNodeReference(), ConstantExpression.NULL));
        }
        cce = new ConstructorCallExpression(ClassNode.SUPER, new ArgumentListExpression(args));
        BlockStatement code = new BlockStatement();
        code.addStatement(new ExpressionStatement(cce));
        Statement oldCode = ctor.getCode();
        if (oldCode != null)
            code.addStatement(oldCode);
        ctor.setCode(code);
    }
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) Statement(org.codehaus.groovy.ast.stmt.Statement) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) ArrayList(java.util.ArrayList) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) Expression(org.codehaus.groovy.ast.expr.Expression) ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) CastExpression(org.codehaus.groovy.ast.expr.CastExpression) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) Parameter(org.codehaus.groovy.ast.Parameter) CastExpression(org.codehaus.groovy.ast.expr.CastExpression)

Example 87 with Parameter

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

the class InnerClassVisitor method visitConstructorCallExpression.

@Override
public void visitConstructorCallExpression(ConstructorCallExpression call) {
    super.visitConstructorCallExpression(call);
    if (!call.isUsingAnonymousInnerClass()) {
        passThisReference(call);
        return;
    }
    InnerClassNode innerClass = (InnerClassNode) call.getType();
    ClassNode outerClass = innerClass.getOuterClass();
    ClassNode superClass = innerClass.getSuperClass();
    if (!superClass.isInterface() && superClass.getOuterClass() != null && !(superClass.isStaticClass() || (superClass.getModifiers() & ACC_STATIC) != 0)) {
        insertThis0ToSuperCall(call, innerClass);
    }
    if (!innerClass.getDeclaredConstructors().isEmpty())
        return;
    if ((innerClass.getModifiers() & ACC_STATIC) != 0)
        return;
    VariableScope scope = innerClass.getVariableScope();
    if (scope == null)
        return;
    boolean isStatic = !inClosure && isStatic(innerClass, scope, call);
    // expressions = constructor call arguments
    List<Expression> expressions = ((TupleExpression) call.getArguments()).getExpressions();
    // block = init code for the constructor we produce
    BlockStatement block = new BlockStatement();
    // parameters = parameters of the constructor
    int additionalParamCount = (isStatic ? 0 : 1) + scope.getReferencedLocalVariablesCount();
    List<Parameter> parameters = new ArrayList<>(expressions.size() + additionalParamCount);
    // superCallArguments = arguments for the super call == the constructor call arguments
    List<Expression> superCallArguments = new ArrayList<>(expressions.size());
    // first we add a super() call for all expressions given in the constructor call expression
    for (int i = 0, n = expressions.size(); i < n; i += 1) {
        // add one parameter for each expression in the constructor call
        Parameter param = new Parameter(ClassHelper.OBJECT_TYPE, "p" + additionalParamCount + i);
        parameters.add(param);
        // add the corresponding argument to the super constructor call
        superCallArguments.add(new VariableExpression(param));
    }
    // add the super call
    ConstructorCallExpression cce = new ConstructorCallExpression(ClassNode.SUPER, new TupleExpression(superCallArguments));
    block.addStatement(new ExpressionStatement(cce));
    int pCount = 0;
    if (!isStatic) {
        // need to pass "this" to access unknown methods/properties
        ClassNode enclosingType = (inClosure ? ClassHelper.CLOSURE_TYPE : outerClass).getPlainNodeReference();
        expressions.add(pCount, new VariableExpression("this", enclosingType));
        Parameter thisParameter = new Parameter(enclosingType, "p" + pCount);
        parameters.add(pCount++, thisParameter);
        // "this" reference is saved in a field named "this$0"
        FieldNode thisField = innerClass.addField("this$0", ACC_FINAL | ACC_SYNTHETIC, enclosingType, null);
        addFieldInit(thisParameter, thisField, block);
    }
    // for each shared variable, add a Reference field
    for (Iterator<Variable> it = scope.getReferencedLocalVariablesIterator(); it.hasNext(); ) {
        Variable var = it.next();
        VariableExpression ve = new VariableExpression(var);
        ve.setClosureSharedVariable(true);
        ve.setUseReferenceDirectly(true);
        expressions.add(pCount, ve);
        ClassNode referenceType = ClassHelper.REFERENCE_TYPE.getPlainNodeReference();
        Parameter p = new Parameter(referenceType, "p" + pCount);
        p.setOriginType(var.getOriginType());
        parameters.add(pCount++, p);
        VariableExpression initial = new VariableExpression(p);
        initial.setSynthetic(true);
        initial.setUseReferenceDirectly(true);
        FieldNode pField = innerClass.addFieldFirst(ve.getName(), ACC_PUBLIC | ACC_SYNTHETIC, referenceType, initial);
        pField.setHolder(true);
        pField.setOriginType(ClassHelper.getWrapper(var.getOriginType()));
    }
    innerClass.addConstructor(ACC_SYNTHETIC, parameters.toArray(Parameter.EMPTY_ARRAY), ClassNode.EMPTY_ARRAY, block);
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) Variable(org.codehaus.groovy.ast.Variable) FieldNode(org.codehaus.groovy.ast.FieldNode) ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) ArrayList(java.util.ArrayList) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) Expression(org.codehaus.groovy.ast.expr.Expression) ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) Parameter(org.codehaus.groovy.ast.Parameter) VariableScope(org.codehaus.groovy.ast.VariableScope)

Example 88 with Parameter

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

the class StaticTypesMethodReferenceExpressionWriter method createParametersWithExactType.

private Parameter[] createParametersWithExactType(final MethodNode abstractMethod, final ClassNode[] inferredParamTypes) {
    // MUST clone the parameters to avoid impacting the original parameter type of SAM
    Parameter[] parameters = GeneralUtils.cloneParams(abstractMethod.getParameters());
    if (inferredParamTypes != null) {
        for (int i = 0, n = parameters.length; i < n; i += 1) {
            ClassNode inferredParamType = inferredParamTypes[i];
            if (inferredParamType == null)
                continue;
            Parameter parameter = parameters[i];
            Parameter targetParameter = parameter;
            ClassNode type = convertParameterType(targetParameter.getType(), parameter.getType(), inferredParamType);
            parameter.setOriginType(type);
            parameter.setType(type);
        }
    }
    return parameters;
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) StaticTypeCheckingSupport.findDGMMethodsForClassNode(org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.findDGMMethodsForClassNode) Parameter(org.codehaus.groovy.ast.Parameter)

Example 89 with Parameter

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

the class StaticVerifier method visitConstructorOrMethod.

@Override
public void visitConstructorOrMethod(MethodNode node, boolean isConstructor) {
    MethodNode oldMethodNode = methodNode;
    methodNode = node;
    super.visitConstructorOrMethod(node, isConstructor);
    if (isConstructor) {
        for (Parameter param : node.getParameters()) {
            if (param.hasInitialExpression()) {
                // initial expression will be argument to special constructor call
                boolean oldIsSpecialConstructorCall = inSpecialConstructorCall;
                inSpecialConstructorCall = true;
                param.getInitialExpression().visit(this);
                inSpecialConstructorCall = oldIsSpecialConstructorCall;
            }
        }
    }
    methodNode = oldMethodNode;
}
Also used : MethodNode(org.codehaus.groovy.ast.MethodNode) Parameter(org.codehaus.groovy.ast.Parameter)

Example 90 with Parameter

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

the class Verifier method addGroovyObjectInterfaceAndMethods.

protected void addGroovyObjectInterfaceAndMethods(final ClassNode node, final String classInternalName) {
    if (!node.isDerivedFromGroovyObject())
        node.addInterface(ClassHelper.make(GroovyObject.class));
    FieldNode metaClassField = getMetaClassField(node);
    boolean shouldAnnotate = classNode.getModule().getContext() != null;
    AnnotationNode generatedAnnotation = shouldAnnotate ? new AnnotationNode(ClassHelper.make(GENERATED_ANNOTATION)) : null;
    AnnotationNode internalAnnotation = shouldAnnotate ? new AnnotationNode(ClassHelper.make(INTERNAL_ANNOTATION)) : null;
    AnnotationNode transientAnnotation = shouldAnnotate ? new AnnotationNode(ClassHelper.make(TRANSIENT_ANNOTATION)) : null;
    if (!node.hasMethod("getMetaClass", Parameter.EMPTY_ARRAY)) {
        metaClassField = setMetaClassFieldIfNotExists(node, metaClassField);
        MethodNode methodNode = addMethod(node, !shouldAnnotate, "getMetaClass", ACC_PUBLIC, ClassHelper.METACLASS_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, new BytecodeSequence(new BytecodeInstruction() {

            @Override
            public void visit(final MethodVisitor mv) {
                Label nullLabel = new Label();
                /*
                             *  the code is:
                             *  if (this.metaClass==null) {
                             *      this.metaClass = this.$getStaticMetaClass()
                             *      return this.metaClass
                             *  } else {
                             *      return this.metaClass
                             *  }
                             *  with the optimization that the result of the
                             *  first this.metaClass is duped on the operand
                             *  stack and reused for the return in the else part
                             */
                mv.visitVarInsn(ALOAD, 0);
                mv.visitFieldInsn(GETFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
                mv.visitInsn(DUP);
                mv.visitJumpInsn(IFNULL, nullLabel);
                mv.visitInsn(ARETURN);
                mv.visitLabel(nullLabel);
                mv.visitInsn(POP);
                mv.visitVarInsn(ALOAD, 0);
                mv.visitInsn(DUP);
                mv.visitMethodInsn(INVOKEVIRTUAL, classInternalName, "$getStaticMetaClass", "()Lgroovy/lang/MetaClass;", false);
                mv.visitFieldInsn(PUTFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
                mv.visitVarInsn(ALOAD, 0);
                mv.visitFieldInsn(GETFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
                mv.visitInsn(ARETURN);
            }
        }));
        if (shouldAnnotate) {
            methodNode.addAnnotation(generatedAnnotation);
            methodNode.addAnnotation(internalAnnotation);
            methodNode.addAnnotation(transientAnnotation);
        }
    }
    Parameter[] parameters = new Parameter[] { new Parameter(ClassHelper.METACLASS_TYPE, "mc") };
    if (!node.hasMethod("setMetaClass", parameters)) {
        metaClassField = setMetaClassFieldIfNotExists(node, metaClassField);
        Statement setMetaClassCode;
        if (isFinal(metaClassField.getModifiers())) {
            ConstantExpression text = new ConstantExpression("cannot set read-only meta class");
            ConstructorCallExpression cce = new ConstructorCallExpression(ClassHelper.make(IllegalArgumentException.class), text);
            setMetaClassCode = new ExpressionStatement(cce);
        } else {
            setMetaClassCode = new BytecodeSequence(new BytecodeInstruction() {

                @Override
                public void visit(final MethodVisitor mv) {
                    /*
                         * the code is (meta class is stored in 1):
                         * this.metaClass = <1>
                         */
                    mv.visitVarInsn(ALOAD, 0);
                    mv.visitVarInsn(ALOAD, 1);
                    mv.visitFieldInsn(PUTFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
                    mv.visitInsn(RETURN);
                }
            });
        }
        MethodNode methodNode = addMethod(node, !shouldAnnotate, "setMetaClass", ACC_PUBLIC, ClassHelper.VOID_TYPE, SET_METACLASS_PARAMS, ClassNode.EMPTY_ARRAY, setMetaClassCode);
        if (shouldAnnotate) {
            methodNode.addAnnotation(generatedAnnotation);
            methodNode.addAnnotation(internalAnnotation);
        }
    }
}
Also used : FieldNode(org.codehaus.groovy.ast.FieldNode) 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) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) Label(org.objectweb.asm.Label) MethodVisitor(org.objectweb.asm.MethodVisitor) MethodNode(org.codehaus.groovy.ast.MethodNode) AnnotationNode(org.codehaus.groovy.ast.AnnotationNode) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) Parameter(org.codehaus.groovy.ast.Parameter)

Aggregations

Parameter (org.codehaus.groovy.ast.Parameter)342 ClassNode (org.codehaus.groovy.ast.ClassNode)202 MethodNode (org.codehaus.groovy.ast.MethodNode)135 InnerClassNode (org.codehaus.groovy.ast.InnerClassNode)117 BlockStatement (org.codehaus.groovy.ast.stmt.BlockStatement)111 VariableExpression (org.codehaus.groovy.ast.expr.VariableExpression)102 Expression (org.codehaus.groovy.ast.expr.Expression)98 MethodCallExpression (org.codehaus.groovy.ast.expr.MethodCallExpression)90 ArgumentListExpression (org.codehaus.groovy.ast.expr.ArgumentListExpression)75 FieldNode (org.codehaus.groovy.ast.FieldNode)71 ExpressionStatement (org.codehaus.groovy.ast.stmt.ExpressionStatement)71 ClassExpression (org.codehaus.groovy.ast.expr.ClassExpression)69 ConstantExpression (org.codehaus.groovy.ast.expr.ConstantExpression)68 ConstructorNode (org.codehaus.groovy.ast.ConstructorNode)66 ConstructorCallExpression (org.codehaus.groovy.ast.expr.ConstructorCallExpression)66 Statement (org.codehaus.groovy.ast.stmt.Statement)66 ArrayList (java.util.ArrayList)62 ClosureExpression (org.codehaus.groovy.ast.expr.ClosureExpression)56 BinaryExpression (org.codehaus.groovy.ast.expr.BinaryExpression)52 PropertyExpression (org.codehaus.groovy.ast.expr.PropertyExpression)51