| // Copyright (c) 2019, 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.desugar.desugaredlibrary.conversiontests; |
| |
| import com.android.tools.r8.TestRuntime.DexRuntime; |
| import com.android.tools.r8.ToolHelper.DexVm; |
| import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase; |
| import com.android.tools.r8.utils.AndroidApiLevel; |
| import com.android.tools.r8.utils.StringUtils; |
| import java.nio.file.Path; |
| import java.util.Collection; |
| import java.util.Iterator; |
| import java.util.function.Consumer; |
| import org.jetbrains.annotations.NotNull; |
| import org.junit.Test; |
| |
| public class ConversionIntroduceInterfaceMethodTest extends DesugaredLibraryTestBase { |
| |
| @Test |
| public void testNoInterfaceMethods() throws Exception { |
| Path customLib = testForD8().addProgramClasses(CustomLibClass.class).compile().writeToZip(); |
| testForD8() |
| .setMinApi(AndroidApiLevel.B) |
| .addProgramClasses( |
| MyCollectionInterface.class, |
| MyCollectionInterfaceAbstract.class, |
| MyCollection.class, |
| Executor.class) |
| .addLibraryClasses(CustomLibClass.class) |
| .enableCoreLibraryDesugaring(AndroidApiLevel.B) |
| .compile() |
| .addDesugaredCoreLibraryRunClassPath(this::buildDesugaredLibrary, AndroidApiLevel.B) |
| .addRunClasspathFiles(customLib) |
| .run(new DexRuntime(DexVm.ART_9_0_0_HOST), Executor.class) |
| .assertSuccessWithOutput( |
| StringUtils.lines( |
| "action called from j$ consumer", |
| "forEach called", |
| "action called from java consumer", |
| "forEach called")); |
| } |
| |
| static class CustomLibClass { |
| |
| @SuppressWarnings({"unchecked", "WeakerAccess"}) |
| public static void callForeach(Iterable iterable) { |
| iterable.forEach(x -> System.out.println("action called from java consumer")); |
| } |
| } |
| |
| static class Executor { |
| |
| @SuppressWarnings("RedundantOperationOnEmptyContainer") |
| public static void main(String[] args) { |
| MyCollection<String> strings = new MyCollection<>(); |
| // Call foreach with j$ consumer. |
| strings.forEach(x -> System.out.println("action called from j$ consumer")); |
| // Call foreach with java consumer. |
| CustomLibClass.callForeach(strings); |
| } |
| } |
| |
| interface MyCollectionInterface<E> extends Collection<E> { |
| |
| // The following method override a method from Iterable and use a desugared type. |
| // API conversion is required. |
| @Override |
| default void forEach(Consumer<? super E> action) { |
| action.accept(null); |
| System.out.println("forEach called"); |
| } |
| } |
| |
| @SuppressWarnings("ConstantConditions") |
| static class MyCollection<E> implements MyCollectionInterface<E> { |
| |
| @Override |
| public int size() { |
| return 0; |
| } |
| |
| @Override |
| public boolean isEmpty() { |
| return false; |
| } |
| |
| @Override |
| public boolean contains(Object o) { |
| return false; |
| } |
| |
| @NotNull |
| @Override |
| public Iterator<E> iterator() { |
| return null; |
| } |
| |
| @NotNull |
| @Override |
| public Object[] toArray() { |
| return new Object[0]; |
| } |
| |
| @NotNull |
| @Override |
| public <T> T[] toArray(@NotNull T[] a) { |
| return null; |
| } |
| |
| @Override |
| public boolean add(E e) { |
| return false; |
| } |
| |
| @Override |
| public boolean remove(Object o) { |
| return false; |
| } |
| |
| @Override |
| public boolean containsAll(@NotNull Collection<?> c) { |
| return false; |
| } |
| |
| @Override |
| public boolean addAll(@NotNull Collection<? extends E> c) { |
| return false; |
| } |
| |
| @Override |
| public boolean removeAll(@NotNull Collection<?> c) { |
| return false; |
| } |
| |
| @Override |
| public boolean retainAll(@NotNull Collection<?> c) { |
| return false; |
| } |
| |
| @Override |
| public void clear() {} |
| } |
| |
| interface MyCollectionInterfaceAbstract<E> extends Collection<E> { |
| |
| // The following method override a method from Iterable and use a desugared type. |
| // API conversion is required. |
| @Override |
| void forEach(Consumer<? super E> action); |
| } |
| } |