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)))); }
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")))))); }
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())); }
/** * 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)); }
/** * 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); }
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); }