aboutsummaryrefslogtreecommitdiff
path: root/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultArgumentsFilter.java
diff options
context:
space:
mode:
Diffstat (limited to 'org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultArgumentsFilter.java')
-rw-r--r--org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultArgumentsFilter.java37
1 files changed, 26 insertions, 11 deletions
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultArgumentsFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultArgumentsFilter.java
index 34f9562c..a7a05cf7 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultArgumentsFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinDefaultArgumentsFilter.java
@@ -38,14 +38,28 @@ import org.objectweb.asm.tree.VarInsnNode;
* </pre>
*
* Where <code>maskVar</code> is penultimate argument of synthetic method with
- * suffix "$default". And its value can't be zero - invocation with all
- * arguments uses original non synthetic method, thus <code>IFEQ</code>
- * instructions should be ignored.
+ * suffix "$default" or of synthetic constructor with last argument
+ * "kotlin.jvm.internal.DefaultConstructorMarker". And its value can't be zero -
+ * invocation with all arguments uses original non synthetic method, thus
+ * <code>IFEQ</code> instructions should be ignored.
*/
public final class KotlinDefaultArgumentsFilter implements IFilter {
- static boolean isDefaultArgumentsMethodName(final String methodName) {
- return methodName.endsWith("$default");
+ static boolean isDefaultArgumentsMethod(final MethodNode methodNode) {
+ return methodNode.name.endsWith("$default");
+ }
+
+ static boolean isDefaultArgumentsConstructor(final MethodNode methodNode) {
+ if (!"<init>".equals(methodNode.name)) {
+ return false;
+ }
+ final Type[] argumentTypes = Type.getMethodType(methodNode.desc)
+ .getArgumentTypes();
+ if (argumentTypes.length < 2) {
+ return false;
+ }
+ return "kotlin.jvm.internal.DefaultConstructorMarker"
+ .equals(argumentTypes[argumentTypes.length - 1].getClassName());
}
public void filter(final MethodNode methodNode,
@@ -53,19 +67,20 @@ public final class KotlinDefaultArgumentsFilter implements IFilter {
if ((methodNode.access & Opcodes.ACC_SYNTHETIC) == 0) {
return;
}
- if (!isDefaultArgumentsMethodName(methodNode.name)) {
- return;
- }
if (!KotlinGeneratedFilter.isKotlinClass(context)) {
return;
}
- new Matcher().match(methodNode, output);
+ if (isDefaultArgumentsMethod(methodNode)) {
+ new Matcher().match(methodNode, output, false);
+ } else if (isDefaultArgumentsConstructor(methodNode)) {
+ new Matcher().match(methodNode, output, true);
+ }
}
private static class Matcher extends AbstractMatcher {
public void match(final MethodNode methodNode,
- final IFilterOutput output) {
+ final IFilterOutput output, final boolean constructor) {
cursor = methodNode.instructions.getFirst();
nextIs(Opcodes.IFNULL);
@@ -91,7 +106,7 @@ public final class KotlinDefaultArgumentsFilter implements IFilter {
final Set<AbstractInsnNode> ignore = new HashSet<AbstractInsnNode>();
final int maskVar = Type.getMethodType(methodNode.desc)
- .getArgumentTypes().length - 2;
+ .getArgumentTypes().length - (constructor ? 1 : 2);
while (true) {
if (cursor.getOpcode() != Opcodes.ILOAD) {
break;