protected void injectDomainHandler(
      ClassNode classNode, String implementation, String datasource) {
    classNode.addMethod(
        new MethodNode(
            DOMAIN_HANDLER_METHOD_NAME,
            Modifier.PUBLIC | Modifier.STATIC,
            GRIFFON_DOMAIN_HANDLER_CLASS,
            Parameter.EMPTY_ARRAY,
            ClassNode.EMPTY_ARRAY,
            returns(domainHandlerInstance())));

    classNode.addMethod(
        new MethodNode(
            MAPPING,
            Modifier.PUBLIC | Modifier.STATIC,
            ClassHelper.STRING_TYPE,
            Parameter.EMPTY_ARRAY,
            ClassNode.EMPTY_ARRAY,
            returns(constx(implementation))));

    classNode.addMethod(
        new MethodNode(
            DATASOURCE,
            Modifier.PUBLIC | Modifier.STATIC,
            ClassHelper.STRING_TYPE,
            Parameter.EMPTY_ARRAY,
            ClassNode.EMPTY_ARRAY,
            returns(constx(datasource))));
  }
Beispiel #2
0
  public void testMethods() throws Exception {
    ClassNode classNode = new ClassNode("Foo", ACC_PUBLIC, ClassHelper.OBJECT_TYPE);
    classNode.addConstructor(new ConstructorNode(ACC_PUBLIC, null));

    Statement statementA = new ReturnStatement(new ConstantExpression("calledA"));
    Statement statementB = new ReturnStatement(new ConstantExpression("calledB"));
    Statement emptyStatement = new BlockStatement();

    classNode.addMethod(
        new MethodNode(
            "a",
            ACC_PUBLIC,
            ClassHelper.OBJECT_TYPE,
            Parameter.EMPTY_ARRAY,
            ClassNode.EMPTY_ARRAY,
            statementA));
    classNode.addMethod(
        new MethodNode(
            "b", ACC_PUBLIC, null, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, statementB));

    classNode.addMethod(
        new MethodNode(
            "noReturnMethodA",
            ACC_PUBLIC,
            null,
            Parameter.EMPTY_ARRAY,
            ClassNode.EMPTY_ARRAY,
            emptyStatement));
    classNode.addMethod(
        new MethodNode(
            "noReturnMethodB",
            ACC_PUBLIC,
            ClassHelper.OBJECT_TYPE,
            Parameter.EMPTY_ARRAY,
            ClassNode.EMPTY_ARRAY,
            emptyStatement));

    classNode.addMethod(
        new MethodNode(
            "c",
            ACC_PUBLIC,
            ClassHelper.VOID_TYPE,
            Parameter.EMPTY_ARRAY,
            ClassNode.EMPTY_ARRAY,
            emptyStatement));

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

    Object bean = fooClass.newInstance();
    assertTrue("Created instance of class: " + bean, bean != null);

    assertCallMethod(bean, "a", "calledA");
    assertCallMethod(bean, "b", "calledB");
    assertCallMethod(bean, "noReturnMethodA", null);
    assertCallMethod(bean, "noReturnMethodB", null);
    assertCallMethod(bean, "c", null);
  }
  private void addAttributesAndBodyMethod(
      ClassNode classNode,
      MethodCallExpression tagLibraryLookupMethodCall,
      String tagName,
      boolean includeBody,
      boolean includeAttrs) {
    BlockStatement methodBody = new BlockStatement();
    ArgumentListExpression arguments = new ArgumentListExpression();
    arguments
        .addExpression(tagLibraryLookupMethodCall)
        .addExpression(
            new MethodCallExpression(
                new VariableExpression("this"),
                GET_TAG_LIB_NAMESPACE_METHOD_NAME,
                new ArgumentListExpression()))
        .addExpression(new ConstantExpression(tagName))
        .addExpression(
            includeAttrs
                ? new CastExpression(ClassHelper.make(Map.class), ATTRS_EXPRESSION)
                : new MapExpression())
        .addExpression(includeBody ? BODY_EXPRESSION : NULL_EXPRESSION)
        .addExpression(
            new CastExpression(
                ClassHelper.make(GrailsWebRequest.class), CURRENT_REQUEST_ATTRIBUTES_METHOD_CALL));

    methodBody.addStatement(
        new ExpressionStatement(
            new MethodCallExpression(
                new ClassExpression(GROOVY_PAGE_CLASS_NODE), "captureTagOutput", arguments)));

    if (includeBody && includeAttrs) {
      if (!methodExists(classNode, tagName, MAP_CLOSURE_PARAMETERS)) {
        classNode.addMethod(
            new MethodNode(
                tagName, Modifier.PUBLIC, OBJECT_CLASS, MAP_CLOSURE_PARAMETERS, null, methodBody));
      }
    } else if (includeAttrs && !includeBody) {
      if (!methodExists(classNode, tagName, MAP_PARAMETERS)) {
        classNode.addMethod(
            new MethodNode(
                tagName, Modifier.PUBLIC, OBJECT_CLASS, MAP_PARAMETERS, null, methodBody));
      }
    } else if (includeBody) {
      if (!methodExists(classNode, tagName, CLOSURE_PARAMETERS)) {
        classNode.addMethod(
            new MethodNode(
                tagName, Modifier.PUBLIC, OBJECT_CLASS, CLOSURE_PARAMETERS, null, methodBody));
      }
    } else {
      if (!methodExists(classNode, tagName, Parameter.EMPTY_ARRAY)) {
        classNode.addMethod(
            new MethodNode(
                tagName, Modifier.PUBLIC, OBJECT_CLASS, Parameter.EMPTY_ARRAY, null, methodBody));
      }
    }
  }
 private void buildCommon(
     ClassNode buildee, AnnotationNode anno, List<FieldNode> fieldNodes, ClassNode builder) {
   String prefix = getMemberStringValue(anno, "prefix", "");
   String buildMethodName = getMemberStringValue(anno, "buildMethodName", "create");
   createBuilderConstructors(builder, buildee, fieldNodes);
   buildee.getModule().addClass(builder);
   String builderMethodName = getMemberStringValue(anno, "builderMethodName", "createInitializer");
   buildee.addMethod(
       createBuilderMethod(buildMethodName, builder, fieldNodes.size(), builderMethodName));
   for (int i = 0; i < fieldNodes.size(); i++) {
     builder.addMethod(createBuilderMethodForField(builder, fieldNodes, prefix, i));
   }
   builder.addMethod(createBuildMethod(builder, buildMethodName, fieldNodes));
 }
 protected void addHasErrorsMethod(final ClassNode paramTypeClassNode) {
   final ASTNode getErrorsMethod =
       paramTypeClassNode.getMethod(
           HAS_ERRORS_METHOD_NAME, GrailsArtefactClassInjector.ZERO_PARAMETERS);
   if (getErrorsMethod == null) {
     final BlockStatement hasErrorsMethodCode = new BlockStatement();
     final Expression initErrorsMethodCallExpression =
         new MethodCallExpression(
             new VariableExpression("this"), INIT_ERRORS_METHOD_NAME, EMPTY_TUPLE);
     hasErrorsMethodCode.addStatement(new ExpressionStatement(initErrorsMethodCallExpression));
     final Statement returnStatement =
         new ReturnStatement(
             new BooleanExpression(
                 new MethodCallExpression(
                     ERRORS_EXPRESSION, HAS_ERRORS_METHOD_NAME, EMPTY_TUPLE)));
     hasErrorsMethodCode.addStatement(returnStatement);
     paramTypeClassNode.addMethod(
         new MethodNode(
             HAS_ERRORS_METHOD_NAME,
             Modifier.PUBLIC,
             new ClassNode(Boolean.class),
             GrailsArtefactClassInjector.ZERO_PARAMETERS,
             GrailsArtefactClassInjector.EMPTY_CLASS_ARRAY,
             hasErrorsMethodCode));
   }
 }
  protected void injectMethodMissing(ClassNode classNode) {
    FieldNode methodMissingInterceptor =
        classNode.addField(
            "this$methodMissingInterceptor",
            Modifier.FINAL | Modifier.STATIC | Modifier.PRIVATE | ACC_SYNTHETIC,
            METHOD_MISSING_INTERCEPTOR_CLASS,
            ctor(
                METHOD_MISSING_INTERCEPTOR_CLASS,
                args(classx(classNode), domainHandlerInstance())));

    classNode.addMethod(
        new MethodNode(
            "$static_methodMissing",
            Modifier.PUBLIC | Modifier.STATIC,
            ClassHelper.OBJECT_TYPE,
            params(
                param(ClassHelper.STRING_TYPE, "methodName"),
                param(ClassHelper.makeWithoutCaching(Object[].class), "arguments")),
            ClassNode.EMPTY_ARRAY,
            returns(
                call(
                    field(methodMissingInterceptor),
                    "handleMethodMissing",
                    args(var("methodName"), var("arguments"))))));
  }
