Unify handling of scoped and global mapping information.
Change-Id: I6e1f0eb64d52d9ec6ebe1004c4276ed97fb35e78
diff --git a/src/main/java/com/android/tools/r8/naming/ClassNameMapper.java b/src/main/java/com/android/tools/r8/naming/ClassNameMapper.java
index 14c2179..70ca4dd 100644
--- a/src/main/java/com/android/tools/r8/naming/ClassNameMapper.java
+++ b/src/main/java/com/android/tools/r8/naming/ClassNameMapper.java
@@ -16,9 +16,9 @@
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.naming.MemberNaming.Signature;
import com.android.tools.r8.naming.mappinginformation.MappingInformation;
-import com.android.tools.r8.naming.mappinginformation.ScopedMappingInformation;
import com.android.tools.r8.naming.mappinginformation.ScopedMappingInformation.ScopeReference;
import com.android.tools.r8.position.Position;
+import com.android.tools.r8.references.Reference;
import com.android.tools.r8.utils.BiMapContainer;
import com.android.tools.r8.utils.ChainableStringConsumer;
import com.android.tools.r8.utils.Reporter;
@@ -39,6 +39,7 @@
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.function.Consumer;
public class ClassNameMapper implements ProguardMap {
@@ -65,10 +66,18 @@
}
@Override
- void addScopedMappingInformation(ScopedMappingInformation scopedMappingInformation) {
- scopedMappingInformation.forEach(
- (ref, info) ->
- scopedMappingInfo.computeIfAbsent(ref, ignoreArgument(ArrayList::new)).add(info));
+ public void addMappingInformation(
+ ScopeReference reference,
+ MappingInformation info,
+ Consumer<MappingInformation> onProhibitedAddition) {
+ List<MappingInformation> additionalMappings =
+ scopedMappingInfo.computeIfAbsent(reference, ignoreArgument(ArrayList::new));
+ for (MappingInformation existing : additionalMappings) {
+ if (!existing.allowOther(info)) {
+ onProhibitedAddition.accept(existing);
+ }
+ }
+ additionalMappings.add(info);
}
@Override
@@ -87,9 +96,11 @@
private ImmutableMap<String, ClassNamingForNameMapper> buildClassNameMappings() {
// Ensure that all scoped references have at least the identity in the final mapping.
for (ScopeReference reference : scopedMappingInfo.keySet()) {
- mapping.computeIfAbsent(
- reference.getHolderReference().getTypeName(),
- t -> ClassNamingForNameMapper.builder(t, t));
+ if (!reference.isGlobalScope()) {
+ mapping.computeIfAbsent(
+ reference.getHolderReference().getTypeName(),
+ t -> ClassNamingForNameMapper.builder(t, t));
+ }
}
ImmutableMap.Builder<String, ClassNamingForNameMapper> builder = ImmutableMap.builder();
builder.orderEntriesByValue(Comparator.comparing(x -> x.originalName));
@@ -266,7 +277,10 @@
// deterministic (and easy to navigate manually).
assert verifyIsSorted();
for (ClassNamingForNameMapper naming : getClassNameMappings().values()) {
- naming.write(consumer);
+ List<MappingInformation> additionalMappingInfo =
+ getAdditionalMappingInfo(
+ ScopeReference.fromClassReference(Reference.classFromTypeName(naming.renamedName)));
+ naming.write(consumer, additionalMappingInfo);
}
}
diff --git a/src/main/java/com/android/tools/r8/naming/ClassNaming.java b/src/main/java/com/android/tools/r8/naming/ClassNaming.java
index 5a282d0..429ed45 100644
--- a/src/main/java/com/android/tools/r8/naming/ClassNaming.java
+++ b/src/main/java/com/android/tools/r8/naming/ClassNaming.java
@@ -3,9 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.naming;
-import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.naming.MemberNaming.Signature;
-import com.android.tools.r8.naming.mappinginformation.MappingInformation;
import com.android.tools.r8.utils.ThrowingConsumer;
/**
@@ -19,13 +17,6 @@
public abstract Builder addMemberEntry(MemberNaming entry);
- public abstract Builder addMappingInformation(MappingInformation mappingInformation);
-
- public abstract Builder addMappingInformation(
- MappingInformation mappingInformation,
- DiagnosticsHandler diagnosticsHandler,
- int lineNumber);
-
public abstract ClassNaming build();
/** This is an optional method, may be implemented as no-op */
diff --git a/src/main/java/com/android/tools/r8/naming/ClassNamingForMapApplier.java b/src/main/java/com/android/tools/r8/naming/ClassNamingForMapApplier.java
index acbb577..c8e2f2b 100644
--- a/src/main/java/com/android/tools/r8/naming/ClassNamingForMapApplier.java
+++ b/src/main/java/com/android/tools/r8/naming/ClassNamingForMapApplier.java
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.naming;
-import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
@@ -11,7 +10,6 @@
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.naming.MemberNaming.Signature;
import com.android.tools.r8.naming.MemberNaming.Signature.SignatureKind;
-import com.android.tools.r8.naming.mappinginformation.MappingInformation;
import com.android.tools.r8.position.Position;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.ThrowingConsumer;
@@ -78,21 +76,6 @@
}
@Override
- public ClassNaming.Builder addMappingInformation(MappingInformation mappingInformation) {
- // Intentionally kept empty until we support additional information with -applymapping.
- return this;
- }
-
- @Override
- public ClassNaming.Builder addMappingInformation(
- MappingInformation mappingInformation,
- DiagnosticsHandler diagnosticsHandler,
- int lineNumber) {
- // Intentionally kept empty until we support additional information with -applymapping.
- return this;
- }
-
- @Override
public ClassNamingForMapApplier build() {
return new ClassNamingForMapApplier(
renamedName, originalName, position, qualifiedMethodMembers, methodMembers, fieldMembers);
diff --git a/src/main/java/com/android/tools/r8/naming/ClassNamingForNameMapper.java b/src/main/java/com/android/tools/r8/naming/ClassNamingForNameMapper.java
index fb084f1..523184b 100644
--- a/src/main/java/com/android/tools/r8/naming/ClassNamingForNameMapper.java
+++ b/src/main/java/com/android/tools/r8/naming/ClassNamingForNameMapper.java
@@ -3,16 +3,13 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.naming;
-import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.naming.MemberNaming.FieldSignature;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.naming.MemberNaming.Signature;
import com.android.tools.r8.naming.MemberNaming.Signature.SignatureKind;
import com.android.tools.r8.naming.mappinginformation.MappingInformation;
-import com.android.tools.r8.naming.mappinginformation.MappingInformationDiagnostics;
import com.android.tools.r8.utils.ChainableStringConsumer;
import com.android.tools.r8.utils.ThrowingConsumer;
-import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import java.util.ArrayList;
@@ -23,7 +20,6 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
-import java.util.function.Consumer;
/**
* Stores name information for a class.
@@ -40,7 +36,6 @@
private final Map<FieldSignature, MemberNaming> fieldMembers = Maps.newHashMap();
private final Map<String, List<MappedRange>> mappedRangesByName = Maps.newHashMap();
private final Map<String, List<MemberNaming>> mappedFieldNamingsByName = Maps.newHashMap();
- private final List<MappingInformation> additionalMappings = new ArrayList<>();
private Builder(String renamedName, String originalName) {
this.originalName = originalName;
@@ -61,39 +56,6 @@
}
@Override
- public ClassNaming.Builder addMappingInformation(MappingInformation mappingInformation) {
- return addMappingInformation(
- mappingInformation,
- other -> {
- assert false;
- });
- }
-
- @Override
- public ClassNaming.Builder addMappingInformation(
- MappingInformation mappingInformation,
- DiagnosticsHandler diagnosticsHandler,
- int lineNumber) {
- return addMappingInformation(
- mappingInformation,
- other ->
- diagnosticsHandler.warning(
- MappingInformationDiagnostics.notAllowedCombination(
- originalName, renamedName, mappingInformation, other, lineNumber)));
- }
-
- private ClassNaming.Builder addMappingInformation(
- MappingInformation mappingInformation, Consumer<MappingInformation> notAllowedCombination) {
- for (MappingInformation information : additionalMappings) {
- if (!information.allowOther(mappingInformation)) {
- notAllowedCombination.accept(information);
- }
- }
- additionalMappings.add(mappingInformation);
- return this;
- }
-
- @Override
public ClassNamingForNameMapper build() {
Map<String, MappedRangesOfName> map;
@@ -107,13 +69,7 @@
}
return new ClassNamingForNameMapper(
- renamedName,
- originalName,
- methodMembers,
- fieldMembers,
- map,
- mappedFieldNamingsByName,
- ImmutableList.copyOf(additionalMappings));
+ renamedName, originalName, methodMembers, fieldMembers, map, mappedFieldNamingsByName);
}
/** The parameters are forwarded to MappedRange constructor, see explanation there. */
@@ -244,24 +200,19 @@
public final Map<String, List<MemberNaming>> mappedFieldNamingsByName;
- private final ImmutableList<MappingInformation> additionalMappings;
-
private ClassNamingForNameMapper(
String renamedName,
String originalName,
Map<MethodSignature, MemberNaming> methodMembers,
Map<FieldSignature, MemberNaming> fieldMembers,
Map<String, MappedRangesOfName> mappedRangesByRenamedName,
- Map<String, List<MemberNaming>> mappedFieldNamingsByName,
- ImmutableList<MappingInformation> additionalMappings) {
+ Map<String, List<MemberNaming>> mappedFieldNamingsByName) {
this.renamedName = renamedName;
this.originalName = originalName;
this.methodMembers = ImmutableMap.copyOf(methodMembers);
this.fieldMembers = ImmutableMap.copyOf(fieldMembers);
this.mappedRangesByRenamedName = mappedRangesByRenamedName;
this.mappedFieldNamingsByName = mappedFieldNamingsByName;
- assert additionalMappings != null;
- this.additionalMappings = additionalMappings;
}
public MappedRangesOfName getMappedRangesForRenamedName(String renamedName) {
@@ -346,11 +297,11 @@
return methodMembers.values();
}
- void write(ChainableStringConsumer consumer) {
+ void write(ChainableStringConsumer consumer, List<MappingInformation> additionalMappingInfo) {
consumer.accept(originalName).accept(" -> ").accept(renamedName).accept(":\n");
// Print all additional mapping information.
- additionalMappings.forEach(info -> consumer.accept("# " + info.serialize()).accept("\n"));
+ additionalMappingInfo.forEach(info -> consumer.accept("# " + info.serialize()).accept("\n"));
// Print field member namings.
forAllFieldNaming(m -> consumer.accept(" ").accept(m.toString()).accept("\n"));
@@ -367,14 +318,10 @@
}
}
- public List<MappingInformation> getAdditionalMappings() {
- return additionalMappings;
- }
-
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
- write(ChainableStringConsumer.wrap(builder::append));
+ write(ChainableStringConsumer.wrap(builder::append), Collections.emptyList());
return builder.toString();
}
diff --git a/src/main/java/com/android/tools/r8/naming/ProguardMap.java b/src/main/java/com/android/tools/r8/naming/ProguardMap.java
index f56e3b8..ee8303f 100644
--- a/src/main/java/com/android/tools/r8/naming/ProguardMap.java
+++ b/src/main/java/com/android/tools/r8/naming/ProguardMap.java
@@ -4,8 +4,10 @@
package com.android.tools.r8.naming;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.naming.mappinginformation.ScopedMappingInformation;
+import com.android.tools.r8.naming.mappinginformation.MappingInformation;
+import com.android.tools.r8.naming.mappinginformation.ScopedMappingInformation.ScopeReference;
import com.android.tools.r8.position.Position;
+import java.util.function.Consumer;
public interface ProguardMap {
@@ -15,7 +17,10 @@
abstract ProguardMap build();
- abstract void addScopedMappingInformation(ScopedMappingInformation scopedMappingInformation);
+ abstract void addMappingInformation(
+ ScopeReference scope,
+ MappingInformation MappingInformation,
+ Consumer<MappingInformation> onProhibitedAddition);
}
boolean hasMapping(DexType type);
diff --git a/src/main/java/com/android/tools/r8/naming/ProguardMapReader.java b/src/main/java/com/android/tools/r8/naming/ProguardMapReader.java
index d7ab9c8..c03cb20 100644
--- a/src/main/java/com/android/tools/r8/naming/ProguardMapReader.java
+++ b/src/main/java/com/android/tools/r8/naming/ProguardMapReader.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.naming.MemberNaming.Signature;
import com.android.tools.r8.naming.ProguardMap.Builder;
import com.android.tools.r8.naming.mappinginformation.MappingInformation;
+import com.android.tools.r8.naming.mappinginformation.MappingInformationDiagnostics;
import com.android.tools.r8.naming.mappinginformation.MetaInfMappingInformation;
import com.android.tools.r8.naming.mappinginformation.ScopedMappingInformation.ClassScopeReference;
import com.android.tools.r8.naming.mappinginformation.ScopedMappingInformation.ScopeReference;
@@ -24,6 +25,7 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
+import java.util.function.BiConsumer;
/**
* Parses a Proguard mapping file and produces mappings from obfuscated class names to the original
@@ -88,7 +90,7 @@
private int lineOffset = 0;
private String line;
private MapVersion version = MapVersion.MapVersionNone;
- private ScopeReference implicitSingletonScope = null;
+ private ScopeReference implicitSingletonScope = ScopeReference.globalScope();
private int peekCodePoint() {
return lineOffset < line.length() ? line.codePointAt(lineOffset) : '\n';
@@ -224,12 +226,17 @@
// Parsing of entries
private void parseClassMappings(ProguardMap.Builder mapBuilder) throws IOException {
+ assert implicitSingletonScope == ScopeReference.globalScope();
while (hasLine()) {
skipWhitespace();
if (isCommentLineWithJsonBrace()) {
- // TODO(b/179665169): Parse the mapping information without doing anything with it, since we
- // at this point do not have a global context.
- parseMappingInformation();
+ parseMappingInformation(
+ (reference, info) -> {
+ if (!reference.isGlobalScope()) {
+ diagnosticsHandler.error(
+ MappingInformationDiagnostics.invalidScopeFor(lineNo, reference, info));
+ }
+ });
// Skip reading the rest of the line.
lineOffset = line.length();
nextLine();
@@ -260,18 +267,23 @@
}
}
- private MappingInformation parseMappingInformation() {
+ private void parseMappingInformation(
+ BiConsumer<ScopeReference, MappingInformation> onMappingInfo) {
MappingInformation info =
MappingInformation.fromJsonObject(
version, parseJsonInComment(), diagnosticsHandler, lineNo, implicitSingletonScope);
if (info == null) {
- return null;
+ return;
}
MetaInfMappingInformation generatorInfo = info.asMetaInfMappingInformation();
if (generatorInfo != null) {
version = generatorInfo.getMapVersion();
}
- return info;
+ if (info.isScopedMappingInformation()) {
+ info.asScopedMappingInformation().forEach(onMappingInfo);
+ } else {
+ onMappingInfo.accept(ScopeReference.globalScope(), info);
+ }
}
private void parseMemberMappings(Builder mapBuilder, ClassNaming.Builder classNamingBuilder)
@@ -284,14 +296,15 @@
Range mappedRange = null;
// Try to parse any information added in comments above member namings
if (isCommentLineWithJsonBrace()) {
- MappingInformation mappingInfo = parseMappingInformation();
- if (mappingInfo != null) {
- if (mappingInfo.isScopedMappingInformation()) {
- mapBuilder.addScopedMappingInformation(mappingInfo.asScopedMappingInformation());
- } else {
- classNamingBuilder.addMappingInformation(mappingInfo, diagnosticsHandler, lineNo);
- }
- }
+ parseMappingInformation(
+ (reference, mappingInfo) ->
+ mapBuilder.addMappingInformation(
+ reference,
+ mappingInfo,
+ conflictingInfo ->
+ diagnosticsHandler.warning(
+ MappingInformationDiagnostics.notAllowedCombination(
+ reference, mappingInfo, conflictingInfo, lineNo))));
// Skip reading the rest of the line.
lineOffset = line.length();
continue;
diff --git a/src/main/java/com/android/tools/r8/naming/SeedMapper.java b/src/main/java/com/android/tools/r8/naming/SeedMapper.java
index 2e5b125..863a2b1 100644
--- a/src/main/java/com/android/tools/r8/naming/SeedMapper.java
+++ b/src/main/java/com/android/tools/r8/naming/SeedMapper.java
@@ -9,7 +9,8 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.naming.MemberNaming.Signature;
-import com.android.tools.r8.naming.mappinginformation.ScopedMappingInformation;
+import com.android.tools.r8.naming.mappinginformation.MappingInformation;
+import com.android.tools.r8.naming.mappinginformation.ScopedMappingInformation.ScopeReference;
import com.android.tools.r8.position.Position;
import com.android.tools.r8.utils.Reporter;
import com.google.common.collect.ImmutableMap;
@@ -24,6 +25,7 @@
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
+import java.util.function.Consumer;
/**
* Mappings read from the given ProGuard map.
@@ -62,7 +64,10 @@
}
@Override
- void addScopedMappingInformation(ScopedMappingInformation scopedMappingInformation) {
+ void addMappingInformation(
+ ScopeReference scope,
+ MappingInformation MappingInformation,
+ Consumer<MappingInformation> onProhibitedAddition) {
// Not needed.
}
diff --git a/src/main/java/com/android/tools/r8/naming/mappinginformation/CompilerSynthesizedMappingInformation.java b/src/main/java/com/android/tools/r8/naming/mappinginformation/CompilerSynthesizedMappingInformation.java
index d44e5e6..a49c4de 100644
--- a/src/main/java/com/android/tools/r8/naming/mappinginformation/CompilerSynthesizedMappingInformation.java
+++ b/src/main/java/com/android/tools/r8/naming/mappinginformation/CompilerSynthesizedMappingInformation.java
@@ -40,6 +40,11 @@
}
@Override
+ public String getId() {
+ return ID;
+ }
+
+ @Override
public boolean isCompilerSynthesizedMappingInformation() {
return true;
}
diff --git a/src/main/java/com/android/tools/r8/naming/mappinginformation/FileNameInformation.java b/src/main/java/com/android/tools/r8/naming/mappinginformation/FileNameInformation.java
index 38eabbf..39d0072 100644
--- a/src/main/java/com/android/tools/r8/naming/mappinginformation/FileNameInformation.java
+++ b/src/main/java/com/android/tools/r8/naming/mappinginformation/FileNameInformation.java
@@ -6,35 +6,33 @@
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.naming.MapVersion;
+import com.google.common.collect.ImmutableList;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
-public class FileNameInformation extends MappingInformation {
+public class FileNameInformation extends ScopedMappingInformation {
private final String fileName;
public static final String ID = "sourceFile";
static final String FILE_NAME_KEY = "fileName";
- private FileNameInformation(String fileName) {
- super(NO_LINE_NUMBER);
+ private FileNameInformation(String fileName, ImmutableList<ScopeReference> scopeReferences) {
+ super(scopeReferences);
this.fileName = fileName;
}
+ @Override
+ public String getId() {
+ return ID;
+ }
+
public String getFileName() {
return fileName;
}
@Override
- public String serialize() {
- JsonObject result = new JsonObject();
- result.add(MAPPING_ID_KEY, new JsonPrimitive(ID));
- result.add(FILE_NAME_KEY, new JsonPrimitive(fileName));
- return result.toString();
- }
-
- @Override
public boolean isFileNameInformation() {
return true;
}
@@ -49,23 +47,39 @@
return !information.isFileNameInformation();
}
- public static FileNameInformation build(String fileName) {
- return new FileNameInformation(fileName);
+ public static FileNameInformation build(ScopeReference classScope, String fileName) {
+ return new FileNameInformation(fileName, ImmutableList.of(classScope));
}
- public static FileNameInformation build(
+ // Hard override of serialize as there is no current support for scope in source-file info.
+ // This should be removed for experimental support of scope in the external format.
+ @Override
+ public String serialize() {
+ return serializeToJsonObject(new JsonObject()).toString();
+ }
+
+ @Override
+ protected JsonObject serializeToJsonObject(JsonObject object) {
+ object.add(MAPPING_ID_KEY, new JsonPrimitive(ID));
+ object.add(FILE_NAME_KEY, new JsonPrimitive(fileName));
+ return object;
+ }
+
+ public static FileNameInformation deserialize(
MapVersion version,
JsonObject object,
DiagnosticsHandler diagnosticsHandler,
- int lineNumber) {
- // Source file information is valid for all map file versions.
+ int lineNumber,
+ ScopeReference implicitSingletonScope) {
+ assert implicitSingletonScope instanceof ClassScopeReference;
try {
JsonElement fileName =
getJsonElementFromObject(object, diagnosticsHandler, lineNumber, FILE_NAME_KEY, ID);
if (fileName == null) {
return null;
}
- return new FileNameInformation(fileName.getAsString());
+ return new FileNameInformation(
+ fileName.getAsString(), ImmutableList.of(implicitSingletonScope));
} catch (UnsupportedOperationException | IllegalStateException ignored) {
diagnosticsHandler.info(
MappingInformationDiagnostics.invalidValueForObjectWithId(lineNumber, FILE_NAME_KEY, ID));
diff --git a/src/main/java/com/android/tools/r8/naming/mappinginformation/MappingInformation.java b/src/main/java/com/android/tools/r8/naming/mappinginformation/MappingInformation.java
index 0ef03d0..beb0b29 100644
--- a/src/main/java/com/android/tools/r8/naming/mappinginformation/MappingInformation.java
+++ b/src/main/java/com/android/tools/r8/naming/mappinginformation/MappingInformation.java
@@ -22,6 +22,8 @@
this.lineNumber = lineNumber;
}
+ public abstract String getId();
+
public int getLineNumber() {
return lineNumber;
}
@@ -100,7 +102,8 @@
return MetaInfMappingInformation.deserialize(
version, object, diagnosticsHandler, lineNumber);
case FileNameInformation.ID:
- return FileNameInformation.build(version, object, diagnosticsHandler, lineNumber);
+ return FileNameInformation.deserialize(
+ version, object, diagnosticsHandler, lineNumber, implicitSingletonScope);
case CompilerSynthesizedMappingInformation.ID:
return CompilerSynthesizedMappingInformation.deserialize(
version, object, diagnosticsHandler, lineNumber, implicitSingletonScope);
diff --git a/src/main/java/com/android/tools/r8/naming/mappinginformation/MappingInformationDiagnostics.java b/src/main/java/com/android/tools/r8/naming/mappinginformation/MappingInformationDiagnostics.java
index 6cc0b28..42cb7ba 100644
--- a/src/main/java/com/android/tools/r8/naming/mappinginformation/MappingInformationDiagnostics.java
+++ b/src/main/java/com/android/tools/r8/naming/mappinginformation/MappingInformationDiagnostics.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.Diagnostic;
import com.android.tools.r8.Keep;
+import com.android.tools.r8.naming.mappinginformation.ScopedMappingInformation.ScopeReference;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.position.Position;
import com.android.tools.r8.position.TextPosition;
@@ -36,6 +37,14 @@
this.position = position;
}
+ public static MappingInformationDiagnostics invalidScopeFor(
+ int lineNumber, ScopeReference reference, MappingInformation info) {
+ return new MappingInformationDiagnostics(
+ String.format(
+ "Cannot use scope %s for mapping information %s", reference.toString(), info.getId()),
+ new TextPosition(1, lineNumber, TextPosition.UNKNOWN_COLUMN));
+ }
+
static MappingInformationDiagnostics noHandlerFor(int lineNumber, String value) {
return new MappingInformationDiagnostics(
String.format("Could not find a handler for %s", value),
@@ -94,20 +103,14 @@
}
public static MappingInformationDiagnostics notAllowedCombination(
- String className,
- String renamedClassName,
- MappingInformation one,
- MappingInformation other,
- int lineNumber) {
+ ScopeReference reference, MappingInformation one, MappingInformation other, int lineNumber) {
return new MappingInformationDiagnostics(
"The mapping '"
+ one.serialize()
+ "' is not allowed in combination with '"
+ other.serialize()
+ "' in the mapping for "
- + className
- + " -> "
- + renamedClassName,
+ + reference.toString(),
new TextPosition(1, lineNumber, TextPosition.UNKNOWN_COLUMN));
}
}
diff --git a/src/main/java/com/android/tools/r8/naming/mappinginformation/MetaInfMappingInformation.java b/src/main/java/com/android/tools/r8/naming/mappinginformation/MetaInfMappingInformation.java
index ba6bb72..abe2990 100644
--- a/src/main/java/com/android/tools/r8/naming/mappinginformation/MetaInfMappingInformation.java
+++ b/src/main/java/com/android/tools/r8/naming/mappinginformation/MetaInfMappingInformation.java
@@ -24,6 +24,11 @@
}
@Override
+ public String getId() {
+ return ID;
+ }
+
+ @Override
public boolean isMetaInfMappingInformation() {
return true;
}
@@ -35,7 +40,7 @@
@Override
public boolean allowOther(MappingInformation information) {
- return !information.isMetaInfMappingInformation();
+ return true;
}
public MapVersion getMapVersion() {
diff --git a/src/main/java/com/android/tools/r8/naming/mappinginformation/ScopedMappingInformation.java b/src/main/java/com/android/tools/r8/naming/mappinginformation/ScopedMappingInformation.java
index 4385f5a..e3f43d5 100644
--- a/src/main/java/com/android/tools/r8/naming/mappinginformation/ScopedMappingInformation.java
+++ b/src/main/java/com/android/tools/r8/naming/mappinginformation/ScopedMappingInformation.java
@@ -5,6 +5,7 @@
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.errors.Unimplemented;
+import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.utils.DescriptorUtils;
@@ -22,6 +23,10 @@
// to map to java.lang.String with the post-minification names.
public abstract static class ScopeReference {
+ public static ScopeReference globalScope() {
+ return GlobalScopeReference.INSTANCE;
+ }
+
public static ScopeReference fromClassReference(ClassReference reference) {
return new ClassScopeReference(reference);
}
@@ -34,6 +39,10 @@
throw new Unimplemented("No support for reference: " + referenceString);
}
+ public boolean isGlobalScope() {
+ return equals(ScopeReference.globalScope());
+ }
+
public abstract String toReferenceString();
public abstract ClassReference getHolderReference();
@@ -50,6 +59,35 @@
}
}
+ public static class GlobalScopeReference extends ScopeReference {
+ private static final GlobalScopeReference INSTANCE = new GlobalScopeReference();
+
+ @Override
+ public String toReferenceString() {
+ throw new Unreachable();
+ }
+
+ @Override
+ public String toString() {
+ return "<global-scope>";
+ }
+
+ @Override
+ public ClassReference getHolderReference() {
+ throw new Unreachable();
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return this == other;
+ }
+
+ @Override
+ public int hashCode() {
+ return System.identityHashCode(this);
+ }
+ }
+
public static class ClassScopeReference extends ScopeReference {
private final ClassReference reference;
@@ -146,7 +184,7 @@
}
@Override
- public final String serialize() {
+ public String serialize() {
JsonObject object = serializeToJsonObject(new JsonObject());
JsonArray scopeArray = new JsonArray();
scopeReferences.forEach(ref -> scopeArray.add(ref.toReferenceString()));
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/RetraceClassResultImpl.java b/src/main/java/com/android/tools/r8/retrace/internal/RetraceClassResultImpl.java
index 1e9397a..1bd8c4c 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/RetraceClassResultImpl.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/RetraceClassResultImpl.java
@@ -11,6 +11,7 @@
import com.android.tools.r8.naming.ClassNamingForNameMapper.MappedRangesOfName;
import com.android.tools.r8.naming.MemberNaming;
import com.android.tools.r8.naming.mappinginformation.MappingInformation;
+import com.android.tools.r8.naming.mappinginformation.ScopedMappingInformation.ScopeReference;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.references.TypeReference;
@@ -29,20 +30,24 @@
private final ClassReference obfuscatedReference;
private final ClassNamingForNameMapper mapper;
- private final Retracer retracer;
+ private final RetracerImpl retracer;
private RetraceClassResultImpl(
- ClassReference obfuscatedReference, ClassNamingForNameMapper mapper, Retracer retracer) {
+ ClassReference obfuscatedReference, ClassNamingForNameMapper mapper, RetracerImpl retracer) {
this.obfuscatedReference = obfuscatedReference;
this.mapper = mapper;
this.retracer = retracer;
}
static RetraceClassResultImpl create(
- ClassReference obfuscatedReference, ClassNamingForNameMapper mapper, Retracer retracer) {
+ ClassReference obfuscatedReference, ClassNamingForNameMapper mapper, RetracerImpl retracer) {
return new RetraceClassResultImpl(obfuscatedReference, mapper, retracer);
}
+ RetracerImpl getRetracerImpl() {
+ return retracer;
+ }
+
@Override
public RetraceFieldResultImpl lookupField(String fieldName) {
return lookupField(FieldDefinition.create(obfuscatedReference, fieldName));
@@ -221,12 +226,13 @@
@Override
public RetraceSourceFileResultImpl retraceSourceFile(String sourceFile) {
- if (mapper != null) {
- for (MappingInformation mappingInformation : mapper.getAdditionalMappings()) {
- if (mappingInformation.isFileNameInformation()) {
- return new RetraceSourceFileResultImpl(
- mappingInformation.asFileNameInformation().getFileName(), false);
- }
+ for (MappingInformation info :
+ classResult
+ .getRetracerImpl()
+ .getAdditionalMappingInfo(
+ ScopeReference.fromClassReference(classResult.obfuscatedReference))) {
+ if (info.isFileNameInformation()) {
+ return new RetraceSourceFileResultImpl(info.asFileNameInformation().getFileName(), false);
}
}
return new RetraceSourceFileResultImpl(
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/RetracerImpl.java b/src/main/java/com/android/tools/r8/retrace/internal/RetracerImpl.java
index 03f515b..4c76e3a 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/RetracerImpl.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/RetracerImpl.java
@@ -6,6 +6,8 @@
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.naming.ClassNameMapper;
+import com.android.tools.r8.naming.mappinginformation.MappingInformation;
+import com.android.tools.r8.naming.mappinginformation.ScopedMappingInformation.ScopeReference;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.references.FieldReference;
import com.android.tools.r8.references.MethodReference;
@@ -14,13 +16,14 @@
import com.android.tools.r8.retrace.ProguardMapProducer;
import com.android.tools.r8.retrace.Retracer;
import java.io.BufferedReader;
+import java.util.Collection;
/** A default implementation for the retrace api using the ClassNameMapper defined in R8. */
public class RetracerImpl implements Retracer {
private final ClassNameMapper classNameMapper;
- private RetracerImpl(ClassNameMapper classNameMapper) {
+ public RetracerImpl(ClassNameMapper classNameMapper) {
this.classNameMapper = classNameMapper;
assert classNameMapper != null;
}
@@ -69,4 +72,8 @@
public RetraceTypeResultImpl retraceType(TypeReference typeReference) {
return RetraceTypeResultImpl.create(typeReference, this);
}
+
+ public Collection<MappingInformation> getAdditionalMappingInfo(ScopeReference reference) {
+ return classNameMapper.getAdditionalMappingInfo(reference);
+ }
}
diff --git a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
index aba61ee..890107b 100644
--- a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
+++ b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.ResourceException;
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.cf.code.CfPosition;
+import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.CfCode;
@@ -49,7 +50,7 @@
import com.android.tools.r8.naming.Range;
import com.android.tools.r8.naming.mappinginformation.CompilerSynthesizedMappingInformation;
import com.android.tools.r8.naming.mappinginformation.FileNameInformation;
-import com.android.tools.r8.naming.mappinginformation.ScopedMappingInformation.ClassScopeReference;
+import com.android.tools.r8.naming.mappinginformation.ScopedMappingInformation.ScopeReference;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.retrace.internal.RetraceUtils;
import com.android.tools.r8.shaking.KeepInfoCollection;
@@ -293,23 +294,28 @@
com.android.tools.r8.position.Position.UNKNOWN));
// Check if source file should be added to the map
+ ScopeReference classScope =
+ ScopeReference.fromClassReference(
+ Reference.classFromDescriptor(renamedDescriptor.toString()));
if (clazz.sourceFile != null) {
String sourceFile = clazz.sourceFile.toString();
if (!RetraceUtils.hasPredictableSourceFileName(clazz.toSourceString(), sourceFile)) {
- Builder builder = onDemandClassNamingBuilder.get();
- builder.addMappingInformation(FileNameInformation.build(sourceFile));
+ classNameMapperBuilder.addMappingInformation(
+ classScope,
+ FileNameInformation.build(classScope, sourceFile),
+ conflictingInfo -> {
+ throw new Unreachable();
+ });
}
}
if (isSyntheticClass && appView.options().testing.enableExperimentalMapFileVersion) {
- onDemandClassNamingBuilder
- .get()
- .addMappingInformation(
- CompilerSynthesizedMappingInformation.builder()
- .addScopeReference(
- new ClassScopeReference(
- Reference.classFromDescriptor(renamedDescriptor.toString())))
- .build());
+ classNameMapperBuilder.addMappingInformation(
+ classScope,
+ CompilerSynthesizedMappingInformation.builder().addScopeReference(classScope).build(),
+ conflictingInfo -> {
+ throw new Unreachable();
+ });
}
// If the class is renamed add it to the classNamingBuilder.
diff --git a/src/test/java/com/android/tools/r8/naming/MapReaderVersionTest.java b/src/test/java/com/android/tools/r8/naming/MapReaderVersionTest.java
index deab412..c2d5e34 100644
--- a/src/test/java/com/android/tools/r8/naming/MapReaderVersionTest.java
+++ b/src/test/java/com/android/tools/r8/naming/MapReaderVersionTest.java
@@ -6,6 +6,7 @@
import static junit.framework.TestCase.assertEquals;
import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestDiagnosticMessagesImpl;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.naming.mappinginformation.MappingInformation;
@@ -53,6 +54,7 @@
@Test
public void testConcatMapFiles() throws IOException {
+ TestDiagnosticMessagesImpl diagnostics = new TestDiagnosticMessagesImpl();
ClassNameMapper mapper =
ClassNameMapper.mapperFromString(
StringUtils.joinLines(
@@ -67,7 +69,9 @@
// concatenates).
"# { id: 'com.android.tools.r8.metainf', map-version: 'none' }",
"pkg.Baz -> a.c:",
- "# { id: 'com.android.tools.r8.synthesized' }"));
+ "# { id: 'com.android.tools.r8.synthesized' }"),
+ diagnostics);
+ diagnostics.assertNoMessages();
assertMapping("a.a", "pkg.Foo", false, mapper);
assertMapping("a.b", "pkg.Bar", true, mapper);
assertMapping("a.c", "pkg.Baz", false, mapper);
diff --git a/src/test/java/com/android/tools/r8/retrace/DuplicateMappingsTest.java b/src/test/java/com/android/tools/r8/retrace/DuplicateMappingsTest.java
index 22fcef4..7d2ec89 100644
--- a/src/test/java/com/android/tools/r8/retrace/DuplicateMappingsTest.java
+++ b/src/test/java/com/android/tools/r8/retrace/DuplicateMappingsTest.java
@@ -23,15 +23,13 @@
@RunWith(Parameterized.class)
public class DuplicateMappingsTest extends TestBase {
- private final TestParameters parameters;
-
@Parameters(name = "{0}")
public static TestParametersCollection data() {
- return getTestParameters().withAllRuntimesAndApiLevels().build();
+ return getTestParameters().withNoneRuntime().build();
}
public DuplicateMappingsTest(TestParameters parameters) {
- this.parameters = parameters;
+ parameters.assertNoneRuntime();
}
@Test
diff --git a/src/test/java/com/android/tools/r8/retrace/SourceFileTest.java b/src/test/java/com/android/tools/r8/retrace/SourceFileTest.java
index 9bfcffa..ff4296d 100644
--- a/src/test/java/com/android/tools/r8/retrace/SourceFileTest.java
+++ b/src/test/java/com/android/tools/r8/retrace/SourceFileTest.java
@@ -62,12 +62,12 @@
((stackTrace, inspector) -> {
assertEquals(FILE_NAME, stackTrace.getStackTraceLines().get(0).fileName);
assertEquals(
- 1,
+ FILE_NAME,
inspector
.clazz(ClassWithCustomFileName.class)
- .getNaming()
- .getAdditionalMappings()
- .size());
+ .retraceUnique()
+ .retraceSourceFile("nofile.java")
+ .getFilename());
}));
}
@@ -76,14 +76,15 @@
runTest(
true,
((stackTrace, inspector) -> {
+ // Since the type has a mapping, the file is inferred from the class name.
assertEquals("SourceFileTest.java", stackTrace.getStackTraceLines().get(0).fileName);
assertEquals(
- 0,
+ "SourceFileTest.java",
inspector
.clazz(ClassWithoutCustomFileName.class)
- .getNaming()
- .getAdditionalMappings()
- .size());
+ .retraceUnique()
+ .retraceSourceFile("nofile.java")
+ .getFilename());
}));
}
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 491bf9d..0e2de72f 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
@@ -10,6 +10,8 @@
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.naming.ClassNamingForNameMapper;
import com.android.tools.r8.references.ClassReference;
+import com.android.tools.r8.retrace.RetraceClassElement;
+import com.android.tools.r8.retrace.RetraceClassResult;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
@@ -213,6 +215,16 @@
}
@Override
+ public RetraceClassResult retrace() {
+ throw new Unreachable("Cannot retrace an absent class");
+ }
+
+ @Override
+ public RetraceClassElement retraceUnique() {
+ throw new Unreachable("Cannot retrace an absent class");
+ }
+
+ @Override
public ClassNamingForNameMapper getNaming() {
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 a794e67..f614059 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
@@ -14,6 +14,8 @@
import com.android.tools.r8.references.MethodReference;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.references.TypeReference;
+import com.android.tools.r8.retrace.RetraceClassElement;
+import com.android.tools.r8.retrace.RetraceClassResult;
import com.android.tools.r8.smali.SmaliBuilder;
import com.android.tools.r8.utils.ListUtils;
import com.google.common.base.Predicates;
@@ -230,6 +232,10 @@
descriptor.substring(0, descriptor.length() - 1) + COMPANION_CLASS_NAME_SUFFIX + ";"));
}
+ public abstract RetraceClassResult retrace();
+
+ public abstract RetraceClassElement retraceUnique();
+
public abstract ClassNamingForNameMapper getNaming();
public abstract String disassembleUsingJavap(boolean verbose) throws Exception;
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
index b782ae2..caea2a4 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
@@ -39,6 +39,7 @@
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.retrace.Retracer;
import com.android.tools.r8.retrace.internal.DirectClassNameMapperProguardMapProducer;
+import com.android.tools.r8.retrace.internal.RetracerImpl;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.BiMapContainer;
import com.android.tools.r8.utils.DescriptorUtils;
@@ -68,6 +69,7 @@
private final ClassNameMapper mapping;
final Map<String, String> originalToObfuscatedMapping;
final Map<String, String> obfuscatedToOriginalMapping;
+ private Retracer lazyRetracer = null;
public static MethodSignature MAIN =
new MethodSignature("main", "void", new String[] {"java.lang.String[]"});
@@ -172,6 +174,13 @@
return dexItemFactory;
}
+ public Retracer getRetracer() {
+ if (lazyRetracer == null) {
+ lazyRetracer = new RetracerImpl(mapping);
+ }
+ return lazyRetracer;
+ }
+
DexType toDexType(String string) {
return dexItemFactory.createType(DescriptorUtils.javaTypeToDescriptor(string));
}
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 c69c4a0..859f58f 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
@@ -6,6 +6,7 @@
import static com.android.tools.r8.KotlinTestBase.METADATA_TYPE;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import com.android.tools.r8.TestRuntime.CfRuntime;
import com.android.tools.r8.ToolHelper;
@@ -33,6 +34,8 @@
import com.android.tools.r8.references.FieldReference;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.references.TypeReference;
+import com.android.tools.r8.retrace.RetraceClassElement;
+import com.android.tools.r8.retrace.RetraceClassResult;
import com.android.tools.r8.retrace.RetraceTypeResult;
import com.android.tools.r8.retrace.RetracedFieldReference;
import com.android.tools.r8.retrace.Retracer;
@@ -46,6 +49,7 @@
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
+import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;
@@ -534,6 +538,25 @@
codeInspector.getFactory().kotlin, annotationSubject.getAnnotation());
}
+ public RetraceClassResult retrace() {
+ assertTrue(mapping.getNaming() != null);
+ return codeInspector
+ .getRetracer()
+ .retraceClass(Reference.classFromTypeName(mapping.getNaming().renamedName));
+ }
+
+ public RetraceClassElement retraceUnique() {
+ RetraceClassResult result = retrace();
+ if (result.isAmbiguous()) {
+ fail("Expected unique retrace of " + this + ", got ambiguous: " + result);
+ }
+ Optional<RetraceClassElement> first = result.stream().findFirst();
+ if (!first.isPresent()) {
+ fail("Expected unique retrace of " + this + ", got empty result");
+ }
+ return first.get();
+ }
+
@Override
public ClassNamingForNameMapper getNaming() {
return mapping.getNaming();