private Expression transformMethodCallExpression(final MethodCallExpression exp) { Expression objectExpression = transform(exp.getObjectExpression()); ClassNode traitReceiver = objectExpression.getNodeMetaData(SuperCallTraitTransformer.class); if (traitReceiver != null) { TraitHelpersTuple helpers = Traits.findHelpers(traitReceiver); // (SomeTrait.super).foo() --> SomeTrait$Helper.foo(this) ClassExpression receiver = new ClassExpression(helpers.getHelper()); ArgumentListExpression newArgs = new ArgumentListExpression(); Expression arguments = exp.getArguments(); newArgs.addExpression(new VariableExpression("this")); if (arguments instanceof TupleExpression) { List<Expression> expressions = ((TupleExpression) arguments).getExpressions(); for (Expression expression : expressions) { newArgs.addExpression(transform(expression)); } } else { newArgs.addExpression(arguments); } MethodCallExpression result = new MethodCallExpression(receiver, exp.getMethod(), newArgs); result.setImplicitThis(false); result.setSpreadSafe(exp.isSpreadSafe()); result.setSafe(exp.isSafe()); result.setSourcePosition(exp); return result; } return super.transform(exp); }
@Override public void visitConstructorCallExpression(final ConstructorCallExpression call) { super.visitConstructorCallExpression(call); MethodNode target = (MethodNode) call.getNodeMetaData(DIRECT_METHOD_CALL_TARGET); if (target == null && call.getLineNumber() > 0) { addError("Target constructor for constructor call expression hasn't been set", call); } else { if (target == null) { // try to find a target ArgumentListExpression argumentListExpression = InvocationWriter.makeArgumentList(call.getArguments()); List<Expression> expressions = argumentListExpression.getExpressions(); ClassNode[] args = new ClassNode[expressions.size()]; for (int i = 0; i < args.length; i++) { args[i] = typeChooser.resolveType(expressions.get(i), classNode); } MethodNode constructor = findMethodOrFail( call, call.isSuperCall() ? classNode.getSuperClass() : classNode, "<init>", args); call.putNodeMetaData(DIRECT_METHOD_CALL_TARGET, constructor); target = constructor; } } if (target != null) { memorizeInitialExpressions(target); } }
private static ThrowStatement createMissingMethodThrowable( ClassNode classNode, MethodNode declaredMethodNode) { ArgumentListExpression exceptionArgs = new ArgumentListExpression(); exceptionArgs.addExpression(new ConstantExpression(declaredMethodNode.getName())); exceptionArgs.addExpression(new ClassExpression(classNode)); return new ThrowStatement( new ConstructorCallExpression(MISSING_METHOD_EXCEPTION, exceptionArgs)); }
private void printSpecialConstructorArgs( PrintWriter out, ConstructorNode node, ConstructorCallExpression constrCall) { // Select a constructor from our class, or super-class which is legal to call, // then write out an invoke w/nulls using casts to avoid ambiguous crapo Parameter[] params = selectAccessibleConstructorFromSuper(node); if (params != null) { out.print("super ("); for (int i = 0; i < params.length; i++) { printDefaultValue(out, params[i].getType()); if (i + 1 < params.length) { out.print(", "); } } out.println(");"); return; } // Otherwise try the older method based on the constructor's call expression Expression arguments = constrCall.getArguments(); if (constrCall.isSuperCall()) { out.print("super("); } else { out.print("this("); } // Else try to render some arguments if (arguments instanceof ArgumentListExpression) { ArgumentListExpression argumentListExpression = (ArgumentListExpression) arguments; List<Expression> args = argumentListExpression.getExpressions(); for (Expression arg : args) { if (arg instanceof ConstantExpression) { ConstantExpression expression = (ConstantExpression) arg; Object o = expression.getValue(); if (o instanceof String) { out.print("(String)null"); } else { out.print(expression.getText()); } } else { ClassNode type = getConstructorArgumentType(arg, node); printDefaultValue(out, type); } if (arg != args.get(args.size() - 1)) { out.print(", "); } } } out.println(");"); }
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 Expression findStaticPropertyAccessorByFullName( ClassNode staticImportType, String accessorMethodName) { // anything will do as we only check size == 1 ArgumentListExpression dummyArgs = new ArgumentListExpression(); dummyArgs.addExpression(new EmptyExpression()); return findStaticMethod( staticImportType, accessorMethodName, (inLeftExpression ? dummyArgs : ArgumentListExpression.EMPTY_ARGUMENTS)); }
protected void addMockCollaborator( String mockType, ClassExpression targetClass, BlockStatement methodBody) { ArgumentListExpression args = new ArgumentListExpression(); args.addExpression(targetClass); methodBody .getStatements() .add( 0, new ExpressionStatement( new MethodCallExpression(THIS_EXPRESSION, "mock" + mockType, args))); }
/** * Creates an argument list from the given parameter types. * * @param parameterTypes The parameter types * @param thisAsFirstArgument Whether to include a reference to 'this' as the first argument * @return the arguments */ public static ArgumentListExpression createArgumentListFromParameters( Parameter[] parameterTypes, boolean thisAsFirstArgument) { ArgumentListExpression arguments = new ArgumentListExpression(); if (thisAsFirstArgument) { arguments.addExpression(AbstractGrailsArtefactTransformer.THIS_EXPRESSION); } for (Parameter parameterType : parameterTypes) { arguments.addExpression(new VariableExpression(parameterType.getName())); } return arguments; }
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; }
/** * Wraps a method body in try / catch logic that catches any errors and logs an error, but does * not rethrow! * * @param methodNode The method node */ public static void wrapMethodBodyInTryCatchDebugStatements(MethodNode methodNode) { BlockStatement code = (BlockStatement) methodNode.getCode(); BlockStatement newCode = new BlockStatement(); TryCatchStatement tryCatchStatement = new TryCatchStatement(code, new BlockStatement()); newCode.addStatement(tryCatchStatement); methodNode.setCode(newCode); BlockStatement catchBlock = new BlockStatement(); ArgumentListExpression logArguments = new ArgumentListExpression(); logArguments.addExpression( new BinaryExpression( new ConstantExpression("Error initializing class: "), Token.newSymbol(Types.PLUS, 0, 0), new VariableExpression("e"))); logArguments.addExpression(new VariableExpression("e")); catchBlock.addStatement( new ExpressionStatement( new MethodCallExpression(new VariableExpression("log"), "error", logArguments))); tryCatchStatement.addCatch( new CatchStatement(new Parameter(new ClassNode(Throwable.class), "e"), catchBlock)); }
@Override public void visitArgumentlistExpression(ArgumentListExpression expression) { // LOG.debug "Transforming expression '${expression}':" if (expression.getLineNumber() >= 0 && expression.getLineNumber() < lineNumbers.length) { // LOG.debug " start from ${expression.lineNumber} to ${lineNumbers[expression.lineNumber // - 1]}" expression.setLineNumber(lineNumbers[expression.getLineNumber() - 1]); } if (expression.getLastLineNumber() > 0 && expression.getLastLineNumber() < lineNumbers.length) { // LOG.debug " end from ${expression.lastLineNumber} to // ${lineNumbers[expression.lastLineNumber - 1]}" expression.setLastLineNumber(lineNumbers[expression.getLastLineNumber() - 1]); } super.visitArgumentlistExpression(expression); }
private IfStatement getAutowiringIfStatement( ClassExpression targetClass, VariableExpression fieldExpression, BinaryExpression testTargetAssignment) { VariableExpression appCtxVar = new VariableExpression("applicationContext"); BooleanExpression applicationContextCheck = new BooleanExpression( new BinaryExpression( new BinaryExpression( fieldExpression, GrailsASTUtils.EQUALS_OPERATOR, GrailsASTUtils.NULL_EXPRESSION), Token.newSymbol("&&", 0, 0), new BinaryExpression( appCtxVar, GrailsASTUtils.NOT_EQUALS_OPERATOR, GrailsASTUtils.NULL_EXPRESSION))); BlockStatement performAutowireBlock = new BlockStatement(); ArgumentListExpression arguments = new ArgumentListExpression(); arguments.addExpression(fieldExpression); arguments.addExpression(new ConstantExpression(1)); arguments.addExpression(new ConstantExpression(false)); BlockStatement assignFromApplicationContext = new BlockStatement(); ArgumentListExpression argWithClassName = new ArgumentListExpression(); MethodCallExpression getClassNameMethodCall = new MethodCallExpression(targetClass, "getName", new ArgumentListExpression()); argWithClassName.addExpression(getClassNameMethodCall); assignFromApplicationContext.addStatement( new ExpressionStatement( new BinaryExpression( fieldExpression, ASSIGN, new MethodCallExpression(appCtxVar, "getBean", argWithClassName)))); BlockStatement elseBlock = new BlockStatement(); elseBlock.addStatement(new ExpressionStatement(testTargetAssignment)); performAutowireBlock.addStatement( new IfStatement( new BooleanExpression( new MethodCallExpression(appCtxVar, "containsBean", argWithClassName)), assignFromApplicationContext, elseBlock)); performAutowireBlock.addStatement( new ExpressionStatement( new MethodCallExpression( new PropertyExpression(appCtxVar, "autowireCapableBeanFactory"), "autowireBeanProperties", arguments))); return new IfStatement(applicationContextCheck, performAutowireBlock, new BlockStatement()); }