Beispiel #7
0
 public static void addMethodIfNotPresent(ClassNode controllerClassNode, MethodNode methodNode) {
   MethodNode existing =
       controllerClassNode.getMethod(methodNode.getName(), methodNode.getParameters());
   if (existing == null) {
     controllerClassNode.addMethod(methodNode);
   }
 }
  private 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"),
            "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"),
            "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)));
  }
 public void buildClass(
     BuilderASTTransformation transform, ClassNode buildee, AnnotationNode anno) {
   List<String> excludes = new ArrayList<String>();
   List<String> includes = new ArrayList<String>();
   if (!getIncludeExclude(transform, anno, buildee, excludes, includes)) return;
   ClassNode builder = createBuilder(anno, buildee);
   createBuilderFactoryMethod(anno, buildee, builder);
   List<FieldNode> fields = getInstancePropertyFields(buildee);
   List<FieldNode> filteredFields = selectFieldsFromExistingClass(fields, includes, excludes);
   for (FieldNode fieldNode : filteredFields) {
     ClassNode correctedType = getCorrectedType(buildee, fieldNode);
     String fieldName = fieldNode.getName();
     builder.addField(createFieldCopy(buildee, fieldName, correctedType));
     builder.addMethod(
         createBuilderMethodForProp(
             builder, new PropertyInfo(fieldName, correctedType), getPrefix(anno)));
   }
   builder.addMethod(createBuildMethod(anno, buildee, filteredFields));
 }
 // no rename so delete and add
 private static void renameMethod(ClassNode buildee, MethodNode mNode, String newName) {
   buildee.addMethod(
       newName,
       mNode.getModifiers(),
       mNode.getReturnType(),
       mNode.getParameters(),
       mNode.getExceptions(),
       mNode.getCode());
   buildee.removeMethod(mNode);
 }
  /**
   * This method is used to add "bridge" methods for private methods of an inner/outer class, so
   * that the outer class is capable of calling them. It does basically the same job as access$000
   * like methods in Java.
   *
   * @param node an inner/outer class node for which to generate bridge methods
   */
  @SuppressWarnings("unchecked")
  private void addPrivateBridgeMethods(final ClassNode node) {
    Set<ASTNode> accessedMethods =
        (Set<ASTNode>) node.getNodeMetaData(StaticTypesMarker.PV_METHODS_ACCESS);
    if (accessedMethods == null) return;
    List<MethodNode> methods = new ArrayList<MethodNode>(node.getAllDeclaredMethods());
    Map<MethodNode, MethodNode> privateBridgeMethods =
        (Map<MethodNode, MethodNode>) node.getNodeMetaData(PRIVATE_BRIDGE_METHODS);
    if (privateBridgeMethods != null) {
      // private bridge methods already added
      return;
    }
    privateBridgeMethods = new HashMap<MethodNode, MethodNode>();
    int i = -1;
    final int access = Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC;
    for (MethodNode method : methods) {
      if (accessedMethods.contains(method)) {
        i++;
        Parameter[] methodParameters = method.getParameters();
        Parameter[] newParams = new Parameter[methodParameters.length + 1];
        System.arraycopy(methodParameters, 0, newParams, 1, methodParameters.length);
        newParams[0] = new Parameter(node.getPlainNodeReference(), "$that");
        Expression arguments;
        if (method.getParameters() == null || method.getParameters().length == 0) {
          arguments = ArgumentListExpression.EMPTY_ARGUMENTS;
        } else {
          List<Expression> args = new LinkedList<Expression>();
          for (Parameter parameter : methodParameters) {
            args.add(new VariableExpression(parameter));
          }
          arguments = new ArgumentListExpression(args);
        }
        Expression receiver =
            method.isStatic() ? new ClassExpression(node) : new VariableExpression(newParams[0]);
        MethodCallExpression mce = new MethodCallExpression(receiver, method.getName(), arguments);
        mce.setMethodTarget(method);

        ExpressionStatement returnStatement = new ExpressionStatement(mce);
        MethodNode bridge =
            node.addMethod(
                "access$" + i,
                access,
                method.getReturnType(),
                newParams,
                method.getExceptions(),
                returnStatement);
        privateBridgeMethods.put(method, bridge);
        bridge.addAnnotation(new AnnotationNode(COMPILESTATIC_CLASSNODE));
      }
    }
    if (!privateBridgeMethods.isEmpty()) {
      node.setNodeMetaData(PRIVATE_BRIDGE_METHODS, privateBridgeMethods);
    }
  }
  @Test
  public void transformationOfAnnotationOnConstructor() {
    ClassNode classNode = new ClassNode("Test", 0, new ClassNode(Object.class));
    this.moduleNode.addClass(classNode);

    ConstructorNode constructorNode = new ConstructorNode(0, null);
    constructorNode.addAnnotation(this.grabAnnotation);
    classNode.addMethod(constructorNode);

    assertGrabAnnotationHasBeenTransformed();
  }
 private void addGetTagLibNamespaceMethod(final ClassNode classNode, final String namespace) {
   final ConstantExpression namespaceConstantExpression = new ConstantExpression(namespace);
   Statement returnNamespaceStatement = new ReturnStatement(namespaceConstantExpression);
   final MethodNode m =
       new MethodNode(
           GET_TAG_LIB_NAMESPACE_METHOD_NAME,
           Modifier.PROTECTED,
           new ClassNode(String.class),
           Parameter.EMPTY_ARRAY,
           null,
           returnNamespaceStatement);
   classNode.addMethod(m);
 }
  @Test
  public void transformationOfAnnotationOnMethod() {
    ClassNode classNode = new ClassNode("Test", 0, new ClassNode(Object.class));
    this.moduleNode.addClass(classNode);

    MethodNode methodNode =
        new MethodNode(
            "test", 0, new ClassNode(Void.class), new Parameter[0], new ClassNode[0], null);
    methodNode.addAnnotation(this.grabAnnotation);
    classNode.addMethod(methodNode);

    assertGrabAnnotationHasBeenTransformed();
  }
 public void buildMethod(
     BuilderASTTransformation transform, MethodNode mNode, AnnotationNode anno) {
   if (transform.getMemberValue(anno, "includes") != null
       || transform.getMemberValue(anno, "includes") != null) {
     transform.addError(
         "Error during "
             + BuilderASTTransformation.MY_TYPE_NAME
             + " processing: includes/excludes only allowed on classes",
         anno);
   }
   ClassNode buildee = mNode.getDeclaringClass();
   ClassNode builder = createBuilder(anno, buildee);
   createBuilderFactoryMethod(anno, buildee, builder);
   for (Parameter parameter : mNode.getParameters()) {
     builder.addField(createFieldCopy(buildee, parameter));
     builder.addMethod(
         createBuilderMethodForProp(
             builder,
             new PropertyInfo(parameter.getName(), parameter.getType()),
             getPrefix(anno)));
   }
   builder.addMethod(createBuildMethodForMethod(anno, buildee, mNode, mNode.getParameters()));
 }
