Emit SourcDebugExtension if kept when writing CF
Bug: 152630052
Change-Id: I22372260db71a3f336366f04f9be3d379fa12527
diff --git a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
index 688d59b..e04f07c 100644
--- a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
@@ -128,7 +128,8 @@
ClassWriter writer = new ClassWriter(0);
int markerStringPoolIndex = writer.newConst(markerString);
assert markerStringPoolIndex == MARKER_STRING_CONSTANT_POOL_INDEX;
- writer.visitSource(clazz.sourceFile != null ? clazz.sourceFile.toString() : null, null);
+ String sourceDebug = getSourceDebugExtension(clazz.annotations());
+ writer.visitSource(clazz.sourceFile != null ? clazz.sourceFile.toString() : null, sourceDebug);
int version = getClassFileVersion(clazz);
int access = clazz.accessFlags.getAsCfAccessFlags();
String desc = namingLens.lookupDescriptor(clazz.type).toString();
@@ -242,6 +243,16 @@
return res.toString();
}
+ private String getSourceDebugExtension(DexAnnotationSet annotations) {
+ DexValue debugExtensions =
+ getSystemAnnotationValue(
+ annotations, application.dexItemFactory.annotationSourceDebugExtension);
+ if (debugExtensions == null) {
+ return null;
+ }
+ return debugExtensions.asDexValueString().getValue().toString();
+ }
+
private ImmutableMap<DexString, DexValue> getAnnotationDefaults(DexAnnotationSet annotations) {
DexValue value =
getSystemAnnotationValue(annotations, application.dexItemFactory.annotationDefault);
diff --git a/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java b/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
index 04a1924..4bb1b2b 100644
--- a/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
+++ b/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
@@ -378,8 +378,7 @@
}
for (DexProgramClass clazz : appView.appInfo().classes()) {
// If [clazz] is mentioned by a keep rule, it could be used for reflection, and we
- // therefore
- // need to keep the enclosing method and inner classes attributes, if requested.
+ // therefore need to keep the enclosing method and inner classes attributes, if requested.
if (appView.appInfo().isPinned(clazz.type)) {
for (InnerClassAttribute innerClassAttribute : clazz.getInnerClasses()) {
DexType inner = innerClassAttribute.getInner();
diff --git a/src/test/java/com/android/tools/r8/annotations/SourceDebugExtensionTest.java b/src/test/java/com/android/tools/r8/annotations/SourceDebugExtensionTest.java
new file mode 100644
index 0000000..4a3180b
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/annotations/SourceDebugExtensionTest.java
@@ -0,0 +1,75 @@
+// 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.annotations;
+
+import static com.android.tools.r8.KotlinCompilerTool.KOTLINC;
+import static com.android.tools.r8.ToolHelper.getFilesInTestFolderRelativeToClass;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import com.android.tools.r8.CompilationFailedException;
+import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRuntime;
+import com.android.tools.r8.TestRuntime.CfRuntime;
+import com.android.tools.r8.ToolHelper.KotlinTargetVersion;
+import com.android.tools.r8.retrace.KotlinInlineFunctionRetraceTest;
+import com.android.tools.r8.shaking.ProguardKeepAttributes;
+import com.android.tools.r8.utils.codeinspector.AnnotationSubject;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.concurrent.ExecutionException;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class SourceDebugExtensionTest extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ public SourceDebugExtensionTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testR8() throws IOException, CompilationFailedException, ExecutionException {
+ CfRuntime cfRuntime =
+ parameters.isCfRuntime() ? parameters.getRuntime().asCf() : TestRuntime.getCheckedInJdk9();
+ Path kotlinSources =
+ kotlinc(cfRuntime, getStaticTemp(), KOTLINC, KotlinTargetVersion.JAVA_8)
+ .addSourceFiles(
+ getFilesInTestFolderRelativeToClass(
+ KotlinInlineFunctionRetraceTest.class, "kt", ".kt"))
+ .compile();
+ CodeInspector kotlinInspector = new CodeInspector(kotlinSources);
+ inspectSourceDebugExtension(kotlinInspector);
+ testForR8(parameters.getBackend())
+ .addProgramFiles(kotlinSources)
+ .addKeepAttributes(ProguardKeepAttributes.SOURCE_DEBUG_EXTENSION)
+ .addKeepAllClassesRule()
+ .setMode(CompilationMode.RELEASE)
+ .compile()
+ .inspect(this::inspectSourceDebugExtension);
+ }
+
+ private void inspectSourceDebugExtension(CodeInspector inspector) {
+ ClassSubject clazz = inspector.clazz("retrace.InlineFunctionKt");
+ assertThat(clazz, isPresent());
+ AnnotationSubject sourceDebugExtensions =
+ clazz.annotation("dalvik.annotation.SourceDebugExtension");
+ assertThat(sourceDebugExtensions, isPresent());
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/Matchers.java b/src/test/java/com/android/tools/r8/utils/codeinspector/Matchers.java
index 98f6b1e..3bbea86 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/Matchers.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/Matchers.java
@@ -102,8 +102,14 @@
@Override
public void describeMismatchSafely(final Subject subject, Description description) {
- description
- .appendText(type(subject) + " ").appendValue(name(subject)).appendText(" was not");
+ if (subject instanceof ClassSubject || subject instanceof MemberSubject) {
+ description
+ .appendText(type(subject) + " ")
+ .appendValue(name(subject))
+ .appendText(" was not");
+ } else {
+ description.appendText(type(subject) + " ").appendText(" was not found");
+ }
}
};
}