Java Code Examples for org.codehaus.groovy.ast.ClassNode#addMethod()

The following examples show how to use org.codehaus.groovy.ast.ClassNode#addMethod() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: TraitComposer.java    From groovy with Apache License 2.0 6 votes vote down vote up
/**
 * Creates a method to dispatch to "super traits" in a "stackable" fashion. The generated method looks like this:
 * <p>
 * <code>ReturnType trait$super$method(Class clazz, Arg1 arg1, Arg2 arg2, ...) {
 *     if (SomeTrait.is(A) { return SomeOtherTrait$Trait$Helper.method(this, arg1, arg2) }
 *     super.method(arg1,arg2)
 * }</code>
 * </p>
 * @param targetNode
 * @param forwarderMethod
 * @param interfacesToGenerateForwarderFor
 * @param genericsSpec
 */
private static void doCreateSuperForwarder(ClassNode targetNode, MethodNode forwarderMethod, ClassNode[] interfacesToGenerateForwarderFor, Map<String,ClassNode> genericsSpec) {
    Parameter[] parameters = forwarderMethod.getParameters();
    Parameter[] superForwarderParams = new Parameter[parameters.length];
    for (int i = 0; i < parameters.length; i++) {
        Parameter parameter = parameters[i];
        ClassNode originType = parameter.getOriginType();
        superForwarderParams[i] = new Parameter(correctToGenericsSpecRecurse(genericsSpec, originType), parameter.getName());
    }
    for (int i = 0; i < interfacesToGenerateForwarderFor.length; i++) {
        final ClassNode current = interfacesToGenerateForwarderFor[i];
        final ClassNode next = i < interfacesToGenerateForwarderFor.length - 1 ? interfacesToGenerateForwarderFor[i + 1] : null;
        String forwarderName = Traits.getSuperTraitMethodName(current, forwarderMethod.getName());
        if (targetNode.getDeclaredMethod(forwarderName, superForwarderParams) == null) {
            ClassNode returnType = correctToGenericsSpecRecurse(genericsSpec, forwarderMethod.getReturnType());
            Statement delegate = next == null ? createSuperFallback(forwarderMethod, returnType) : createDelegatingForwarder(forwarderMethod, next);
            MethodNode methodNode = targetNode.addMethod(forwarderName, Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC, returnType, superForwarderParams, ClassNode.EMPTY_ARRAY, delegate);
            methodNode.setGenericsTypes(forwarderMethod.getGenericsTypes());
        }
    }
}
 
Example 2
Source File: TraitASTTransformation.java    From groovy with Apache License 2.0 6 votes vote down vote up
private static MethodNode createInitMethod(final boolean isStatic, final ClassNode cNode, final ClassNode helper) {
    MethodNode initializer = new MethodNode(
            isStatic?Traits.STATIC_INIT_METHOD:Traits.INIT_METHOD,
            ACC_STATIC | ACC_PUBLIC | ACC_SYNTHETIC,
            ClassHelper.VOID_TYPE,
            new Parameter[]{createSelfParameter(cNode, isStatic)},
            ClassNode.EMPTY_ARRAY,
            new BlockStatement()
    );
    helper.addMethod(initializer);

    // Cannot add static compilation of init method because of GROOVY-7217, see example 2 of test case
    //AnnotationNode an = new AnnotationNode(TraitComposer.COMPILESTATIC_CLASSNODE);
    //initializer.addAnnotation(an);
    //cNode.addTransform(StaticCompileTransformation.class, an);

    return initializer;
}
 
Example 3
Source File: GenericsUtils.java    From groovy with Apache License 2.0 6 votes vote down vote up
private static ClassNode resolveClassNode(final SourceUnit sourceUnit, final CompilationUnit compilationUnit, final MethodNode mn, final ASTNode usage, final ClassNode parsedNode) {
    ClassNode dummyClass = new ClassNode("dummy", 0, ClassHelper.OBJECT_TYPE);
    dummyClass.setModule(new ModuleNode(sourceUnit));
    dummyClass.setGenericsTypes(mn.getDeclaringClass().getGenericsTypes());
    MethodNode dummyMN = new MethodNode(
            "dummy",
            0,
            parsedNode,
            Parameter.EMPTY_ARRAY,
            ClassNode.EMPTY_ARRAY,
            EmptyStatement.INSTANCE
    );
    dummyMN.setGenericsTypes(mn.getGenericsTypes());
    dummyClass.addMethod(dummyMN);
    ResolveVisitor visitor = new ResolveVisitor(compilationUnit) {
        @Override
        public void addError(final String msg, final ASTNode expr) {
            sourceUnit.addError(new IncorrectTypeHintException(mn, msg, usage.getLineNumber(), usage.getColumnNumber()));
        }
    };
    visitor.startResolving(dummyClass, sourceUnit);
    return dummyMN.getReturnType();
}
 
