You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by cc...@apache.org on 2017/12/14 21:56:59 UTC

[34/57] [abbrv] [partial] groovy git commit: Move Java source set into `src/main/java`

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/ast/decompiled/ClassSignatureParser.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/decompiled/ClassSignatureParser.java b/src/main/java/org/codehaus/groovy/ast/decompiled/ClassSignatureParser.java
new file mode 100644
index 0000000..2222590
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/ast/decompiled/ClassSignatureParser.java
@@ -0,0 +1,84 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 org.codehaus.groovy.ast.decompiled;
+
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.GenericsType;
+import org.objectweb.asm.signature.SignatureReader;
+import org.objectweb.asm.signature.SignatureVisitor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Peter Gromov
+ */
+class ClassSignatureParser {
+    static void configureClass(ClassNode classNode, ClassStub stub, AsmReferenceResolver resolver) {
+        if (stub.signature != null) {
+            parseClassSignature(classNode, stub.signature, resolver);
+            return;
+        }
+
+        if (stub.superName != null) {
+            classNode.setSuperClass(resolver.resolveClass(AsmDecompiler.fromInternalName(stub.superName)));
+        }
+
+        ClassNode[] interfaces = new ClassNode[stub.interfaceNames.length];
+        for (int i = 0; i < stub.interfaceNames.length; i++) {
+            interfaces[i] = resolver.resolveClass(AsmDecompiler.fromInternalName(stub.interfaceNames[i]));
+        }
+        classNode.setInterfaces(interfaces);
+    }
+
+    private static void parseClassSignature(final ClassNode classNode, String signature, final AsmReferenceResolver resolver) {
+        final List<ClassNode> interfaces = new ArrayList<ClassNode>();
+        FormalParameterParser v = new FormalParameterParser(resolver) {
+
+            @Override
+            public SignatureVisitor visitSuperclass() {
+                flushTypeParameter();
+                return new TypeSignatureParser(resolver) {
+                    @Override
+                    void finished(ClassNode result) {
+                        classNode.setSuperClass(result);
+                    }
+                };
+            }
+
+            @Override
+            public SignatureVisitor visitInterface() {
+                flushTypeParameter();
+                return new TypeSignatureParser(resolver) {
+                    @Override
+                    void finished(ClassNode result) {
+                        interfaces.add(result);
+                    }
+                };
+            }
+
+        };
+        new SignatureReader(signature).accept(v);
+        GenericsType[] typeParameters = v.getTypeParameters();
+        if (typeParameters.length > 0) {
+            classNode.setGenericsTypes(typeParameters);
+        }
+        classNode.setInterfaces(interfaces.toArray(new ClassNode[interfaces.size()]));
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/ast/decompiled/ClassStub.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/decompiled/ClassStub.java b/src/main/java/org/codehaus/groovy/ast/decompiled/ClassStub.java
new file mode 100644
index 0000000..364b69d
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/ast/decompiled/ClassStub.java
@@ -0,0 +1,117 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 org.codehaus.groovy.ast.decompiled;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Peter Gromov
+ */
+public class ClassStub extends MemberStub {
+    final String className;
+    final int accessModifiers;
+    final String signature;
+    final String superName;
+    final String[] interfaceNames;
+    List<MethodStub> methods;
+    List<FieldStub> fields;
+    final Map<String, Integer> innerClassModifiers = new HashMap<String, Integer>();
+
+    public ClassStub(String className, int accessModifiers, String signature, String superName, String[] interfaceNames) {
+        this.className = className;
+        this.accessModifiers = accessModifiers;
+        this.signature = signature;
+        this.superName = superName;
+        this.interfaceNames = interfaceNames;
+    }
+}
+
+class MemberStub {
+    List<AnnotationStub> annotations = null;
+
+    AnnotationStub addAnnotation(String desc) {
+        AnnotationStub stub = new AnnotationStub(desc);
+        if (annotations == null) annotations = new ArrayList<AnnotationStub>(1);
+        annotations.add(stub);
+        return stub;
+    }
+}
+
+class MethodStub extends MemberStub {
+    final String methodName;
+    final int accessModifiers;
+    final String desc;
+    final String signature;
+    final String[] exceptions;
+    Map<Integer, List<AnnotationStub>> parameterAnnotations;
+    Object annotationDefault;
+
+    public MethodStub(String methodName, int accessModifiers, String desc, String signature, String[] exceptions) {
+        this.methodName = methodName;
+        this.accessModifiers = accessModifiers;
+        this.desc = desc;
+        this.signature = signature;
+        this.exceptions = exceptions;
+    }
+}
+
+class FieldStub extends MemberStub {
+    final String fieldName;
+    final int accessModifiers;
+    final String desc;
+    final String signature;
+
+    public FieldStub(String fieldName, int accessModifiers, String desc, String signature) {
+        this.fieldName = fieldName;
+        this.accessModifiers = accessModifiers;
+        this.desc = desc;
+        this.signature = signature;
+    }
+}
+
+class AnnotationStub {
+    final String className;
+    final Map<String, Object> members = new LinkedHashMap<String, Object>();
+
+    public AnnotationStub(String className) {
+        this.className = className;
+    }
+}
+
+class TypeWrapper {
+    final String desc;
+
+    public TypeWrapper(String desc) {
+        this.desc = desc;
+    }
+}
+
+class EnumConstantWrapper {
+    final String enumDesc;
+    final String constant;
+
+    public EnumConstantWrapper(String enumDesc, String constant) {
+        this.enumDesc = enumDesc;
+        this.constant = constant;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/ast/decompiled/DecompiledClassNode.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/decompiled/DecompiledClassNode.java b/src/main/java/org/codehaus/groovy/ast/decompiled/DecompiledClassNode.java
new file mode 100644
index 0000000..18cc79f
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/ast/decompiled/DecompiledClassNode.java
@@ -0,0 +1,242 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 org.codehaus.groovy.ast.decompiled;
+
+import org.codehaus.groovy.ast.AnnotatedNode;
+import org.codehaus.groovy.ast.AnnotationNode;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.ConstructorNode;
+import org.codehaus.groovy.ast.FieldNode;
+import org.codehaus.groovy.ast.GenericsType;
+import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.ast.MixinNode;
+import org.codehaus.groovy.classgen.Verifier;
+
+import java.lang.reflect.Modifier;
+import java.util.List;
+
+/**
+ * A {@link ClassNode} kind representing the classes coming from *.class files decompiled using ASM.
+ *
+ * @see AsmDecompiler
+ * @author Peter Gromov
+ */
+public class DecompiledClassNode extends ClassNode {
+    private final ClassStub classData;
+    private final AsmReferenceResolver resolver;
+    private boolean supersInitialized = false;
+    private boolean membersInitialized = false;
+
+    public DecompiledClassNode(ClassStub data, AsmReferenceResolver resolver) {
+        super(data.className, getFullModifiers(data, resolver), null, null, MixinNode.EMPTY_ARRAY);
+        classData = data;
+        this.resolver = resolver;
+        isPrimaryNode = false;
+    }
+
+    /**
+     * Static inner classes don't have "static" part in their own modifiers. Their containing classes have to be inspected
+     * whether they have an inner class with the same name that's static. '$' separator convention is used to search
+     * for parent classes.
+     */
+    private static int getFullModifiers(ClassStub data, AsmReferenceResolver resolver) {
+        String className = data.className;
+        int bound = className.length();
+        while (bound > 0) {
+            int idx = className.lastIndexOf('$', bound);
+            if (idx > 0) {
+                ClassNode outerClass = resolver.resolveClassNullable(className.substring(0, idx));
+                if (outerClass instanceof DecompiledClassNode) {
+                    Integer outerModifiers = ((DecompiledClassNode) outerClass).classData.innerClassModifiers.get(className.substring(idx + 1));
+                    if (outerModifiers != null) {
+                        return data.accessModifiers | outerModifiers;
+                    }
+                }
+            }
+            bound = idx - 1;
+        }
+        return data.accessModifiers;
+    }
+
+    public long getCompilationTimeStamp() {
+        if (classData.fields != null) {
+            for (FieldStub field : classData.fields) {
+                if (Modifier.isStatic(field.accessModifiers)) {
+                    Long timestamp = Verifier.getTimestampFromFieldName(field.fieldName);
+                    if (timestamp != null) {
+                        return timestamp;
+                    }
+                }
+            }
+        }
+        return Long.MAX_VALUE;
+    }
+
+    @Override
+    public GenericsType[] getGenericsTypes() {
+        lazyInitSupers();
+        return super.getGenericsTypes();
+    }
+
+    @Override
+    public boolean isUsingGenerics() {
+        lazyInitSupers();
+        return super.isUsingGenerics();
+    }
+
+    @Override
+    public List<FieldNode> getFields() {
+        lazyInitMembers();
+        return super.getFields();
+    }
+
+    @Override
+    public ClassNode[] getInterfaces() {
+        lazyInitSupers();
+        return super.getInterfaces();
+    }
+
+    @Override
+    public List<MethodNode> getMethods() {
+        lazyInitMembers();
+        return super.getMethods();
+    }
+
+    @Override
+    public List<ConstructorNode> getDeclaredConstructors() {
+        lazyInitMembers();
+        return super.getDeclaredConstructors();
+    }
+
+    @Override
+    public FieldNode getDeclaredField(String name) {
+        lazyInitMembers();
+        return super.getDeclaredField(name);
+    }
+
+    @Override
+    public List<MethodNode> getDeclaredMethods(String name) {
+        lazyInitMembers();
+        return super.getDeclaredMethods(name);
+    }
+
+    @Override
+    public ClassNode getUnresolvedSuperClass(boolean useRedirect) {
+        lazyInitSupers();
+        return super.getUnresolvedSuperClass(useRedirect);
+    }
+
+    @Override
+    public ClassNode[] getUnresolvedInterfaces(boolean useRedirect) {
+        lazyInitSupers();
+        return super.getUnresolvedInterfaces(useRedirect);
+    }
+
+    @Override
+    public List<AnnotationNode> getAnnotations() {
+        lazyInitSupers();
+        return super.getAnnotations();
+    }
+
+    @Override
+    public List<AnnotationNode> getAnnotations(ClassNode type) {
+        lazyInitSupers();
+        return super.getAnnotations(type);
+    }
+
+    @Override
+    public void setRedirect(ClassNode cn) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void setGenericsPlaceHolder(boolean b) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void setUsingGenerics(boolean b) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String setName(String name) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isResolved() {
+        return true;
+    }
+
+    @Override
+    public Class getTypeClass() {
+        return resolver.resolveJvmClass(getName());
+    }
+
+    private void lazyInitSupers() {
+        synchronized (lazyInitLock) {
+            if (!supersInitialized) {
+                ClassSignatureParser.configureClass(this, this.classData, this.resolver);
+                addAnnotations(classData, this);
+                supersInitialized = true;
+            }
+        }
+
+    }
+
+    private void lazyInitMembers() {
+        synchronized (lazyInitLock) {
+            if (!membersInitialized) {
+                if (classData.methods != null) {
+                    for (MethodStub method : classData.methods) {
+                        MethodNode node = addAnnotations(method, MemberSignatureParser.createMethodNode(resolver, method));
+                        if (node instanceof ConstructorNode) {
+                            addConstructor((ConstructorNode) node);
+                        } else {
+                            addMethod(node);
+                        }
+                    }
+                }
+
+                if (classData.fields != null) {
+                    for (FieldStub field : classData.fields) {
+                        addField(addAnnotations(field, MemberSignatureParser.createFieldNode(field, resolver, this)));
+                    }
+                }
+
+                membersInitialized = true;
+            }
+        }
+    }
+
+    private <T extends AnnotatedNode> T addAnnotations(MemberStub stub, T node) {
+        List<AnnotationStub> annotations = stub.annotations;
+        if (annotations != null) {
+            for (AnnotationStub annotation : annotations) {
+                AnnotationNode annotationNode = Annotations.createAnnotationNode(annotation, resolver);
+                if (annotationNode != null) {
+                    node.addAnnotation(annotationNode);
+                }
+            }
+        }
+        return node;
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/ast/decompiled/FormalParameterParser.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/decompiled/FormalParameterParser.java b/src/main/java/org/codehaus/groovy/ast/decompiled/FormalParameterParser.java
new file mode 100644
index 0000000..98277d8
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/ast/decompiled/FormalParameterParser.java
@@ -0,0 +1,80 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 org.codehaus.groovy.ast.decompiled;
+
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.GenericsType;
+import org.codehaus.groovy.vmplugin.v5.Java5;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.signature.SignatureVisitor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+* @author Peter Gromov
+*/
+abstract class FormalParameterParser extends SignatureVisitor {
+    private final AsmReferenceResolver resolver;
+    private String currentTypeParameter;
+    private final List<ClassNode> parameterBounds = new ArrayList<ClassNode>();
+    private final List<GenericsType> typeParameters = new ArrayList<GenericsType>();
+
+    public FormalParameterParser(AsmReferenceResolver resolver) {
+        super(Opcodes.ASM5);
+        this.resolver = resolver;
+    }
+
+    @Override
+    public void visitFormalTypeParameter(String name) {
+        flushTypeParameter();
+        currentTypeParameter = name;
+    }
+
+    protected void flushTypeParameter() {
+        if (currentTypeParameter != null) {
+            ClassNode ref = Java5.configureTypeVariableReference(currentTypeParameter);
+            ClassNode[] boundNodes = parameterBounds.toArray(new ClassNode[parameterBounds.size()]);
+            typeParameters.add(Java5.configureTypeVariableDefinition(ref, boundNodes));
+
+            currentTypeParameter = null;
+            parameterBounds.clear();
+        }
+    }
+
+    @Override
+    public SignatureVisitor visitClassBound() {
+        return new TypeSignatureParser(resolver) {
+            @Override
+            void finished(ClassNode result) {
+                parameterBounds.add(result);
+            }
+        };
+    }
+
+    @Override
+    public SignatureVisitor visitInterfaceBound() {
+        return visitClassBound();
+    }
+
+    public GenericsType[] getTypeParameters() {
+        flushTypeParameter();
+        return typeParameters.toArray(new GenericsType[typeParameters.size()]);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/ast/decompiled/MemberSignatureParser.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/decompiled/MemberSignatureParser.java b/src/main/java/org/codehaus/groovy/ast/decompiled/MemberSignatureParser.java
new file mode 100644
index 0000000..6627c85
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/ast/decompiled/MemberSignatureParser.java
@@ -0,0 +1,155 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 org.codehaus.groovy.ast.decompiled;
+
+import org.codehaus.groovy.ast.AnnotationNode;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.ConstructorNode;
+import org.codehaus.groovy.ast.FieldNode;
+import org.codehaus.groovy.ast.GenericsType;
+import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.ast.Parameter;
+import org.codehaus.groovy.ast.expr.ConstantExpression;
+import org.codehaus.groovy.ast.stmt.ReturnStatement;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.signature.SignatureReader;
+import org.objectweb.asm.signature.SignatureVisitor;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Peter Gromov
+ */
+class MemberSignatureParser {
+    static MethodNode createMethodNode(final AsmReferenceResolver resolver, MethodStub method) {
+        GenericsType[] typeParameters = null;
+
+        Type[] argumentTypes = Type.getArgumentTypes(method.desc);
+        final ClassNode[] parameterTypes = new ClassNode[argumentTypes.length];
+        for (int i = 0; i < argumentTypes.length; i++) {
+            parameterTypes[i] = resolver.resolveType(argumentTypes[i]);
+        }
+
+        final ClassNode[] exceptions = new ClassNode[method.exceptions.length];
+        for (int i = 0; i < method.exceptions.length; i++) {
+            exceptions[i] = resolver.resolveClass(AsmDecompiler.fromInternalName(method.exceptions[i]));
+        }
+
+        final ClassNode[] returnType = {resolver.resolveType(Type.getReturnType(method.desc))};
+
+        if (method.signature != null) {
+            FormalParameterParser v = new FormalParameterParser(resolver) {
+                int paramIndex = 0;
+
+                @Override
+                public SignatureVisitor visitParameterType() {
+                    return new TypeSignatureParser(resolver) {
+                        @Override
+                        void finished(ClassNode result) {
+                            parameterTypes[paramIndex] = applyErasure(result, parameterTypes[paramIndex]);
+                            paramIndex++;
+                        }
+                    };
+                }
+
+                @Override
+                public SignatureVisitor visitReturnType() {
+                    return new TypeSignatureParser(resolver) {
+                        @Override
+                        void finished(ClassNode result) {
+                            returnType[0] = applyErasure(result, returnType[0]);
+                        }
+                    };
+                }
+
+                int exceptionIndex = 0;
+
+                @Override
+                public SignatureVisitor visitExceptionType() {
+                    return new TypeSignatureParser(resolver) {
+                        @Override
+                        void finished(ClassNode result) {
+                            exceptions[exceptionIndex] = applyErasure(result, exceptions[exceptionIndex]);
+                            exceptionIndex++;
+                        }
+                    };
+                }
+            };
+            new SignatureReader(method.signature).accept(v);
+            typeParameters = v.getTypeParameters();
+        }
+
+        Parameter[] parameters = new Parameter[parameterTypes.length];
+        for (int i = 0; i < parameterTypes.length; i++) {
+            parameters[i] = new Parameter(parameterTypes[i], "param" + i);
+        }
+
+        if (method.parameterAnnotations != null) {
+            for (Map.Entry<Integer, List<AnnotationStub>> entry : method.parameterAnnotations.entrySet()) {
+                for (AnnotationStub stub : entry.getValue()) {
+                    AnnotationNode annotationNode = Annotations.createAnnotationNode(stub, resolver);
+                    if (annotationNode != null) {
+                        parameters[entry.getKey()].addAnnotation(annotationNode);
+                    }
+                }
+            }
+        }
+
+        MethodNode result;
+        if ("<init>".equals(method.methodName)) {
+            result = new ConstructorNode(method.accessModifiers, parameters, exceptions, null);
+        } else {
+            result = new MethodNode(method.methodName, method.accessModifiers, returnType[0], parameters, exceptions, null);
+            if (method.annotationDefault != null) {
+                result.setCode(new ReturnStatement(new ConstantExpression(method.annotationDefault)));
+                result.setAnnotationDefault(true);
+            } else {
+                // Seems wrong but otherwise some tests fail (e.g. TestingASTTransformsTest)
+                result.setCode(new ReturnStatement(ConstantExpression.NULL));
+            }
+
+        }
+        if (typeParameters != null && typeParameters.length > 0) {
+            result.setGenericsTypes(typeParameters);
+        }
+        return result;
+    }
+
+    private static ClassNode applyErasure(ClassNode genericType, ClassNode erasure) {
+        if (genericType.isGenericsPlaceHolder()) {
+            genericType.setRedirect(erasure);
+        }
+        return genericType;
+    }
+
+    static FieldNode createFieldNode(FieldStub field, AsmReferenceResolver resolver, DecompiledClassNode owner) {
+        final ClassNode[] type = {resolver.resolveType(Type.getType(field.desc))};
+        if (field.signature != null) {
+            new SignatureReader(field.signature).accept(new TypeSignatureParser(resolver) {
+                @Override
+                void finished(ClassNode result) {
+                    type[0] = applyErasure(result, type[0]);
+                }
+            });
+        }
+        return new FieldNode(field.fieldName, field.accessModifiers, type[0], owner, null);
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/ast/decompiled/TypeSignatureParser.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/decompiled/TypeSignatureParser.java b/src/main/java/org/codehaus/groovy/ast/decompiled/TypeSignatureParser.java
new file mode 100644
index 0000000..7d971ed
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/ast/decompiled/TypeSignatureParser.java
@@ -0,0 +1,123 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 org.codehaus.groovy.ast.decompiled;
+
+import org.codehaus.groovy.ast.ClassHelper;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.GenericsType;
+import org.codehaus.groovy.vmplugin.v5.Java5;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.signature.SignatureVisitor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+* @author Peter Gromov
+*/
+abstract class TypeSignatureParser extends SignatureVisitor {
+    private final AsmReferenceResolver resolver;
+
+    public TypeSignatureParser(AsmReferenceResolver resolver) {
+        super(Opcodes.ASM5);
+        this.resolver = resolver;
+    }
+
+    abstract void finished(ClassNode result);
+
+    private String baseName;
+    private final List<GenericsType> arguments = new ArrayList<GenericsType>();
+
+    @Override
+    public void visitTypeVariable(String name) {
+        finished(Java5.configureTypeVariableReference(name));
+    }
+
+    @Override
+    public void visitBaseType(char descriptor) {
+        finished(resolver.resolveType(Type.getType(String.valueOf(descriptor))));
+    }
+
+    @Override
+    public SignatureVisitor visitArrayType() {
+        final TypeSignatureParser outer = this;
+        return new TypeSignatureParser(resolver) {
+            @Override
+            void finished(ClassNode result) {
+                outer.finished(result.makeArray());
+            }
+        };
+    }
+
+    @Override
+    public void visitClassType(String name) {
+        baseName = AsmDecompiler.fromInternalName(name);
+    }
+
+    @Override
+    public void visitTypeArgument() {
+        arguments.add(createWildcard(new ClassNode[]{ClassHelper.OBJECT_TYPE}, null));
+    }
+
+    @Override
+    public SignatureVisitor visitTypeArgument(final char wildcard) {
+        return new TypeSignatureParser(resolver) {
+            @Override
+            void finished(ClassNode result) {
+                if (wildcard == INSTANCEOF) {
+                    arguments.add(new GenericsType(result));
+                    return;
+                }
+
+                ClassNode[] upper = wildcard == EXTENDS ? new ClassNode[]{result} : null;
+                ClassNode lower = wildcard == SUPER ? result : null;
+                arguments.add(createWildcard(upper, lower));
+            }
+        };
+    }
+
+    private static GenericsType createWildcard(ClassNode[] upper, ClassNode lower) {
+        ClassNode base = ClassHelper.makeWithoutCaching("?");
+        base.setRedirect(ClassHelper.OBJECT_TYPE);
+        GenericsType t = new GenericsType(base, upper, lower);
+        t.setWildcard(true);
+        return t;
+    }
+
+    @Override
+    public void visitInnerClassType(String name) {
+        baseName += "$" + name;
+        arguments.clear();
+    }
+
+    @Override
+    public void visitEnd() {
+        ClassNode base = resolver.resolveClass(baseName);
+        if (arguments.isEmpty()) {
+            finished(base);
+            return;
+        }
+
+        ClassNode bound = base.getPlainNodeReference();
+        bound.setGenericsTypes(arguments.toArray(new GenericsType[arguments.size()]));
+        finished(bound);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/ast/expr/AnnotationConstantExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/expr/AnnotationConstantExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/AnnotationConstantExpression.java
new file mode 100644
index 0000000..bb4d78f
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/ast/expr/AnnotationConstantExpression.java
@@ -0,0 +1,50 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 org.codehaus.groovy.ast.expr;
+
+import org.codehaus.groovy.ast.AnnotationNode;
+import org.codehaus.groovy.ast.GroovyCodeVisitor;
+
+import java.util.Map;
+
+/**
+ * Represents an annotation "constant" that may appear in annotation attributes
+ * (mainly used as a marker).
+ *
+ * @author <a href='mailto:the[dot]mindstorm[at]gmail[dot]com'>Alex Popescu</a>
+ */
+public class AnnotationConstantExpression extends ConstantExpression {
+    public AnnotationConstantExpression(AnnotationNode node) {
+        super(node);
+        setType(node.getClassNode());
+    }
+
+    public void visit(GroovyCodeVisitor visitor) {
+        AnnotationNode node = (AnnotationNode) getValue();
+        Map<String, Expression> attrs = node.getMembers();
+        for (Expression expr : attrs.values()) {
+            expr.visit(visitor);
+        }
+        super.visit(visitor);
+    }
+
+    public String toString() {
+        return "AnnotationConstantExpression[" + getValue() + "]";
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/ast/expr/ArgumentListExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/expr/ArgumentListExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/ArgumentListExpression.java
new file mode 100644
index 0000000..de835b7
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/ast/expr/ArgumentListExpression.java
@@ -0,0 +1,78 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 org.codehaus.groovy.ast.expr;
+
+import org.codehaus.groovy.ast.GroovyCodeVisitor;
+import org.codehaus.groovy.ast.Parameter;
+
+import java.util.List;
+
+/**
+ * Represents one or more arguments being passed into a method
+ * 
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public class ArgumentListExpression extends TupleExpression {
+
+    public static final Object[] EMPTY_ARRAY = {
+    };
+    
+    public static final ArgumentListExpression EMPTY_ARGUMENTS = new ArgumentListExpression();
+
+    public ArgumentListExpression() {
+    }
+
+    public ArgumentListExpression(List<Expression> expressions) {
+        super(expressions);
+    }
+
+    public ArgumentListExpression(Expression[] expressions) {
+        super(expressions);
+    }
+
+    public ArgumentListExpression(Parameter[] parameters) {
+        for (int i = 0; i < parameters.length; i++) {
+            Parameter parameter = parameters[i];
+            addExpression(new VariableExpression(parameter));
+        }
+    }
+    
+    public ArgumentListExpression(Expression expr) {
+        super(expr);
+    }
+
+    public ArgumentListExpression(Expression expr1, Expression expr2) {
+        super(expr1, expr2);
+    }
+
+    public ArgumentListExpression(Expression expr1, Expression expr2, Expression expr3) {
+        super(expr1, expr2, expr3);
+    }
+
+    public Expression transformExpression(ExpressionTransformer transformer) {
+        Expression ret = new ArgumentListExpression(transformExpressions(getExpressions(), transformer));
+        ret.setSourcePosition(this);
+        ret.copyNodeMetaData(this);
+        return ret;
+    }
+    
+    public void visit(GroovyCodeVisitor visitor) {
+        visitor.visitArgumentlistExpression(this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/ast/expr/ArrayExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/expr/ArrayExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/ArrayExpression.java
new file mode 100644
index 0000000..a70102d
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/ast/expr/ArrayExpression.java
@@ -0,0 +1,136 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 org.codehaus.groovy.ast.expr;
+
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.GroovyCodeVisitor;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Represents an array object construction either using a fixed size
+ * or an initializer expression
+ *
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public class ArrayExpression extends Expression {
+    private final List<Expression> expressions;
+    private final List<Expression> sizeExpression;
+
+    private final ClassNode elementType;
+
+    private static ClassNode makeArray(ClassNode base, List<Expression> sizeExpression) {
+        ClassNode ret = base.makeArray();
+        if (sizeExpression == null) return ret;
+        int size = sizeExpression.size();
+        for (int i = 1; i < size; i++) {
+            ret = ret.makeArray();
+        }
+        return ret;
+    }
+
+    public ArrayExpression(ClassNode elementType, List<Expression> expressions, List<Expression> sizeExpression) {
+        //expect to get the elementType
+        super.setType(makeArray(elementType, sizeExpression));
+        if (expressions == null) expressions = Collections.emptyList();
+        this.elementType = elementType;
+        this.expressions = expressions;
+        this.sizeExpression = sizeExpression;
+
+        for (Object item : expressions) {
+            if (item != null && !(item instanceof Expression)) {
+                throw new ClassCastException("Item: " + item + " is not an Expression");
+            }
+        }
+        if (sizeExpression != null) {
+            for (Object item : sizeExpression) {
+                if (!(item instanceof Expression)) {
+                    throw new ClassCastException("Item: " + item + " is not an Expression");
+                }
+            }
+        }
+    }
+
+
+    /**
+     * Creates an array using an initializer expression
+     */
+    public ArrayExpression(ClassNode elementType, List<Expression> expressions) {
+        this(elementType, expressions, null);
+    }
+
+    public void addExpression(Expression expression) {
+        expressions.add(expression);
+    }
+
+    public List<Expression> getExpressions() {
+        return expressions;
+    }
+
+    public void visit(GroovyCodeVisitor visitor) {
+        visitor.visitArrayExpression(this);
+    }
+
+    public boolean isDynamic() {
+        return false;
+    }
+
+    public Expression transformExpression(ExpressionTransformer transformer) {
+        List<Expression> exprList = transformExpressions(expressions, transformer);
+        List<Expression> sizes = null;
+        if (sizeExpression != null) sizes = transformExpressions(sizeExpression, transformer);
+        Expression ret = new ArrayExpression(elementType, exprList, sizes);
+        ret.setSourcePosition(this);
+        ret.copyNodeMetaData(this);
+        return ret;
+    }
+
+    public Expression getExpression(int i) {
+        return expressions.get(i);
+    }
+
+    public ClassNode getElementType() {
+        return elementType;
+    }
+
+    public String getText() {
+        StringBuilder buffer = new StringBuilder("[");
+        boolean first = true;
+        for (Expression expression : expressions) {
+            if (first) {
+                first = false;
+            } else {
+                buffer.append(", ");
+            }
+
+            buffer.append(expression.getText());
+        }
+        buffer.append("]");
+        return buffer.toString();
+    }
+
+    public List<Expression> getSizeExpression() {
+        return sizeExpression;
+    }
+
+    public String toString() {
+        return super.toString() + expressions;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/ast/expr/AttributeExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/expr/AttributeExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/AttributeExpression.java
new file mode 100644
index 0000000..a52929c
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/ast/expr/AttributeExpression.java
@@ -0,0 +1,50 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 org.codehaus.groovy.ast.expr;
+
+import org.codehaus.groovy.ast.GroovyCodeVisitor;
+
+
+/**
+ * Represents an attribute access (accessing the field of a class) such as the expression "foo.@bar".
+ * 
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public class AttributeExpression extends PropertyExpression {
+
+    public AttributeExpression(Expression objectExpression, Expression property) {
+        super(objectExpression, property, false);
+    }
+
+    public AttributeExpression(Expression objectExpression, Expression property, boolean safe) {
+        super(objectExpression, property, safe);
+    }
+
+    public void visit(GroovyCodeVisitor visitor) {
+        visitor.visitAttributeExpression(this);
+    }
+
+    public Expression transformExpression(ExpressionTransformer transformer) {
+        AttributeExpression ret = new AttributeExpression(transformer.transform(getObjectExpression()),transformer.transform(getProperty()),isSafe());
+        ret.setSourcePosition(this);
+        ret.setSpreadSafe(isSpreadSafe());
+        ret.copyNodeMetaData(this);
+        return ret;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/ast/expr/BinaryExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/expr/BinaryExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/BinaryExpression.java
new file mode 100644
index 0000000..e970947
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/ast/expr/BinaryExpression.java
@@ -0,0 +1,135 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 org.codehaus.groovy.ast.expr;
+
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.GroovyCodeVisitor;
+import org.codehaus.groovy.ast.Variable;
+import org.codehaus.groovy.syntax.Token;
+import org.codehaus.groovy.syntax.Types;
+
+/**
+ * Represents two expressions and an operation
+ *
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public class BinaryExpression extends Expression {
+
+    private Expression leftExpression;
+    private Expression rightExpression;
+    private final Token operation;
+    private boolean safe = false;
+
+    public BinaryExpression(Expression leftExpression,
+                            Token operation,
+                            Expression rightExpression) {
+        this.leftExpression = leftExpression;
+        this.operation = operation;
+        this.rightExpression = rightExpression;
+    }
+
+    public BinaryExpression(Expression leftExpression,
+                            Token operation,
+                            Expression rightExpression,
+                            boolean safe) {
+        this(leftExpression, operation, rightExpression);
+        this.safe = safe;
+    }
+
+    public String toString() {
+        return super.toString() + "[" + leftExpression + operation + rightExpression + "]";
+    }
+
+    public void visit(GroovyCodeVisitor visitor) {
+        visitor.visitBinaryExpression(this);
+    }
+
+    public Expression transformExpression(ExpressionTransformer transformer) {
+        Expression ret = new BinaryExpression(transformer.transform(leftExpression), operation, transformer.transform(rightExpression), safe);
+        ret.setSourcePosition(this);
+        ret.copyNodeMetaData(this);
+        return ret;
+    }
+
+    public Expression getLeftExpression() {
+        return leftExpression;
+    }
+
+    public void setLeftExpression(Expression leftExpression) {
+        this.leftExpression = leftExpression;
+    }
+
+    public void setRightExpression(Expression rightExpression) {
+        this.rightExpression = rightExpression;
+    }
+
+    public Token getOperation() {
+        return operation;
+    }
+
+    public Expression getRightExpression() {
+        return rightExpression;
+    }
+
+    public String getText() {
+        if (operation.getType() == Types.LEFT_SQUARE_BRACKET) {
+            return leftExpression.getText() + (safe ? "?" : "") + "[" + rightExpression.getText() + "]";
+        }
+        return "(" + leftExpression.getText() + " " + operation.getText() + " " + rightExpression.getText() + ")";
+    }
+
+    public boolean isSafe() {
+        return safe;
+    }
+
+    public void setSafe(boolean safe) {
+        this.safe = safe;
+    }
+
+    /**
+     * Creates an assignment expression in which the specified expression
+     * is written into the specified variable name.
+     */
+
+    public static BinaryExpression newAssignmentExpression(Variable variable, Expression rhs) {
+        VariableExpression lhs = new VariableExpression(variable);
+        Token operator = Token.newPlaceholder(Types.ASSIGN);
+
+        return new BinaryExpression(lhs, operator, rhs);
+    }
+
+
+    /**
+     * Creates variable initialization expression in which the specified expression
+     * is written into the specified variable name.
+     */
+
+    public static BinaryExpression newInitializationExpression(String variable, ClassNode type, Expression rhs) {
+        VariableExpression lhs = new VariableExpression(variable);
+
+        if (type != null) {
+            lhs.setType(type);
+        }
+
+        Token operator = Token.newPlaceholder(Types.ASSIGN);
+
+        return new BinaryExpression(lhs, operator, rhs);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/ast/expr/BitwiseNegationExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/expr/BitwiseNegationExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/BitwiseNegationExpression.java
new file mode 100644
index 0000000..dece59d
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/ast/expr/BitwiseNegationExpression.java
@@ -0,0 +1,58 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 org.codehaus.groovy.ast.expr;
+
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.GroovyCodeVisitor;
+
+/**
+ * @author phk
+ */
+public class BitwiseNegationExpression extends Expression {
+
+    private final Expression expression;
+
+    public BitwiseNegationExpression(Expression expression) {
+        this.expression = expression;
+    }
+
+    public Expression getExpression() {
+        return expression;
+    }
+
+    public void visit(GroovyCodeVisitor visitor) {
+        visitor.visitBitwiseNegationExpression(this);
+    }
+
+    public Expression transformExpression(ExpressionTransformer transformer) {
+        Expression ret = new BitwiseNegationExpression(transformer.transform(expression));
+        ret.setSourcePosition(this);
+        ret.copyNodeMetaData(this);
+        return ret;
+    }
+
+    public String getText() {
+        return expression.getText();
+    }
+
+    public ClassNode getType() {
+        return expression.getType();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/ast/expr/BooleanExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/expr/BooleanExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/BooleanExpression.java
new file mode 100644
index 0000000..5cab929
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/ast/expr/BooleanExpression.java
@@ -0,0 +1,56 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 org.codehaus.groovy.ast.expr;
+
+import org.codehaus.groovy.ast.ClassHelper;
+import org.codehaus.groovy.ast.GroovyCodeVisitor;
+
+/**
+ * Represents a boolean expression
+ * 
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public class BooleanExpression extends Expression {
+    private final Expression expression;
+
+    public BooleanExpression(Expression expression) {
+        this.expression = expression;
+        setType(ClassHelper.boolean_TYPE); // for consistency with AsmClassGenerator. see AsmClassGenerator.visitBooleanExpression.
+    }
+    
+    public Expression getExpression() {
+        return expression;
+    }
+
+    public void visit(GroovyCodeVisitor visitor) {
+        visitor.visitBooleanExpression(this);
+    }
+
+    public Expression transformExpression(ExpressionTransformer transformer) {
+        Expression ret = new BooleanExpression(transformer.transform(expression));
+        ret.setSourcePosition(this);
+        ret.copyNodeMetaData(this);
+        return ret;
+    }
+    
+    public String getText() {
+        return expression.getText();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/ast/expr/CastExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/expr/CastExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/CastExpression.java
new file mode 100644
index 0000000..f6145bb
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/ast/expr/CastExpression.java
@@ -0,0 +1,111 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 org.codehaus.groovy.ast.expr;
+
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.GroovyCodeVisitor;
+
+/**
+ * Represents a type cast expression
+ * 
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public class CastExpression extends Expression {
+    
+    private final Expression expression;
+    private boolean ignoreAutoboxing=false;
+    private boolean coerce = false;
+    private boolean strict = false;
+
+    public static CastExpression asExpression(ClassNode type, Expression expression) {
+        CastExpression answer = new CastExpression(type, expression);
+        answer.setCoerce(true);
+        return answer;
+    }
+
+    public CastExpression(ClassNode type, Expression expression) {
+        this(type,expression,false);
+    }
+
+    public CastExpression(ClassNode type, Expression expression, boolean ignoreAutoboxing) {
+        super.setType(type);
+        this.expression = expression;
+        this.ignoreAutoboxing = ignoreAutoboxing;
+    }
+    
+    public boolean isIgnoringAutoboxing(){
+        return ignoreAutoboxing;
+    }
+
+    public boolean isCoerce() {
+        return coerce;
+    }
+
+    public void setCoerce(boolean coerce) {
+        this.coerce = coerce;
+    }
+
+    /**
+     * If strict mode is true, then when the compiler generates a cast, it will disable
+     * Groovy casts and rely on a strict cast (CHECKCAST)
+     * @return true if strict mode is enable
+     */
+    public boolean isStrict() {
+        return strict;
+    }
+
+    /**
+     * If strict mode is true, then when the compiler generates a cast, it will disable
+     * Groovy casts and rely on a strict cast (CHECKCAST)
+     * @param strict strict mode
+     */
+    public void setStrict(final boolean strict) {
+        this.strict = strict;
+    }
+
+    public String toString() {
+        return super.toString() +"[(" + getType().getName() + ") " + expression + "]";
+    }
+
+    public void visit(GroovyCodeVisitor visitor) {
+        visitor.visitCastExpression(this);
+    }
+
+    public Expression transformExpression(ExpressionTransformer transformer) {
+        CastExpression ret =  new CastExpression(getType(), transformer.transform(expression));
+        ret.setSourcePosition(this);
+        ret.setCoerce(this.isCoerce());
+        ret.setStrict(this.isStrict());
+        ret.copyNodeMetaData(this);
+        return ret;
+    }
+    
+    public String getText() {
+        return "(" + getType() + ") " + expression.getText();
+    }
+ 
+    public Expression getExpression() {
+        return expression;
+    }
+    
+    public void setType(ClassNode t) {
+        super.setType(t);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/ast/expr/ClassExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/expr/ClassExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/ClassExpression.java
new file mode 100644
index 0000000..9b29e5c
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/ast/expr/ClassExpression.java
@@ -0,0 +1,51 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 org.codehaus.groovy.ast.expr;
+
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.GroovyCodeVisitor;
+
+/**
+ * Represents access to a Java/Groovy class in an expression, such
+ * as when invoking a static method or accessing a static type
+ * 
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public class ClassExpression extends Expression {
+
+    public ClassExpression(ClassNode type) {
+        super.setType(type);
+    }
+
+    public void visit(GroovyCodeVisitor visitor) {
+        visitor.visitClassExpression(this);
+    }
+    
+    public Expression transformExpression(ExpressionTransformer transformer) {
+        return this;
+    }
+    
+    public String getText() {
+        return getType().getName();
+    }
+
+    public String toString() {
+       return super.toString() + "[type: " + getType().getName() + "]";
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/ast/expr/ClosureExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/expr/ClosureExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/ClosureExpression.java
new file mode 100644
index 0000000..802a6ee
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/ast/expr/ClosureExpression.java
@@ -0,0 +1,105 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 org.codehaus.groovy.ast.expr;
+
+import org.codehaus.groovy.ast.AstToTextHelper;
+import org.codehaus.groovy.ast.ClassHelper;
+import org.codehaus.groovy.ast.GroovyCodeVisitor;
+import org.codehaus.groovy.ast.Parameter;
+import org.codehaus.groovy.ast.VariableScope;
+import org.codehaus.groovy.ast.stmt.Statement;
+import org.codehaus.groovy.runtime.InvokerHelper;
+
+/**
+ * Represents a closure expression such as { statement }
+ * or { i -> statement } or { i, x, String y ->  statement }
+ * 
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ * @author Hamlet D'Arcy
+ */
+public class ClosureExpression extends Expression {
+    
+    private final Parameter[] parameters;
+    private Statement code;
+    private VariableScope variableScope;
+    
+    public ClosureExpression(Parameter[] parameters, Statement code) {
+        this.parameters = parameters;
+        this.code = code;
+        super.setType(ClassHelper.CLOSURE_TYPE.getPlainNodeReference());
+    }
+    
+    public void visit(GroovyCodeVisitor visitor) {
+        visitor.visitClosureExpression(this);
+    }
+
+    public Expression transformExpression(ExpressionTransformer transformer) {
+        return this;
+    }
+    
+    public String toString() {
+        return super.toString() + InvokerHelper.toString(parameters) + "{ " + code + " }";
+    }
+
+    /**
+     * This gets the code statement of the closure. You can read this method to find out what actions
+     * the closure is going to perform.
+     *
+     * @return the code statement of the closure
+     */
+    public Statement getCode() {
+        return code;
+    }
+
+    /**
+     * This sets the code statement of the closure. You can use this method in order to add more actions
+     * during the closure execution.
+     *
+     * @param code the new Statement
+     */
+    public void setCode(Statement code) {
+        this.code = code;
+    }
+
+    public Parameter[] getParameters() {
+        return parameters;
+    }
+
+    public boolean isParameterSpecified() {
+        return parameters != null && parameters.length > 0;
+    }
+    
+    public VariableScope getVariableScope() {
+        return variableScope;
+    }
+
+    public void setVariableScope(VariableScope variableScope) {
+        this.variableScope = variableScope;
+    }
+
+    @Override
+    public String getText() {
+        String paramText = AstToTextHelper.getParametersText(parameters);
+        if (paramText.length() > 0) {
+            return "{ " + paramText + " -> ... }";
+        } else {
+            return "{ -> ... }";
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/ast/expr/ClosureListExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/expr/ClosureListExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/ClosureListExpression.java
new file mode 100644
index 0000000..ecbd333
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/ast/expr/ClosureListExpression.java
@@ -0,0 +1,88 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 org.codehaus.groovy.ast.expr;
+
+import org.codehaus.groovy.ast.GroovyCodeVisitor;
+import org.codehaus.groovy.ast.VariableScope;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class represents a list of expressions used to
+ * create closures. Example:
+ * <code>
+ * def foo = (1;2;;)
+ * </code>
+ * The right side is a ClosureListExpression consisting of
+ * two ConstantExpressions for the values 1 and 2, and two
+ * EmptyStatement entries. The ClosureListExpression defines a new 
+ * variable scope. All created Closures share this scope.
+ * 
+ * 
+ * @author Jochen Theodorou
+ */
+public class ClosureListExpression extends ListExpression {
+
+    private VariableScope scope;
+    
+    public ClosureListExpression(List<Expression> expressions) {
+        super(expressions);
+        scope = new VariableScope();
+    }
+    
+    public ClosureListExpression() {
+        this(new ArrayList<Expression>(3));
+    }
+    
+    public void visit(GroovyCodeVisitor visitor) {
+        visitor.visitClosureListExpression(this);
+    }
+    
+    public Expression transformExpression(ExpressionTransformer transformer) {
+        Expression ret = new ClosureListExpression(transformExpressions(getExpressions(), transformer));
+        ret.setSourcePosition(this);
+        ret.copyNodeMetaData(this);
+        return ret;       
+    }
+    
+    public void setVariableScope(VariableScope scope) {
+        this.scope = scope;
+    }
+    
+    public VariableScope getVariableScope() {
+        return scope;
+    }
+    
+    public String getText() {
+        StringBuilder buffer = new StringBuilder("(");
+        boolean first = true;
+        for (Expression expression : getExpressions()) {
+            if (first) {
+                first = false;
+            } else {
+                buffer.append("; ");
+            }
+            
+            buffer.append(expression.getText());
+        }
+        buffer.append(")");
+        return buffer.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/ast/expr/ConstantExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/expr/ConstantExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/ConstantExpression.java
new file mode 100644
index 0000000..dfa2c52
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/ast/expr/ConstantExpression.java
@@ -0,0 +1,124 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 org.codehaus.groovy.ast.expr;
+
+import org.codehaus.groovy.ast.ClassHelper;
+import org.codehaus.groovy.ast.GroovyCodeVisitor;
+
+/**
+ * Represents a constant expression such as null, true, false
+ * 
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ */
+public class ConstantExpression extends Expression {
+    // The following fields are only used internally; every occurrence of a user-defined expression of the same kind
+    // has its own instance so as to preserve line information. Consequently, to test for such an expression, don't
+    // compare against the field but call isXXXExpression() instead.
+    public static final ConstantExpression NULL = new ConstantExpression(null);
+    public static final ConstantExpression TRUE = new ConstantExpression(Boolean.TRUE);
+    public static final ConstantExpression FALSE = new ConstantExpression(Boolean.FALSE);
+    public static final ConstantExpression EMPTY_STRING = new ConstantExpression("");
+    public static final ConstantExpression PRIM_TRUE = new ConstantExpression(Boolean.TRUE, true);
+    public static final ConstantExpression PRIM_FALSE = new ConstantExpression(Boolean.FALSE, true);
+    //public static final Expression EMPTY_ARRAY = new PropertyExpression(new ClassExpression(ArgumentListExpression.class.getName()), "EMPTY_ARRAY");
+
+    // the following fields are only used internally; there are no user-defined expressions of the same kind
+    public static final ConstantExpression VOID = new ConstantExpression(Void.class);
+    public static final ConstantExpression EMPTY_EXPRESSION = new ConstantExpression(null);
+    
+    private final Object value;
+    private String constantName;
+
+    public ConstantExpression(Object value) {
+        this(value,false);
+    }
+
+    public ConstantExpression(Object value, boolean keepPrimitive) {
+        this.value = value;
+        if (value != null) {
+            if (keepPrimitive) {
+                if (value instanceof Integer) {
+                    setType(ClassHelper.int_TYPE);
+                } else if (value instanceof Long) {
+                    setType(ClassHelper.long_TYPE);
+                } else if (value instanceof Boolean) {
+                    setType(ClassHelper.boolean_TYPE);
+                } else if (value instanceof Double) {
+                    setType(ClassHelper.double_TYPE);
+                } else if (value instanceof Float) {
+                    setType(ClassHelper.float_TYPE);
+                } else if (value instanceof Character) {
+                    setType(ClassHelper.char_TYPE);
+                } else {
+                    setType(ClassHelper.make(value.getClass()));
+                }
+                //TODO: more cases here
+            } else {
+                setType(ClassHelper.make(value.getClass()));
+            }
+        }
+    }
+
+    public String toString() {
+        return "ConstantExpression[" + value + "]";
+    }
+
+    public void visit(GroovyCodeVisitor visitor) {
+        visitor.visitConstantExpression(this);
+    }
+
+    public Expression transformExpression(ExpressionTransformer transformer) {
+        return this;
+    }
+
+    /**
+     * @return the value of this constant expression
+     */    
+    public Object getValue() {
+        return value;
+    }
+
+    public String getText() {
+        return (value == null) ? "null" : value.toString();
+    }
+
+    public String getConstantName() {
+        return constantName;
+    }
+
+    public void setConstantName(String constantName) {
+        this.constantName = constantName;
+    }
+
+    public boolean isNullExpression() {
+        return value == null;
+    }
+
+    public boolean isTrueExpression() {
+        return Boolean.TRUE.equals(value);
+    }
+
+    public boolean isFalseExpression() {
+        return Boolean.FALSE.equals(value);
+    }
+
+    public boolean isEmptyStringExpression() {
+        return "".equals(value);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/ast/expr/ConstructorCallExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/expr/ConstructorCallExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/ConstructorCallExpression.java
new file mode 100644
index 0000000..0c040fa
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/ast/expr/ConstructorCallExpression.java
@@ -0,0 +1,105 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 org.codehaus.groovy.ast.expr;
+
+import org.codehaus.groovy.ast.ASTNode;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.GroovyCodeVisitor;
+
+/**
+ * A constructor call
+ *
+ * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
+ * @author Jochen Theodorou
+ */
+public class ConstructorCallExpression extends Expression implements MethodCall {
+
+    private final Expression arguments;
+    private boolean usesAnonymousInnerClass;
+
+    public ConstructorCallExpression(ClassNode type, Expression arguments) {
+        super.setType(type);
+        if (!(arguments instanceof TupleExpression)) {
+            this.arguments = new TupleExpression(arguments);
+        } else {
+            this.arguments = arguments;
+        }
+    }
+
+    public void visit(GroovyCodeVisitor visitor) {
+        visitor.visitConstructorCallExpression(this);
+    }
+
+    public Expression transformExpression(ExpressionTransformer transformer) {
+        Expression args = transformer.transform(arguments);
+        ConstructorCallExpression ret = new ConstructorCallExpression(getType(), args);
+        ret.setSourcePosition(this);
+        ret.setUsingAnonymousInnerClass(isUsingAnonymousInnerClass());
+        ret.copyNodeMetaData(this);
+        return ret;
+    }
+
+    public ASTNode getReceiver() {
+        return null;
+    }
+
+    public String getMethodAsString() {
+        return "<init>";
+    }
+
+    public Expression getArguments() {
+        return arguments;
+    }
+
+    public String getText() {
+        String text = null;
+        if (isSuperCall()) {
+            text = "super ";
+        } else if (isThisCall()) {
+            text = "this ";
+        } else {
+            text = "new " + getType().getName();
+        }
+        return text + arguments.getText();
+    }
+
+    public String toString() {
+        return super.toString() + "[type: " + getType() + " arguments: " + arguments + "]";
+    }
+
+    public boolean isSuperCall() {
+        return getType() == ClassNode.SUPER;
+    }
+
+    public boolean isSpecialCall() {
+        return isThisCall() || isSuperCall();
+    }
+
+    public boolean isThisCall() {
+        return getType() == ClassNode.THIS;
+    }
+
+    public void setUsingAnonymousInnerClass(boolean usage) {
+        this.usesAnonymousInnerClass = usage;
+    }
+
+    public boolean isUsingAnonymousInnerClass() {
+        return usesAnonymousInnerClass;
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/ast/expr/DeclarationExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/expr/DeclarationExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/DeclarationExpression.java
new file mode 100644
index 0000000..6c082a7
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/ast/expr/DeclarationExpression.java
@@ -0,0 +1,168 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 org.codehaus.groovy.ast.expr;
+
+import org.codehaus.groovy.GroovyBugError;
+import org.codehaus.groovy.ast.GroovyCodeVisitor;
+import org.codehaus.groovy.syntax.Token;
+
+/**
+ * Represents one or more local variables. Typically it is a single local variable
+ * declared by name with an expression like "def foo" or with type "String foo". However, 
+ * the multiple assignment feature allows you to create two or more variables using
+ * an expression like: <code>def (x, y) = [1, 2]</code>.
+ * <p>
+ * You can access the left hand side of a declaration using the
+ * "<code>Expression getLeftExpression()</code>" method. In which case you might then
+ * use <code>instanceof</code> and casting to perform operations specific to a
+ * single local variable (<code>VariableExpression</code>) or for the multiple
+ * assignment case (<code>TupleExpression</code>).
+ * <p>
+ * Alternatively, if <code>isMultipleAssignmentDeclaration()</code> is <code>false</code>
+ * you can use the method "<code>VariableExpression getVariableExpression()</code>" method.
+ * Similarly, if <code>isMultipleAssignmentDeclaration()</code> is <code>true</code>
+ * you can use the method "<code>TupleExpression getTupleExpression()</code>" method.
+ * Calling either of these expression getters when the "isMultipleAssignment" condition
+ * is not appropriate is unsafe and will result in a <code>ClassCastException</code>.
+ *
+ * @author Jochen Theodorou
+ * @author Hamlet D'Arcy
+ */
+public class DeclarationExpression extends BinaryExpression {
+    
+    /**
+     * Creates a DeclarationExpression for VariableExpressions like "def x" or "String y = 'foo'". 
+     * @param left
+     *      the left hand side of a variable declaration
+     * @param operation
+     *      the operation, typically an assignment operator
+     * @param right
+     *      the right hand side of a declaration
+     */ 
+    public DeclarationExpression(VariableExpression left, Token operation, Expression right) {
+        super(left,operation,right);
+    }
+    
+    /**
+     * Creates a DeclarationExpression for Expressions like "def (x, y) = [1, 2]"
+     * @param left
+     *      the left hand side of a declaration. Must be either a VariableExpression or 
+     *      a TupleExpression with at least one element.  
+     * @param operation
+     *       the operation, typically an assignment operator
+     * @param right
+     *       the right hand side of a declaration
+     */ 
+    public DeclarationExpression(Expression left, Token operation, Expression right) {
+        super(left,operation,right);
+        check(left);
+    }
+    
+    private static void check(Expression left) {
+        if (left instanceof VariableExpression) {
+            //nothing
+        } else if (left instanceof TupleExpression) {
+            TupleExpression tuple = (TupleExpression) left;
+            if (tuple.getExpressions().isEmpty()) throw new GroovyBugError("one element required for left side");
+        } else {
+            throw new GroovyBugError("illegal left expression for declaration: "+left);
+        }
+    }
+
+    public void visit(GroovyCodeVisitor visitor) {
+        visitor.visitDeclarationExpression(this);
+    }
+
+    /**
+     * This method returns the left hand side of the declaration cast to the VariableExpression type.
+     * This is an unsafe method to call. In a multiple assignment statement, the left hand side will
+     * be a TupleExpression and a ClassCastException will occur. If you invoke this method then
+     * be sure to invoke isMultipleAssignmentDeclaration() first to check that it is safe to do so. 
+     * If that method returns true then this method is safe to call.
+     *
+     * @return left hand side of normal variable declarations
+     * @throws ClassCastException if the left hand side is not a VariableExpression (and is probably a multiple assignment statement).
+     */
+    public VariableExpression getVariableExpression() {
+        Expression leftExpression = this.getLeftExpression();
+
+        return leftExpression instanceof VariableExpression
+                    ? (VariableExpression) leftExpression
+                    : null;
+    }
+    
+    /**
+     * This method returns the left hand side of the declaration cast to the TupleExpression type.
+     * This is an unsafe method to call. In a single assignment statement, the left hand side will
+     * be a VariableExpression and a ClassCastException will occur. If you invoke this method then
+     * be sure to invoke isMultipleAssignmentDeclaration() first to check that it is safe to do so. 
+     * If that method returns true then this method is safe to call. 
+     * @return
+     *      left hand side of multiple assignment declarations
+     * @throws ClassCastException 
+     *      if the left hand side is not a TupleExpression (and is probably a VariableExpression).
+     *
+     */
+    public TupleExpression getTupleExpression() {
+        Expression leftExpression = this.getLeftExpression();
+
+        return leftExpression instanceof TupleExpression
+                    ? (TupleExpression) leftExpression
+                    : null;
+    }
+    
+    /**
+     * This method sets the leftExpression for this BinaryExpression. The parameter must be
+     * either a VariableExpression or a TupleExpression with one or more elements. 
+     * @param leftExpression
+     *      either a VariableExpression or a TupleExpression with one or more elements. 
+     */ 
+    public void setLeftExpression(Expression leftExpression) {
+        check(leftExpression);
+        super.setLeftExpression(leftExpression);
+    }
+    
+    public void setRightExpression(Expression rightExpression) {
+        super.setRightExpression(rightExpression);
+    }
+    
+    public Expression transformExpression(ExpressionTransformer transformer) {
+        Expression ret = new DeclarationExpression(transformer.transform(getLeftExpression()),
+                getOperation(), transformer.transform(getRightExpression()));
+        ret.setSourcePosition(this);
+        ret.addAnnotations(getAnnotations());
+        ret.setDeclaringClass(getDeclaringClass());
+        ret.copyNodeMetaData(this);
+        return ret;
+    }
+    
+    /**
+     * This method tells you if this declaration is a multiple assignment declaration, which 
+     * has the form "def (x, y) = ..." in Groovy. If this method returns true, then the left
+     * hand side is an ArgumentListExpression. Do not call "getVariableExpression()" on this 
+     * object if this method returns true, instead use "getLeftExpression()". 
+     * @return
+     *      true if this declaration is a multiple assignment declaration, which means the
+     *      left hand side is an ArgumentListExpression. 
+     */ 
+    public boolean isMultipleAssignmentDeclaration() {
+        return getLeftExpression() instanceof TupleExpression;
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/ast/expr/ElvisOperatorExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/expr/ElvisOperatorExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/ElvisOperatorExpression.java
new file mode 100644
index 0000000..64df749
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/ast/expr/ElvisOperatorExpression.java
@@ -0,0 +1,71 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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 org.codehaus.groovy.ast.expr;
+
+import org.codehaus.groovy.ast.GroovyCodeVisitor;
+
+/**
+ * Represents a short ternary expression x ?: y, which is equal 
+ * to 
+ * <pre>
+ * def truePart = x
+ * def booleanPart = truePart as boolean
+ * booleanPart? truePart : y
+ * </pre>
+ * Even if x is no atomic expression, x will be evaluated only 
+ * once. Example:
+ * <pre class="groovyTestCase">
+ * class Foo { 
+ *   def index=0 
+ *   def getX(){ index++; return index }
+ * }
+ * def foo = new Foo()
+ * def result = foo.x ?: "false case" 
+ * assert foo.index == 1
+ * assert result == 1 
+ * </pre>
+ * 
+ * @author <a href="mailto:blackdrag@gmx.org">Jochen Theodorou</a>
+ * @since 1.5
+ */
+public class ElvisOperatorExpression extends TernaryExpression {
+
+    public ElvisOperatorExpression(Expression base, Expression falseExpression) {
+        super(getBool(base), base, falseExpression);
+    }
+    
+    private static BooleanExpression getBool(Expression base) {
+       BooleanExpression be = new BooleanExpression(base);
+       be.setSourcePosition(base);
+       return be;
+    }
+
+    public void visit(GroovyCodeVisitor visitor) {
+        visitor.visitShortTernaryExpression(this);
+    }
+    
+    public Expression transformExpression(ExpressionTransformer transformer) {
+        Expression ret = new ElvisOperatorExpression(
+                transformer.transform(getTrueExpression()),
+                transformer.transform(getFalseExpression()));
+        ret.setSourcePosition(this);
+        ret.copyNodeMetaData(this);
+        return ret; 
+    }
+}