From 9c6bb3371efdad77175d6bbf3ee139d3b7c9356f Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov Date: Fri, 5 Oct 2018 02:09:18 +0200 Subject: Add filter for Kotlin "unsafe" cast operator (#761) --- .../core/internal/analysis/filter/Filters.java | 3 +- .../filter/KotlinUnsafeCastOperatorFilter.java | 71 ++++++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilter.java (limited to 'org.jacoco.core/src/org/jacoco/core/internal/analysis') diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/Filters.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/Filters.java index 03c85d7d..f6a7a1df 100644 --- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/Filters.java +++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/Filters.java @@ -34,7 +34,8 @@ public final class Filters implements IFilter { new StringSwitchJavacFilter(), new StringSwitchEcjFilter(), new EnumEmptyConstructorFilter(), new AnnotationGeneratedFilter(), new KotlinGeneratedFilter(), new KotlinLateinitFilter(), - new KotlinWhenFilter(), new KotlinWhenStringFilter()); + new KotlinWhenFilter(), new KotlinWhenStringFilter(), + new KotlinUnsafeCastOperatorFilter()); private final IFilter[] filters; 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 new file mode 100644 index 00000000..b65cac27 --- /dev/null +++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinUnsafeCastOperatorFilter.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Evgeny Mandrikov - initial API and implementation + * + *******************************************************************************/ +package org.jacoco.core.internal.analysis.filter; + +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.JumpInsnNode; +import org.objectweb.asm.tree.LdcInsnNode; +import org.objectweb.asm.tree.MethodNode; + +/** + * Filters branch in bytecode that Kotlin compiler generates for "unsafe" cast + * operator. + */ +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 (AbstractInsnNode i = methodNode.instructions + .getFirst(); i != null; i = i.getNext()) { + matcher.match(i, output); + } + } + + private static class Matcher extends AbstractMatcher { + public void match(final AbstractInsnNode start, + final IFilterOutput output) { + + if (Opcodes.IFNONNULL != start.getOpcode()) { + return; + } + cursor = start; + + nextIsNew(KOTLIN_TYPE_CAST_EXCEPTION); + nextIs(Opcodes.DUP); + nextIs(Opcodes.LDC); + if (cursor == null) { + return; + } + final LdcInsnNode ldc = (LdcInsnNode) cursor; + if (!(ldc.cst instanceof String && ((String) ldc.cst) + .startsWith("null cannot be cast to non-null type"))) { + return; + } + nextIsInvokeSuper(KOTLIN_TYPE_CAST_EXCEPTION, + "(Ljava/lang/String;)V"); + nextIs(Opcodes.ATHROW); + if (cursor == null) { + return; + } + if (cursor.getNext() != ((JumpInsnNode) start).label) { + return; + } + + output.ignore(start, cursor); + } + } + +} -- cgit v1.2.3