Example 4
Source File: StaticTypesLambdaWriter.java    From groovy with Apache License 2.0 6 votes vote down vote up
private MethodNode addSyntheticLambdaMethodNode(final LambdaExpression expression, final ClassNode lambdaClass, final MethodNode abstractMethod) {
    Parameter[] parametersWithExactType = createParametersWithExactType(expression);
    Parameter[] localVariableParameters = getLambdaSharedVariables(expression);
    removeInitialValues(localVariableParameters);

    MethodNode doCallMethod = lambdaClass.addMethod(
            "doCall",
            ACC_PUBLIC,
            abstractMethod.getReturnType(),
            Arrays.copyOf(parametersWithExactType, parametersWithExactType.length),
            ClassNode.EMPTY_ARRAY,
            expression.getCode()
    );
    doCallMethod.putNodeMetaData(ORIGINAL_PARAMETERS_WITH_EXACT_TYPE, parametersWithExactType);
    expression.putNodeMetaData(LAMBDA_SHARED_VARIABLES, localVariableParameters);
    doCallMethod.setSourcePosition(expression);

    return doCallMethod;
}
 
Example 5
Source File: Verifier.java    From groovy with Apache License 2.0 5 votes vote down vote up
/**
 * Helper method to add a new method to a ClassNode.  Depending on the shouldBeSynthetic flag the
 * call will either be made to ClassNode.addSyntheticMethod() or ClassNode.addMethod(). If a non-synthetic method
 * is to be added the ACC_SYNTHETIC modifier is removed if it has been accidentally supplied.
 */
protected MethodNode addMethod(ClassNode node, boolean shouldBeSynthetic, String name, int modifiers, ClassNode returnType, Parameter[] parameters,
                               ClassNode[] exceptions, Statement code) {
    if (shouldBeSynthetic) {
        return node.addSyntheticMethod(name, modifiers, returnType, parameters, exceptions, code);
    } else {
        return node.addMethod(name, modifiers & ~ACC_SYNTHETIC, returnType, parameters, exceptions, code);
    }
}
 
Example 6
Source File: StaticTypesClosureWriter.java    From groovy with Apache License 2.0 5 votes vote down vote up
private static void createDirectCallMethod(final ClassNode closureClass, final MethodNode doCallMethod) {
    // in case there is no "call" method on the closure, we can create a "fast invocation" paths
    // to avoid going through ClosureMetaClass by call(Object...) method

    // we can't have a specialized version of call(Object...) because the dispatch logic in ClosureMetaClass
    // is too complex!

    // call(Object)
    Parameter args = new Parameter(ClassHelper.OBJECT_TYPE, "args");
    MethodCallExpression doCall1arg = new MethodCallExpression(
            new VariableExpression("this", closureClass),
            "doCall",
            new ArgumentListExpression(new VariableExpression(args))
    );
    doCall1arg.setImplicitThis(true);
    doCall1arg.setMethodTarget(doCallMethod);
    closureClass.addMethod(
            new MethodNode("call",
                    Opcodes.ACC_PUBLIC,
                    ClassHelper.OBJECT_TYPE,
                    new Parameter[]{args},
                    ClassNode.EMPTY_ARRAY,
                    new ReturnStatement(doCall1arg)));

    // call()
    MethodCallExpression doCallNoArgs = new MethodCallExpression(new VariableExpression("this", closureClass), "doCall", new ArgumentListExpression(new ConstantExpression(null)));
    doCallNoArgs.setImplicitThis(true);
    doCallNoArgs.setMethodTarget(doCallMethod);
    closureClass.addMethod(
            new MethodNode("call",
                    Opcodes.ACC_PUBLIC,
                    ClassHelper.OBJECT_TYPE,
                    Parameter.EMPTY_ARRAY,
                    ClassNode.EMPTY_ARRAY,
                    new ReturnStatement(doCallNoArgs)));
}
 