Beispiel #16
0
  /**
   * Adds a delegate method to the target class node where the first argument is to the delegate
   * method is 'this'. In other words a method such as foo(Object instance, String bar) would be
   * added with a signature of foo(String) and 'this' is passed to the delegate instance
   *
   * @param classNode The class node
   * @param delegate The expression that looks up the delegate
   * @param declaredMethod The declared method
   * @param thisAsFirstArgument Whether 'this' should be passed as the first argument to the method
   * @return The added method node or null if it couldn't be added
   */
  public static MethodNode addDelegateInstanceMethod(
      ClassNode classNode,
      Expression delegate,
      MethodNode declaredMethod,
      boolean thisAsFirstArgument) {
    Parameter[] parameterTypes =
        thisAsFirstArgument
            ? getRemainingParameterTypes(declaredMethod.getParameters())
            : declaredMethod.getParameters();
    String methodName = declaredMethod.getName();
    if (classNode.hasDeclaredMethod(methodName, parameterTypes)) {
      return null;
    }
    String propertyName = GrailsClassUtils.getPropertyForGetter(methodName);
    if (propertyName != null && parameterTypes.length == 0 && classNode.hasProperty(propertyName)) {
      return null;
    }
    propertyName = GrailsClassUtils.getPropertyForSetter(methodName);
    if (propertyName != null && parameterTypes.length == 1 && classNode.hasProperty(propertyName)) {
      return null;
    }

    BlockStatement methodBody = new BlockStatement();
    ArgumentListExpression arguments =
        createArgumentListFromParameters(parameterTypes, thisAsFirstArgument);

    ClassNode returnType = nonGeneric(declaredMethod.getReturnType());

    MethodCallExpression methodCallExpression =
        new MethodCallExpression(delegate, methodName, arguments);
    methodCallExpression.setMethodTarget(declaredMethod);
    ThrowStatement missingMethodException = createMissingMethodThrowable(classNode, declaredMethod);
    VariableExpression apiVar = addApiVariableDeclaration(delegate, declaredMethod, methodBody);
    IfStatement ifStatement =
        createIfElseStatementForApiMethodCall(methodCallExpression, apiVar, missingMethodException);

    methodBody.addStatement(ifStatement);
    MethodNode methodNode =
        new MethodNode(
            methodName,
            Modifier.PUBLIC,
            returnType,
            copyParameters(parameterTypes),
            GrailsArtefactClassInjector.EMPTY_CLASS_ARRAY,
            methodBody);
    methodNode.addAnnotations(declaredMethod.getAnnotations());

    classNode.addMethod(methodNode);
    return methodNode;
  }
  private void changeBaseScriptType(
      final AnnotatedNode parent, final ClassNode cNode, final ClassNode baseScriptType) {
    if (!cNode.isScriptBody()) {
      addError("Annotation " + MY_TYPE_NAME + " can only be used within a Script.", parent);
      return;
    }

    if (!baseScriptType.isScript()) {
      addError(
          "Declared type " + baseScriptType + " does not extend groovy.lang.Script class!", parent);
      return;
    }

    cNode.setSuperClass(baseScriptType);

    // Method in base script that will contain the script body code.
    MethodNode runScriptMethod = ClassHelper.findSAM(baseScriptType);

    // If they want to use a name other than than "run", then make the change.
    if (isCustomScriptBodyMethod(runScriptMethod)) {
      MethodNode defaultMethod = cNode.getDeclaredMethod("run", Parameter.EMPTY_ARRAY);
      // GROOVY-6706: Sometimes an NPE is thrown here.
      // The reason is that our transform is getting called more than once sometimes.
      if (defaultMethod != null) {
        cNode.removeMethod(defaultMethod);
        MethodNode methodNode =
            new MethodNode(
                runScriptMethod.getName(),
                runScriptMethod.getModifiers() & ~ACC_ABSTRACT,
                runScriptMethod.getReturnType(),
                runScriptMethod.getParameters(),
                runScriptMethod.getExceptions(),
                defaultMethod.getCode());
        // The AST node metadata has the flag that indicates that this method is a script body.
        // It may also be carrying data for other AST transforms.
        methodNode.copyNodeMetaData(defaultMethod);
        cNode.addMethod(methodNode);
      }
    }

    // If the new script base class does not have a contextual constructor (g.l.Binding), then we
    // won't either.
    // We have to do things this way (and rely on just default constructors) because the logic that
    // generates
    // the constructors for our script class have already run.
    if (cNode.getSuperClass().getDeclaredConstructor(CONTEXT_CTOR_PARAMETERS) == null) {
      ConstructorNode orphanedConstructor = cNode.getDeclaredConstructor(CONTEXT_CTOR_PARAMETERS);
      cNode.removeConstructor(orphanedConstructor);
    }
  }
 /**
  * If a method with the given name and parameters is already defined then it is returned otherwise
  * the given method is added to this node. This method is useful for default method adding like
  * getProperty() or invokeMethod() where there may already be a method defined in a class and so
  * the default implementations should not be added if already present.
  */
 public MethodNode addMethod(
     String name,
     int modifiers,
     ClassNode returnType,
     Parameter[] parameters,
     ClassNode[] exceptions,
     Statement code) {
   MethodNode other = getDeclaredMethod(name, parameters);
   // let's not add duplicate methods
   if (other != null) {
     return other;
   }
   MethodNode node = new MethodNode(name, modifiers, returnType, parameters, exceptions, code);
   addMethod(node);
   return node;
 }
 private void addAttributesAndStringBodyMethod(ClassNode classNode, String tagName) {
   BlockStatement methodBody = new BlockStatement();
   ArgumentListExpression arguments = new ArgumentListExpression();
   ArgumentListExpression constructorArgs = new ArgumentListExpression();
   constructorArgs.addExpression(BODY_EXPRESSION);
   arguments
       .addExpression(new CastExpression(ClassHelper.make(Map.class), ATTRS_EXPRESSION))
       .addExpression(
           new ConstructorCallExpression(
               new ClassNode(GroovyPage.ConstantClosure.class), constructorArgs));
   methodBody.addStatement(
       new ExpressionStatement(
           new MethodCallExpression(new VariableExpression("this"), tagName, arguments)));
   classNode.addMethod(
       new MethodNode(
           tagName, Modifier.PUBLIC, OBJECT_CLASS, MAP_CHARSEQUENCE_PARAMETERS, null, methodBody));
 }
