/*
 * Copyright 2016 yihtserns.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.github.yihtserns.groovy.decorator;

import java.util.ArrayList;
import java.util.List;
import org.codehaus.groovy.ast.ASTNode;
import org.codehaus.groovy.ast.AnnotationNode;
import org.codehaus.groovy.ast.MethodNode;
import org.codehaus.groovy.ast.Parameter;
import org.codehaus.groovy.ast.VariableScope;
import org.codehaus.groovy.ast.expr.ClosureExpression;
import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.ast.expr.ListExpression;
import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.classX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.closureX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS;
import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
import org.codehaus.groovy.control.CompilePhase;
import org.codehaus.groovy.control.SourceUnit;
import org.codehaus.groovy.transform.ASTTransformation;
import org.codehaus.groovy.transform.GroovyASTTransformation;

/**
 *
 * @author yihtserns
 */
@GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS)
public class DecoratorASTTransformation implements ASTTransformation {

    @Override
    public void visit(ASTNode[] astNodes, final SourceUnit sourceUnit) {
        AnnotationNode annotation = (AnnotationNode) astNodes[0];

        DecoratorClass decoratorClass = (DecoratorClass) annotation.getClassNode().getTypeClass().getAnnotation(DecoratorClass.class);

        MethodNode method = (MethodNode) astNodes[1];
        ClosureExpression closuredOriginalCode = closureX(method.getParameters(), method.getCode());
        closuredOriginalCode.setVariableScope(new VariableScope());

        List<Expression> arguments = new ArrayList<Expression>();
        arguments.add(constX(method.getName()));
        arguments.add(closuredOriginalCode);
        arguments.add(new ListExpression(toVars(method.getParameters())));

        method.setCode(returnS(callX(classX(decoratorClass.value()), "call", args(arguments))));
    }

    private static List<Expression> toVars(Parameter[] parameters) {
        List<Expression> variables = new ArrayList<Expression>();
        for (Parameter parameter : parameters) {
            variables.add(varX(parameter.getName()));
        }

        return variables;
    }
}

@@ -2656,27 +2656,8 @@
 add(
-new ListExpression(
 toVa
@@ -2683,17 +2683,16 @@
 ters()))
-)
 ;%0D%0A%0D%0A   
@@ -2814,25 +2814,24 @@
  static List
-%3C
 Expression%3E 
@@ -2828,17 +2828,16 @@
 pression
-%3E
  toVars(
@@ -2867,33 +2867,32 @@
  %7B%0D%0A        List
-%3C
 Expression%3E vari
@@ -2885,17 +2885,16 @@
 pression
-%3E
  variabl
@@ -2898,34 +2898,28 @@
 ables = new 
-Array
 List
-%3C
 Expression%3E(
@@ -2908,33 +2908,32 @@
 w ListExpression
-%3E
 ();%0D%0A        for
@@ -2963,32 +2963,32 @@
  parameters) %7B%0D%0A
-
             vari
@@ -2996,16 +2996,26 @@
 bles.add
+Expression
 (varX(pa

Remove unnecessary temporary list.