Reflection package access
Change-Id: I35d4534766a2076f779e7e7e32baf1b2db704fdf
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldAssignmentTracker.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldAssignmentTracker.java
index 0df3c80..3bc0ebe 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldAssignmentTracker.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldaccess/FieldAssignmentTracker.java
@@ -311,7 +311,6 @@
DexEncodedField field =
appView.appInfo().resolveField(info.getField()).getResolvedField();
if (field == null) {
- assert false;
return;
}
if (!info.hasReflectiveAccess() && !info.isWrittenFromMethodHandle()) {
diff --git a/src/test/examplesJava11/annotations/NeverClassInline.java b/src/test/examplesJava11/com/android/tools/r8/NeverClassInline.java
similarity index 89%
rename from src/test/examplesJava11/annotations/NeverClassInline.java
rename to src/test/examplesJava11/com/android/tools/r8/NeverClassInline.java
index 0c8b9d1..19c4504 100644
--- a/src/test/examplesJava11/annotations/NeverClassInline.java
+++ b/src/test/examplesJava11/com/android/tools/r8/NeverClassInline.java
@@ -2,6 +2,6 @@
// 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 annotations;
+package com.android.tools.r8;
public @interface NeverClassInline {}
diff --git a/src/test/examplesJava11/annotations/NeverInline.java b/src/test/examplesJava11/com/android/tools/r8/NeverInline.java
similarity index 91%
rename from src/test/examplesJava11/annotations/NeverInline.java
rename to src/test/examplesJava11/com/android/tools/r8/NeverInline.java
index 1c22094..cd01ce1 100644
--- a/src/test/examplesJava11/annotations/NeverInline.java
+++ b/src/test/examplesJava11/com/android/tools/r8/NeverInline.java
@@ -2,7 +2,7 @@
// 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 annotations;
+package com.android.tools.r8;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
diff --git a/src/test/examplesJava11/horizontalclassmerging/BasicNestHostHorizontalClassMerging.java b/src/test/examplesJava11/horizontalclassmerging/BasicNestHostHorizontalClassMerging.java
index 2e24e97..2362165 100644
--- a/src/test/examplesJava11/horizontalclassmerging/BasicNestHostHorizontalClassMerging.java
+++ b/src/test/examplesJava11/horizontalclassmerging/BasicNestHostHorizontalClassMerging.java
@@ -4,8 +4,8 @@
package horizontalclassmerging;
-import annotations.NeverClassInline;
-import annotations.NeverInline;
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
public class BasicNestHostHorizontalClassMerging {
// Prevent merging with BasicNestHostHorizontalClassMerging2.
@@ -17,16 +17,13 @@
@NeverInline
private void print(String v) {
- /* if (System.currentTimeMillis() < 0) {
- name = "never";
- } */
System.out.println(name + ": " + v);
}
public static void main(String[] args) {
BasicNestHostHorizontalClassMerging host = new BasicNestHostHorizontalClassMerging("1");
- A a = new A(host);
- B b = new B(host);
+ new A(host);
+ new B(host);
BasicNestHostHorizontalClassMerging2.main(args);
}
diff --git a/src/test/examplesJava11/horizontalclassmerging/BasicNestHostHorizontalClassMerging2.java b/src/test/examplesJava11/horizontalclassmerging/BasicNestHostHorizontalClassMerging2.java
index d25b8d2..78718e1 100644
--- a/src/test/examplesJava11/horizontalclassmerging/BasicNestHostHorizontalClassMerging2.java
+++ b/src/test/examplesJava11/horizontalclassmerging/BasicNestHostHorizontalClassMerging2.java
@@ -4,18 +4,14 @@
package horizontalclassmerging;
-import annotations.NeverClassInline;
-import annotations.NeverInline;
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
public class BasicNestHostHorizontalClassMerging2 {
@NeverInline
public static void main(String[] args) {
- A a = new A();
- B b = new B();
- if (System.currentTimeMillis() < 0) {
- System.out.println(a);
- System.out.println(b);
- }
+ new A();
+ new B();
}
@NeverInline
diff --git a/src/test/examplesJava11/nesthostexample/BasicNestHostClassMerging.java b/src/test/examplesJava11/nesthostexample/BasicNestHostClassMerging.java
index d1b6a5c..184c201 100644
--- a/src/test/examplesJava11/nesthostexample/BasicNestHostClassMerging.java
+++ b/src/test/examplesJava11/nesthostexample/BasicNestHostClassMerging.java
@@ -4,7 +4,7 @@
package nesthostexample;
-import annotations.NeverInline;
+import com.android.tools.r8.NeverInline;
public class BasicNestHostClassMerging {
diff --git a/src/test/examplesJava11/nesthostexample/BasicNestHostTreePruning.java b/src/test/examplesJava11/nesthostexample/BasicNestHostTreePruning.java
index 3088ed4..484c81a 100644
--- a/src/test/examplesJava11/nesthostexample/BasicNestHostTreePruning.java
+++ b/src/test/examplesJava11/nesthostexample/BasicNestHostTreePruning.java
@@ -4,7 +4,7 @@
package nesthostexample;
-import annotations.NeverInline;
+import com.android.tools.r8.NeverInline;
public class BasicNestHostTreePruning {
diff --git a/src/test/examplesJava11/nesthostexample/NestHostInliningSubclasses.java b/src/test/examplesJava11/nesthostexample/NestHostInliningSubclasses.java
index 6185c37..4221307 100644
--- a/src/test/examplesJava11/nesthostexample/NestHostInliningSubclasses.java
+++ b/src/test/examplesJava11/nesthostexample/NestHostInliningSubclasses.java
@@ -4,7 +4,7 @@
package nesthostexample;
-import annotations.NeverInline;
+import com.android.tools.r8.NeverInline;
public class NestHostInliningSubclasses {
diff --git a/src/test/examplesJava11/nesthostexample/NestPvtMethodCallInlined.java b/src/test/examplesJava11/nesthostexample/NestPvtMethodCallInlined.java
index 7a5f40e..cdbe725 100644
--- a/src/test/examplesJava11/nesthostexample/NestPvtMethodCallInlined.java
+++ b/src/test/examplesJava11/nesthostexample/NestPvtMethodCallInlined.java
@@ -4,7 +4,7 @@
package nesthostexample;
-import annotations.NeverInline;
+import com.android.tools.r8.NeverInline;
public class NestPvtMethodCallInlined {
diff --git a/src/test/java/com/android/tools/r8/TestBase.java b/src/test/java/com/android/tools/r8/TestBase.java
index f9eaa24..c3c51de 100644
--- a/src/test/java/com/android/tools/r8/TestBase.java
+++ b/src/test/java/com/android/tools/r8/TestBase.java
@@ -72,6 +72,8 @@
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.Pair;
import com.android.tools.r8.utils.PreloadedClassFileProvider;
+import com.android.tools.r8.utils.ReflectiveBuildPathUtils;
+import com.android.tools.r8.utils.ReflectiveBuildPathUtils.ExamplesClass;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.TestDescriptionWatcher;
@@ -1654,6 +1656,10 @@
return clazz.getTypeName();
}
+ public static String examplesTypeName(Class<? extends ExamplesClass> clazz) throws Exception {
+ return ReflectiveBuildPathUtils.resolveClassName(clazz);
+ }
+
public static AndroidApiLevel apiLevelWithDefaultInterfaceMethodsSupport() {
return AndroidApiLevel.N;
}
diff --git a/src/test/java/com/android/tools/r8/TestBaseBuilder.java b/src/test/java/com/android/tools/r8/TestBaseBuilder.java
index 1fe43fb..1e75de5 100644
--- a/src/test/java/com/android/tools/r8/TestBaseBuilder.java
+++ b/src/test/java/com/android/tools/r8/TestBaseBuilder.java
@@ -10,6 +10,8 @@
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.ListUtils;
+import com.android.tools.r8.utils.ReflectiveBuildPathUtils;
+import com.android.tools.r8.utils.ReflectiveBuildPathUtils.ExamplesRootPackage;
import com.google.common.collect.ImmutableMap;
import java.nio.file.Path;
import java.util.Arrays;
@@ -54,6 +56,12 @@
return self();
}
+ public T addExamplesProgramFiles(Class<? extends ExamplesRootPackage> rootPackage)
+ throws Exception {
+ Collection<Path> files = ReflectiveBuildPathUtils.allClassFiles(rootPackage);
+ return addProgramFiles(files);
+ }
+
public T addLibraryProvider(ClassFileResourceProvider provider) {
builder.addLibraryResourceProvider(provider);
return self();
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/NestClassTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/NestClassTest.java
index 97ad3ce..5edc29f 100644
--- a/src/test/java/com/android/tools/r8/classmerging/horizontal/NestClassTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/NestClassTest.java
@@ -7,42 +7,38 @@
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPrivate;
import static com.android.tools.r8.utils.codeinspector.Matchers.isStatic;
-import static org.hamcrest.CoreMatchers.not;
+import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestRuntime.CfVm;
-import com.android.tools.r8.desugar.nestaccesscontrol.NestAccessControlTestUtils;
+import com.android.tools.r8.classmerging.horizontal.NestClassTest.R.horizontalclassmerging.BasicNestHostHorizontalClassMerging;
+import com.android.tools.r8.classmerging.horizontal.NestClassTest.R.horizontalclassmerging.BasicNestHostHorizontalClassMerging2;
import com.android.tools.r8.utils.BooleanUtils;
+import com.android.tools.r8.utils.ReflectiveBuildPathUtils.ExamplesClass;
+import com.android.tools.r8.utils.ReflectiveBuildPathUtils.ExamplesJava11RootPackage;
+import com.android.tools.r8.utils.ReflectiveBuildPathUtils.ExamplesPackage;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
-import com.google.common.collect.ImmutableList;
-import java.nio.file.Path;
import java.util.List;
-import java.util.stream.Collectors;
import org.junit.Test;
import org.junit.runners.Parameterized;
public class NestClassTest extends HorizontalClassMergingTestBase {
- public static final String PACKAGE_NAME = "horizontalclassmerging.";
- private final String NEST_MAIN_CLASS_1 = PACKAGE_NAME + "BasicNestHostHorizontalClassMerging";
- private final String NEST_MAIN_CLASS_1A = NEST_MAIN_CLASS_1 + "$A";
- private final String NEST_MAIN_CLASS_1B = NEST_MAIN_CLASS_1 + "$B";
- private final String NEST_MAIN_CLASS_2 = PACKAGE_NAME + "BasicNestHostHorizontalClassMerging2";
- private final String NEST_MAIN_CLASS_2A = NEST_MAIN_CLASS_2 + "$A";
- private final String NEST_MAIN_CLASS_2B = NEST_MAIN_CLASS_2 + "$B";
+ public static class R extends ExamplesJava11RootPackage {
+ public static class horizontalclassmerging extends ExamplesPackage {
+ public static class BasicNestHostHorizontalClassMerging extends ExamplesClass {
+ public static class A extends ExamplesClass {}
- private List<Path> resolveProgramFiles() {
- return ImmutableList.of(
- NEST_MAIN_CLASS_1,
- NEST_MAIN_CLASS_1A,
- NEST_MAIN_CLASS_1B,
- NEST_MAIN_CLASS_2,
- NEST_MAIN_CLASS_2A,
- NEST_MAIN_CLASS_2B)
- .stream()
- .map(NestAccessControlTestUtils.CLASSES_PATH::resolve)
- .collect(Collectors.toList());
+ public static class B extends ExamplesClass {}
+ }
+
+ public static class BasicNestHostHorizontalClassMerging2 extends ExamplesClass {
+ public static class A extends ExamplesClass {}
+
+ public static class B extends ExamplesClass {}
+ }
+ }
}
public NestClassTest(TestParameters parameters, boolean enableHorizontalClassMerging) {
@@ -59,21 +55,27 @@
@Test
public void testR8() throws Exception {
testForR8(parameters.getBackend())
- .addKeepMainRule(NEST_MAIN_CLASS_1)
- .addProgramFiles(resolveProgramFiles())
+ .addKeepMainRule(examplesTypeName(BasicNestHostHorizontalClassMerging.class))
+ .addExamplesProgramFiles(R.class)
.addOptionsModification(
options -> options.enableHorizontalClassMerging = enableHorizontalClassMerging)
.enableInliningAnnotations()
.enableNeverClassInliningAnnotations()
.compile()
- .run(parameters.getRuntime(), NEST_MAIN_CLASS_1)
+ .run(parameters.getRuntime(), examplesTypeName(BasicNestHostHorizontalClassMerging.class))
.assertSuccessWithOutputLines("1: a", "1: b", "2: a", "2: b")
.inspect(
codeInspector -> {
- ClassSubject class1A = codeInspector.clazz(NEST_MAIN_CLASS_1A);
- ClassSubject class2A = codeInspector.clazz(NEST_MAIN_CLASS_2A);
- ClassSubject class1 = codeInspector.clazz(NEST_MAIN_CLASS_1);
- ClassSubject class2 = codeInspector.clazz(NEST_MAIN_CLASS_2);
+ ClassSubject class1A =
+ codeInspector.clazz(
+ examplesTypeName(BasicNestHostHorizontalClassMerging.A.class));
+ ClassSubject class2A =
+ codeInspector.clazz(
+ examplesTypeName(BasicNestHostHorizontalClassMerging2.A.class));
+ ClassSubject class1 =
+ codeInspector.clazz(examplesTypeName(BasicNestHostHorizontalClassMerging.class));
+ ClassSubject class2 =
+ codeInspector.clazz(examplesTypeName(BasicNestHostHorizontalClassMerging2.class));
assertThat(class1, isPresent());
assertThat(class2, isPresent());
assertThat(class1A, isPresent());
@@ -90,13 +92,16 @@
assertThat(printClass2MethodSubject, isPrivate());
assertThat(printClass2MethodSubject, isStatic());
- if (enableHorizontalClassMerging) {
- assertThat(codeInspector.clazz(NEST_MAIN_CLASS_1B), not(isPresent()));
- assertThat(codeInspector.clazz(NEST_MAIN_CLASS_2B), not(isPresent()));
- } else {
- assertThat(codeInspector.clazz(NEST_MAIN_CLASS_1B), isPresent());
- assertThat(codeInspector.clazz(NEST_MAIN_CLASS_2B), isPresent());
- }
+ assertThat(
+ codeInspector.clazz(
+ examplesTypeName(BasicNestHostHorizontalClassMerging.B.class)),
+ notIf(isPresent(), enableHorizontalClassMerging));
+ assertThat(
+ codeInspector.clazz(
+ examplesTypeName(BasicNestHostHorizontalClassMerging2.B.class)),
+ notIf(isPresent(), enableHorizontalClassMerging));
+
+ // TODO(b/165517236): Explicitly check 1.B is merged into 1.A, and 2.B into 2.A.
});
}
}
diff --git a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestClassMergingTest.java b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestClassMergingTest.java
index b65e764..e45ef92 100644
--- a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestClassMergingTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestClassMergingTest.java
@@ -96,7 +96,7 @@
options.enableClassInlining = false;
options.enableNestReduction = false;
})
- .enableInliningAnnotations("nesthostexample")
+ .enableInliningAnnotations()
.addProgramFiles(bothNestsAndOutsideClassToCompile)
.compile()
.inspect(NestAttributesUpdateTest::assertNestAttributesCorrect);
diff --git a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestMethodInlinedTest.java b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestMethodInlinedTest.java
index 4fcfea3..373f6fc 100644
--- a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestMethodInlinedTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestMethodInlinedTest.java
@@ -59,7 +59,7 @@
options.enableClassInlining = false;
options.enableVerticalClassMerging = false;
})
- .enableInliningAnnotations("nesthostexample")
+ .enableInliningAnnotations()
.addProgramFiles(toCompile)
.compile()
.inspect(this::assertMethodsInlined)
diff --git a/src/test/java/com/android/tools/r8/utils/ReflectiveBuildPathUtils.java b/src/test/java/com/android/tools/r8/utils/ReflectiveBuildPathUtils.java
new file mode 100644
index 0000000..ed991f2
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/utils/ReflectiveBuildPathUtils.java
@@ -0,0 +1,168 @@
+// 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;
+
+import com.android.tools.r8.ToolHelper;
+import com.google.common.collect.Iterables;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+public class ReflectiveBuildPathUtils {
+
+ public interface PackageUtils {
+ String getPackageName() throws Exception;
+
+ Path getPackagePath() throws Exception;
+
+ PackageUtils getParentPackageUtils() throws Exception;
+
+ Iterable<PackageUtils> getAllPackageUtils();
+ }
+
+ public interface ClassUtils {
+ String getClassName() throws Exception;
+
+ String getSimpleClassName() throws Exception;
+
+ Path getClassPath() throws Exception;
+ }
+
+ public abstract static class ExamplesRootPackage implements PackageUtils {
+ public abstract Path getPackagePath();
+
+ @Override
+ public String getPackageName() {
+ return "";
+ }
+
+ @Override
+ public PackageUtils getParentPackageUtils() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Iterable<PackageUtils> getAllPackageUtils() {
+ return instantiateAllPackageUtils(getClass());
+ }
+ }
+
+ public abstract static class ExamplesJava11RootPackage extends ExamplesRootPackage {
+ @Override
+ public Path getPackagePath() {
+ return Paths.get(ToolHelper.EXAMPLES_JAVA11_BUILD_DIR);
+ }
+ }
+
+ public abstract static class ExamplesPackage implements PackageUtils {
+ public List<String> getName() {
+ return Collections.singletonList(getClass().getSimpleName());
+ }
+
+ @Override
+ public PackageUtils getParentPackageUtils() throws Exception {
+ return (PackageUtils) getClass().getDeclaringClass().getConstructor().newInstance();
+ }
+
+ @Override
+ public Path getPackagePath() throws Exception {
+ Path path = getParentPackageUtils().getPackagePath();
+ for (String folder : getName()) {
+ path = path.resolve(folder);
+ }
+ return path;
+ }
+
+ @Override
+ public String getPackageName() throws Exception {
+ return getParentPackageUtils().getPackageName() + String.join(".", getName()) + ".";
+ }
+
+ @Override
+ public Iterable<PackageUtils> getAllPackageUtils() {
+ return instantiateAllPackageUtils(getClass());
+ }
+ }
+
+ public static class ExamplesClass implements PackageUtils, ClassUtils {
+ @Override
+ public PackageUtils getParentPackageUtils() throws Exception {
+ return (PackageUtils) getClass().getDeclaringClass().getConstructor().newInstance();
+ }
+
+ public String getSimpleClassName() throws Exception {
+ Object parent = getClass().getDeclaringClass().getConstructor().newInstance();
+ if (parent instanceof ClassUtils) {
+ return ((ClassUtils) parent).getSimpleClassName() + "$" + getClass().getSimpleName();
+ } else {
+ return getClass().getSimpleName();
+ }
+ }
+
+ @Override
+ public String getClassName() throws Exception {
+ return getParentPackageUtils().getPackageName() + getSimpleClassName();
+ }
+
+ @Override
+ public Path getClassPath() throws Exception {
+ return getParentPackageUtils().getPackagePath().resolve(getSimpleClassName() + ".class");
+ }
+
+ @Override
+ public String getPackageName() throws Exception {
+ return getParentPackageUtils().getPackageName();
+ }
+
+ @Override
+ public Path getPackagePath() throws Exception {
+ return getParentPackageUtils().getPackagePath();
+ }
+
+ @Override
+ public Iterable<PackageUtils> getAllPackageUtils() {
+ return instantiateAllPackageUtils(getClass());
+ }
+ }
+
+ public static Iterable<PackageUtils> instantiateAllPackageUtils(Class<?> parentClazz) {
+ Collection<PackageUtils> children = instantiatePackageUtils(parentClazz);
+ return Iterables.concat(
+ children,
+ Iterables.concat(Iterables.transform(children, PackageUtils::getAllPackageUtils)));
+ }
+
+ public static Collection<PackageUtils> instantiatePackageUtils(Class<?> parentClazz) {
+ Collection<PackageUtils> packageUtils = new ArrayList<>();
+ for (Class<?> clazz : parentClazz.getDeclaredClasses()) {
+ try {
+ Object obj = clazz.getConstructor().newInstance();
+ if (obj instanceof PackageUtils) {
+ packageUtils.add((PackageUtils) obj);
+ }
+ } catch (Exception ex) {
+ }
+ }
+ return packageUtils;
+ }
+
+ public static String resolveClassName(Class<? extends ExamplesClass> clazz) throws Exception {
+ return clazz.getConstructor().newInstance().getClassName();
+ }
+
+ public static Collection<Path> allClassFiles(Class<? extends ExamplesRootPackage> clazz)
+ throws Exception {
+ Collection<Path> classFiles = new ArrayList<>();
+ for (PackageUtils util : clazz.getConstructor().newInstance().getAllPackageUtils()) {
+ if (util instanceof ClassUtils) {
+ classFiles.add(((ClassUtils) util).getClassPath());
+ }
+ }
+ return classFiles;
+ }
+}