| // 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.graph; |
| |
| import static org.hamcrest.CoreMatchers.hasItems; |
| import static org.hamcrest.CoreMatchers.not; |
| import static org.junit.Assert.assertThat; |
| |
| import com.android.tools.r8.ToolHelper; |
| import com.android.tools.r8.dex.ApplicationReader; |
| import com.android.tools.r8.utils.AndroidApp; |
| import com.android.tools.r8.utils.InternalOptions; |
| import com.android.tools.r8.utils.Timing; |
| import java.util.Set; |
| import org.junit.BeforeClass; |
| import org.junit.Test; |
| |
| public class DexTypeTest { |
| |
| private static DexItemFactory factory; |
| private static AppInfoWithSubtyping appInfo; |
| |
| @BeforeClass |
| public static void makeAppInfo() throws Exception { |
| InternalOptions options = new InternalOptions(); |
| DexApplication application = |
| new ApplicationReader( |
| AndroidApp.builder() |
| .addLibraryFiles(ToolHelper.getDefaultAndroidJar()) |
| .addLibraryFiles(ToolHelper.getKotlinStdlibJar()) |
| .build(), |
| options, |
| new Timing(DexType.class.getName())) |
| .read() |
| .toDirect(); |
| factory = options.itemFactory; |
| appInfo = new AppInfoWithSubtyping(application); |
| } |
| |
| @Test |
| public void implementedInterfaces_collections_java() { |
| DexType serializable = factory.createType("Ljava/io/Serializable;"); |
| DexType iterable = factory.createType("Ljava/lang/Iterable;"); |
| // interface Collection extends Iterable |
| DexType collection = factory.createType("Ljava/util/Collection;"); |
| // interface List extends Collection |
| DexType list = factory.createType("Ljava/util/List;"); |
| // interface Queue extends Collection |
| DexType queue = factory.createType("Ljava/util/Queue;"); |
| // interface Deque extends Queue |
| DexType deque = factory.createType("Ljava/util/Deque;"); |
| |
| // class ArrayList implements List |
| DexType arrayList = factory.createType("Ljava/util/ArrayList;"); |
| Set<DexType> interfaces = appInfo.implementedInterfaces(arrayList); |
| assertThat(interfaces, hasItems(serializable)); |
| assertThat(interfaces, hasItems(iterable)); |
| assertThat(interfaces, hasItems(collection)); |
| assertThat(interfaces, hasItems(list)); |
| assertThat(interfaces, not(hasItems(queue))); |
| |
| // class LinkedList implements List, Deque |
| DexType linkedList = factory.createType("Ljava/util/LinkedList;"); |
| interfaces = appInfo.implementedInterfaces(linkedList); |
| assertThat(interfaces, hasItems(serializable)); |
| assertThat(interfaces, hasItems(iterable)); |
| assertThat(interfaces, hasItems(collection)); |
| assertThat(interfaces, hasItems(list)); |
| assertThat(interfaces, hasItems(deque)); |
| assertThat(interfaces, hasItems(queue)); |
| } |
| |
| @Test |
| public void implementedInterfaces_collections_kotlin() { |
| DexType iterable = factory.createType("Ljava/lang/Iterable;"); |
| // interface Collection extends Iterable |
| DexType collection = factory.createType("Ljava/util/Collection;"); |
| // interface List extends Collection |
| DexType list = factory.createType("Ljava/util/List;"); |
| // interface Set extends Collection |
| DexType set = factory.createType("Ljava/util/Set;"); |
| |
| DexType ktAbsList = factory.createType("Lkotlin/collections/AbstractList;"); |
| DexType ktAbsSet = factory.createType("Lkotlin/collections/AbstractSet;"); |
| |
| Set<DexType> interfaces = appInfo.implementedInterfaces(ktAbsList); |
| assertThat(interfaces, hasItems(iterable)); |
| assertThat(interfaces, hasItems(collection)); |
| assertThat(interfaces, hasItems(list)); |
| assertThat(interfaces, not(hasItems(set))); |
| |
| interfaces = appInfo.implementedInterfaces(ktAbsSet); |
| assertThat(interfaces, hasItems(iterable)); |
| assertThat(interfaces, hasItems(collection)); |
| assertThat(interfaces, hasItems(set)); |
| assertThat(interfaces, not(hasItems(list))); |
| } |
| |
| @Test |
| public void implementedInterfaces_reflect_java() { |
| DexType serializable = factory.createType("Ljava/io/Serializable;"); |
| DexType annotatedElement = factory.createType("Ljava/lang/reflect/AnnotatedElement;"); |
| // interface GenericDeclaration extends AnnotatedElement |
| DexType genericDeclaration = factory.createType("Ljava/lang/reflect/GenericDeclaration;"); |
| DexType type = factory.createType("Ljava/lang/reflect/Type;"); |
| DexType pType = factory.createType("Ljava/lang/reflect/ParameterizedType;"); |
| DexType klass = factory.createType("Ljava/lang/Class;"); |
| |
| Set<DexType> interfaces = appInfo.implementedInterfaces(klass); |
| assertThat(interfaces, hasItems(serializable)); |
| assertThat(interfaces, hasItems(annotatedElement)); |
| assertThat(interfaces, hasItems(genericDeclaration)); |
| assertThat(interfaces, hasItems(type)); |
| assertThat(interfaces, not(hasItems(pType))); |
| } |
| |
| @Test |
| public void implementedInterfaces_reflect_kotlin() { |
| DexType kCallable = factory.createType("Lkotlin/reflect/KCallable;"); |
| // interface KProperty : KFunction |
| DexType kFunction = factory.createType("Lkotlin/reflect/KFunction;"); |
| // interface KProperty : KCallable |
| DexType kProperty = factory.createType("Lkotlin/reflect/KProperty;"); |
| // interface KMutableProperty : KProperty |
| DexType kMutableProperty = factory.createType("Lkotlin/reflect/KMutableProperty;"); |
| // interface KMutableProperty0 : KProperty, KMutableProperty |
| DexType kMutableProperty0 = factory.createType("Lkotlin/reflect/KMutableProperty0;"); |
| // class MutablePropertyReference0 : KMutableProperty0 |
| DexType mutableReference0 = |
| factory.createType("Lkotlin/jvm/internal/MutablePropertyReference0;"); |
| |
| Set<DexType> interfaces = appInfo.implementedInterfaces(mutableReference0); |
| assertThat(interfaces, hasItems(kCallable)); |
| assertThat(interfaces, hasItems(kProperty)); |
| assertThat(interfaces, hasItems(kMutableProperty)); |
| assertThat(interfaces, hasItems(kMutableProperty0)); |
| assertThat(interfaces, not(hasItems(kFunction))); |
| } |
| |
| @Test |
| public void implementedInterfaces_lambda_kotlin() { |
| DexType function = factory.createType("Lkotlin/Function;"); |
| DexType functionBase = factory.createType("Lkotlin/jvm/internal/FunctionBase;"); |
| // class Lambda : Function, FunctionBase |
| DexType lambda = factory.createType("Lkotlin/jvm/internal/Lambda;"); |
| // interface Function0 : Function |
| DexType function0 = factory.createType("Lkotlin/jvm/functions/Function0;"); |
| |
| Set<DexType> interfaces = appInfo.implementedInterfaces(lambda); |
| assertThat(interfaces, not(hasItems(lambda))); |
| assertThat(interfaces, hasItems(function)); |
| assertThat(interfaces, hasItems(functionBase)); |
| |
| interfaces = appInfo.implementedInterfaces(function0); |
| assertThat(interfaces, hasItems(function0)); |
| assertThat(interfaces, hasItems(function)); |
| assertThat(interfaces, not(hasItems(functionBase))); |
| } |
| |
| } |