Example 7
Source File: ClassCompletionVerifierTest.java    From groovy with Apache License 2.0 5 votes vote down vote up
private void checkDetectsDuplicateMethods(int modifiers, String expectedErrorMessage, Parameter[] params) {
    ClassNode node = new ClassNode("zzz", modifiers, ClassHelper.OBJECT_TYPE);
    node.addMethod(new MethodNode("xxx", ACC_PUBLIC, ClassHelper.OBJECT_TYPE, params, ClassNode.EMPTY_ARRAY, null));
    node.addMethod(new MethodNode("xxx", ACC_PUBLIC, ClassHelper.OBJECT_TYPE, params, ClassNode.EMPTY_ARRAY, null));
    verifier.visitClass(node);
    checkErrorCount(2);
    checkErrorMessage(expectedErrorMessage);
}
 
Example 8
Source File: ClassCompletionVerifierTest.java    From groovy with Apache License 2.0 5 votes vote down vote up
public void testDetectsFinalAndStaticMethodsInInterface() throws Exception {
    ClassNode node = new ClassNode("zzz", ACC_ABSTRACT | ACC_INTERFACE, ClassHelper.OBJECT_TYPE);
    node.addMethod(new MethodNode("xxx", ACC_PUBLIC | ACC_FINAL, ClassHelper.OBJECT_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, null));
    node.addMethod(new MethodNode("yyy", ACC_PUBLIC | ACC_STATIC, ClassHelper.OBJECT_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, null));
    addDummyConstructor(node);
    verifier.visitClass(node);
    checkErrorCount(2);
    checkErrorMessage(EXPECTED_INTERFACE_FINAL_METHOD_ERROR_MESSAGE);
    checkErrorMessage(EXPECTED_INTERFACE_STATIC_METHOD_ERROR_MESSAGE);
}
 
Example 9
Source File: ClassCompletionVerifierTest.java    From groovy with Apache License 2.0 5 votes vote down vote up
public void testDetectsIncorrectMethodModifiersInInterface() throws Exception {
    // can't check volatile here as it doubles up with bridge
    ClassNode node = new ClassNode("zzz", ACC_ABSTRACT | ACC_INTERFACE, ClassHelper.OBJECT_TYPE);
    node.addMethod(new MethodNode("st", ACC_STRICT, ClassHelper.OBJECT_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, null));
    node.addMethod(new MethodNode("na", ACC_NATIVE, ClassHelper.OBJECT_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, null));
    node.addMethod(new MethodNode("sy", ACC_SYNCHRONIZED, ClassHelper.OBJECT_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, null));
    addDummyConstructor(node);
    verifier.visitClass(node);
    checkErrorCount(3);
    checkErrorMessage(EXPECTED_STRICT_METHOD_ERROR_MESSAGE);
    checkErrorMessage(EXPECTED_NATIVE_METHOD_ERROR_MESSAGE);
    checkErrorMessage(EXPECTED_SYNCHRONIZED_METHOD_ERROR_MESSAGE);
}
 
Example 10
Source File: ClassCompletionVerifierTest.java    From groovy with Apache License 2.0 5 votes vote down vote up
public void testDetectsIncorrectMemberVisibilityInInterface() throws Exception {
    ClassNode node = new ClassNode("zzz", ACC_ABSTRACT | ACC_INTERFACE, ClassHelper.OBJECT_TYPE);
    node.addMethod(new MethodNode("prim", ACC_PRIVATE, ClassHelper.OBJECT_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, null));
    node.addMethod(new MethodNode("prom", ACC_PROTECTED, ClassHelper.OBJECT_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, null));
    node.addField("prif", ACC_PRIVATE, ClassHelper.OBJECT_TYPE, null);
    node.addField("prof", ACC_PROTECTED, ClassHelper.OBJECT_TYPE, null);
    addDummyConstructor(node);
    verifier.visitClass(node);
    checkErrorCount(4);
    checkErrorMessage(EXPECTED_PROTECTED_FIELD_ERROR_MESSAGE);
    checkErrorMessage(EXPECTED_PRIVATE_FIELD_ERROR_MESSAGE);
    checkErrorMessage(EXPECTED_PROTECTED_METHOD_ERROR_MESSAGE);
    checkErrorMessage(EXPECTED_PRIVATE_METHOD_ERROR_MESSAGE);
}
 
