diff options
author | Evgeny Mandrikov <138671+Godin@users.noreply.github.com> | 2020-02-09 20:14:24 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-02-09 19:14:23 +0100 |
commit | 71f9341e088bb3347ecfea2f114e5e40bdc4326b (patch) | |
tree | 95a052f842c76f044447bceddb5f71f400253381 /org.jacoco.core.test/src | |
parent | 04fe2006c0786a96462ef7336d162e4a527759e0 (diff) | |
download | jacoco-71f9341e088bb3347ecfea2f114e5e40bdc4326b.tar.gz |
Update filter for suspending functions with tail call optimization (#1016)
Diffstat (limited to 'org.jacoco.core.test/src')
-rw-r--r-- | org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinCoroutineFilterTest.java | 76 |
1 files changed, 76 insertions, 0 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 c8ba9eb3..4f471c3c 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 @@ -374,4 +374,80 @@ public class KotlinCoroutineFilterTest extends FilterTestBase { assertIgnored(range0, range1, range2); } + /** + * <pre> + * suspend fun example(b: Boolean) { + * if (b) + * suspendingFunction() + * else + * suspendingFunction() + * } + * </pre> + */ + @Test + public void should_filter_suspending_functions_with_tail_call_optimization() { + final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0, + "example", + "(ZLkotlin/coroutines/Continuation;)Ljava/lang/Object;", null, + null); + context.classAnnotations + .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC); + + final Label exit = new Label(); + + m.visitVarInsn(Opcodes.ILOAD, 1); + final Label next = new Label(); + m.visitJumpInsn(Opcodes.IFEQ, next); + + m.visitVarInsn(Opcodes.ALOAD, 0); + m.visitVarInsn(Opcodes.ALOAD, 2); + m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "", "suspendingFunction", + "(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", false); + final Range range1 = new Range(); + { + m.visitInsn(Opcodes.DUP); + range1.fromInclusive = m.instructions.getLast(); + m.visitMethodInsn(Opcodes.INVOKESTATIC, + "kotlin/coroutines/intrinsics/IntrinsicsKt", + "getCOROUTINE_SUSPENDED", "()Ljava/lang/Object;", false); + final Label label = new Label(); + m.visitJumpInsn(Opcodes.IF_ACMPNE, label); + m.visitInsn(Opcodes.ARETURN); + m.visitLabel(label); + m.visitInsn(Opcodes.POP); + range1.toInclusive = m.instructions.getLast(); + } + + m.visitJumpInsn(Opcodes.GOTO, exit); + m.visitLabel(next); + + m.visitVarInsn(Opcodes.ALOAD, 0); + m.visitVarInsn(Opcodes.ALOAD, 2); + m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "", "suspendingFunction", + "(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", false); + final Range range2 = new Range(); + { + m.visitInsn(Opcodes.DUP); + range2.fromInclusive = m.instructions.getLast(); + m.visitMethodInsn(Opcodes.INVOKESTATIC, + "kotlin/coroutines/intrinsics/IntrinsicsKt", + "getCOROUTINE_SUSPENDED", "()Ljava/lang/Object;", false); + final Label label = new Label(); + m.visitJumpInsn(Opcodes.IF_ACMPNE, label); + m.visitInsn(Opcodes.ARETURN); + m.visitLabel(label); + m.visitInsn(Opcodes.POP); + range2.toInclusive = m.instructions.getLast(); + } + + m.visitLabel(exit); + m.visitFieldInsn(Opcodes.GETSTATIC, "kotlin/Unit", "INSTANCE", + "Lkotlin/Unit;"); + m.visitInsn(Opcodes.ARETURN); + + filter.filter(m, context, output); + + assertIgnored(range1, range2); + } + } |