This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/master by this push:
new b50739745c GROOVY-11568: try
`invokeMethod(Class,Object,Object[],boolean,boolean)`
b50739745c is described below
commit b50739745c19b7ab556cb2b5da94a73a74377076
Author: Eric Milles <[email protected]>
AuthorDate: Sun Feb 16 20:25:26 2025 -0600
GROOVY-11568: try `invokeMethod(Class,Object,Object[],boolean,boolean)`
---
src/main/java/groovy/lang/MetaClassImpl.java | 33 +++++++----
.../groovy/runtime/metaclass/ClosureMetaClass.java | 2 +-
.../v8/IndyGuardsFiltersAndSignatures.java | 66 ++++++++++-----------
.../org/codehaus/groovy/vmplugin/v8/Selector.java | 26 +++++++--
src/spec/test/builder/NodeBuilderTest.groovy | 7 ++-
src/test/groovy/bugs/Groovy11568.groovy | 67 ++++++++++++++++++++++
src/test/groovy/lang/MixinTest.groovy | 3 +-
.../groovy/groovy/xml/MarkupBuilderTest.groovy | 32 +++++------
8 files changed, 165 insertions(+), 71 deletions(-)
diff --git a/src/main/java/groovy/lang/MetaClassImpl.java
b/src/main/java/groovy/lang/MetaClassImpl.java
index 6908e3b6f2..495639eac8 100644
--- a/src/main/java/groovy/lang/MetaClassImpl.java
+++ b/src/main/java/groovy/lang/MetaClassImpl.java
@@ -324,9 +324,7 @@ public class MetaClassImpl implements MetaClass,
MutableMetaClass {
}
/**
- * Returns the class this object this is the metaclass of.
- *
- * @return The class contained by this metaclass
+ * Returns the class this metaclass represents.
*/
@Override
public Class getTheClass() {
@@ -334,14 +332,19 @@ public class MetaClassImpl implements MetaClass,
MutableMetaClass {
}
/**
- * Return whether the class represented by this metaclass instance is an
instance of the GroovyObject class
- *
- * @return true if this is a groovy class, false otherwise.
+ * Indicates if the represented class is an instance of the {@link
GroovyObject} class.
*/
public boolean isGroovyObject() {
return isGroovyObject;
}
+ /**
+ * Indicates if the represented class comes from a Groovy closure or
lambda expression.
+ */
+ private boolean isGroovyFunctor() {
+ return GeneratedClosure.class.isAssignableFrom(theClass);
+ }
+
private void fillMethodIndex() {
mainClassMethodHeader = metaMethodIndex.getHeader(theClass);
@@ -671,7 +674,10 @@ public class MetaClassImpl implements MetaClass,
MutableMetaClass {
private Object getMethods(final Class<?> sender, final String name, final
boolean isCallToSuper) {
Object answer;
- final MetaMethodIndex.Cache entry = metaMethodIndex.getMethods(sender,
name);
+ var entry = metaMethodIndex.getMethods( sender , name);
+ if (entry == null && !isGroovyFunctor()) {
+ entry = metaMethodIndex.getMethods(theClass, name);
+ }
if (entry == null) {
answer = FastArray.EMPTY_LIST;
} else if (isCallToSuper) {
@@ -1086,7 +1092,7 @@ public class MetaClassImpl implements MetaClass,
MutableMetaClass {
throw new NullPointerException("Cannot invoke method: " +
methodName + " on null object");
}
- final Object[] arguments = originalArguments == null ? EMPTY_ARGUMENTS
: originalArguments;
+ final Object[] arguments =
Optional.ofNullable(originalArguments).orElse(EMPTY_ARGUMENTS);
MetaMethod method = getMetaMethod(sender, object, methodName,
isCallToSuper, arguments);
@@ -1237,9 +1243,9 @@ public class MetaClassImpl implements MetaClass,
MutableMetaClass {
method = getMethodWithCaching(sender, methodName, arguments,
isCallToSuper);
}
MetaClassHelper.unwrap(arguments);
-
- if (method == null)
+ if (method == null) {
method = tryListParamMetaMethod(sender, methodName, isCallToSuper,
arguments);
+ }
return method;
}
@@ -1330,6 +1336,9 @@ public class MetaClassImpl implements MetaClass,
MutableMetaClass {
: (isCallToSuper && e.methodsForSuper == null)) { //
allow "super.name()" to find DGM if class declares method "name"
e = metaMethodIndex.getMethods(sender.getSuperclass(), methodName);
}
+ if (e == null && !isGroovyFunctor()) { // GROOVY-4322, GROOVY-11568
+ e = metaMethodIndex.getMethods(theClass, methodName);
+ }
if (e == null) {
return null;
} else if (isCallToSuper) {
@@ -2932,7 +2941,7 @@ public class MetaClassImpl implements MetaClass,
MutableMetaClass {
*/
@Override
public ClassNode getClassNode() {
- if (classNode == null &&
GroovyObject.class.isAssignableFrom(theClass)) {
+ if (classNode == null && isGroovyObject()) {
// let's try load it from the classpath
String groovyFile = theClass.getName();
int idx = groovyFile.indexOf('$');
@@ -3465,7 +3474,7 @@ public class MetaClassImpl implements MetaClass,
MutableMetaClass {
if (!GroovyCategorySupport.hasCategoryInCurrentThread() && !(this
instanceof AdaptingMetaClass)) {
Class[] params = MetaClassHelper.convertToTypeArray(args);
CallSite tempSite = site;
- if (site.getName().equals(CALL_METHOD) &&
GeneratedClosure.class.isAssignableFrom(theClass)) {
+ if (site.getName().equals(CALL_METHOD) && isGroovyFunctor()) {
// here, we want to point to a method named "doCall" instead
of "call"
// but we don't want to replace the original call site name,
otherwise
// we lose the fact that the original method name was "call"
so instead
diff --git
a/src/main/java/org/codehaus/groovy/runtime/metaclass/ClosureMetaClass.java
b/src/main/java/org/codehaus/groovy/runtime/metaclass/ClosureMetaClass.java
index 2d7332d332..479c6b20e9 100644
--- a/src/main/java/org/codehaus/groovy/runtime/metaclass/ClosureMetaClass.java
+++ b/src/main/java/org/codehaus/groovy/runtime/metaclass/ClosureMetaClass.java
@@ -365,7 +365,7 @@ public final class ClosureMetaClass extends MetaClassImpl {
}
Class thisType = sender;
while (GeneratedClosure.class.isAssignableFrom(thisType)) thisType =
thisType.getEnclosingClass();
- if (thisType != sender && thisType != object.getClass() &&
thisType.isInstance(object)) { // GROOVY-2433, GROOVY-11128
+ if (thisType != object.getClass() && thisType.isInstance(object)) { //
GROOVY-2433, GROOVY-11128
try {
return ((GroovyObject)
object).getMetaClass().invokeMethod(thisType, object, methodName, arguments,
false, true);
} catch (GroovyRuntimeException gre) {
diff --git
a/src/main/java/org/codehaus/groovy/vmplugin/v8/IndyGuardsFiltersAndSignatures.java
b/src/main/java/org/codehaus/groovy/vmplugin/v8/IndyGuardsFiltersAndSignatures.java
index db2d6307bc..a992f38c21 100644
---
a/src/main/java/org/codehaus/groovy/vmplugin/v8/IndyGuardsFiltersAndSignatures.java
+++
b/src/main/java/org/codehaus/groovy/vmplugin/v8/IndyGuardsFiltersAndSignatures.java
@@ -56,15 +56,14 @@ public class IndyGuardsFiltersAndSignatures {
private static final MethodType
OBJECT_FILTER = MethodType.methodType(Object.class, Object.class),
- OBJECT_GUARD = MethodType.methodType(boolean.class, Object.class),
- INVOKER = MethodType.methodType(Object.class, Object.class,
String.class, Object[].class);
+ OBJECT_GUARD = MethodType.methodType(boolean.class, Object.class);
protected static final MethodHandle
SAME_CLASS, SAME_CLASSES, SAME_MC, IS_NULL, NON_NULL,
UNWRAP_METHOD, UNWRAP_EXCEPTION,
HAS_CATEGORY_IN_CURRENT_THREAD_GUARD,
- META_METHOD_INVOKER, GROOVY_OBJECT_INVOKER,
GROOVY_OBJECT_GET_PROPERTY,
- META_CLASS_INVOKE_STATIC_METHOD,
+ GROOVY_OBJECT_INVOKER,
GROOVY_OBJECT_GET_PROPERTY,META_METHOD_INVOKER,
+ META_CLASS_INVOKE_METHOD, META_CLASS_INVOKE_STATIC_METHOD,
BEAN_CONSTRUCTOR_PROPERTY_SETTER,
META_PROPERTY_GETTER,
SLOW_META_CLASS_FIND,
@@ -78,35 +77,36 @@ public class IndyGuardsFiltersAndSignatures {
static {
try {
- SAME_CLASS =
LOOKUP.findStatic(IndyGuardsFiltersAndSignatures.class, "sameClass",
MethodType.methodType(boolean.class, Class.class, Object.class));
- SAME_CLASSES =
LOOKUP.findStatic(IndyGuardsFiltersAndSignatures.class, "sameClasses",
MethodType.methodType(boolean.class, Class[].class, Object[].class));
- SAME_MC = LOOKUP.findStatic(IndyGuardsFiltersAndSignatures.class,
"isSameMetaClass", MethodType.methodType(boolean.class, MetaClass.class,
Object.class));
- IS_NULL = LOOKUP.findStatic(IndyGuardsFiltersAndSignatures.class,
"isNull", OBJECT_GUARD);
- NON_NULL = LOOKUP.findStatic(Objects.class, "nonNull",
MethodType.methodType(boolean.class, Object.class));
- UNWRAP_METHOD =
LOOKUP.findStatic(IndyGuardsFiltersAndSignatures.class, "unwrap",
OBJECT_FILTER);
- UNWRAP_EXCEPTION =
LOOKUP.findStatic(IndyGuardsFiltersAndSignatures.class, "unwrap",
MethodType.methodType(Object.class, GroovyRuntimeException.class));
- HAS_CATEGORY_IN_CURRENT_THREAD_GUARD =
LOOKUP.findStatic(GroovyCategorySupport.class, "hasCategoryInCurrentThread",
MethodType.methodType(boolean.class));
- META_METHOD_INVOKER = LOOKUP.findVirtual(MetaMethod.class,
"doMethodInvoke", MethodType.methodType(Object.class, Object.class,
Object[].class));
- GROOVY_OBJECT_INVOKER =
LOOKUP.findStatic(IndyGuardsFiltersAndSignatures.class,
"invokeGroovyObjectInvoker", INVOKER.insertParameterTypes(0,
MissingMethodException.class));
- GROOVY_OBJECT_GET_PROPERTY =
LOOKUP.findVirtual(GroovyObject.class, "getProperty",
MethodType.methodType(Object.class, String.class));
- META_CLASS_INVOKE_STATIC_METHOD =
LOOKUP.findVirtual(MetaObjectProtocol.class, "invokeStaticMethod", INVOKER);
- BEAN_CONSTRUCTOR_PROPERTY_SETTER =
LOOKUP.findStatic(IndyGuardsFiltersAndSignatures.class, "setBeanProperties",
MethodType.methodType(Object.class, MetaClass.class, Object.class, Map.class));
- META_PROPERTY_GETTER = LOOKUP.findVirtual(MetaProperty.class,
"getProperty", OBJECT_FILTER);
- SLOW_META_CLASS_FIND = LOOKUP.findStatic(InvokerHelper.class,
"getMetaClass", MethodType.methodType(MetaClass.class, Object.class));
- MOP_GET = LOOKUP.findVirtual(MetaObjectProtocol.class,
"getProperty", MethodType.methodType(Object.class, Object.class, String.class));
- MOP_INVOKE_CONSTRUCTOR =
LOOKUP.findVirtual(MetaObjectProtocol.class, "invokeConstructor",
MethodType.methodType(Object.class, Object[].class));
- MOP_INVOKE_METHOD = LOOKUP.findVirtual(MetaObjectProtocol.class,
"invokeMethod", INVOKER);
- INTERCEPTABLE_INVOKER = LOOKUP.findVirtual(GroovyObject.class,
"invokeMethod", MethodType.methodType(Object.class, String.class,
Object.class));
-
- BOOLEAN_IDENTITY = MethodHandles.identity(Boolean.class);
- CLASS_FOR_NAME = LOOKUP.findStatic(Class.class, "forName",
MethodType.methodType(Class.class, String.class, boolean.class,
ClassLoader.class));
- DTT_CAST_TO_TYPE =
LOOKUP.findStatic(DefaultTypeTransformation.class, "castToType",
MethodType.methodType(Object.class, Object.class, Class.class));
- SAM_CONVERSION = LOOKUP.findStatic(CachedSAMClass.class,
"coerceToSAM", MethodType.methodType(Object.class, Closure.class, Method.class,
Class.class));
- HASHSET_CONSTRUCTOR = LOOKUP.findConstructor(HashSet.class,
MethodType.methodType(void.class, Collection.class));
- ARRAYLIST_CONSTRUCTOR = LOOKUP.findConstructor(ArrayList.class,
MethodType.methodType(void.class, Collection.class));
- GROOVY_CAST_EXCEPTION =
LOOKUP.findConstructor(GroovyCastException.class,
MethodType.methodType(void.class, Object.class, Class.class));
-
- EQUALS = LOOKUP.findVirtual(Object.class, "equals", OBJECT_GUARD);
+ SAME_CLASS = LOOKUP.findStatic
(IndyGuardsFiltersAndSignatures.class, "sameClass",
MethodType.methodType(boolean.class, Class.class, Object.class));
+ SAME_CLASSES = LOOKUP.findStatic
(IndyGuardsFiltersAndSignatures.class, "sameClasses",
MethodType.methodType(boolean.class, Class[].class, Object[].class));
+ SAME_MC = LOOKUP.findStatic
(IndyGuardsFiltersAndSignatures.class, "isSameMetaClass",
MethodType.methodType(boolean.class, MetaClass.class, Object.class));
+ IS_NULL = LOOKUP.findStatic
(IndyGuardsFiltersAndSignatures.class, "isNull", OBJECT_GUARD);
+ NON_NULL = LOOKUP.findStatic
(Objects.class, "nonNull", MethodType.methodType(boolean.class, Object.class));
+ UNWRAP_METHOD = LOOKUP.findStatic
(IndyGuardsFiltersAndSignatures.class, "unwrap", OBJECT_FILTER);
+ UNWRAP_EXCEPTION = LOOKUP.findStatic
(IndyGuardsFiltersAndSignatures.class, "unwrap",
MethodType.methodType(Object.class, GroovyRuntimeException.class));
+ HAS_CATEGORY_IN_CURRENT_THREAD_GUARD = LOOKUP.findStatic
(GroovyCategorySupport.class, "hasCategoryInCurrentThread",
MethodType.methodType(boolean.class));
+ GROOVY_OBJECT_INVOKER = LOOKUP.findStatic
(IndyGuardsFiltersAndSignatures.class, "invokeGroovyObjectInvoker",
MethodType.methodType(Object.class, MissingMethodException.class, Object.class,
String.class, Object[].class));
+ GROOVY_OBJECT_GET_PROPERTY =
LOOKUP.findVirtual(GroovyObject.class, "getProperty",
MethodType.methodType(Object.class, String.class));
+ META_METHOD_INVOKER =
LOOKUP.findVirtual(MetaMethod.class, "doMethodInvoke",
MethodType.methodType(Object.class, Object.class, Object[].class));
+ META_CLASS_INVOKE_METHOD =
LOOKUP.findVirtual(MetaClass.class, "invokeMethod",
MethodType.methodType(Object.class, Class.class, Object.class, String.class,
Object[].class, boolean.class, boolean.class));
+ META_CLASS_INVOKE_STATIC_METHOD =
LOOKUP.findVirtual(MetaObjectProtocol.class, "invokeStaticMethod",
MethodType.methodType(Object.class, Object.class, String.class,
Object[].class));
+ BEAN_CONSTRUCTOR_PROPERTY_SETTER = LOOKUP.findStatic
(IndyGuardsFiltersAndSignatures.class, "setBeanProperties",
MethodType.methodType(Object.class, MetaClass.class, Object.class, Map.class));
+ META_PROPERTY_GETTER =
LOOKUP.findVirtual(MetaProperty.class, "getProperty", OBJECT_FILTER);
+ SLOW_META_CLASS_FIND = LOOKUP.findStatic
(InvokerHelper.class, "getMetaClass", MethodType.methodType(MetaClass.class,
Object.class));
+ MOP_GET =
LOOKUP.findVirtual(MetaObjectProtocol.class, "getProperty",
MethodType.methodType(Object.class, Object.class, String.class));
+ MOP_INVOKE_CONSTRUCTOR =
LOOKUP.findVirtual(MetaObjectProtocol.class, "invokeConstructor",
MethodType.methodType(Object.class, Object[].class));
+ MOP_INVOKE_METHOD =
LOOKUP.findVirtual(MetaObjectProtocol.class, "invokeMethod",
MethodType.methodType(Object.class, Object.class, String.class,
Object[].class));
+ INTERCEPTABLE_INVOKER =
LOOKUP.findVirtual(GroovyObject.class, "invokeMethod",
MethodType.methodType(Object.class, String.class, Object.class));
+
+ BOOLEAN_IDENTITY =
MethodHandles.identity(Boolean.class);
+ CLASS_FOR_NAME =
LOOKUP.findStatic(Class.class, "forName", MethodType.methodType(Class.class,
String.class, boolean.class, ClassLoader.class));
+ DTT_CAST_TO_TYPE =
LOOKUP.findStatic(DefaultTypeTransformation.class, "castToType",
MethodType.methodType(Object.class, Object.class, Class.class));
+ SAM_CONVERSION =
LOOKUP.findStatic(CachedSAMClass.class, "coerceToSAM",
MethodType.methodType(Object.class, Closure.class, Method.class, Class.class));
+ HASHSET_CONSTRUCTOR =
LOOKUP.findConstructor(HashSet.class, MethodType.methodType(void.class,
Collection.class));
+ ARRAYLIST_CONSTRUCTOR =
LOOKUP.findConstructor(ArrayList.class, MethodType.methodType(void.class,
Collection.class));
+ GROOVY_CAST_EXCEPTION =
LOOKUP.findConstructor(GroovyCastException.class,
MethodType.methodType(void.class, Object.class, Class.class));
+
+ EQUALS =
LOOKUP.findVirtual(Object.class, "equals", OBJECT_GUARD);
} catch (Exception e) {
throw new GroovyBugError(e);
}
diff --git a/src/main/java/org/codehaus/groovy/vmplugin/v8/Selector.java
b/src/main/java/org/codehaus/groovy/vmplugin/v8/Selector.java
index b9da452a7e..be586fdff0 100644
--- a/src/main/java/org/codehaus/groovy/vmplugin/v8/Selector.java
+++ b/src/main/java/org/codehaus/groovy/vmplugin/v8/Selector.java
@@ -79,6 +79,7 @@ import static
org.codehaus.groovy.vmplugin.v8.IndyGuardsFiltersAndSignatures.HAS
import static
org.codehaus.groovy.vmplugin.v8.IndyGuardsFiltersAndSignatures.HAS_CATEGORY_IN_CURRENT_THREAD_GUARD;
import static
org.codehaus.groovy.vmplugin.v8.IndyGuardsFiltersAndSignatures.INTERCEPTABLE_INVOKER;
import static
org.codehaus.groovy.vmplugin.v8.IndyGuardsFiltersAndSignatures.IS_NULL;
+import static
org.codehaus.groovy.vmplugin.v8.IndyGuardsFiltersAndSignatures.META_CLASS_INVOKE_METHOD;
import static
org.codehaus.groovy.vmplugin.v8.IndyGuardsFiltersAndSignatures.META_CLASS_INVOKE_STATIC_METHOD;
import static
org.codehaus.groovy.vmplugin.v8.IndyGuardsFiltersAndSignatures.META_METHOD_INVOKER;
import static
org.codehaus.groovy.vmplugin.v8.IndyGuardsFiltersAndSignatures.META_PROPERTY_GETTER;
@@ -727,6 +728,13 @@ public abstract class Selector {
return targetType;
}
+ private Method metaClassMethod(String name, Class<?>... signature) {
+ try { return mc.getClass().getMethod(name, signature);
+ } catch (ReflectiveOperationException e) {
+ throw new GroovyBugError(e);
+ }
+ }
+
/**
* Creates a MethodHandle, which will use the metaclass path.
* This method is called only if no handle has been created before.
This
@@ -741,9 +749,19 @@ public abstract class Selector {
handle = META_CLASS_INVOKE_STATIC_METHOD.bindTo(mc);
if (LOG_ENABLED) LOG.info("use invokeStaticMethod with bound
meta class");
} else {
- handle = MOP_INVOKE_METHOD.bindTo(mc);
- if (LOG_ENABLED) LOG.info("use invokeMethod with bound meta
class");
-
+ if (standardMetaClass
+ || metaClassMethod("invokeMethod", Object.class,
String.class, Object[].class).getDeclaringClass().isAssignableFrom(
+ metaClassMethod("invokeMethod", Class.class,
Object.class, String.class, Object[].class, boolean.class,
boolean.class).getDeclaringClass())
+ ) {
+ // GROOVY-11568: use
MetaClass#invokeMethod(Class,Object,Object[],boolean,boolean)
+ handle = META_CLASS_INVOKE_METHOD;
+ handle = handle.bindTo(mc).bindTo(sender);
+ handle = MethodHandles.insertArguments(handle, 3,
Boolean.FALSE, Boolean.FALSE);
+ if (LOG_ENABLED) LOG.info("use invokeMethod with bound
meta class and sender class");
+ } else {
+ handle = MOP_INVOKE_METHOD.bindTo(mc);
+ if (LOG_ENABLED) LOG.info("use invokeMethod with bound
meta class");
+ }
if (receiver instanceof GroovyObject) {
// if the metaclass call fails we may still want to fall
back to call
// GroovyObject#invokeMethod if the receiver is a
GroovyObject
@@ -1011,7 +1029,7 @@ public abstract class Selector {
}
/**
- * Sets a handle to call {@link
GroovyInterceptable#invokeMethod(String, Object)}
+ * Sets a handle to call {@link
GroovyObject#invokeMethod(String,Object)}
*/
public boolean setInterceptor() {
if (!(args[0] instanceof GroovyInterceptable)) return false;
diff --git a/src/spec/test/builder/NodeBuilderTest.groovy
b/src/spec/test/builder/NodeBuilderTest.groovy
index 9871e1e393..82034d0d89 100644
--- a/src/spec/test/builder/NodeBuilderTest.groovy
+++ b/src/spec/test/builder/NodeBuilderTest.groovy
@@ -18,10 +18,11 @@
*/
package builder
-import groovy.test.GroovyTestCase
+import org.junit.jupiter.api.Test
-class NodeBuilderTest extends GroovyTestCase {
+final class NodeBuilderTest {
+ @Test
void testNodeBuilder() {
// tag::node_builder_example[]
def nodeBuilder = new NodeBuilder()
@@ -41,6 +42,7 @@ class NodeBuilderTest extends GroovyTestCase {
}
// GROOVY-7044
+ @Test
void testNodeCloning() {
def node = new NodeBuilder().a {
b()
@@ -53,6 +55,7 @@ class NodeBuilderTest extends GroovyTestCase {
}
// GROOVY-7044
+ @Test
void testNodeCloningWithAttributes() {
def node = new NodeBuilder().a(foo: 'bar') {
b()
diff --git a/src/test/groovy/bugs/Groovy11568.groovy
b/src/test/groovy/bugs/Groovy11568.groovy
new file mode 100644
index 0000000000..a9b9405c5e
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy11568.groovy
@@ -0,0 +1,67 @@
+/*
+ * 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 groovy.bugs
+
+import org.junit.jupiter.api.Test
+
+import static groovy.test.GroovyAssert.assertScript
+
+final class Groovy11568 {
+ @Test
+ void testPrivateMethodWithCustomMetaClass() {
+ assertScript '''
+ class CMC extends MetaClassImpl {
+ CMC(Class theClass) {
+ super(theClass)
+ }
+ @Override
+ Object invokeMethod(Object object, String methodName, Object
arguments) {
+ super.invokeMethod(object, methodName, arguments)
+ }
+ @Override
+ Object invokeMethod(Object object, String methodName, Object[]
originalArguments) {
+ super.invokeMethod(object, methodName, originalArguments)
+ }
+ @Override
+ Object invokeMethod(Class sender, Object object, String
methodName, Object[] arguments, boolean isCallToSuper, boolean fromInsideClass)
{
+ super.invokeMethod(sender, object, methodName, arguments,
isCallToSuper, fromInsideClass)
+ }
+ }
+
+ class C {
+ def publicMethod() {
+ privateMethod()
+ }
+ private privateMethod() {
+ 'C#privateMethod()'
+ }
+ }
+
+ class D extends C {
+ }
+
+ def cmc = new CMC(D.class)
+ cmc.initialize()
+ def obj = new D()
+ obj.setMetaClass(cmc)
+ def str = obj.publicMethod()
+ assert str == 'C#privateMethod()'
+ '''
+ }
+}
diff --git a/src/test/groovy/lang/MixinTest.groovy
b/src/test/groovy/lang/MixinTest.groovy
index 8d27dc51d9..3694da2252 100644
--- a/src/test/groovy/lang/MixinTest.groovy
+++ b/src/test/groovy/lang/MixinTest.groovy
@@ -306,9 +306,8 @@ class MixinTest extends GroovyTestCase {
u << 2
assertEquals 6, u.size()
- assertEquals 6, ((List) u).size()
assertEquals 6, ((Collection) u).size()
- assertEquals 2, u.mixedIn[Set].size()
+ assertEquals 6, ((List) u).size()
assertEquals 2, ((Set) u).size()
}
diff --git
a/subprojects/groovy-xml/src/test/groovy/groovy/xml/MarkupBuilderTest.groovy
b/subprojects/groovy-xml/src/test/groovy/groovy/xml/MarkupBuilderTest.groovy
index 916ba581ab..b943bc5457 100644
--- a/subprojects/groovy-xml/src/test/groovy/groovy/xml/MarkupBuilderTest.groovy
+++ b/subprojects/groovy-xml/src/test/groovy/groovy/xml/MarkupBuilderTest.groovy
@@ -23,7 +23,7 @@ package groovy.xml
* to MarkupBuilder. Functionality in common with StreamingMarkupBuilder
* is tested in the BuilderTestSupport parent class.
*/
-class MarkupBuilderTest extends BuilderTestSupport {
+final class MarkupBuilderTest extends BuilderTestSupport {
private StringWriter writer
private MarkupBuilder xml
@@ -238,18 +238,19 @@ class MarkupBuilderTest extends BuilderTestSupport {
assertExpectedXmlDefault "<element />"
}
+ // GROOVY-4322
void testDelegateOnlyToSkipInternalClosureMethods() {
def items = {
- pizza(price: 8.5)
- curry(price: 8)
+ pizza (price: 8.5)
+ curry (price: 8 )
burger(price: 7.5)
}
items.resolveStrategy = Closure.DELEGATE_ONLY
xml.menu(items)
assertExpectedXmlDefault '''
<menu>
- <pizza price='8.5' />
- <curry price='8' />
+ <pizza price='8.5' />
+ <curry price='8' />
<burger price='7.5' />
</menu>
'''
@@ -278,29 +279,22 @@ class MarkupBuilderTest extends BuilderTestSupport {
}
void testEscapingOfAttributes() {
- def writer = new StringWriter()
- def builder = new groovy.xml.MarkupBuilder(writer)
- builder.a(href: "http://www.example.com?foo=1&bar=2")
+ xml.a(href: 'http://www.example.com?foo=1&bar=2')
assert
writer.toString().contains('http://www.example.com?foo=1&bar=2')
}
void testNoEscapingOfAttributes() {
- def writer = new StringWriter()
- def builder = new groovy.xml.MarkupBuilder(writer)
- builder.escapeAttributes = false
- builder.a(href: "http://www.example.com?foo=1&bar=2")
+ xml.escapeAttributes = false
+ xml.a(href: 'http://www.example.com?foo=1&bar=2')
assert writer.toString().contains('http://www.example.com?foo=1&bar=2')
}
- private myMethod(x) {
- x.value='call to outside'
- return x
- }
-
+ @Override
protected assertExpectedXml(Closure markup, String expectedXml) {
assertExpectedXml markup, null, expectedXml
}
+ @Override
protected assertExpectedXml(Closure markup, Closure configureBuilder,
String expectedXml) {
def writer = new StringWriter()
def builder = new MarkupBuilder(writer)
@@ -310,4 +304,8 @@ class MarkupBuilderTest extends BuilderTestSupport {
checkXml(expectedXml, writer)
}
+ private myMethod(x) {
+ x.value = 'call to outside'
+ x
+ }
}