Always create KmType for library types.
Also, for better inspection of R8-processed @Metadata, this CL expands
inspector subjects to KmPackage. Since KmPackage is just another
abstraction of KmDeclarationContainer, which is a super type of both
KmPackage (file-level container) and KmClass (obviously, class-level
container), many utils can be shared, e.g., retrieving class subjects
that appear at extension definitions. This CL also includes refactoring
about KmDeclarationContainer subject.
Bug: 147402444, 70169921
Change-Id: I539b09394c31bd90905fa07e8e0a0b0b3b434a7e
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataSynthesizer.java b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataSynthesizer.java
index 5f7843f..ef9419c 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataSynthesizer.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataSynthesizer.java
@@ -55,10 +55,6 @@
kmType.visitClass(descriptorToInternalName(convertedType.toDescriptorString()));
return kmType;
}
- DexClass clazz = appView.definitionFor(type);
- if (clazz == null) {
- return null;
- }
// For library or classpath class, synthesize @Metadata always.
// For a program class, make sure it is live.
if (!appView.appInfo().isNonProgramTypeOrLiveProgramType(type)) {
@@ -66,7 +62,8 @@
}
DexType renamedType = lens.lookupType(type, appView.dexItemFactory());
// For library or classpath class, we should not have renamed it.
- assert clazz.isProgramClass() || renamedType == type
+ DexClass clazz = appView.definitionFor(type);
+ assert clazz == null || clazz.isProgramClass() || renamedType == type
: type.toSourceString() + " -> " + renamedType.toSourceString();
// TODO(b/70169921): Mysterious, why attempts to properly set flags bothers kotlinc?
// and/or why wiping out flags works for KmType but not KmFunction?!
diff --git a/src/test/java/com/android/tools/r8/ProguardTestBuilder.java b/src/test/java/com/android/tools/r8/ProguardTestBuilder.java
index e53fdce..9012ca4 100644
--- a/src/test/java/com/android/tools/r8/ProguardTestBuilder.java
+++ b/src/test/java/com/android/tools/r8/ProguardTestBuilder.java
@@ -94,6 +94,9 @@
if (!enableTreeShaking) {
command.add("-dontshrink");
}
+ if (!enableOptimization) {
+ command.add("-dontoptimize");
+ }
if (!enableMinification) {
command.add("-dontobfuscate");
}
diff --git a/src/test/java/com/android/tools/r8/TestShrinkerBuilder.java b/src/test/java/com/android/tools/r8/TestShrinkerBuilder.java
index 84fc2ee..19c6edd 100644
--- a/src/test/java/com/android/tools/r8/TestShrinkerBuilder.java
+++ b/src/test/java/com/android/tools/r8/TestShrinkerBuilder.java
@@ -21,8 +21,9 @@
T extends TestShrinkerBuilder<C, B, CR, RR, T>>
extends TestCompilerBuilder<C, B, CR, RR, T> {
- protected boolean enableMinification = true;
protected boolean enableTreeShaking = true;
+ protected boolean enableOptimization = true;
+ protected boolean enableMinification = true;
TestShrinkerBuilder(TestState state, B builder, Backend backend) {
super(state, builder, backend);
@@ -37,6 +38,15 @@
return treeShaking(false);
}
+ public T optimization(boolean enable) {
+ enableOptimization = enable;
+ return self();
+ }
+
+ public T noOptimization() {
+ return optimization(false);
+ }
+
public T minification(boolean enable) {
enableMinification = enable;
return self();
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInLibraryTypeTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInLibraryTypeTest.java
new file mode 100644
index 0000000..603dd6e
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInLibraryTypeTest.java
@@ -0,0 +1,111 @@
+// Copyright (c) 2020, 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.metadata;
+
+import static com.android.tools.r8.KotlinCompilerTool.KOTLINC;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.R8TestCompileResult;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.KotlinTargetVersion;
+import com.android.tools.r8.shaking.ProguardKeepAttributes;
+import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.KmPackageSubject;
+import java.nio.file.Path;
+import java.util.Collection;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class MetadataRenameInLibraryTypeTest extends KotlinMetadataTestBase {
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0} target: {1}")
+ public static Collection<Object[]> data() {
+ return buildParameters(
+ getTestParameters().withCfRuntimes().build(), KotlinTargetVersion.values());
+ }
+
+ public MetadataRenameInLibraryTypeTest(
+ TestParameters parameters, KotlinTargetVersion targetVersion) {
+ super(targetVersion);
+ this.parameters = parameters;
+ }
+
+ private static Path baseLibJar;
+ private static Path extLibJar;
+ private static Path appJar;
+
+ @BeforeClass
+ public static void createLibJar() throws Exception {
+ String baseLibFolder = PKG_PREFIX + "/libtype_lib_base";
+ baseLibJar =
+ kotlinc(KOTLINC, KotlinTargetVersion.JAVA_8)
+ .addSourceFiles(getKotlinFileInTest(baseLibFolder, "base"))
+ .compile();
+ String extLibFolder = PKG_PREFIX + "/libtype_lib_ext";
+ extLibJar =
+ kotlinc(KOTLINC, KotlinTargetVersion.JAVA_8)
+ .addClasspathFiles(baseLibJar)
+ .addSourceFiles(getKotlinFileInTest(extLibFolder, "ext"))
+ .compile();
+ String appFolder = PKG_PREFIX + "/libtype_app";
+ appJar =
+ kotlinc(KOTLINC, KotlinTargetVersion.JAVA_8)
+ .addClasspathFiles(baseLibJar)
+ .addClasspathFiles(extLibJar)
+ .addSourceFiles(getKotlinFileInTest(appFolder, "main"))
+ .compile();
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ String pkg = getClass().getPackage().getName();
+ String main = pkg + ".libtype_app.MainKt";
+ R8TestCompileResult compileResult =
+ testForR8(parameters.getBackend())
+ // Intentionally not providing basLibJar as lib file nor classpath file.
+ .addProgramFiles(extLibJar, appJar)
+ // Keep Ext extension method which requires metadata to be called with Kotlin syntax
+ // from other kotlin code.
+ .addKeepRules("-keep class **.ExtKt { <methods>; }")
+ // Keep the main entry.
+ .addKeepMainRule(main)
+ .addKeepAttributes(ProguardKeepAttributes.RUNTIME_VISIBLE_ANNOTATIONS)
+ .addOptionsModification(InternalOptions::enableKotlinMetadataRewriting)
+ // -dontoptimize so that basic code structure is kept.
+ .noOptimization()
+ .compile();
+ final String extClassName = pkg + ".libtype_lib_ext.ExtKt";
+ compileResult.inspect(inspector -> {
+ ClassSubject ext = inspector.clazz(extClassName);
+ assertThat(ext, isPresent());
+ assertThat(ext, not(isRenamed()));
+ // API entry is kept, hence the presence of Metadata.
+ KmPackageSubject kmPackage = ext.getKmPackage();
+ assertThat(kmPackage, isPresent());
+ // Type appearance of library type, Base, should be kept, even if it's not provided.
+ // Note that the resulting ClassSubject for Base is an absent one as we don't provide it, and
+ // thus we can't use `getReturnTypesInFunctions`, which filters out absent class subject.
+ assertTrue(kmPackage.getReturnTypeDescriptorsInFunctions().stream().anyMatch(
+ returnType -> returnType.contains("Base")));
+ });
+
+ Path out = compileResult.writeToZip();
+ testForJvm()
+ .addRunClasspathFiles(ToolHelper.getKotlinStdlibJar(), baseLibJar)
+ .addClasspath(out)
+ .run(parameters.getRuntime(), main)
+ .assertSuccessWithOutputLines("Sub::foo", "Sub::boo", "true");
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/libtype_app/main.kt b/src/test/java/com/android/tools/r8/kotlin/metadata/libtype_app/main.kt
new file mode 100644
index 0000000..a2d204a
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/libtype_app/main.kt
@@ -0,0 +1,14 @@
+// Copyright (c) 2020, 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.metadata.libtype_app
+
+import com.android.tools.r8.kotlin.metadata.libtype_lib_base.Sub
+import com.android.tools.r8.kotlin.metadata.libtype_lib_ext.boo
+
+fun main() {
+ val s = Sub()
+ s.foo()
+ val b = s.boo()
+ println(s == b)
+}
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/libtype_lib_base/base.kt b/src/test/java/com/android/tools/r8/kotlin/metadata/libtype_lib_base/base.kt
new file mode 100644
index 0000000..0348987
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/libtype_lib_base/base.kt
@@ -0,0 +1,16 @@
+// Copyright (c) 2020, 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.metadata.libtype_lib_base
+
+open class Base {
+ open fun foo() {
+ println("Base::foo")
+ }
+}
+
+class Sub : Base() {
+ override fun foo() {
+ println("Sub::foo")
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/libtype_lib_ext/ext.kt b/src/test/java/com/android/tools/r8/kotlin/metadata/libtype_lib_ext/ext.kt
new file mode 100644
index 0000000..81c924b
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/libtype_lib_ext/ext.kt
@@ -0,0 +1,12 @@
+// Copyright (c) 2020, 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.metadata.libtype_lib_ext
+
+import com.android.tools.r8.kotlin.metadata.libtype_lib_base.Base
+import com.android.tools.r8.kotlin.metadata.libtype_lib_base.Sub
+
+fun Sub.boo(): Base {
+ println("Sub::boo")
+ return this
+}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentClassSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentClassSubject.java
index e665dcf..a471b18 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentClassSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentClassSubject.java
@@ -142,4 +142,9 @@
public KmClassSubject getKmClass() {
return null;
}
+
+ @Override
+ public KmPackageSubject getKmPackage() {
+ return null;
+ }
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentKmClassSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentKmClassSubject.java
index 201f644..2704774 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentKmClassSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentKmClassSubject.java
@@ -4,8 +4,7 @@
package com.android.tools.r8.utils.codeinspector;
import com.android.tools.r8.graph.DexClass;
-import com.android.tools.r8.kotlin.Kotlin;
-import kotlinx.metadata.KmClass;
+import java.util.List;
public class AbsentKmClassSubject extends KmClassSubject {
@@ -15,11 +14,6 @@
}
@Override
- public KmClass getKmClass(Kotlin kotlin) {
- return null;
- }
-
- @Override
public boolean isPresent() {
return false;
}
@@ -33,4 +27,44 @@
public boolean isSynthetic() {
return false;
}
+
+ @Override
+ public List<String> getParameterTypeDescriptorsInFunctions() {
+ return null;
+ }
+
+ @Override
+ public List<String> getReturnTypeDescriptorsInFunctions() {
+ return null;
+ }
+
+ @Override
+ public List<String> getReturnTypeDescriptorsInProperties() {
+ return null;
+ }
+
+ @Override
+ public List<ClassSubject> getParameterTypesInFunctions() {
+ return null;
+ }
+
+ @Override
+ public List<ClassSubject> getReturnTypesInFunctions() {
+ return null;
+ }
+
+ @Override
+ public List<ClassSubject> getReturnTypesInProperties() {
+ return null;
+ }
+
+ @Override
+ public List<String> getSuperTypeDescriptors() {
+ return null;
+ }
+
+ @Override
+ public List<ClassSubject> getSuperTypes() {
+ return null;
+ }
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentKmPackageSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentKmPackageSubject.java
new file mode 100644
index 0000000..6ea407a
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentKmPackageSubject.java
@@ -0,0 +1,54 @@
+// Copyright (c) 2020, 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.utils.codeinspector;
+
+import java.util.List;
+
+public class AbsentKmPackageSubject extends KmPackageSubject {
+
+ @Override
+ public boolean isPresent() {
+ return false;
+ }
+
+ @Override
+ public boolean isRenamed() {
+ return false;
+ }
+
+ @Override
+ public boolean isSynthetic() {
+ return false;
+ }
+
+ @Override
+ public List<String> getParameterTypeDescriptorsInFunctions() {
+ return null;
+ }
+
+ @Override
+ public List<String> getReturnTypeDescriptorsInFunctions() {
+ return null;
+ }
+
+ @Override
+ public List<String> getReturnTypeDescriptorsInProperties() {
+ return null;
+ }
+
+ @Override
+ public List<ClassSubject> getParameterTypesInFunctions() {
+ return null;
+ }
+
+ @Override
+ public List<ClassSubject> getReturnTypesInFunctions() {
+ return null;
+ }
+
+ @Override
+ public List<ClassSubject> getReturnTypesInProperties() {
+ return null;
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/ClassSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/ClassSubject.java
index d7f09cb..d72d1a8 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/ClassSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/ClassSubject.java
@@ -172,4 +172,6 @@
public abstract String getFinalSignatureAttribute();
public abstract KmClassSubject getKmClass();
+
+ public abstract KmPackageSubject getKmPackage();
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java
index adc0dbd..3e83c5d 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java
@@ -345,4 +345,18 @@
KotlinClassMetadata.Class kClass = (KotlinClassMetadata.Class) metadata;
return new FoundKmClassSubject(codeInspector, getDexClass(), kClass.toKmClass());
}
+
+ @Override
+ public KmPackageSubject getKmPackage() {
+ AnnotationSubject annotationSubject = annotation(METADATA_TYPE);
+ if (!annotationSubject.isPresent()) {
+ return new AbsentKmPackageSubject();
+ }
+ KotlinClassMetadata metadata =
+ KotlinClassMetadataReader.toKotlinClassMetadata(
+ codeInspector.getFactory().kotlin, annotationSubject.getAnnotation());
+ assertTrue(metadata instanceof KotlinClassMetadata.FileFacade);
+ KotlinClassMetadata.FileFacade kFile = (KotlinClassMetadata.FileFacade) metadata;
+ return new FoundKmPackageSubject(codeInspector, getDexClass(), kFile.toKmPackage());
+ }
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmClassSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmClassSubject.java
index e4ce45d..e60f9f3 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmClassSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmClassSubject.java
@@ -3,20 +3,15 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.utils.codeinspector;
-import static com.android.tools.r8.utils.DescriptorUtils.getDescriptorFromKotlinClassifier;
-
import com.android.tools.r8.graph.DexClass;
-import com.android.tools.r8.kotlin.Kotlin;
-import com.android.tools.r8.references.Reference;
-import com.android.tools.r8.utils.Box;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import kotlinx.metadata.KmClass;
-import kotlinx.metadata.KmType;
-import kotlinx.metadata.KmTypeVisitor;
+import kotlinx.metadata.KmDeclarationContainer;
-public class FoundKmClassSubject extends KmClassSubject {
+public class FoundKmClassSubject extends KmClassSubject
+ implements FoundKmDeclarationContainerSubject {
private final CodeInspector codeInspector;
private final DexClass clazz;
private final KmClass kmClass;
@@ -33,7 +28,12 @@
}
@Override
- public KmClass getKmClass(Kotlin kotlin) {
+ public CodeInspector codeInspector() {
+ return codeInspector;
+ }
+
+ @Override
+ public KmDeclarationContainer getKmDeclarationContainer() {
return kmClass;
}
@@ -54,26 +54,6 @@
return false;
}
- // TODO(b/145824437): This is a dup of DescriptorUtils#getDescriptorFromKmType
- private String getDescriptorFromKmType(KmType kmType) {
- if (kmType == null) {
- return null;
- }
- Box<String> descriptor = new Box<>(null);
- kmType.accept(new KmTypeVisitor() {
- @Override
- public void visitClass(String name) {
- descriptor.set(getDescriptorFromKotlinClassifier(name));
- }
-
- @Override
- public void visitTypeAlias(String name) {
- descriptor.set(getDescriptorFromKotlinClassifier(name));
- }
- });
- return descriptor.get();
- }
-
@Override
public List<String> getSuperTypeDescriptors() {
return kmClass.getSupertypes().stream()
@@ -83,70 +63,10 @@
}
@Override
- public List<String> getParameterTypeDescriptorsInFunctions() {
- return kmClass.getFunctions().stream()
- .flatMap(kmFunction ->
- kmFunction.getValueParameters().stream()
- .map(kmValueParameter -> getDescriptorFromKmType(kmValueParameter.getType()))
- .filter(Objects::nonNull))
- .collect(Collectors.toList());
- }
-
- @Override
- public List<String> getReturnTypeDescriptorsInFunctions() {
- return kmClass.getFunctions().stream()
- .map(kmFunction -> getDescriptorFromKmType(kmFunction.getReturnType()))
- .filter(Objects::nonNull)
- .collect(Collectors.toList());
- }
-
- @Override
- public List<String> getReturnTypeDescriptorsInProperties() {
- return kmClass.getProperties().stream()
- .map(kmProperty -> getDescriptorFromKmType(kmProperty.getReturnType()))
- .filter(Objects::nonNull)
- .collect(Collectors.toList());
- }
-
- private ClassSubject getClassSubjectFromKmType(KmType kmType) {
- String descriptor = getDescriptorFromKmType(kmType);
- if (descriptor == null) {
- return new AbsentClassSubject();
- }
- return codeInspector.clazz(Reference.classFromDescriptor(descriptor));
- }
-
- @Override
public List<ClassSubject> getSuperTypes() {
return kmClass.getSupertypes().stream()
.map(this::getClassSubjectFromKmType)
.filter(ClassSubject::isPresent)
.collect(Collectors.toList());
}
-
- @Override
- public List<ClassSubject> getParameterTypesInFunctions() {
- return kmClass.getFunctions().stream()
- .flatMap(kmFunction ->
- kmFunction.getValueParameters().stream()
- .map(kmValueParameter -> getClassSubjectFromKmType(kmValueParameter.getType()))
- .filter(ClassSubject::isPresent))
- .collect(Collectors.toList());
- }
-
- @Override
- public List<ClassSubject> getReturnTypesInFunctions() {
- return kmClass.getFunctions().stream()
- .map(kmFunction -> getClassSubjectFromKmType(kmFunction.getReturnType()))
- .filter(ClassSubject::isPresent)
- .collect(Collectors.toList());
- }
-
- @Override
- public List<ClassSubject> getReturnTypesInProperties() {
- return kmClass.getProperties().stream()
- .map(kmProperty -> getClassSubjectFromKmType(kmProperty.getReturnType()))
- .filter(ClassSubject::isPresent)
- .collect(Collectors.toList());
- }
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmDeclarationContainerSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmDeclarationContainerSubject.java
new file mode 100644
index 0000000..45607ed
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmDeclarationContainerSubject.java
@@ -0,0 +1,101 @@
+// Copyright (c) 2020, 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.utils.codeinspector;
+
+import static com.android.tools.r8.utils.DescriptorUtils.getDescriptorFromKotlinClassifier;
+
+import com.android.tools.r8.references.Reference;
+import com.android.tools.r8.utils.Box;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+import kotlinx.metadata.KmDeclarationContainer;
+import kotlinx.metadata.KmType;
+import kotlinx.metadata.KmTypeVisitor;
+
+public interface FoundKmDeclarationContainerSubject extends KmDeclarationContainerSubject {
+
+ CodeInspector codeInspector();
+ KmDeclarationContainer getKmDeclarationContainer();
+
+ // TODO(b/145824437): This is a dup of DescriptorUtils#getDescriptorFromKmType
+ default String getDescriptorFromKmType(KmType kmType) {
+ if (kmType == null) {
+ return null;
+ }
+ Box<String> descriptor = new Box<>(null);
+ kmType.accept(new KmTypeVisitor() {
+ @Override
+ public void visitClass(String name) {
+ descriptor.set(getDescriptorFromKotlinClassifier(name));
+ }
+
+ @Override
+ public void visitTypeAlias(String name) {
+ descriptor.set(getDescriptorFromKotlinClassifier(name));
+ }
+ });
+ return descriptor.get();
+ }
+
+ @Override
+ default List<String> getParameterTypeDescriptorsInFunctions() {
+ return getKmDeclarationContainer().getFunctions().stream()
+ .flatMap(kmFunction ->
+ kmFunction.getValueParameters().stream()
+ .map(kmValueParameter -> getDescriptorFromKmType(kmValueParameter.getType()))
+ .filter(Objects::nonNull))
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ default List<String> getReturnTypeDescriptorsInFunctions() {
+ return getKmDeclarationContainer().getFunctions().stream()
+ .map(kmFunction -> getDescriptorFromKmType(kmFunction.getReturnType()))
+ .filter(Objects::nonNull)
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ default List<String> getReturnTypeDescriptorsInProperties() {
+ return getKmDeclarationContainer().getProperties().stream()
+ .map(kmProperty -> getDescriptorFromKmType(kmProperty.getReturnType()))
+ .filter(Objects::nonNull)
+ .collect(Collectors.toList());
+ }
+
+ default ClassSubject getClassSubjectFromKmType(KmType kmType) {
+ String descriptor = getDescriptorFromKmType(kmType);
+ if (descriptor == null) {
+ return new AbsentClassSubject();
+ }
+ return codeInspector().clazz(Reference.classFromDescriptor(descriptor));
+ }
+
+ @Override
+ default List<ClassSubject> getParameterTypesInFunctions() {
+ return getKmDeclarationContainer().getFunctions().stream()
+ .flatMap(kmFunction ->
+ kmFunction.getValueParameters().stream()
+ .map(kmValueParameter -> getClassSubjectFromKmType(kmValueParameter.getType()))
+ .filter(ClassSubject::isPresent))
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ default List<ClassSubject> getReturnTypesInFunctions() {
+ return getKmDeclarationContainer().getFunctions().stream()
+ .map(kmFunction -> getClassSubjectFromKmType(kmFunction.getReturnType()))
+ .filter(ClassSubject::isPresent)
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ default List<ClassSubject> getReturnTypesInProperties() {
+ return getKmDeclarationContainer().getProperties().stream()
+ .map(kmProperty -> getClassSubjectFromKmType(kmProperty.getReturnType()))
+ .filter(ClassSubject::isPresent)
+ .collect(Collectors.toList());
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmPackageSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmPackageSubject.java
new file mode 100644
index 0000000..8bc9459
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmPackageSubject.java
@@ -0,0 +1,48 @@
+// Copyright (c) 2020, 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.utils.codeinspector;
+
+import com.android.tools.r8.graph.DexClass;
+import kotlinx.metadata.KmDeclarationContainer;
+import kotlinx.metadata.KmPackage;
+
+public class FoundKmPackageSubject extends KmPackageSubject
+ implements FoundKmDeclarationContainerSubject {
+ private final CodeInspector codeInspector;
+ private final DexClass clazz;
+ private final KmPackage kmPackage;
+
+ FoundKmPackageSubject(CodeInspector codeInspector, DexClass clazz, KmPackage kmPackage) {
+ this.codeInspector = codeInspector;
+ this.clazz = clazz;
+ this.kmPackage = kmPackage;
+ }
+
+ @Override
+ public CodeInspector codeInspector() {
+ return codeInspector;
+ }
+
+ @Override
+ public KmDeclarationContainer getKmDeclarationContainer() {
+ return kmPackage;
+ }
+
+ @Override
+ public boolean isPresent() {
+ return true;
+ }
+
+ @Override
+ public boolean isRenamed() {
+ return false;
+ }
+
+ @Override
+ public boolean isSynthetic() {
+ // TODO(b/70169921): This should return `true` conditionally if we start synthesizing @Metadata
+ // from scratch.
+ return false;
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/KmClassSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/KmClassSubject.java
index aac5196..d36f233 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/KmClassSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/KmClassSubject.java
@@ -4,43 +4,12 @@
package com.android.tools.r8.utils.codeinspector;
import com.android.tools.r8.graph.DexClass;
-import com.android.tools.r8.kotlin.Kotlin;
import java.util.List;
-import kotlinx.metadata.KmClass;
-public abstract class KmClassSubject extends Subject {
+public abstract class KmClassSubject extends Subject implements KmDeclarationContainerSubject {
public abstract DexClass getDexClass();
- public abstract KmClass getKmClass(Kotlin kotlin);
- public List<String> getSuperTypeDescriptors() {
- return null;
- }
+ public abstract List<String> getSuperTypeDescriptors();
- public List<String> getParameterTypeDescriptorsInFunctions() {
- return null;
- }
-
- public List<String> getReturnTypeDescriptorsInFunctions() {
- return null;
- }
-
- public List<String> getReturnTypeDescriptorsInProperties() {
- return null;
- }
-
- public List<ClassSubject> getSuperTypes() {
- return null;
- }
-
- public List<ClassSubject> getParameterTypesInFunctions() {
- return null;
- }
-
- public List<ClassSubject> getReturnTypesInFunctions() {
- return null;
- }
-
- public List<ClassSubject> getReturnTypesInProperties() {
- return null;
- }
+ public abstract List<ClassSubject> getSuperTypes();
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/KmDeclarationContainerSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/KmDeclarationContainerSubject.java
new file mode 100644
index 0000000..d553228
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/KmDeclarationContainerSubject.java
@@ -0,0 +1,20 @@
+// Copyright (c) 2020, 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.utils.codeinspector;
+
+import java.util.List;
+
+public interface KmDeclarationContainerSubject {
+ List<String> getParameterTypeDescriptorsInFunctions();
+
+ List<String> getReturnTypeDescriptorsInFunctions();
+
+ List<String> getReturnTypeDescriptorsInProperties();
+
+ List<ClassSubject> getParameterTypesInFunctions();
+
+ List<ClassSubject> getReturnTypesInFunctions();
+
+ List<ClassSubject> getReturnTypesInProperties();
+}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/KmPackageSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/KmPackageSubject.java
new file mode 100644
index 0000000..8e00ce3
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/KmPackageSubject.java
@@ -0,0 +1,7 @@
+// Copyright (c) 2020, 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.utils.codeinspector;
+
+public abstract class KmPackageSubject extends Subject implements KmDeclarationContainerSubject {
+}