aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvgeny Mandrikov <138671+Godin@users.noreply.github.com>2019-03-04 23:01:39 +0100
committerMarc R. Hoffmann <hoffmann@mountainminds.com>2019-03-04 23:01:39 +0100
commitc30eb290f7958dce50c072527fbe6234e8388dd2 (patch)
treedade3590649d0462bf9ace8b86628fcdbfd72c4f
parent5f46dcf8c7ed2c7646daa76389201b404250b1fc (diff)
downloadplatform_external_jacoco-c30eb290f7958dce50c072527fbe6234e8388dd2.tar.gz
platform_external_jacoco-c30eb290f7958dce50c072527fbe6234e8388dd2.tar.bz2
platform_external_jacoco-c30eb290f7958dce50c072527fbe6234e8388dd2.zip
Update KotlinCoroutineFilter for Kotlin 1.3.30 (#849)
-rw-r--r--org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilterTest.java86
-rw-r--r--org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilter.java34
-rw-r--r--org.jacoco.doc/docroot/doc/changes.html8
3 files changed, 114 insertions, 14 deletions
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilterTest.java
index 40b04c3f..b5b06743 100644
--- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilterTest.java
+++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilterTest.java
@@ -24,6 +24,92 @@ public class KotlinCoroutineFilterTest extends FilterTestBase {
private final IFilter filter = new KotlinCoroutineFilter();
+ @Test
+ public void should_filter_suspending_lambdas_generated_by_Kotlin_1_3_30() {
+ final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
+ "invokeSuspend", "(Ljava/lang/Object;)Ljava/lang/Object;", null,
+ null);
+ context.classAnnotations
+ .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC);
+
+ m.visitLabel(new Label());
+ final Range range1 = new Range();
+ range1.fromInclusive = m.instructions.getLast();
+ m.visitMethodInsn(Opcodes.INVOKESTATIC,
+ "kotlin/coroutines/intrinsics/IntrinsicsKt",
+ "getCOROUTINE_SUSPENDED", "()Ljava/lang/Object;", false);
+ m.visitVarInsn(Opcodes.ASTORE, 4);
+
+ m.visitVarInsn(Opcodes.ALOAD, 0);
+ // line of "runBlocking"
+ m.visitFieldInsn(Opcodes.GETFIELD, "Target", "label", "I");
+ final Label dflt = new Label();
+ final Label state0 = new Label();
+ final Label state1 = new Label();
+ m.visitTableSwitchInsn(0, 1, dflt, state0, state1);
+
+ m.visitLabel(state0);
+
+ {
+ m.visitVarInsn(Opcodes.ALOAD, 1);
+ m.visitMethodInsn(Opcodes.INVOKESTATIC, "kotlin/ResultKt",
+ "throwOnFailure", "", false);
+ range1.toInclusive = m.instructions.getLast();
+ }
+
+ // line before "suspendingFunction"
+ m.visitInsn(Opcodes.NOP);
+
+ // line of "suspendingFunction"
+ m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "", "suspendingFunction",
+ "(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", false);
+
+ m.visitInsn(Opcodes.DUP);
+ final Range range2 = new Range();
+ range2.fromInclusive = m.instructions.getLast();
+ m.visitVarInsn(Opcodes.ALOAD, 4);
+ final Label continuationLabelAfterLoadedResult = new Label();
+ m.visitJumpInsn(Opcodes.IF_ACMPNE, continuationLabelAfterLoadedResult);
+ // line of "runBlocking"
+ m.visitVarInsn(Opcodes.ALOAD, 4);
+ m.visitInsn(Opcodes.ARETURN);
+
+ m.visitLabel(state1);
+
+ m.visitVarInsn(Opcodes.ALOAD, 0);
+ m.visitFieldInsn(Opcodes.GETFIELD, "Target", "I$0", "I");
+ m.visitVarInsn(Opcodes.ISTORE, 3);
+
+ {
+ m.visitVarInsn(Opcodes.ALOAD, 1);
+ m.visitMethodInsn(Opcodes.INVOKESTATIC, "kotlin/ResultKt",
+ "throwOnFailure", "", false);
+ }
+ m.visitVarInsn(Opcodes.ALOAD, 1);
+ range2.toInclusive = m.instructions.getLast();
+ m.visitLabel(continuationLabelAfterLoadedResult);
+
+ // line after "suspendingFunction"
+ m.visitInsn(Opcodes.NOP);
+ m.visitInsn(Opcodes.ARETURN);
+
+ m.visitLabel(dflt);
+ final Range range0 = new Range();
+ range0.fromInclusive = m.instructions.getLast();
+ m.visitTypeInsn(Opcodes.NEW, "java/lang/IllegalStateException");
+ m.visitInsn(Opcodes.DUP);
+ m.visitLdcInsn("call to 'resume' before 'invoke' with coroutine");
+ m.visitMethodInsn(Opcodes.INVOKESPECIAL,
+ "java/lang/IllegalStateException", "<init>",
+ "(Ljava/lang/String;)V", false);
+ m.visitInsn(Opcodes.ATHROW);
+ range0.toInclusive = m.instructions.getLast();
+
+ filter.filter(m, context, output);
+
+ assertIgnored(range0, range1, range2);
+ }
+
/**
* <pre>
* runBlocking {
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilter.java
index b1d448af..e2bed498 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilter.java
@@ -73,13 +73,7 @@ public final class KotlinCoroutineFilter implements IFilter {
s.labels.size() * 2);
nextIs(Opcodes.ALOAD);
- nextIs(Opcodes.DUP);
- nextIsType(Opcodes.INSTANCEOF, "kotlin/Result$Failure");
- nextIs(Opcodes.IFEQ);
- nextIsType(Opcodes.CHECKCAST, "kotlin/Result$Failure");
- nextIs(Opcodes.GETFIELD);
- nextIs(Opcodes.ATHROW);
- nextIs(Opcodes.POP);
+ nextIsThrowOnFailure();
if (cursor == null) {
return;
@@ -109,13 +103,7 @@ public final class KotlinCoroutineFilter implements IFilter {
for (AbstractInsnNode j = i; j != null; j = j.getNext()) {
cursor = j;
nextIs(Opcodes.ALOAD);
- nextIs(Opcodes.DUP);
- nextIsType(Opcodes.INSTANCEOF, "kotlin/Result$Failure");
- nextIs(Opcodes.IFEQ);
- nextIsType(Opcodes.CHECKCAST, "kotlin/Result$Failure");
- nextIs(Opcodes.GETFIELD);
- nextIs(Opcodes.ATHROW);
- nextIs(Opcodes.POP);
+ nextIsThrowOnFailure();
nextIs(Opcodes.ALOAD);
if (cursor != null && skipNonOpcodes(cursor
@@ -149,6 +137,24 @@ public final class KotlinCoroutineFilter implements IFilter {
}
}
+ private void nextIsThrowOnFailure() {
+ final AbstractInsnNode c = cursor;
+ nextIsInvokeStatic("kotlin/ResultKt", "throwOnFailure");
+ if (cursor == null) {
+ cursor = c;
+ // Before resolution of
+ // https://youtrack.jetbrains.com/issue/KT-28015 in
+ // Kotlin 1.3.30
+ nextIs(Opcodes.DUP);
+ nextIsType(Opcodes.INSTANCEOF, "kotlin/Result$Failure");
+ nextIs(Opcodes.IFEQ);
+ nextIsType(Opcodes.CHECKCAST, "kotlin/Result$Failure");
+ nextIs(Opcodes.GETFIELD);
+ nextIs(Opcodes.ATHROW);
+ nextIs(Opcodes.POP);
+ }
+ }
+
private void nextIsCreateStateInstance() {
nextIs(Opcodes.INSTANCEOF);
diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html
index b1c9f715..c9109e96 100644
--- a/org.jacoco.doc/docroot/doc/changes.html
+++ b/org.jacoco.doc/docroot/doc/changes.html
@@ -20,6 +20,14 @@
<h2>Snapshot Build @qualified.bundle.version@ (@build.date@)</h2>
+<h3>New Features</h3>
+
+<ul>
+ <li>Branches added by the Kotlin compiler version 1.3.30 for suspending lambdas
+ and functions are filtered out during generation of report
+ (GitHub <a href="https://github.com/jacoco/jacoco/issues/849">#849</a>).</li>
+</ul>
+
<h2>Release 0.8.3 (2019/01/23)</h2>
<h3>New Features</h3>