Beispiel #20
0
  /**
   * Adds a static method to the given class node that delegates to the given method and resolves
   * the object to invoke the method on from the given expression.
   *
   * @param expression The expression
   * @param classNode The class node
   * @param delegateMethod The delegate method
   * @return The added method node or null if it couldn't be added
   */
  public static MethodNode addDelegateStaticMethod(
      Expression expression, ClassNode classNode, MethodNode delegateMethod) {
    Parameter[] parameterTypes = delegateMethod.getParameters();
    String declaredMethodName = delegateMethod.getName();
    if (classNode.hasDeclaredMethod(declaredMethodName, parameterTypes)) {
      return null;
    }

    BlockStatement methodBody = new BlockStatement();
    ArgumentListExpression arguments = new ArgumentListExpression();

    for (Parameter parameterType : parameterTypes) {
      arguments.addExpression(new VariableExpression(parameterType.getName()));
    }
    MethodCallExpression methodCallExpression =
        new MethodCallExpression(expression, declaredMethodName, arguments);
    methodCallExpression.setMethodTarget(delegateMethod);

    ThrowStatement missingMethodException = createMissingMethodThrowable(classNode, delegateMethod);
    VariableExpression apiVar = addApiVariableDeclaration(expression, delegateMethod, methodBody);
    IfStatement ifStatement =
        createIfElseStatementForApiMethodCall(methodCallExpression, apiVar, missingMethodException);

    methodBody.addStatement(ifStatement);
    ClassNode returnType = nonGeneric(delegateMethod.getReturnType());
    if (METHOD_MISSING_METHOD_NAME.equals(declaredMethodName)) {
      declaredMethodName = STATIC_METHOD_MISSING_METHOD_NAME;
    }
    MethodNode methodNode = classNode.getDeclaredMethod(declaredMethodName, parameterTypes);
    if (methodNode == null) {
      methodNode =
          new MethodNode(
              declaredMethodName,
              Modifier.PUBLIC | Modifier.STATIC,
              returnType,
              copyParameters(parameterTypes),
              GrailsArtefactClassInjector.EMPTY_CLASS_ARRAY,
              methodBody);
      methodNode.addAnnotations(delegateMethod.getAnnotations());

      classNode.addMethod(methodNode);
    }
    return methodNode;
  }
  protected void injectMethod(ClassNode classNode, MethodSignature methodSignature) {
    Parameter[] parameters = makeParameters(methodSignature.getParameterTypes());

    int modifiers = Modifier.PUBLIC;
    if (methodSignature.isStatic()) modifiers |= Modifier.STATIC;
    String returnTypeClassName = methodSignature.getReturnType().getName();
    ClassNode returnType =
        GRIFFON_DOMAIN_CLASSNAME.equals(returnTypeClassName)
            ? classNode
            : ClassHelper.makeWithoutCaching(methodSignature.getReturnType());
    classNode.addMethod(
        new MethodNode(
            methodSignature.getMethodName(),
            modifiers,
            returnType,
            parameters,
            ClassNode.EMPTY_ARRAY,
            makeMethodBody(classNode, methodSignature, parameters)));
  }
 protected void addClearErrorsMethod(final ClassNode paramTypeClassNode) {
   final ASTNode clearErrorsMethod =
       paramTypeClassNode.getMethod(
           CLEAR_ERRORS_METHOD_NAME, GrailsArtefactClassInjector.ZERO_PARAMETERS);
   if (clearErrorsMethod == null) {
     final BlockStatement clearErrorsMethodCode = new BlockStatement();
     Expression nullOutErrorsFieldExpression =
         new BinaryExpression(ERRORS_EXPRESSION, EQUALS_SYMBOL, NULL_EXPRESSION);
     clearErrorsMethodCode.addStatement(new ExpressionStatement(nullOutErrorsFieldExpression));
     paramTypeClassNode.addMethod(
         new MethodNode(
             CLEAR_ERRORS_METHOD_NAME,
             Modifier.PUBLIC,
             ClassHelper.VOID_TYPE,
             GrailsArtefactClassInjector.ZERO_PARAMETERS,
             GrailsArtefactClassInjector.EMPTY_CLASS_ARRAY,
             clearErrorsMethodCode));
   }
 }
 private BlockStatement getJunit4Setup(ClassNode classNode) {
   MethodNode setupMethod =
       classNode.getMethod(SET_UP_METHOD, GrailsArtefactClassInjector.ZERO_PARAMETERS);
   if (setupMethod == null) {
     setupMethod =
         new MethodNode(
             SET_UP_METHOD,
             Modifier.PUBLIC,
             ClassHelper.VOID_TYPE,
             GrailsArtefactClassInjector.ZERO_PARAMETERS,
             null,
             new BlockStatement());
     setupMethod.addAnnotation(MIXIN_METHOD_ANNOTATION);
     classNode.addMethod(setupMethod);
   }
   if (setupMethod.getAnnotations(BEFORE_CLASS_NODE).size() == 0) {
     setupMethod.addAnnotation(BEFORE_ANNOTATION);
   }
   return getOrCreateMethodBody(classNode, setupMethod, SET_UP_METHOD);
 }
