You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2016/11/11 13:33:47 UTC
[20/20] groovy git commit: Implement the new parser
Implement the new parser
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/91c04014
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/91c04014
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/91c04014
Branch: refs/heads/parrot
Commit: 91c04014fb6cc6a2e09f93d81fd0bd95ea84d7dc
Parents: 7efbf9a
Author: Daniel Sun <su...@apache.org>
Authored: Fri Nov 11 21:24:16 2016 +0800
Committer: Daniel Sun <su...@apache.org>
Committed: Fri Nov 11 21:24:20 2016 +0800
----------------------------------------------------------------------
.travis.yml | 2 +-
src/main/groovy/lang/MetaClassImpl.java | 172 +-
.../groovy/ast/expr/BinaryExpression.java | 18 +-
.../groovy/ast/expr/DeclarationExpression.java | 12 +-
.../groovy/ast/expr/LambdaExpression.java | 47 +
.../ast/expr/MethodReferenceExpression.java | 45 +
.../groovy/ast/stmt/TryCatchStatement.java | 30 +-
.../classgen/asm/BinaryExpressionHelper.java | 30 +-
.../groovy/classgen/asm/CallSiteWriter.java | 23 +-
.../groovy/classgen/asm/InvocationWriter.java | 20 +-
.../groovy/classgen/asm/StatementWriter.java | 67 +-
.../classgen/asm/indy/IndyCallSiteWriter.java | 2 +-
.../classgen/asm/indy/InvokeDynamicWriter.java | 4 +-
.../asm/sc/StaticTypesCallSiteWriter.java | 2 +-
.../codehaus/groovy/runtime/ArrayTypeUtils.java | 98 +
.../codehaus/groovy/runtime/MethodClosure.java | 83 +-
src/spec/test/builder/CliBuilderTest.groovy | 2 +-
src/test/groovy/EqualsTest.groovy | 15 +-
src/test/groovy/EscapedUnicodeTest.groovy | 9 +
.../apache/groovy/parser/antlr4/GroovyLexer.g4 | 804 +
.../apache/groovy/parser/antlr4/GroovyParser.g4 | 1183 ++
.../groovy/parser/antlr4/Java.g4.v20160306.zip | Bin 0 -> 5805 bytes
.../parser/antlr4/util/GroovyTestRig.groovy | 74 +
.../apache/groovy/parser/AbstractParser.java | 83 +
.../org/apache/groovy/parser/Antlr2Parser.java | 34 +
.../org/apache/groovy/parser/Antlr4Parser.java | 39 +
.../parser/antlr4/Antlr4ParserPlugin.java | 45 +
.../parser/antlr4/Antlr4PluginFactory.java | 17 +
.../apache/groovy/parser/antlr4/AstBuilder.java | 4344 +++++
.../groovy/parser/antlr4/GroovyLangLexer.java | 45 +
.../groovy/parser/antlr4/GroovyLangParser.java | 38 +
.../parser/antlr4/SemanticPredicates.java | 94 +
.../TryWithResourcesASTTransformation.java | 339 +
.../parser/antlr4/internal/AtnManager.java | 107 +
.../internal/DescriptiveErrorStrategy.java | 102 +
.../groovy/parser/antlr4/util/StringUtils.java | 145 +
.../parser/antlr4/Geb10SourcesTest.groovy | 1684 ++
.../parser/antlr4/Gradle310SourcesTest.groovy | 15941 +++++++++++++++++
.../parser/antlr4/Grails320SourcesTest.groovy | 4648 +++++
.../parser/antlr4/Groovy250ScriptsTest.groovy | 11081 ++++++++++++
.../parser/antlr4/Groovy250SourcesTest.groovy | 7427 ++++++++
.../parser/antlr4/GroovyParserTest.groovy | 303 +
.../parser/antlr4/Spock11RC2SourcesTest.groovy | 1224 ++
.../groovy/parser/antlr4/SyntaxErrorTest.groovy | 132 +
.../groovy/parser/antlr4/TestUtils.groovy | 259 +
.../antlr4/util/ASTComparatorCategory.groovy | 526 +
.../groovy/parser/antlr4/util/AstDumper.groovy | 1025 ++
.../core/AnnotationDeclaration_01.groovy | 39 +
.../test/resources/core/Annotation_01.groovy | 1 +
.../test/resources/core/Annotation_02.groovy | 2 +
.../test/resources/core/Annotation_03.groovy | 3 +
.../test/resources/core/Annotation_04.groovy | 2 +
.../test/resources/core/Annotation_05.groovy | 1 +
.../test/resources/core/Annotation_06.groovy | 2 +
.../test/resources/core/Annotation_07.groovy | 2 +
.../test/resources/core/Annotation_08.groovy | 10 +
.../test/resources/core/Annotation_09.groovy | 14 +
.../test/resources/core/Annotation_10x.groovy | 20 +
.../src/test/resources/core/Assert_01.groovy | 28 +
.../src/test/resources/core/Assert_02x.groovy | 37 +
.../src/test/resources/core/Assert_03x.groovy | 26 +
.../resources/core/ClassDeclaration_01.groovy | 47 +
.../resources/core/ClassDeclaration_02.groovy | 42 +
.../resources/core/ClassDeclaration_03.groovy | 51 +
.../resources/core/ClassDeclaration_04.groovy | 22 +
.../resources/core/ClassDeclaration_05.groovy | 20 +
.../resources/core/ClassDeclaration_06.groovy | 83 +
.../resources/core/ClassDeclaration_07.groovy | 27 +
.../src/test/resources/core/Closure_01.groovy | 1 +
.../src/test/resources/core/Closure_02.groovy | 1 +
.../src/test/resources/core/Closure_03.groovy | 1 +
.../src/test/resources/core/Closure_04.groovy | 3 +
.../src/test/resources/core/Closure_05.groovy | 3 +
.../src/test/resources/core/Closure_06.groovy | 9 +
.../src/test/resources/core/Closure_07.groovy | 3 +
.../src/test/resources/core/Closure_08.groovy | 16 +
.../src/test/resources/core/Closure_09.groovy | 16 +
.../src/test/resources/core/Closure_10.groovy | 4 +
.../src/test/resources/core/Command_01.groovy | 14 +
.../src/test/resources/core/Command_02.groovy | 11 +
.../src/test/resources/core/Command_03.groovy | 66 +
.../src/test/resources/core/Command_04.groovy | 7 +
.../src/test/resources/core/Command_05.groovy | 59 +
.../src/test/resources/core/Command_06x.groovy | 8 +
.../src/test/resources/core/Comments_01.groovy | 28 +
.../src/test/resources/core/Comments_02.groovy | 107 +
.../src/test/resources/core/DoWhile_01x.groovy | 7 +
.../src/test/resources/core/DoWhile_02x.groovy | 8 +
.../src/test/resources/core/DoWhile_03x.groovy | 11 +
.../src/test/resources/core/DoWhile_04x.groovy | 14 +
.../resources/core/EnumDeclaration_01.groovy | 44 +
.../resources/core/EnumDeclaration_02.groovy | 52 +
.../resources/core/EnumDeclaration_03.groovy | 6 +
.../test/resources/core/Expression_01.groovy | 230 +
.../test/resources/core/Expression_02.groovy | 6 +
.../test/resources/core/Expression_03.groovy | 31 +
.../test/resources/core/Expression_04.groovy | 62 +
.../test/resources/core/Expression_05.groovy | 40 +
.../test/resources/core/Expression_06.groovy | 6 +
.../test/resources/core/Expression_07.groovy | 9 +
.../test/resources/core/Expression_08.groovy | 6 +
.../test/resources/core/Expression_09.groovy | 16 +
.../test/resources/core/Expression_10.groovy | 25 +
.../test/resources/core/Expression_11.groovy | 16 +
.../test/resources/core/Expression_12.groovy | 17 +
.../test/resources/core/Expression_13.groovy | 45 +
.../test/resources/core/Expression_14.groovy | 22 +
.../test/resources/core/Expression_15.groovy | 127 +
.../test/resources/core/Expression_16.groovy | 22 +
.../test/resources/core/Expression_17.groovy | 141 +
.../test/resources/core/Expression_18.groovy | 26 +
.../test/resources/core/Expression_19.groovy | 32 +
.../test/resources/core/Expression_20.groovy | 2 +
.../test/resources/core/Expression_21x.groovy | 6 +
.../src/test/resources/core/For_01.groovy | 55 +
.../src/test/resources/core/For_02.groovy | 36 +
.../src/test/resources/core/For_03.groovy | 37 +
.../src/test/resources/core/GString_01.groovy | 30 +
.../src/test/resources/core/GString_02.groovy | 59 +
.../src/test/resources/core/GString_03.groovy | 49 +
.../test/resources/core/IdenticalOp_01x.groovy | 10 +
.../src/test/resources/core/IfElse_01.groovy | 44 +
.../resources/core/ImportDeclaration_01.groovy | 1 +
.../resources/core/ImportDeclaration_02.groovy | 1 +
.../resources/core/ImportDeclaration_03.groovy | 4 +
.../resources/core/ImportDeclaration_04.groovy | 5 +
.../resources/core/ImportDeclaration_05.groovy | 1 +
.../resources/core/ImportDeclaration_06.groovy | 3 +
.../resources/core/ImportDeclaration_07.groovy | 6 +
.../resources/core/ImportDeclaration_08.groovy | 28 +
.../core/InterfaceDeclaration_01.groovy | 36 +
.../core/InterfaceDeclaration_02.groovy | 42 +
.../core/InterfaceDeclaration_03.groovy | 7 +
.../src/test/resources/core/Label_01.groovy | 15 +
.../src/test/resources/core/Lambda_01x.groovy | 47 +
.../src/test/resources/core/List_01.groovy | 15 +
.../src/test/resources/core/Literal_01.groovy | 79 +
.../src/test/resources/core/Literal_02.groovy | 48 +
.../src/test/resources/core/Literal_03.groovy | 3 +
.../core/LocalVariableDeclaration_01.groovy | 110 +
.../src/test/resources/core/Map_01.groovy | 29 +
.../resources/core/MethodDeclaration_01.groovy | 32 +
.../resources/core/MethodDeclaration_02.groovy | 41 +
.../resources/core/MethodPointer_01x.groovy | 5 +
.../resources/core/MethodReference_01x.groovy | 85 +
.../resources/core/PackageDeclaration_01.groovy | 1 +
.../resources/core/PackageDeclaration_02.groovy | 1 +
.../resources/core/PackageDeclaration_03.groovy | 1 +
.../resources/core/PackageDeclaration_04.groovy | 20 +
.../resources/core/PackageDeclaration_05.groovy | 23 +
.../resources/core/PackageDeclaration_06.groovy | 1 +
.../src/test/resources/core/Return_01.groovy | 8 +
.../test/resources/core/SafeIndex_01x.groovy | 10 +
.../src/test/resources/core/Switch_01.groovy | 60 +
.../test/resources/core/Synchronized_01.groovy | 36 +
.../src/test/resources/core/Throw_01.groovy | 2 +
.../resources/core/TraitDeclaration_01.groovy | 42 +
.../resources/core/TraitDeclaration_02.groovy | 40 +
.../resources/core/TraitDeclaration_03.groovy | 48 +
.../resources/core/TraitDeclaration_04.groovy | 28 +
.../resources/core/TraitDeclaration_05.groovy | 23 +
.../src/test/resources/core/TryCatch_01.groovy | 112 +
.../resources/core/TryWithResources_01x.groovy | 241 +
.../src/test/resources/core/Unicode_01.groovy | 24 +
.../src/test/resources/core/While_01.groovy | 58 +
.../src/test/resources/core/While_02x.groovy | 5 +
.../resources/fail/AbstractMethod_01x.groovy | 3 +
.../resources/fail/AbstractMethod_02x.groovy | 4 +
.../resources/fail/AbstractMethod_03x.groovy | 3 +
.../resources/fail/AbstractMethod_04x.groovy | 1 +
.../resources/fail/AbstractMethod_05x.groovy | 1 +
.../resources/fail/AbstractMethod_06x.groovy | 1 +
.../src/test/resources/fail/Break_01x.groovy | 1 +
.../src/test/resources/fail/Break_02x.groovy | 3 +
.../src/test/resources/fail/Continue_01x.groovy | 1 +
.../src/test/resources/fail/Continue_02x.groovy | 3 +
.../src/test/resources/fail/DoWhile_01x.groovy | 4 +
.../test/resources/fail/Expression_01.groovy | 1 +
.../test/resources/fail/Expression_02.groovy | 1 +
.../test/resources/fail/Expression_03.groovy | 1 +
.../test/resources/fail/Expression_04.groovy | 1 +
.../test/resources/fail/Expression_05.groovy | 1 +
.../test/resources/fail/Expression_06.groovy | 1 +
.../test/resources/fail/Expression_07.groovy | 1 +
.../test/resources/fail/Expression_08.groovy | 1 +
.../test/resources/fail/Expression_09.groovy | 1 +
.../src/test/resources/fail/List_01.groovy | 1 +
.../fail/LocalVariableDeclaration_01.groovy | 1 +
.../resources/fail/ParExpression_01x.groovy | 1 +
.../resources/fail/ParExpression_02x.groovy | 1 +
.../resources/fail/ParExpression_03x.groovy | 1 +
.../src/test/resources/fail/Super_01x.groovy | 6 +
.../src/test/resources/fail/Switch_01.groovy | 9 +
.../src/test/resources/fail/This_01x.groovy | 8 +
.../fail/UnexpectedCharacter_01x.groovy | 1 +
.../src/test/resources/geb-1.0/allsources.txt | 409 +
.../resources/geb-1.0/geb-1.0-allsources.zip | Bin 0 -> 503324 bytes
.../test/resources/gradle-3.1/allsources.txt | 3963 ++++
.../gradle-3.1/gradle-3.1-allsources.zip | Bin 0 -> 5966721 bytes
.../test/resources/grails-3.2.0/allsources.txt | 1150 ++
.../grails-3.2.0/grails-3.2.0-allsources.zip | Bin 0 -> 1674411 bytes
.../test/resources/groovy-2.5.0/allscripts.txt | 2744 +++
.../test/resources/groovy-2.5.0/allsources.txt | 1844 ++
...roovy-2.5.0-SNAPSHOT-20160921-allscripts.zip | Bin 0 -> 1071812 bytes
...roovy-2.5.0-SNAPSHOT-20160921-allsources.zip | Bin 0 -> 2711417 bytes
.../spock-spock-1.1-rc-2/allsources.txt | 294 +
.../spock-spock-1.1-rc-2-allsources.zip | Bin 0 -> 338519 bytes
207 files changed, 66305 insertions(+), 198 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/groovy/blob/91c04014/.travis.yml
----------------------------------------------------------------------
diff --git a/.travis.yml b/.travis.yml
index 09d1e5f..43a3aa3 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -27,7 +27,7 @@ matrix:
install: true
-script: travis_wait 35 ./gradlew test
+script: travis_wait 60 ./gradlew -PuseAntlr4=true test
before_cache:
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
http://git-wip-us.apache.org/repos/asf/groovy/blob/91c04014/src/main/groovy/lang/MetaClassImpl.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/MetaClassImpl.java b/src/main/groovy/lang/MetaClassImpl.java
index d7d8d9b..2814dd1 100644
--- a/src/main/groovy/lang/MetaClassImpl.java
+++ b/src/main/groovy/lang/MetaClassImpl.java
@@ -24,66 +24,23 @@ import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.classgen.asm.BytecodeHelper;
import org.codehaus.groovy.control.CompilationUnit;
import org.codehaus.groovy.control.Phases;
-import org.codehaus.groovy.reflection.CachedClass;
-import org.codehaus.groovy.reflection.CachedConstructor;
-import org.codehaus.groovy.reflection.CachedField;
-import org.codehaus.groovy.reflection.CachedMethod;
-import org.codehaus.groovy.reflection.ClassInfo;
-import org.codehaus.groovy.reflection.GeneratedMetaMethod;
-import org.codehaus.groovy.reflection.ParameterTypes;
-import org.codehaus.groovy.reflection.ReflectionCache;
-import org.codehaus.groovy.runtime.ConvertedClosure;
-import org.codehaus.groovy.runtime.CurriedClosure;
-import org.codehaus.groovy.runtime.DefaultGroovyMethods;
-import org.codehaus.groovy.runtime.GeneratedClosure;
-import org.codehaus.groovy.runtime.GroovyCategorySupport;
-import org.codehaus.groovy.runtime.InvokerHelper;
-import org.codehaus.groovy.runtime.InvokerInvocationException;
-import org.codehaus.groovy.runtime.MetaClassHelper;
-import org.codehaus.groovy.runtime.MethodClosure;
-import org.codehaus.groovy.runtime.callsite.AbstractCallSite;
-import org.codehaus.groovy.runtime.callsite.CallSite;
-import org.codehaus.groovy.runtime.callsite.ConstructorSite;
-import org.codehaus.groovy.runtime.callsite.MetaClassConstructorSite;
-import org.codehaus.groovy.runtime.callsite.PogoMetaClassSite;
-import org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite;
-import org.codehaus.groovy.runtime.callsite.PojoMetaClassSite;
-import org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite;
-import org.codehaus.groovy.runtime.callsite.StaticMetaClassSite;
-import org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite;
-import org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod;
+import org.codehaus.groovy.reflection.*;
+import org.codehaus.groovy.reflection.android.AndroidSupport;
+import org.codehaus.groovy.runtime.*;
+import org.codehaus.groovy.runtime.callsite.*;
+import org.codehaus.groovy.runtime.metaclass.*;
import org.codehaus.groovy.runtime.metaclass.MethodMetaProperty.GetBeanMethodMetaProperty;
import org.codehaus.groovy.runtime.metaclass.MethodMetaProperty.GetMethodMetaProperty;
-import org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl;
-import org.codehaus.groovy.runtime.metaclass.MetaMethodIndex;
-import org.codehaus.groovy.runtime.metaclass.MethodSelectionException;
-import org.codehaus.groovy.runtime.metaclass.MissingMethodExceptionNoStack;
-import org.codehaus.groovy.runtime.metaclass.MissingMethodExecutionFailed;
-import org.codehaus.groovy.runtime.metaclass.MissingPropertyExceptionNoStack;
-import org.codehaus.groovy.runtime.metaclass.MixinInstanceMetaMethod;
-import org.codehaus.groovy.runtime.metaclass.MultipleSetterProperty;
-import org.codehaus.groovy.runtime.metaclass.NewInstanceMetaMethod;
-import org.codehaus.groovy.runtime.metaclass.NewMetaMethod;
-import org.codehaus.groovy.runtime.metaclass.NewStaticMetaMethod;
-import org.codehaus.groovy.runtime.metaclass.TransformMetaMethod;
import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
import org.codehaus.groovy.runtime.typehandling.NumberMathModificationInfo;
import org.codehaus.groovy.runtime.wrappers.Wrapper;
import org.codehaus.groovy.util.ComplexKeyHashMap;
import org.codehaus.groovy.util.FastArray;
import org.codehaus.groovy.util.SingleKeyHashMap;
-import org.codehaus.groovy.reflection.android.AndroidSupport;
import org.objectweb.asm.ClassVisitor;
-import java.beans.BeanInfo;
-import java.beans.EventSetDescriptor;
-import java.beans.IntrospectionException;
-import java.beans.Introspector;
-import java.beans.PropertyDescriptor;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.lang.reflect.Proxy;
+import java.beans.*;
+import java.lang.reflect.*;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedActionException;
@@ -139,8 +96,8 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
private final MetaProperty arrayLengthProperty = new MetaArrayLengthProperty();
private final Index classPropertyIndexForSuper = new MethodIndex();
private final Set<MetaMethod> newGroovyMethodsSet = new HashSet<MetaMethod>();
- private final MetaMethod [] myNewMetaMethods;
- private final MetaMethod [] additionalMetaMethods;
+ private final MetaMethod[] myNewMetaMethods;
+ private final MetaMethod[] additionalMetaMethods;
protected MetaMethod getPropertyMethod;
protected MetaMethod invokeMethodMethod;
@@ -162,7 +119,7 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
* @param theClass The class this is the metaclass dor
* @param add The methods for this class
*/
- public MetaClassImpl(final Class theClass, MetaMethod [] add) {
+ public MetaClassImpl(final Class theClass, MetaMethod[] add) {
this.theClass = theClass;
theCachedClass = ReflectionCache.getCachedClass(theClass);
this.isGroovyObject = GroovyObject.class.isAssignableFrom(theClass);
@@ -226,7 +183,7 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
/**
* Returns the registry for this metaclass
- *
+ *
* @return The resgistry
*/
public MetaClassRegistry getRegistry() {
@@ -310,7 +267,7 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
/**
*Returns the class this object this is the metaclass of.
- *
+ *
* @return The class contained by this metaclass
*/
public Class getTheClass() {
@@ -557,7 +514,7 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
int to = index;
while (to < mopMethods.length-1 && mopMethods[to+1].getName().equals(fixedMopName))
to++;
-
+
int matchingMethod = findMatchingMethod(mopMethods, from, to, method);
if (matchingMethod != -1) {
e.methodsForSuper = mopMethods[matchingMethod];
@@ -741,7 +698,7 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
}
/**
- * Returns all the normal static methods on this class for the given name
+ * Returns all the normal static methods on this class for the given name
*
* @return all the normal static methods available on this class for the
* given name
@@ -840,7 +797,7 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
public Object invokeMissingMethod(Object instance, String methodName, Object[] arguments) {
return invokeMissingMethod(instance, methodName, arguments, null, false);
}
-
+
/**
* Invoke a missing property on the given object with the given arguments.
*
@@ -955,13 +912,13 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
} catch (InvokerInvocationException iie) {
if (methodMissing instanceof ClosureMetaMethod && iie.getCause() instanceof MissingMethodException) {
MissingMethodException mme = (MissingMethodException) iie.getCause();
- throw new MissingMethodExecutionFailed (mme.getMethod(), mme.getClass(),
+ throw new MissingMethodExecutionFailed(mme.getMethod(), mme.getClass(),
mme.getArguments(),mme.isStatic(),mme);
}
throw iie;
} catch (MissingMethodException mme) {
if (methodMissing instanceof ClosureMetaMethod)
- throw new MissingMethodExecutionFailed (mme.getMethod(), mme.getClass(),
+ throw new MissingMethodExecutionFailed(mme.getMethod(), mme.getClass(),
mme.getArguments(),mme.isStatic(),mme);
else
throw mme;
@@ -1019,9 +976,9 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
throw new MissingPropertyException(propertyName, theClass);
}
-
+
/**
- * Invokes a method on the given receiver for the specified arguments.
+ * Invokes a method on the given receiver for the specified arguments.
* The MetaClass will attempt to establish the method to invoke based on the name and arguments provided.
*
*
@@ -1030,13 +987,79 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
* @param originalArguments The arguments to the method
*
* @return The return value of the method
- *
+ *
* @see MetaClass#invokeMethod(Class, Object, String, Object[], boolean, boolean)
*/
public Object invokeMethod(Object object, String methodName, Object[] originalArguments) {
return invokeMethod(theClass, object, methodName, originalArguments, false, false);
}
+ private Object invokeMethodClosure(Object object, String methodName, Object[] arguments) {
+ final MethodClosure mc = (MethodClosure) object;
+ final Object owner = mc.getOwner();
+
+ methodName = mc.getMethod();
+ final Class ownerClass = owner instanceof Class ? (Class) owner : owner.getClass();
+ final MetaClass ownerMetaClass = registry.getMetaClass(ownerClass);
+
+ // To conform to "Least Surprise" principle, try to invoke method with original arguments first, which can match most of use cases
+ try {
+ return ownerMetaClass.invokeMethod(ownerClass, owner, methodName, arguments, false, false);
+ } catch (MissingMethodExceptionNoStack e) {
+ // CONSTRUCTOR REFERENCE
+ if (owner instanceof Class && MethodClosure.NEW.equals(methodName)) {
+ if (ownerClass.isArray()) {
+ if (0 == arguments.length) {
+ throw new GroovyRuntimeException("The arguments(specifying size) are required to create array[" + ownerClass.getCanonicalName() + "]");
+ }
+
+ int arrayDimension = ArrayTypeUtils.dimension(ownerClass);
+
+ if (arguments.length > arrayDimension) {
+ throw new GroovyRuntimeException("The length[" + arguments.length + "] of arguments should not be greater than the dimensions[" + arrayDimension + "] of array[" + ownerClass.getCanonicalName() + "]");
+ }
+
+ int[] sizeArray = new int[arguments.length];
+
+ for (int i = 0, n = sizeArray.length; i < n; i++) {
+ Object argument = arguments[i];
+
+ if (argument instanceof Integer) {
+ sizeArray[i] = (Integer) argument;
+ } else {
+ sizeArray[i] = Integer.parseInt(String.valueOf(argument));
+ }
+ }
+
+ Class arrayType =
+ arguments.length == arrayDimension
+ ? ArrayTypeUtils.elementType(ownerClass) // Just for better performance, though we can use reduceDimension only
+ : ArrayTypeUtils.reduceDimension(ownerClass, (arrayDimension - arguments.length));
+ return Array.newInstance(arrayType, sizeArray);
+ }
+
+ return ownerMetaClass.invokeConstructor(arguments);
+ }
+
+ // METHOD REFERENCE
+ // if and only if the owner is a class and the method closure can be related to some instance methods,
+ // try to invoke method with adjusted arguments(first argument is the actual owner) again.
+ // otherwise throw the MissingMethodExceptionNoStack.
+ if (!(owner instanceof Class
+ && ((Boolean) mc.getProperty(MethodClosure.ANY_INSTANCE_METHOD_EXISTS)).booleanValue())) {
+
+ throw e;
+ }
+
+ if (arguments.length <= 0) {
+ return invokeMissingMethod(object, methodName, arguments);
+ }
+
+ Object newOwner = arguments[0];
+ Object[] newArguments = Arrays.copyOfRange(arguments, 1, arguments.length);
+ return ownerMetaClass.invokeMethod(ownerClass, newOwner, methodName, newArguments, false, false);
+ }
+ }
/**
* <p>Invokes a method on the given receiver for the specified arguments. The sender is the class that invoked the method on the object.
@@ -1070,7 +1093,7 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
MetaMethod method = null;
if (CLOSURE_CALL_METHOD.equals(methodName) && object instanceof GeneratedClosure) {
method = getMethodWithCaching(sender, "doCall", arguments, isCallToSuper);
- }
+ }
if (method==null) {
method = getMethodWithCaching(sender, methodName, arguments, isCallToSuper);
}
@@ -1082,17 +1105,12 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
final boolean isClosure = object instanceof Closure;
if (isClosure) {
final Closure closure = (Closure) object;
-
final Object owner = closure.getOwner();
if (CLOSURE_CALL_METHOD.equals(methodName) || CLOSURE_DO_CALL_METHOD.equals(methodName)) {
final Class objectClass = object.getClass();
if (objectClass == MethodClosure.class) {
- final MethodClosure mc = (MethodClosure) object;
- methodName = mc.getMethod();
- final Class ownerClass = owner instanceof Class ? (Class) owner : owner.getClass();
- final MetaClass ownerMetaClass = registry.getMetaClass(ownerClass);
- return ownerMetaClass.invokeMethod(ownerClass, owner, methodName, arguments, false, false);
+ return this.invokeMethodClosure(object, methodName, arguments);
} else if (objectClass == CurriedClosure.class) {
final CurriedClosure cc = (CurriedClosure) object;
// change the arguments for an uncurried call
@@ -1659,7 +1677,7 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
"before any invocation or field/property " +
"access can be done");
}
-
+
/**
* This is a helper class introduced in Groovy 2.1.0, which is used only by
* indy. This class is for internal use only.
@@ -1689,7 +1707,7 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
public CachedConstructor getCachedConstrcutor() { return cc; }
public boolean isBeanConstructor() { return beanConstructor; }
}
-
+
/**
* This is a helper method added in Groovy 2.1.0, which is used only by indy.
* This method is for internal use only.
@@ -1707,9 +1725,9 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
if (arguments.length == 1 && arguments[0] instanceof Map) {
res = chooseMethod("<init>", constructors, MetaClassHelper.EMPTY_TYPE_ARRAY);
} else if (
- arguments.length == 2 && arguments[1] instanceof Map &&
- theClass.getEnclosingClass()!=null &&
- theClass.getEnclosingClass().isAssignableFrom(argClasses[0]))
+ arguments.length == 2 && arguments[1] instanceof Map &&
+ theClass.getEnclosingClass()!=null &&
+ theClass.getEnclosingClass().isAssignableFrom(argClasses[0]))
{
res = chooseMethod("<init>", constructors, new Class[]{argClasses[0]});
}
@@ -1719,7 +1737,7 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
return null;
}
-
+
private Object invokeConstructor(Class at, Object[] arguments) {
checkInitalised();
if (arguments == null) arguments = EMPTY_ARGUMENTS;
@@ -2460,7 +2478,7 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
if (name == null) {
// assume "is" or "[gs]et"
String stripped = methodName.startsWith("is") ? methodName.substring(2) : methodName.substring(3);
- String propName = java.beans.Introspector.decapitalize(stripped);
+ String propName = Introspector.decapitalize(stripped);
PROP_NAMES.putIfAbsent(methodName, propName);
name = PROP_NAMES.get(methodName);
}
http://git-wip-us.apache.org/repos/asf/groovy/blob/91c04014/src/main/org/codehaus/groovy/ast/expr/BinaryExpression.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/ast/expr/BinaryExpression.java b/src/main/org/codehaus/groovy/ast/expr/BinaryExpression.java
index 5cd35f7..1487dfc 100644
--- a/src/main/org/codehaus/groovy/ast/expr/BinaryExpression.java
+++ b/src/main/org/codehaus/groovy/ast/expr/BinaryExpression.java
@@ -34,6 +34,7 @@ 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,
@@ -43,6 +44,14 @@ public class BinaryExpression extends Expression {
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 + "]";
}
@@ -52,7 +61,7 @@ public class BinaryExpression extends Expression {
}
public Expression transformExpression(ExpressionTransformer transformer) {
- Expression ret = new BinaryExpression(transformer.transform(leftExpression), operation, transformer.transform(rightExpression));
+ Expression ret = new BinaryExpression(transformer.transform(leftExpression), operation, transformer.transform(rightExpression), safe);
ret.setSourcePosition(this);
ret.copyNodeMetaData(this);
return ret;
@@ -85,6 +94,13 @@ public class BinaryExpression extends Expression {
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
http://git-wip-us.apache.org/repos/asf/groovy/blob/91c04014/src/main/org/codehaus/groovy/ast/expr/DeclarationExpression.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/ast/expr/DeclarationExpression.java b/src/main/org/codehaus/groovy/ast/expr/DeclarationExpression.java
index 51dad92..6c082a7 100644
--- a/src/main/org/codehaus/groovy/ast/expr/DeclarationExpression.java
+++ b/src/main/org/codehaus/groovy/ast/expr/DeclarationExpression.java
@@ -100,7 +100,11 @@ public class DeclarationExpression extends BinaryExpression {
* @throws ClassCastException if the left hand side is not a VariableExpression (and is probably a multiple assignment statement).
*/
public VariableExpression getVariableExpression() {
- return (VariableExpression) this.getLeftExpression();
+ Expression leftExpression = this.getLeftExpression();
+
+ return leftExpression instanceof VariableExpression
+ ? (VariableExpression) leftExpression
+ : null;
}
/**
@@ -116,7 +120,11 @@ public class DeclarationExpression extends BinaryExpression {
*
*/
public TupleExpression getTupleExpression() {
- return (TupleExpression) this.getLeftExpression();
+ Expression leftExpression = this.getLeftExpression();
+
+ return leftExpression instanceof TupleExpression
+ ? (TupleExpression) leftExpression
+ : null;
}
/**
http://git-wip-us.apache.org/repos/asf/groovy/blob/91c04014/src/main/org/codehaus/groovy/ast/expr/LambdaExpression.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/ast/expr/LambdaExpression.java b/src/main/org/codehaus/groovy/ast/expr/LambdaExpression.java
new file mode 100644
index 0000000..f4f1001
--- /dev/null
+++ b/src/main/org/codehaus/groovy/ast/expr/LambdaExpression.java
@@ -0,0 +1,47 @@
+/*
+ * 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.Parameter;
+import org.codehaus.groovy.ast.stmt.Statement;
+
+/**
+ * Represents a lambda expression such as e -> e * 2
+ * or (x, y) -> x + y or (x, y) -> { x + y } or (int x, int y) -> { x + y }
+ *
+ * @author <a href="mailto:realbluesun@hotmail.com">Daniel.Sun</a>
+ * Created on 2016/10/18
+ */
+public class LambdaExpression extends ClosureExpression {
+ public LambdaExpression(Parameter[] parameters, Statement code) {
+ super(parameters, code);
+ }
+
+ @Override
+ public String getText() {
+ String paramText = AstToTextHelper.getParametersText(this.getParameters());
+ if (paramText.length() > 0) {
+ return "(" + paramText + ") -> { ... }";
+ } else {
+ return "() -> { ... }";
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/groovy/blob/91c04014/src/main/org/codehaus/groovy/ast/expr/MethodReferenceExpression.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/ast/expr/MethodReferenceExpression.java b/src/main/org/codehaus/groovy/ast/expr/MethodReferenceExpression.java
new file mode 100644
index 0000000..0a8ebc8
--- /dev/null
+++ b/src/main/org/codehaus/groovy/ast/expr/MethodReferenceExpression.java
@@ -0,0 +1,45 @@
+/*
+ * 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;
+
+/**
+ * Represents a method reference or a constructor reference,
+ * e.g. System.out::println OR Objects::requireNonNull OR Integer::new OR int[]::new
+ *
+ * @author <a href="mailto:realbluesun@hotmail.com">Daniel.Sun</a>
+ * Created on 2016/10/19
+ */
+public class MethodReferenceExpression extends MethodPointerExpression {
+ public MethodReferenceExpression(Expression expression, Expression methodName) {
+ super(expression, methodName);
+ }
+
+ @Override
+ public String getText() {
+ Expression expression = this.getExpression();
+ Expression methodName = this.getMethodName();
+
+ if (expression == null) {
+ return "::" + methodName;
+ } else {
+ return expression.getText() + "::" + methodName.getText();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/groovy/blob/91c04014/src/main/org/codehaus/groovy/ast/stmt/TryCatchStatement.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/ast/stmt/TryCatchStatement.java b/src/main/org/codehaus/groovy/ast/stmt/TryCatchStatement.java
index e8dea4e..f05460f 100644
--- a/src/main/org/codehaus/groovy/ast/stmt/TryCatchStatement.java
+++ b/src/main/org/codehaus/groovy/ast/stmt/TryCatchStatement.java
@@ -18,11 +18,12 @@
*/
package org.codehaus.groovy.ast.stmt;
+import org.codehaus.groovy.ast.GroovyCodeVisitor;
+import org.codehaus.groovy.ast.expr.DeclarationExpression;
+
import java.util.ArrayList;
import java.util.List;
-import org.codehaus.groovy.ast.GroovyCodeVisitor;
-
/**
* Represents a try { ... } catch () finally {} statement in Groovy
*
@@ -31,6 +32,7 @@ import org.codehaus.groovy.ast.GroovyCodeVisitor;
public class TryCatchStatement extends Statement {
private Statement tryStatement;
+ private List<ExpressionStatement> resourceStatements = new ArrayList<ExpressionStatement>();
private List<CatchStatement> catchStatements = new ArrayList<CatchStatement>();
private Statement finallyStatement;
@@ -43,7 +45,11 @@ public class TryCatchStatement extends Statement {
public void visit(GroovyCodeVisitor visitor) {
visitor.visitTryCatchFinally(this);
}
-
+
+ public List<ExpressionStatement> getResourceStatements() {
+ return resourceStatements;
+ }
+
public List<CatchStatement> getCatchStatements() {
return catchStatements;
}
@@ -56,6 +62,14 @@ public class TryCatchStatement extends Statement {
return tryStatement;
}
+ public void addResource(ExpressionStatement resourceStatement) {
+ if (!(resourceStatement.getExpression() instanceof DeclarationExpression)) {
+ throw new IllegalArgumentException("resourceStatement should be a variable declaration statement");
+ }
+
+ resourceStatements.add(resourceStatement);
+ }
+
public void addCatch(CatchStatement catchStatement) {
catchStatements.add(catchStatement);
}
@@ -70,6 +84,16 @@ public class TryCatchStatement extends Statement {
return null;
}
+ /**
+ * @return the resource statement of the given index or null
+ */
+ public ExpressionStatement getResourceStatement(int idx) {
+ if (idx >= 0 && idx < resourceStatements.size()) {
+ return resourceStatements.get(idx);
+ }
+ return null;
+ }
+
public void setTryStatement(Statement tryStatement) {
this.tryStatement = tryStatement;
}
http://git-wip-us.apache.org/repos/asf/groovy/blob/91c04014/src/main/org/codehaus/groovy/classgen/asm/BinaryExpressionHelper.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/classgen/asm/BinaryExpressionHelper.java b/src/main/org/codehaus/groovy/classgen/asm/BinaryExpressionHelper.java
index 633f447..d86c58d 100644
--- a/src/main/org/codehaus/groovy/classgen/asm/BinaryExpressionHelper.java
+++ b/src/main/org/codehaus/groovy/classgen/asm/BinaryExpressionHelper.java
@@ -23,23 +23,7 @@ import groovy.lang.GroovyRuntimeException;
import org.codehaus.groovy.GroovyBugError;
import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.expr.ArgumentListExpression;
-import org.codehaus.groovy.ast.expr.ArrayExpression;
-import org.codehaus.groovy.ast.expr.BinaryExpression;
-import org.codehaus.groovy.ast.expr.ClassExpression;
-import org.codehaus.groovy.ast.expr.ConstantExpression;
-import org.codehaus.groovy.ast.expr.ElvisOperatorExpression;
-import org.codehaus.groovy.ast.expr.EmptyExpression;
-import org.codehaus.groovy.ast.expr.Expression;
-import org.codehaus.groovy.ast.expr.FieldExpression;
-import org.codehaus.groovy.ast.expr.ListExpression;
-import org.codehaus.groovy.ast.expr.MethodCallExpression;
-import org.codehaus.groovy.ast.expr.PostfixExpression;
-import org.codehaus.groovy.ast.expr.PrefixExpression;
-import org.codehaus.groovy.ast.expr.PropertyExpression;
-import org.codehaus.groovy.ast.expr.TernaryExpression;
-import org.codehaus.groovy.ast.expr.TupleExpression;
-import org.codehaus.groovy.ast.expr.VariableExpression;
+import org.codehaus.groovy.ast.expr.*;
import org.codehaus.groovy.ast.tools.WideningCategories;
import org.codehaus.groovy.classgen.AsmClassGenerator;
import org.codehaus.groovy.classgen.BytecodeExpression;
@@ -55,6 +39,8 @@ import static org.objectweb.asm.Opcodes.*;
public class BinaryExpressionHelper {
//compare
+ private static final MethodCaller compareIdenticalMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "compareIdentical");
+ private static final MethodCaller compareNotIdenticalMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "compareNotIdentical");
private static final MethodCaller compareEqualMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "compareEqual");
private static final MethodCaller compareNotEqualMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "compareNotEqual");
private static final MethodCaller compareToMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "compareTo");
@@ -251,10 +237,12 @@ public class BinaryExpressionHelper {
break;
case COMPARE_IDENTICAL:
+ evaluateCompareExpression(compareIdenticalMethod, expression);
+ break;
+
case COMPARE_NOT_IDENTICAL:
- Token op = expression.getOperation();
- Throwable cause = new SyntaxException("Operator " + op + " not supported", op.getStartLine(), op.getStartColumn(), op.getStartLine(), op.getStartColumn()+3);
- throw new GroovyRuntimeException(cause);
+ evaluateCompareExpression(compareNotIdenticalMethod, expression);
+ break;
default:
throw new GroovyBugError("Operation: " + expression.getOperation() + " not supported");
@@ -526,7 +514,7 @@ public class BinaryExpressionHelper {
// ensure VariableArguments are read, not stored
compileStack.pushLHS(false);
- controller.getInvocationWriter().makeSingleArgumentCall(receiver, message, arguments);
+ controller.getInvocationWriter().makeSingleArgumentCall(receiver, message, arguments, binExp.isSafe());
compileStack.popLHS();
}
http://git-wip-us.apache.org/repos/asf/groovy/blob/91c04014/src/main/org/codehaus/groovy/classgen/asm/CallSiteWriter.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/classgen/asm/CallSiteWriter.java b/src/main/org/codehaus/groovy/classgen/asm/CallSiteWriter.java
index 0e3910d..0309138 100644
--- a/src/main/org/codehaus/groovy/classgen/asm/CallSiteWriter.java
+++ b/src/main/org/codehaus/groovy/classgen/asm/CallSiteWriter.java
@@ -18,26 +18,17 @@
*/
package org.codehaus.groovy.classgen.asm;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
-
import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.InterfaceHelperClassNode;
-import org.codehaus.groovy.ast.expr.ArgumentListExpression;
-import org.codehaus.groovy.ast.expr.CastExpression;
-import org.codehaus.groovy.ast.expr.ClassExpression;
-import org.codehaus.groovy.ast.expr.Expression;
-import org.codehaus.groovy.ast.expr.TupleExpression;
+import org.codehaus.groovy.ast.expr.*;
import org.codehaus.groovy.classgen.AsmClassGenerator;
import org.codehaus.groovy.runtime.callsite.CallSite;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
+import java.util.*;
+
import static org.objectweb.asm.Opcodes.*;
/**
@@ -247,14 +238,18 @@ public class CallSiteWriter {
}
}
- public void makeSingleArgumentCall(Expression receiver, String message, Expression arguments) {
+ public final void makeSingleArgumentCall(Expression receiver, String message, Expression arguments) {
+ makeSingleArgumentCall(receiver, message, arguments, false);
+ }
+
+ public void makeSingleArgumentCall(Expression receiver, String message, Expression arguments, boolean safe) {
OperandStack operandStack = controller.getOperandStack();
int m1 = operandStack.getStackLength();
//slow Path
prepareSiteAndReceiver(receiver, message, false, controller.getCompileStack().isLHS());
visitBoxedArgument(arguments);
int m2 = operandStack.getStackLength();
- controller.getMethodVisitor().visitMethodInsn(INVOKEINTERFACE, "org/codehaus/groovy/runtime/callsite/CallSite", "call", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", true);
+ controller.getMethodVisitor().visitMethodInsn(INVOKEINTERFACE, "org/codehaus/groovy/runtime/callsite/CallSite", safe ? "callSafe" : "call", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", true);
operandStack.replace(ClassHelper.OBJECT_TYPE, m2-m1);
}
http://git-wip-us.apache.org/repos/asf/groovy/blob/91c04014/src/main/org/codehaus/groovy/classgen/asm/InvocationWriter.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/classgen/asm/InvocationWriter.java b/src/main/org/codehaus/groovy/classgen/asm/InvocationWriter.java
index 5557983..49cdc95 100644
--- a/src/main/org/codehaus/groovy/classgen/asm/InvocationWriter.java
+++ b/src/main/org/codehaus/groovy/classgen/asm/InvocationWriter.java
@@ -18,15 +18,6 @@
*/
package org.codehaus.groovy.classgen.asm;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.TreeMap;
-
import org.codehaus.groovy.ast.*;
import org.codehaus.groovy.ast.expr.*;
import org.codehaus.groovy.ast.tools.WideningCategories;
@@ -39,6 +30,9 @@ import org.codehaus.groovy.syntax.SyntaxException;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
+import java.lang.reflect.Modifier;
+import java.util.*;
+
import static org.objectweb.asm.Opcodes.*;
public class InvocationWriter {
@@ -617,8 +611,12 @@ public class InvocationWriter {
}
}
- public void makeSingleArgumentCall(Expression receiver, String message, Expression arguments) {
- controller.getCallSiteWriter().makeSingleArgumentCall(receiver, message, arguments);
+ public final void makeSingleArgumentCall(Expression receiver, String message, Expression arguments) {
+ makeSingleArgumentCall(receiver, message, arguments, false);
+ }
+
+ public void makeSingleArgumentCall(Expression receiver, String message, Expression arguments, boolean safe) {
+ controller.getCallSiteWriter().makeSingleArgumentCall(receiver, message, arguments, safe);
}
public void writeSpecialConstructorCall(final ConstructorCallExpression call) {
http://git-wip-us.apache.org/repos/asf/groovy/blob/91c04014/src/main/org/codehaus/groovy/classgen/asm/StatementWriter.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/classgen/asm/StatementWriter.java b/src/main/org/codehaus/groovy/classgen/asm/StatementWriter.java
index 5c14e73..4ff1a99 100644
--- a/src/main/org/codehaus/groovy/classgen/asm/StatementWriter.java
+++ b/src/main/org/codehaus/groovy/classgen/asm/StatementWriter.java
@@ -18,41 +18,18 @@
*/
package org.codehaus.groovy.classgen.asm;
-import java.util.Iterator;
-import java.util.List;
-
import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.Parameter;
-import org.codehaus.groovy.ast.expr.ArgumentListExpression;
-import org.codehaus.groovy.ast.expr.BooleanExpression;
-import org.codehaus.groovy.ast.expr.ClosureListExpression;
-import org.codehaus.groovy.ast.expr.ConstantExpression;
-import org.codehaus.groovy.ast.expr.EmptyExpression;
-import org.codehaus.groovy.ast.expr.Expression;
-import org.codehaus.groovy.ast.expr.MethodCallExpression;
-import org.codehaus.groovy.ast.stmt.AssertStatement;
-import org.codehaus.groovy.ast.stmt.BlockStatement;
-import org.codehaus.groovy.ast.stmt.BreakStatement;
-import org.codehaus.groovy.ast.stmt.CaseStatement;
-import org.codehaus.groovy.ast.stmt.CatchStatement;
-import org.codehaus.groovy.ast.stmt.ContinueStatement;
-import org.codehaus.groovy.ast.stmt.DoWhileStatement;
-import org.codehaus.groovy.ast.stmt.EmptyStatement;
-import org.codehaus.groovy.ast.stmt.ExpressionStatement;
-import org.codehaus.groovy.ast.stmt.ForStatement;
-import org.codehaus.groovy.ast.stmt.IfStatement;
-import org.codehaus.groovy.ast.stmt.ReturnStatement;
-import org.codehaus.groovy.ast.stmt.Statement;
-import org.codehaus.groovy.ast.stmt.SwitchStatement;
-import org.codehaus.groovy.ast.stmt.SynchronizedStatement;
-import org.codehaus.groovy.ast.stmt.ThrowStatement;
-import org.codehaus.groovy.ast.stmt.TryCatchStatement;
-import org.codehaus.groovy.ast.stmt.WhileStatement;
+import org.codehaus.groovy.ast.expr.*;
+import org.codehaus.groovy.ast.stmt.*;
import org.codehaus.groovy.classgen.asm.CompileStack.BlockRecorder;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
+import java.util.Iterator;
+import java.util.List;
+
import static org.objectweb.asm.Opcodes.*;
public class StatementWriter {
@@ -218,18 +195,7 @@ public class StatementWriter {
}
}
- public void writeWhileLoop(WhileStatement loop) {
- controller.getAcg().onLineNumber(loop,"visitWhileLoop");
- writeStatementLabel(loop);
-
- MethodVisitor mv = controller.getMethodVisitor();
-
- controller.getCompileStack().pushLoop(loop.getStatementLabels());
- Label continueLabel = controller.getCompileStack().getContinueLabel();
- Label breakLabel = controller.getCompileStack().getBreakLabel();
-
- mv.visitLabel(continueLabel);
- BooleanExpression bool = loop.getBooleanExpression();
+ private void visitConditionOfLoopingStatement(BooleanExpression bool, Label breakLabel, MethodVisitor mv) {
boolean boolHandled = false;
if (bool.getExpression() instanceof ConstantExpression) {
ConstantExpression constant = (ConstantExpression) bool.getExpression();
@@ -246,7 +212,21 @@ public class StatementWriter {
bool.visit(controller.getAcg());
controller.getOperandStack().jump(IFEQ, breakLabel);
}
+ }
+
+ public void writeWhileLoop(WhileStatement loop) {
+ controller.getAcg().onLineNumber(loop,"visitWhileLoop");
+ writeStatementLabel(loop);
+ MethodVisitor mv = controller.getMethodVisitor();
+
+ controller.getCompileStack().pushLoop(loop.getStatementLabels());
+ Label continueLabel = controller.getCompileStack().getContinueLabel();
+ Label breakLabel = controller.getCompileStack().getBreakLabel();
+
+ mv.visitLabel(continueLabel);
+
+ this.visitConditionOfLoopingStatement(loop.getBooleanExpression(), breakLabel, mv);
loop.getLoopBlock().visit(controller.getAcg());
mv.visitJumpInsn(GOTO, continueLabel);
@@ -262,14 +242,15 @@ public class StatementWriter {
MethodVisitor mv = controller.getMethodVisitor();
controller.getCompileStack().pushLoop(loop.getStatementLabels());
- Label breakLabel = controller.getCompileStack().getBreakLabel();
Label continueLabel = controller.getCompileStack().getContinueLabel();
+ Label breakLabel = controller.getCompileStack().getBreakLabel();
+
mv.visitLabel(continueLabel);
loop.getLoopBlock().visit(controller.getAcg());
+ this.visitConditionOfLoopingStatement(loop.getBooleanExpression(), breakLabel, mv);
- loop.getBooleanExpression().visit(controller.getAcg());
- controller.getOperandStack().jump(IFEQ, continueLabel);
+ mv.visitJumpInsn(GOTO, continueLabel);
mv.visitLabel(breakLabel);
controller.getCompileStack().pop();
http://git-wip-us.apache.org/repos/asf/groovy/blob/91c04014/src/main/org/codehaus/groovy/classgen/asm/indy/IndyCallSiteWriter.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/classgen/asm/indy/IndyCallSiteWriter.java b/src/main/org/codehaus/groovy/classgen/asm/indy/IndyCallSiteWriter.java
index 45acea8..963fa04 100644
--- a/src/main/org/codehaus/groovy/classgen/asm/indy/IndyCallSiteWriter.java
+++ b/src/main/org/codehaus/groovy/classgen/asm/indy/IndyCallSiteWriter.java
@@ -42,7 +42,7 @@ public class IndyCallSiteWriter extends CallSiteWriter {
Expression arguments, boolean safe, boolean implicitThis,
boolean callCurrent, boolean callStatic) {}
@Override
- public void makeSingleArgumentCall(Expression receiver, String message, Expression arguments) {}
+ public void makeSingleArgumentCall(Expression receiver, String message, Expression arguments, boolean safe) {}
@Override
public void prepareCallSite(String message) {}
@Override
http://git-wip-us.apache.org/repos/asf/groovy/blob/91c04014/src/main/org/codehaus/groovy/classgen/asm/indy/InvokeDynamicWriter.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/classgen/asm/indy/InvokeDynamicWriter.java b/src/main/org/codehaus/groovy/classgen/asm/indy/InvokeDynamicWriter.java
index 9cd08c5..9cd5ac3 100644
--- a/src/main/org/codehaus/groovy/classgen/asm/indy/InvokeDynamicWriter.java
+++ b/src/main/org/codehaus/groovy/classgen/asm/indy/InvokeDynamicWriter.java
@@ -166,8 +166,8 @@ public class InvokeDynamicWriter extends InvocationWriter {
}
@Override
- public void makeSingleArgumentCall(Expression receiver, String message, Expression arguments) {
- makeIndyCall(invokeMethod, receiver, false, false, message, arguments);
+ public void makeSingleArgumentCall(Expression receiver, String message, Expression arguments, boolean safe) {
+ makeIndyCall(invokeMethod, receiver, false, safe, message, arguments);
}
private static int getPropertyFlags(boolean safe, boolean implicitThis, boolean groovyObject) {
http://git-wip-us.apache.org/repos/asf/groovy/blob/91c04014/src/main/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java b/src/main/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
index a2900b4..3a13c6b 100644
--- a/src/main/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
+++ b/src/main/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
@@ -621,7 +621,7 @@ public class StaticTypesCallSiteWriter extends CallSiteWriter implements Opcodes
}
@Override
- public void makeSingleArgumentCall(final Expression receiver, final String message, final Expression arguments) {
+ public void makeSingleArgumentCall(final Expression receiver, final String message, final Expression arguments, boolean safe) {
TypeChooser typeChooser = controller.getTypeChooser();
ClassNode classNode = controller.getClassNode();
ClassNode rType = typeChooser.resolveType(receiver, classNode);
http://git-wip-us.apache.org/repos/asf/groovy/blob/91c04014/src/main/org/codehaus/groovy/runtime/ArrayTypeUtils.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/runtime/ArrayTypeUtils.java b/src/main/org/codehaus/groovy/runtime/ArrayTypeUtils.java
new file mode 100644
index 0000000..2a6e409
--- /dev/null
+++ b/src/main/org/codehaus/groovy/runtime/ArrayTypeUtils.java
@@ -0,0 +1,98 @@
+/*
+ * 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.runtime;
+
+/**
+ * Utilities for handling array types
+ *
+ * @author <a href="mailto:realbluesun@hotmail.com">Daniel.Sun</a>
+ * Created on 2016/10/28
+ */
+public class ArrayTypeUtils {
+
+ /**
+ * Calculate the dimension of array
+ *
+ * @param clazz the type of array
+ * @return the dimension of array
+ */
+ public static int dimension(Class clazz) {
+ checkArrayType(clazz);
+
+ int result = 0;
+ while (clazz.isArray()) {
+ result++;
+ clazz = clazz.getComponentType();
+ }
+
+ return result;
+ }
+
+ /**
+ * Get the type of array elements
+ *
+ * @param clazz the type of array
+ * @return the type of elements
+ */
+ public static Class elementType(Class clazz) {
+ checkArrayType(clazz);
+
+ while (clazz.isArray()) {
+ clazz = clazz.getComponentType();
+ }
+
+ return clazz;
+ }
+
+ /**
+ * Reduce the dimension of array
+ *
+ * @param clazz the type of array
+ * @param dim the target dimension
+ * @return the result array
+ */
+ public static Class reduceDimension(Class clazz, int dim) {
+ checkArrayType(clazz);
+
+ if (dim < 0) {
+ throw new IllegalArgumentException("The target dimension should not be less than zero: " + dim);
+ }
+
+ while (clazz.isArray() && dimension(clazz) > dim) {
+ clazz = clazz.getComponentType();
+ }
+
+ return clazz;
+ }
+
+ /**
+ * Check whether the type passed in is array type.
+ * If the type is not array type, throw IllegalArgumentException.
+ */
+ private static void checkArrayType(Class clazz) {
+ if (null == clazz) {
+ throw new IllegalArgumentException("clazz can not be null");
+ }
+
+ if (!clazz.isArray()) {
+ throw new IllegalArgumentException(clazz.getCanonicalName() + " is not array type");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/groovy/blob/91c04014/src/main/org/codehaus/groovy/runtime/MethodClosure.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/runtime/MethodClosure.java b/src/main/org/codehaus/groovy/runtime/MethodClosure.java
index 7ead0c7..60a6a3f 100644
--- a/src/main/org/codehaus/groovy/runtime/MethodClosure.java
+++ b/src/main/org/codehaus/groovy/runtime/MethodClosure.java
@@ -20,8 +20,11 @@ package org.codehaus.groovy.runtime;
import groovy.lang.Closure;
import groovy.lang.MetaMethod;
+import org.codehaus.groovy.reflection.CachedConstructor;
+import org.codehaus.groovy.reflection.ReflectionCache;
import java.io.IOException;
+import java.util.Arrays;
import java.util.List;
@@ -32,36 +35,90 @@ import java.util.List;
* @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
*/
public class MethodClosure extends Closure {
-
+ public static final String NEW = "new";
+ public static final String ANY_INSTANCE_METHOD_EXISTS = "anyInstanceMethodExists";
public static boolean ALLOW_RESOLVE = false;
private static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
private final String method;
+ private final boolean anyInstanceMethodExists; // whether the method closure is related to instance method
public MethodClosure(Object owner, String method) {
super(owner);
this.method = method;
- final Class clazz = owner.getClass()==Class.class?(Class) owner:owner.getClass();
-
- maximumNumberOfParameters = 0;
- parameterTypes = EMPTY_CLASS_ARRAY;
+ final Class clazz = owner.getClass() == Class.class ? (Class) owner : owner.getClass();
+
+ this.maximumNumberOfParameters = 0;
+ this.parameterTypes = EMPTY_CLASS_ARRAY;
List<MetaMethod> methods = InvokerHelper.getMetaClass(clazz).respondsTo(owner, method);
-
- for(MetaMethod m : methods) {
- if (m.getParameterTypes().length > maximumNumberOfParameters) {
- Class[] pt = m.getNativeParameterTypes();
- maximumNumberOfParameters = pt.length;
- parameterTypes = pt;
+
+ int instanceMethodCnt = 0;
+ for (MetaMethod m : methods) {
+ Class[] newParameterTypes = this.makeParameterTypes(owner, m);
+
+ this.setParameterTypesAndNumber(newParameterTypes);
+
+ if (!m.isStatic()) {
+ instanceMethodCnt++;
+ }
+ }
+
+ this.anyInstanceMethodExists = instanceMethodCnt > 0;
+
+ if (NEW.equals(method)) {
+ if (clazz.isArray()) {
+ Class[] sizeTypes = new Class[ArrayTypeUtils.dimension(clazz)];
+ Arrays.fill(sizeTypes, int.class);
+
+ this.setParameterTypesAndNumber(sizeTypes);
+ } else {
+ for (CachedConstructor c : ReflectionCache.getCachedClass(clazz).getConstructors()) {
+ Class[] newParameterTypes = c.getNativeParameterTypes();
+
+ this.setParameterTypesAndNumber(newParameterTypes);
+ }
}
}
}
+
+ private void setParameterTypesAndNumber(Class[] newParameterTypes) {
+ if (!(newParameterTypes.length > this.maximumNumberOfParameters)) {
+ return;
+ }
+
+ this.maximumNumberOfParameters = newParameterTypes.length;
+ this.parameterTypes = newParameterTypes;
+ }
+
+ /*
+ * Create a new array of parameter type.
+ *
+ * If the owner is a class instance(e.g. String) and the method is instance method,
+ * we expand the original array of parameter type by inserting the owner at the first place of the expanded array
+ */
+ private Class[] makeParameterTypes(Object owner, MetaMethod m) {
+ Class[] newParameterTypes;
+
+ if (owner instanceof Class && !m.isStatic()) {
+ Class[] nativeParameterTypes = m.getNativeParameterTypes();
+ newParameterTypes = new Class[nativeParameterTypes.length + 1];
+
+ System.arraycopy(nativeParameterTypes, 0, newParameterTypes, 1, nativeParameterTypes.length);
+ newParameterTypes[0] = (Class) owner;
+ } else {
+ newParameterTypes = m.getNativeParameterTypes();
+ }
+
+ return newParameterTypes;
+ }
public String getMethod() {
return method;
}
+ // TODO confirm: The "doCall" method seems to be never called..., because MetaClassImpl.invokeMethod will intercept calls and return the result
protected Object doCall(Object arguments) {
return InvokerHelper.invokeMethod(getOwner(), method, arguments);
}
@@ -83,6 +140,8 @@ public class MethodClosure extends Closure {
public Object getProperty(String property) {
if ("method".equals(property)) {
return getMethod();
- } else return super.getProperty(property);
+ } else if (ANY_INSTANCE_METHOD_EXISTS.equals(property)) {
+ return this.anyInstanceMethodExists;
+ } else return super.getProperty(property);
}
}
http://git-wip-us.apache.org/repos/asf/groovy/blob/91c04014/src/spec/test/builder/CliBuilderTest.groovy
----------------------------------------------------------------------
diff --git a/src/spec/test/builder/CliBuilderTest.groovy b/src/spec/test/builder/CliBuilderTest.groovy
index 1d039a1..b086fe6 100644
--- a/src/spec/test/builder/CliBuilderTest.groovy
+++ b/src/spec/test/builder/CliBuilderTest.groovy
@@ -264,7 +264,7 @@ class CliBuilderTest extends GroovyTestCase {
def options = cli.parse(argz)
assert options.a == 'john'
assert options.b == 'MARY'
- assert options.d.format('dd-MMM-yyyy') == '01-Jan-2016'
+ assert options.d.format('yyyy-MM-dd') == '2016-01-01'
assert options.arguments() == ['and', 'some', 'more']
// end::withConvert[]
}
http://git-wip-us.apache.org/repos/asf/groovy/blob/91c04014/src/test/groovy/EqualsTest.groovy
----------------------------------------------------------------------
diff --git a/src/test/groovy/EqualsTest.groovy b/src/test/groovy/EqualsTest.groovy
index 8011ea9..afe20f4 100644
--- a/src/test/groovy/EqualsTest.groovy
+++ b/src/test/groovy/EqualsTest.groovy
@@ -38,14 +38,13 @@ class EqualsTest extends GroovyShellTestCase {
}
void testIdentical() {
- shouldFail {
- shell.evaluate """
- def x = []
- def y = []
-
- assert y !== x
- """
- }
+ assert 'a' === 'a'
+ assert null === null
+
+ def x = []
+ def y = []
+ assert y !== x
+
}
}
http://git-wip-us.apache.org/repos/asf/groovy/blob/91c04014/src/test/groovy/EscapedUnicodeTest.groovy
----------------------------------------------------------------------
diff --git a/src/test/groovy/EscapedUnicodeTest.groovy b/src/test/groovy/EscapedUnicodeTest.groovy
index b3826f1..a463218 100644
--- a/src/test/groovy/EscapedUnicodeTest.groovy
+++ b/src/test/groovy/EscapedUnicodeTest.groovy
@@ -16,6 +16,13 @@
* specific language governing permissions and limitations
* under the License.
*/
+package groovy
+
+class EscapedUnicodeTest extends GroovyTestCase {
+ void testNothing() {}
+}
+
+/*
\u0063\u006c\u0061\u0073\u0073\u0020\u0045\u0073\u0063\u0061\u0070\u0065\u0064\u0055\u006e\u0069\u0063\u006f\u0064\u0065\u0054\u0065\u0073\u0074\u0020\u0065\u0078\u0074\u0065\u006e\u0064\u0073\u0020\u0047\u0072\u006f\u006f\u0076\u0079\u0054\u0065\u0073\u0074\u0043\u0061\u0073\u0065\u0020\u007b
\u0020\u0020\u0020\u0020\u0076\u006f\u0069\u0064\u0020\u0074\u0065\u0073\u0074\u0041\u0073\u0073\u0065\u0072\u0074\u0028\u0029\u0020\u007b
@@ -42,3 +49,5 @@
\u0020\u0020\u0020\u0020\u007d
\u0009\u0020\u0020\u0020\u0020
\u007d
+*/
+