From bb96d8e1bc4b313cf5e117d2b4c953bc976d11ca Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov Date: Fri, 18 Dec 2020 10:54:08 +0100 Subject: [PATCH 1/8] (WIP) Upgrade Kotlin to 1.4.0 --- org.jacoco.core.test.validation.kotlin/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.jacoco.core.test.validation.kotlin/pom.xml b/org.jacoco.core.test.validation.kotlin/pom.xml index 7b3ef76a7b..70db682558 100644 --- a/org.jacoco.core.test.validation.kotlin/pom.xml +++ b/org.jacoco.core.test.validation.kotlin/pom.xml @@ -25,7 +25,7 @@ JaCoCo :: Test :: Core :: Validation Kotlin - 1.3.61 + 1.4.0 From ee1639976d472e71fa9ebbcf0e75120b5b7aea0a Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov Date: Fri, 18 Dec 2020 11:45:10 +0100 Subject: [PATCH 2/8] (WIP) Add unit test --- .../KotlinUnsafeCastOperatorFilterTest.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilterTest.java index 14d7c617a0..c7d67bb59e 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilterTest.java @@ -50,4 +50,26 @@ public void should_filter() { assertIgnored(new Range(expectedFrom, expectedTo)); } + @Test + public void should_filter_Kotlin_1_4() { + final Label label = new Label(); + + m.visitInsn(Opcodes.DUP); + m.visitJumpInsn(Opcodes.IFNONNULL, label); + final AbstractInsnNode expectedFrom = m.instructions.getLast(); + m.visitTypeInsn(Opcodes.NEW, "java/lang/NullPointerException"); + m.visitInsn(Opcodes.DUP); + m.visitLdcInsn("null cannot be cast to non-null type kotlin.String"); + m.visitMethodInsn(Opcodes.INVOKESPECIAL, + "java/lang/NullPointerException", "", + "(Ljava/lang/String;)V", false); + m.visitInsn(Opcodes.ATHROW); + final AbstractInsnNode expectedTo = m.instructions.getLast(); + m.visitLabel(label); + + filter.filter(m, context, output); + + assertIgnored(new Range(expectedFrom, expectedTo)); + } + } From e0d0c6854e2cf7bacbc5dc249c3f03512d12e828 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov Date: Fri, 18 Dec 2020 11:50:06 +0100 Subject: [PATCH 3/8] (WIP) Update filter --- .../filter/KotlinUnsafeCastOperatorFilter.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilter.java index 726243f60a..45246af9ae 100644 --- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilter.java +++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilter.java @@ -24,26 +24,26 @@ */ public final class KotlinUnsafeCastOperatorFilter implements IFilter { - private static final String KOTLIN_TYPE_CAST_EXCEPTION = "kotlin/TypeCastException"; - public void filter(final MethodNode methodNode, final IFilterContext context, final IFilterOutput output) { final Matcher matcher = new Matcher(); for (final AbstractInsnNode i : methodNode.instructions) { - matcher.match(i, output); + matcher.match("kotlin/TypeCastException", i, output); + // Since Kotlin 1.4.0: + matcher.match("java/lang/NullPointerException", i, output); } } private static class Matcher extends AbstractMatcher { - public void match(final AbstractInsnNode start, - final IFilterOutput output) { + public void match(final String exceptionType, + final AbstractInsnNode start, final IFilterOutput output) { if (Opcodes.IFNONNULL != start.getOpcode()) { return; } cursor = start; - nextIsType(Opcodes.NEW, KOTLIN_TYPE_CAST_EXCEPTION); + nextIsType(Opcodes.NEW, exceptionType); nextIs(Opcodes.DUP); nextIs(Opcodes.LDC); if (cursor == null) { @@ -54,8 +54,8 @@ public void match(final AbstractInsnNode start, .startsWith("null cannot be cast to non-null type"))) { return; } - nextIsInvoke(Opcodes.INVOKESPECIAL, KOTLIN_TYPE_CAST_EXCEPTION, - "", "(Ljava/lang/String;)V"); + nextIsInvoke(Opcodes.INVOKESPECIAL, exceptionType, "", + "(Ljava/lang/String;)V"); nextIs(Opcodes.ATHROW); if (cursor == null) { return; From 483c6f57d36246d0c1dd08582135abcd338e7b64 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov Date: Fri, 18 Dec 2020 12:02:43 +0100 Subject: [PATCH 4/8] (WIP) Update changelog --- org.jacoco.doc/docroot/doc/changes.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index ac047356a2..8bba0ae124 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -27,6 +27,9 @@

New Features

#1097).
  • Experimental support for Java 17 class files (GitHub #1132).
  • +
  • Branch added by the Kotlin compiler version 1.4.0 and above for "unsafe" cast + operator is filtered out during generation of report + (GitHub #1143).
  • Non-functional Changes

    From 66bac4981bc4e71c29bd16785956ae0bc8e1678d Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov Date: Mon, 21 Dec 2020 11:02:42 +0100 Subject: [PATCH 5/8] (WIP) Add unit test --- .../KotlinUnsafeCastOperatorFilterTest.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilterTest.java index c7d67bb59e..5a60513204 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilterTest.java @@ -72,4 +72,32 @@ public void should_filter_Kotlin_1_4() { assertIgnored(new Range(expectedFrom, expectedTo)); } + /** + *
    +	 *   fun f(o: Any?) {
    +	 *     if (o == null)
    +	 *       throw NullPointerException("null cannot be cast to non-null type")
    +	 *   }
    +	 * 
    + */ + @Test + public void should_not_filter() { + m.visitVarInsn(Opcodes.ALOAD, 1); + final Label label = new Label(); + m.visitJumpInsn(Opcodes.IFNONNULL, label); + m.visitTypeInsn(Opcodes.NEW, "java/lang/NullPointerException"); + m.visitInsn(Opcodes.DUP); + m.visitLdcInsn("null cannot be cast to non-null type"); + m.visitMethodInsn(Opcodes.INVOKESPECIAL, + "java/lang/NullPointerException", "", + "(Ljava/lang/String;)V", false); + m.visitInsn(Opcodes.ATHROW); + m.visitLabel(label); + m.visitInsn(Opcodes.RETURN); + + filter.filter(m, context, output); + + assertIgnored(); + } + } From c84c0e25b3f83441782e359c458c8dc1680ea322 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov Date: Mon, 21 Dec 2020 11:54:12 +0100 Subject: [PATCH 6/8] (WIP) Update filter --- .../filter/KotlinUnsafeCastOperatorFilterTest.java | 4 ++-- .../analysis/filter/KotlinUnsafeCastOperatorFilter.java | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilterTest.java index 5a60513204..1586dd425e 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilterTest.java @@ -34,8 +34,8 @@ public void should_filter() { final Label label = new Label(); m.visitInsn(Opcodes.DUP); - m.visitJumpInsn(Opcodes.IFNONNULL, label); final AbstractInsnNode expectedFrom = m.instructions.getLast(); + m.visitJumpInsn(Opcodes.IFNONNULL, label); m.visitTypeInsn(Opcodes.NEW, "kotlin/TypeCastException"); m.visitInsn(Opcodes.DUP); m.visitLdcInsn("null cannot be cast to non-null type kotlin.String"); @@ -55,8 +55,8 @@ public void should_filter_Kotlin_1_4() { final Label label = new Label(); m.visitInsn(Opcodes.DUP); - m.visitJumpInsn(Opcodes.IFNONNULL, label); final AbstractInsnNode expectedFrom = m.instructions.getLast(); + m.visitJumpInsn(Opcodes.IFNONNULL, label); m.visitTypeInsn(Opcodes.NEW, "java/lang/NullPointerException"); m.visitInsn(Opcodes.DUP); m.visitLdcInsn("null cannot be cast to non-null type kotlin.String"); diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilter.java index 45246af9ae..720492ae13 100644 --- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilter.java +++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilter.java @@ -38,11 +38,12 @@ private static class Matcher extends AbstractMatcher { public void match(final String exceptionType, final AbstractInsnNode start, final IFilterOutput output) { - if (Opcodes.IFNONNULL != start.getOpcode()) { + if (Opcodes.DUP != start.getOpcode()) { return; } cursor = start; - + nextIs(Opcodes.IFNONNULL); + final JumpInsnNode jumpInsnNode = (JumpInsnNode) cursor; nextIsType(Opcodes.NEW, exceptionType); nextIs(Opcodes.DUP); nextIs(Opcodes.LDC); @@ -60,7 +61,7 @@ public void match(final String exceptionType, if (cursor == null) { return; } - if (cursor.getNext() != ((JumpInsnNode) start).label) { + if (cursor.getNext() != jumpInsnNode.label) { return; } From 345cf9d9187b65e230dafa23f53971ba4d70d25d Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov Date: Mon, 21 Dec 2020 12:30:25 +0100 Subject: [PATCH 7/8] (WIP) Add unit test --- .../KotlinUnsafeCastOperatorFilterTest.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilterTest.java index 1586dd425e..64efadb98b 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilterTest.java @@ -31,6 +31,8 @@ public class KotlinUnsafeCastOperatorFilterTest extends FilterTestBase { @Test public void should_filter() { + context.classAnnotations + .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC); final Label label = new Label(); m.visitInsn(Opcodes.DUP); @@ -52,6 +54,8 @@ public void should_filter() { @Test public void should_filter_Kotlin_1_4() { + context.classAnnotations + .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC); final Label label = new Label(); m.visitInsn(Opcodes.DUP); @@ -82,6 +86,8 @@ public void should_filter_Kotlin_1_4() { */ @Test public void should_not_filter() { + context.classAnnotations + .add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC); m.visitVarInsn(Opcodes.ALOAD, 1); final Label label = new Label(); m.visitJumpInsn(Opcodes.IFNONNULL, label); @@ -100,4 +106,23 @@ public void should_not_filter() { assertIgnored(); } + @Test + public void should_not_filter_when_not_kotlin() { + m.visitInsn(Opcodes.DUP); + final Label label = new Label(); + m.visitJumpInsn(Opcodes.IFNONNULL, label); + m.visitTypeInsn(Opcodes.NEW, "java/lang/NullPointerException"); + m.visitInsn(Opcodes.DUP); + m.visitLdcInsn("null cannot be cast to non-null type kotlin.String"); + m.visitMethodInsn(Opcodes.INVOKESPECIAL, + "java/lang/NullPointerException", "", + "(Ljava/lang/String;)V", false); + m.visitInsn(Opcodes.ATHROW); + m.visitLabel(label); + + filter.filter(m, context, output); + + assertIgnored(); + } + } From 050d6b1c866411f4567049553f6e47921277568a Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov Date: Mon, 21 Dec 2020 13:05:22 +0100 Subject: [PATCH 8/8] (WIP) Update filter --- .../analysis/filter/KotlinUnsafeCastOperatorFilter.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilter.java index 720492ae13..1712ec4eb9 100644 --- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilter.java +++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilter.java @@ -26,6 +26,9 @@ public final class KotlinUnsafeCastOperatorFilter implements IFilter { public void filter(final MethodNode methodNode, final IFilterContext context, final IFilterOutput output) { + if (!KotlinGeneratedFilter.isKotlinClass(context)) { + return; + } final Matcher matcher = new Matcher(); for (final AbstractInsnNode i : methodNode.instructions) { matcher.match("kotlin/TypeCastException", i, output);