Beispiel #24
0
  public void configureClassNode(CompileUnit compileUnit, ClassNode classNode) {
    Class clazz = classNode.getTypeClass();
    Field[] fields = clazz.getDeclaredFields();
    for (Field f : fields) {
      ClassNode ret = makeClassNode(compileUnit, f.getGenericType(), f.getType());
      classNode.addField(f.getName(), f.getModifiers(), ret, null);
    }
    Method[] methods = clazz.getDeclaredMethods();
    for (Method m : methods) {
      ClassNode ret = makeClassNode(compileUnit, m.getGenericReturnType(), m.getReturnType());
      Parameter[] params =
          makeParameters(compileUnit, m.getGenericParameterTypes(), m.getParameterTypes());
      ClassNode[] exceptions =
          makeClassNodes(compileUnit, m.getGenericExceptionTypes(), m.getExceptionTypes());
      MethodNode mn = new MethodNode(m.getName(), m.getModifiers(), ret, params, exceptions, null);
      setMethodDefaultValue(mn, m);
      setAnnotationMetaData(m.getAnnotations(), mn);
      mn.setGenericsTypes(configureTypeVariable(m.getTypeParameters()));
      classNode.addMethod(mn);
    }
    Constructor[] constructors = clazz.getDeclaredConstructors();
    for (Constructor ctor : constructors) {
      Parameter[] params =
          makeParameters(compileUnit, ctor.getGenericParameterTypes(), ctor.getParameterTypes());
      ClassNode[] exceptions =
          makeClassNodes(compileUnit, ctor.getGenericExceptionTypes(), ctor.getExceptionTypes());
      classNode.addConstructor(ctor.getModifiers(), params, exceptions, null);
    }

    Class sc = clazz.getSuperclass();
    if (sc != null)
      classNode.setUnresolvedSuperClass(
          makeClassNode(compileUnit, clazz.getGenericSuperclass(), sc));
    makeInterfaceTypes(compileUnit, classNode, clazz);
    setAnnotationMetaData(classNode.getTypeClass().getAnnotations(), classNode);

    PackageNode packageNode = classNode.getPackage();
    if (packageNode != null) {
      setAnnotationMetaData(classNode.getTypeClass().getPackage().getAnnotations(), packageNode);
    }
  }
 protected void addSetErrorsMethod(final ClassNode paramTypeClassNode) {
   final String errorsArgumentName = "$errorsArg";
   MethodNode setErrorsMethod =
       paramTypeClassNode.getMethod(
           SET_ERRORS_METHOD_NAME,
           new Parameter[] {new Parameter(ERRORS_CLASS_NODE, errorsArgumentName)});
   if (setErrorsMethod == null) {
     final Expression assignErrorsExpression =
         new BinaryExpression(
             ERRORS_EXPRESSION, EQUALS_SYMBOL, new VariableExpression(errorsArgumentName));
     setErrorsMethod =
         new MethodNode(
             SET_ERRORS_METHOD_NAME,
             Modifier.PUBLIC,
             ClassHelper.VOID_TYPE,
             new Parameter[] {new Parameter(ERRORS_CLASS_NODE, errorsArgumentName)},
             GrailsArtefactClassInjector.EMPTY_CLASS_ARRAY,
             new ExpressionStatement(assignErrorsExpression));
     paramTypeClassNode.addMethod(setErrorsMethod);
   }
 }
 private static void createBuildeeMethods(
     ClassNode buildee, MethodNode mNode, ClassNode builder, List<FieldNode> fields) {
   ClassNode paramType = makeClassSafeWithGenerics(builder, setGenTypes(fields.size()));
   List<Expression> argsList = new ArrayList<Expression>();
   Parameter initParam = param(paramType, "initializer");
   for (FieldNode fieldNode : fields) {
     argsList.add(propX(varX(initParam), fieldNode.getName()));
   }
   String newName =
       "$"
           + mNode
               .getName(); // can't have private and public methods of the same name, so rename
                           // original
   buildee.addMethod(
       mNode.getName(),
       PUBLIC_STATIC,
       mNode.getReturnType(),
       params(param(paramType, "initializer")),
       NO_EXCEPTIONS,
       block(stmt(callX(buildee, newName, args(argsList)))));
   renameMethod(buildee, mNode, newName);
 }
  protected void addInitErrorsMethod(final ClassNode paramTypeClassNode) {
    final ASTNode initErrorsMethod =
        paramTypeClassNode.getMethod(
            INIT_ERRORS_METHOD_NAME, GrailsArtefactClassInjector.ZERO_PARAMETERS);
    if (initErrorsMethod == null) {
      final BlockStatement initErrorsMethodCode = new BlockStatement();

      final BinaryExpression errorsIsNullExpression =
          new BinaryExpression(
              ERRORS_EXPRESSION, Token.newSymbol(Types.COMPARE_EQUAL, 0, 0), NULL_EXPRESSION);

      Expression beanPropertyBindingResultConstructorArgs =
          new ArgumentListExpression(
              new VariableExpression("this"), new ConstantExpression(paramTypeClassNode.getName()));
      final Statement newEvaluatorExpression =
          new ExpressionStatement(
              new BinaryExpression(
                  ERRORS_EXPRESSION,
                  EQUALS_SYMBOL,
                  new ConstructorCallExpression(
                      new ClassNode(ValidationErrors.class),
                      beanPropertyBindingResultConstructorArgs)));
      final Statement initErrorsIfNullStatement =
          new IfStatement(
              new BooleanExpression(errorsIsNullExpression),
              newEvaluatorExpression,
              new ExpressionStatement(new EmptyExpression()));
      initErrorsMethodCode.addStatement(initErrorsIfNullStatement);
      paramTypeClassNode.addMethod(
          new MethodNode(
              INIT_ERRORS_METHOD_NAME,
              Modifier.PRIVATE,
              ClassHelper.VOID_TYPE,
              GrailsArtefactClassInjector.ZERO_PARAMETERS,
              GrailsArtefactClassInjector.EMPTY_CLASS_ARRAY,
              initErrorsMethodCode));
    }
  }
  @Test
  public void transformationOfAnnotationOnLocalVariable() {
    ClassNode classNode = new ClassNode("Test", 0, new ClassNode(Object.class));
    this.moduleNode.addClass(classNode);

    DeclarationExpression declarationExpression =
        new DeclarationExpression(
            new VariableExpression("test"), null, new ConstantExpression("test"));
    declarationExpression.addAnnotation(this.grabAnnotation);

    BlockStatement code =
        new BlockStatement(
            Arrays.asList((Statement) new ExpressionStatement(declarationExpression)),
            new VariableScope());

    MethodNode methodNode =
        new MethodNode(
            "test", 0, new ClassNode(Void.class), new Parameter[0], new ClassNode[0], code);

    classNode.addMethod(methodNode);

    assertGrabAnnotationHasBeenTransformed();
  }
  private void injectToStringMethod(ClassNode classNode) {
    final boolean hasToString = /*GrailsASTUtils.*/ implementsZeroArgMethod(classNode, "toString");

    if (!hasToString) {
      GStringExpression ge = new GStringExpression(classNode.getName() + " : ${id}");
      ge.addString(new ConstantExpression(classNode.getName() + " : "));
      ge.addValue(new VariableExpression("id"));
      Statement s = new ReturnStatement(ge);
      MethodNode mn =
          new MethodNode(
              "toString",
              Modifier.PUBLIC,
              new ClassNode(String.class),
              new Parameter[0],
              new ClassNode[0],
              s);
      // if(LOG.isDebugEnabled()) {
      //    LOG.debug("[GrailsDomainInjector] Adding method [toString()] to class [" +
      // classNode.getName() + "]");
      // }
      classNode.addMethod(mn);
    }
  }
  /** Adds special accessors for private constants so that inner classes can retrieve them. */
  @SuppressWarnings("unchecked")
  private void addPrivateFieldsAccessors(ClassNode node) {
    Set<ASTNode> accessedFields =
        (Set<ASTNode>) node.getNodeMetaData(StaticTypesMarker.PV_FIELDS_ACCESS);
    if (accessedFields == null) return;
    Map<String, MethodNode> privateConstantAccessors =
        (Map<String, MethodNode>) node.getNodeMetaData(PRIVATE_FIELDS_ACCESSORS);
    if (privateConstantAccessors != null) {
      // already added
      return;
    }
    int acc = -1;
    privateConstantAccessors = new HashMap<String, MethodNode>();
    final int access = Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC;
    for (FieldNode fieldNode : node.getFields()) {
      if (accessedFields.contains(fieldNode)) {

        acc++;
        Parameter param = new Parameter(node.getPlainNodeReference(), "$that");
        Expression receiver =
            fieldNode.isStatic() ? new ClassExpression(node) : new VariableExpression(param);
        Statement stmt =
            new ExpressionStatement(new PropertyExpression(receiver, fieldNode.getName()));
        MethodNode accessor =
            node.addMethod(
                "pfaccess$" + acc,
                access,
                fieldNode.getOriginType(),
                new Parameter[] {param},
                ClassNode.EMPTY_ARRAY,
                stmt);
        privateConstantAccessors.put(fieldNode.getName(), accessor);
      }
    }
    node.setNodeMetaData(PRIVATE_FIELDS_ACCESSORS, privateConstantAccessors);
  }