Skip to content
Permalink
Browse files
GROOVY-10558: no spread for one argument in inner class methodMissing
  • Loading branch information
eric-milles committed Apr 1, 2022
1 parent 8e1ffe6 commit 5260908f348fd867301dbcef3bb6f3ed7a476edf
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 32 deletions.
@@ -34,58 +34,51 @@
import java.util.ArrayList;
import java.util.List;

import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
import static org.codehaus.groovy.ast.tools.GeneralUtils.assignS;
import static org.codehaus.groovy.ast.tools.GeneralUtils.assignX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.castX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.eqX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.fieldX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.ifS;
import static org.codehaus.groovy.ast.tools.GeneralUtils.indexX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.isInstanceOfX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.notX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.propX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS;
import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
import static org.codehaus.groovy.ast.ClassHelper.isObjectType;

public abstract class InnerClassVisitorHelper extends ClassCodeVisitorSupport {

private static final ClassNode OBJECT_ARRAY = ClassHelper.OBJECT_TYPE.makeArray();

protected static void addFieldInit(final Parameter p, final FieldNode fn, final BlockStatement block) {
block.addStatement(assignS(fieldX(fn), varX(p)));
}

protected static void setPropertyGetterDispatcher(final BlockStatement block, final Expression target, final Parameter[] parameters) {
block.addStatement(
returnS(
propX(
target,
dynName(parameters[0])
)
)
);
block.addStatement(returnS(propX(target, dynName(parameters[0]))));
}

protected static void setPropertySetterDispatcher(final BlockStatement block, final Expression target, final Parameter[] parameters) {
block.addStatement(
stmt(
assignX(
propX(
target,
dynName(parameters[0])
),
varX(parameters[1])
)
)
);
block.addStatement(stmt(assignX(propX(target, dynName(parameters[0])), varX(parameters[1]))));
}

protected static void setMethodDispatcherCode(final BlockStatement block, final Expression target, final Parameter[] parameters) {
block.addStatement(
returnS(
callX(
target,
dynName(parameters[0]),
args(new SpreadExpression(varX(parameters[1])))
)
)
);
protected static void setMethodDispatcherCode (final BlockStatement block, final Expression target, final Parameter[] parameters) {
// if (!(args instanceof Object[])) return target."$name"(args)
block.addStatement(ifS(
notX(isInstanceOfX(varX(parameters[1]), OBJECT_ARRAY)),
returnS(callX(target, dynName(parameters[0]), varX(parameters[1])))));

// if (((Object[])args).length == 1) return target."$name"(args[0])
block.addStatement(ifS(
eqX(propX(castX(OBJECT_ARRAY, varX(parameters[1])), "length"), constX(1, true)),
returnS(callX(target, dynName(parameters[0]), indexX(castX(OBJECT_ARRAY, varX(parameters[1])), constX(0, true))))));

// return target."$name"(*args)
block.addStatement(returnS(callX(target, dynName(parameters[0]), new SpreadExpression(varX(parameters[1])))));
}

private static Expression dynName(final Parameter p) {
@@ -109,7 +102,7 @@ protected static ClassNode getClassNode(final ClassNode cn, final boolean isStat

protected static int getObjectDistance(ClassNode cn) {
int count = 0;
while (cn != null && !isObjectType(cn)) {
while (cn != null && !ClassHelper.isObjectType(cn)) {
cn = cn.getSuperClass();
count += 1;
}
@@ -1010,6 +1010,27 @@ final class InnerClassTest {
'''
}

@Test // GROOVY-10558
void testUsageOfOuterMethod6() {
assertScript '''
class Outer {
static byte[] hash(byte[] bytes) {
bytes
}
static class Inner {
def test(byte[] bytes) {
hash(bytes)
}
}
}
Object result = new Outer.Inner().test(new byte[1])
assert result instanceof byte[]
assert result.length == 1
assert result[0] == 0
'''
}

@Test
void testUsageOfOuterMethodOverridden() {
assertScript '''

0 comments on commit 5260908

Please sign in to comment.