Example 11
Source File: ClassCompletionVerifierTest.java    From groovy with Apache License 2.0 5 votes vote down vote up
public void testDetectsCorrectMethodModifiersInClass() throws Exception {
    // can't check volatile here as it doubles up with bridge
    ClassNode node = new ClassNode("zzz", ACC_PUBLIC, ClassHelper.OBJECT_TYPE);
    node.addMethod(new MethodNode("st", ACC_STRICT, ClassHelper.OBJECT_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, null));
    node.addMethod(new MethodNode("na", ACC_NATIVE, ClassHelper.OBJECT_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, null));
    node.addMethod(new MethodNode("sy", ACC_SYNCHRONIZED, ClassHelper.OBJECT_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, null));
    addDummyConstructor(node);
    verifier.visitClass(node);
    checkErrorCount(0);
}
 
Example 12
Source File: FieldASTTransformation.java    From groovy with Apache License 2.0 4 votes vote down vote up
public void visit(ASTNode[] nodes, SourceUnit source) {
    sourceUnit = source;
    if (nodes.length != 2 || !(nodes[0] instanceof AnnotationNode) || !(nodes[1] instanceof AnnotatedNode)) {
        throw new GroovyBugError("Internal error: expecting [AnnotationNode, AnnotatedNode] but got: " + Arrays.asList(nodes));
    }

    AnnotatedNode parent = (AnnotatedNode) nodes[1];
    AnnotationNode node = (AnnotationNode) nodes[0];
    if (!MY_TYPE.equals(node.getClassNode())) return;

    if (parent instanceof DeclarationExpression) {
        DeclarationExpression de = (DeclarationExpression) parent;
        ClassNode cNode = de.getDeclaringClass();
        if (!cNode.isScript()) {
            addError("Annotation " + MY_TYPE_NAME + " can only be used within a Script.", parent);
            return;
        }
        candidate = de;
        // GROOVY-4548: temp fix to stop CCE until proper support is added
        if (de.isMultipleAssignmentDeclaration()) {
            addError("Annotation " + MY_TYPE_NAME + " not supported with multiple assignment notation.", parent);
            return;
        }
        VariableExpression ve = de.getVariableExpression();
        variableName = ve.getName();
        // set owner null here, it will be updated by addField
        fieldNode = new FieldNode(variableName, ve.getModifiers(), ve.getType(), null, de.getRightExpression());
        fieldNode.setSourcePosition(de);
        cNode.addField(fieldNode);
        // provide setter for CLI Builder purposes unless final
        if (fieldNode.isFinal()) {
            if (!de.getAnnotations(OPTION_TYPE).isEmpty()) {
                addError("Can't have a final field also annotated with @" + OPTION_TYPE.getNameWithoutPackage(), de);
            }
        } else {
            String setterName = getSetterName(variableName);
            cNode.addMethod(setterName, ACC_PUBLIC | ACC_SYNTHETIC, ClassHelper.VOID_TYPE, params(param(ve.getType(), variableName)), ClassNode.EMPTY_ARRAY, block(
                    stmt(assignX(propX(varX("this"), variableName), varX(variableName)))
            ));
        }

        // GROOVY-4833 : annotations that are not Groovy transforms should be transferred to the generated field
        // GROOVY-6112 : also copy acceptable Groovy transforms
        final List<AnnotationNode> annotations = de.getAnnotations();
        for (AnnotationNode annotation : annotations) {
            // GROOVY-6337 HACK: in case newly created field is @Lazy
            if (annotation.getClassNode().equals(LAZY_TYPE)) {
                LazyASTTransformation.visitField(this, annotation, fieldNode);
            }
            final ClassNode annotationClassNode = annotation.getClassNode();
            if (notTransform(annotationClassNode) || acceptableTransform(annotation)) {
                fieldNode.addAnnotation(annotation);
            }
        }

        super.visitClass(cNode);
        // GROOVY-5207 So that Closures can see newly added fields
        // (not super efficient for a very large class with many @Fields but we chose simplicity
        // and understandability of this solution over more complex but efficient alternatives)
        VariableScopeVisitor scopeVisitor = new VariableScopeVisitor(source);
        scopeVisitor.visitClass(cNode);
    }
}
 
