| // Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| package com.android.tools.r8.kotlin; |
| |
| import static org.junit.Assert.assertEquals; |
| |
| import com.android.tools.r8.ToolHelper.KotlinTargetVersion; |
| import com.android.tools.r8.naming.MemberNaming.MethodSignature; |
| import com.android.tools.r8.utils.InternalOptions; |
| import com.android.tools.r8.utils.codeinspector.ClassSubject; |
| import com.android.tools.r8.utils.codeinspector.CodeInspector; |
| import com.android.tools.r8.utils.codeinspector.InstructionSubject; |
| import com.android.tools.r8.utils.codeinspector.MethodSubject; |
| import com.google.common.collect.ImmutableList; |
| import org.junit.Test; |
| |
| public class SimplifyIfNotNullKotlinTest extends AbstractR8KotlinTestBase { |
| private static final String FOLDER = "non_null"; |
| private static final String STRING = "java.lang.String"; |
| |
| public SimplifyIfNotNullKotlinTest( |
| KotlinTargetVersion targetVersion, boolean allowAccessModification) { |
| super(targetVersion, allowAccessModification); |
| } |
| |
| @Test |
| public void test_example1() throws Exception { |
| final TestKotlinClass ex1 = new TestKotlinClass("non_null.Example1Kt"); |
| final MethodSignature testMethodSignature = |
| new MethodSignature("forMakeAndModel", "java.util.SortedMap", |
| ImmutableList.of("java.util.Collection", STRING, STRING, "java.lang.Integer")); |
| |
| final String mainClassName = ex1.getClassName(); |
| final String extraRules = |
| keepMainMethod(mainClassName) + neverInlineMethod(mainClassName, testMethodSignature); |
| runTest( |
| FOLDER, |
| mainClassName, |
| extraRules, |
| InternalOptions::enableCallSiteOptimizationInfoPropagation, |
| app -> { |
| CodeInspector codeInspector = new CodeInspector(app); |
| ClassSubject clazz = checkClassIsKept(codeInspector, ex1.getClassName()); |
| |
| MethodSubject testMethod = checkMethodIsKept(clazz, testMethodSignature); |
| long ifzCount = |
| testMethod.streamInstructions().filter(i -> i.isIfEqz() || i.isIfNez()).count(); |
| long paramNullCheckCount = countCall(testMethod, "Intrinsics", "checkParameterIsNotNull"); |
| // One after Iterator#hasNext, and another in the filter predicate: sinceYear != null. |
| assertEquals(2, ifzCount); |
| assertEquals(allowAccessModification ? 0 : 5, paramNullCheckCount); |
| }); |
| } |
| |
| @Test |
| public void test_example2() throws Exception { |
| final TestKotlinClass ex2 = new TestKotlinClass("non_null.Example2Kt"); |
| final MethodSignature testMethodSignature = |
| new MethodSignature("aOrDefault", STRING, ImmutableList.of(STRING, STRING)); |
| |
| final String mainClassName = ex2.getClassName(); |
| final String extraRules = |
| keepMainMethod(mainClassName) + neverInlineMethod(mainClassName, testMethodSignature); |
| runTest(FOLDER, mainClassName, extraRules, |
| InternalOptions::enableCallSiteOptimizationInfoPropagation, |
| app -> { |
| CodeInspector codeInspector = new CodeInspector(app); |
| ClassSubject clazz = checkClassIsKept(codeInspector, ex2.getClassName()); |
| |
| MethodSubject testMethod = checkMethodIsKept(clazz, testMethodSignature); |
| long ifzCount = testMethod.streamInstructions().filter(InstructionSubject::isIfEqz).count(); |
| long paramNullCheckCount = |
| countCall(testMethod, "Intrinsics", "checkParameterIsNotNull"); |
| // ?: in aOrDefault |
| assertEquals(1, ifzCount); |
| assertEquals(allowAccessModification ? 0 : 1, paramNullCheckCount); |
| }); |
| } |
| |
| @Test |
| public void test_example3() throws Exception { |
| final TestKotlinClass ex3 = new TestKotlinClass("non_null.Example3Kt"); |
| final MethodSignature testMethodSignature = |
| new MethodSignature("neverThrowNPE", "void", ImmutableList.of("non_null.Foo")); |
| |
| final String mainClassName = ex3.getClassName(); |
| final String extraRules = |
| keepMainMethod(mainClassName) + neverInlineMethod(mainClassName, testMethodSignature); |
| runTest(FOLDER, mainClassName, extraRules, |
| InternalOptions::enableCallSiteOptimizationInfoPropagation, |
| app -> { |
| CodeInspector codeInspector = new CodeInspector(app); |
| ClassSubject clazz = checkClassIsKept(codeInspector, ex3.getClassName()); |
| |
| MethodSubject testMethod = checkMethodIsKept(clazz, testMethodSignature); |
| long ifzCount = testMethod.streamInstructions().filter(InstructionSubject::isIfEqz).count(); |
| // !! operator inside explicit null check should be gone. |
| // One explicit null-check as well as 4 bar? accesses. |
| assertEquals(5, ifzCount); |
| }); |
| } |
| } |