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;
+ }
+}