Skip to content

Commit

Permalink
KotlinDefaultArgumentsFilter should not assume that all parameters co…
Browse files Browse the repository at this point in the history
…nsume one slot (#908)
  • Loading branch information
Godin authored and marchof committed Jul 22, 2019
1 parent 103c66f commit 07f1079
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 2 deletions.
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

0 comments on commit 07f1079

Please sign in to comment.