Example 13
Source File: GStringTest.java    From groovy with Apache License 2.0 4 votes vote down vote up
public void testConstructor() throws Exception {
    ClassNode classNode = new ClassNode("Foo", ACC_PUBLIC, ClassHelper.OBJECT_TYPE);

    //Statement printStatement = createPrintlnStatement(new VariableExpression("str"));

    // simulate "Hello ${user}!"
    GStringExpression compositeStringExpr = new GStringExpression("hello ${user}!");
    compositeStringExpr.addString(new ConstantExpression("Hello "));
    compositeStringExpr.addValue(new VariableExpression("user"));
    compositeStringExpr.addString(new ConstantExpression("!"));
    BlockStatement block = new BlockStatement();
    block.addStatement(
            new ExpressionStatement(
                    new DeclarationExpression(
                            new VariableExpression("user"),
                            Token.newSymbol("=", -1, -1),
                            new ConstantExpression("World"))));
    block.addStatement(
            new ExpressionStatement(
                    new DeclarationExpression(new VariableExpression("str"), Token.newSymbol("=", -1, -1), compositeStringExpr)));
    block.addStatement(
            new ExpressionStatement(
                    new MethodCallExpression(VariableExpression.THIS_EXPRESSION, "println", new VariableExpression("str"))));

    block.addStatement(
            new ExpressionStatement(
                    new DeclarationExpression(
                            new VariableExpression("text"),
                            Token.newSymbol("=", -1, -1),
                            new MethodCallExpression(new VariableExpression("str"), "toString", MethodCallExpression.NO_ARGUMENTS))));

    block.addStatement(
            new AssertStatement(
                    new BooleanExpression(
                            new BinaryExpression(
                                    new VariableExpression("text"),
                                    Token.newSymbol("==", -1, -1),
                                    new ConstantExpression("Hello World!"))),
                    new ConstantExpression("Assertion failed") // TODO FIX if empty, AssertionWriter fails because source text is null
            )
    );
    classNode.addMethod(new MethodNode("stringDemo", ACC_PUBLIC, ClassHelper.VOID_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, block));

    Class fooClass = loadClass(classNode);
    assertTrue("Loaded a new class", fooClass != null);

    Object bean = fooClass.getDeclaredConstructor().newInstance();
    assertTrue("Managed to create bean", bean != null);

    //Object[] array = { new Integer(1234), "abc", "def" };

    try {
        InvokerHelper.invokeMethod(bean, "stringDemo", null);
    }
    catch (InvokerInvocationException e) {
        System.out.println("Caught: " + e.getCause());
        e.getCause().printStackTrace();
        fail("Should not have thrown an exception");
    }
}
 
Example 14
Source File: ClassCompletionVerifierTest.java    From groovy with Apache License 2.0 4 votes vote down vote up
public void testDetectsAbstractPrivateMethod() throws Exception {
    ClassNode node = new ClassNode("X", ACC_ABSTRACT, ClassHelper.OBJECT_TYPE);
    node.addMethod(new MethodNode("y", ACC_PRIVATE | ACC_ABSTRACT, ClassHelper.VOID_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, null));
    verifier.visitClass(node);
    checkErrorMessage(EXPECTED_ABSTRACT_PRIVATE_METHOD_ERROR_MESSAGE);
}
 
Example 15
Source File: ClassCompletionVerifierTest.java    From groovy with Apache License 2.0 4 votes vote down vote up
private void addDummyConstructor(ClassNode node) {
    // constructors should not be treated as errors (they have no real meaning for interfaces anyway)
    node.addMethod(new MethodNode("<clinit>", ACC_PUBLIC | ACC_STATIC, ClassHelper.OBJECT_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, null));
}
 
Example 16
Source File: ClassNodeUtils.java    From groovy with Apache License 2.0 2 votes vote down vote up
/**
 * Add a method and mark it as {@code @Generated}.
 *
 * @see ClassNode#addMethod(MethodNode)
 */
public static void addGeneratedMethod(ClassNode cNode, MethodNode mNode) {
    cNode.addMethod(mNode);
    markAsGenerated(cNode, mNode);
}