Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KotlinDefaultArgumentsFilter should not assume that all parameters consume one slot #908

Merged
merged 5 commits into from Jul 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -19,6 +19,9 @@ object KotlinDefaultArgumentsTarget {
private fun f(a: String = "a", b: String = "b") { // assertFullyCovered(0, 0)
}

private fun longParameter(x: Long = 0) { // assertFullyCovered()
}

private fun branch(a: Boolean, b: String = if (a) "a" else "b") { // assertFullyCovered(0, 2)
}

Expand All @@ -38,6 +41,9 @@ object KotlinDefaultArgumentsTarget {
/* next invocation doesn't use synthetic method: */
f("a", "b")

longParameter()
longParameter(1)

branch(false)
branch(true)

Expand Down
Expand Up @@ -184,4 +184,38 @@ public void should_filter_constructors() {
assertIgnored(new Range(m.instructions.get(3), m.instructions.get(3)));
}

/**
* <pre>
* data class C(val x: Long = 42)
* </pre>
*/
@Test
public void should_filter_methods_with_parameters_that_consume_two_slots() {
final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION,
Opcodes.ACC_SYNTHETIC, "<init>",
"(JILkotlin/jvm/internal/DefaultConstructorMarker;)V", null,
null);
context.classAnnotations
.add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC);

m.visitVarInsn(Opcodes.ILOAD, 3);
m.visitInsn(Opcodes.ICONST_1);
m.visitInsn(Opcodes.IAND);
final Label label = new Label();
m.visitJumpInsn(Opcodes.IFEQ, label);
// default argument
m.visitLdcInsn(Integer.valueOf(42));
m.visitVarInsn(Opcodes.ISTORE, 1);
m.visitLabel(label);
m.visitVarInsn(Opcodes.ALOAD, 0);
m.visitVarInsn(Opcodes.ILOAD, 1);
m.visitMethodInsn(Opcodes.INVOKESPECIAL, "Owner", "<init>", "(J)V",
false);
m.visitInsn(Opcodes.RETURN);

filter.filter(m, context, output);

assertIgnored(new Range(m.instructions.get(3), m.instructions.get(3)));
}

}
Expand Up @@ -105,8 +105,7 @@ public void match(final MethodNode methodNode,
}

final Set<AbstractInsnNode> ignore = new HashSet<AbstractInsnNode>();
final int maskVar = Type.getMethodType(methodNode.desc)
.getArgumentTypes().length - (constructor ? 1 : 2);
final int maskVar = maskVar(methodNode.desc, constructor);
while (true) {
if (cursor.getOpcode() != Opcodes.ILOAD) {
break;
Expand All @@ -129,6 +128,22 @@ public void match(final MethodNode methodNode,
output.ignore(i, i);
}
}

private static int maskVar(final String desc,
final boolean constructor) {
int slot = 0;
if (constructor) {
// one slot for reference to current object
slot++;
}
final Type[] argumentTypes = Type.getMethodType(desc)
.getArgumentTypes();
final int penultimateArgument = argumentTypes.length - 2;
for (int i = 0; i < penultimateArgument; i++) {
slot += argumentTypes[i].getSize();
}
return slot;
}
}

}
4 changes: 4 additions & 0 deletions org.jacoco.doc/docroot/doc/changes.html
Expand Up @@ -36,6 +36,10 @@ <h3>Fixed bugs</h3>
(GitHub <a href="https://github.com/jacoco/jacoco/issues/888">#888</a>).</li>
<li>Instrumentation should update indexes of local variables in annotations
(GitHub <a href="https://github.com/jacoco/jacoco/issues/894">#894</a>).</li>
<li>Branches added by the Kotlin compiler for functions with default arguments
and containing arguments of type <code>long</code> or <code>double</code>
should be filtered out during generation of report
(GitHub <a href="https://github.com/jacoco/jacoco/issues/908">#908</a>).</li>
</ul>

<h2>Release 0.8.4 (2019/05/08)</h2>
Expand Down