[Retrace] Add support for mapping information on member namings
This will allow us to not repeat referential information such as synthesized and outlining for each mapped range and it will also allow us to track rewritten and synthetic information regarding fields.
Bug: b/169953605
Bug: b/172014416
Bug: b/241763080
Bug: b/242673239
Bug: b/247116675
Change-Id: Ia912713f6b7fb584a6192d621cbccbbcf2398e59
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 6083e8b..138e738 100644
--- a/src/main/java/com/android/tools/r8/naming/ClassNaming.java
+++ b/src/main/java/com/android/tools/r8/naming/ClassNaming.java
@@ -18,7 +18,7 @@
abstract class Builder {
- public abstract Builder addMemberEntry(MemberNaming entry, Signature residualSignature);
+ public abstract Builder addMemberEntry(MemberNaming entry);
public abstract ClassNaming build();
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 93a5666..cbfb5e3 100644
--- a/src/main/java/com/android/tools/r8/naming/ClassNamingForMapApplier.java
+++ b/src/main/java/com/android/tools/r8/naming/ClassNamingForMapApplier.java
@@ -19,6 +19,7 @@
import com.google.common.collect.ImmutableMap;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -55,7 +56,7 @@
}
@Override
- public ClassNaming.Builder addMemberEntry(MemberNaming entry, Signature residualSignature) {
+ public ClassNaming.Builder addMemberEntry(MemberNaming entry) {
// Unlike {@link ClassNamingForNameMapper.Builder#addMemberEntry},
// the key is original signature.
if (entry.isMethodNaming()) {
@@ -170,32 +171,26 @@
public MemberNaming lookup(Signature renamedSignature) {
// As the key is inverted, this looks a lot like
// {@link ClassNamingForNameMapper#lookupByOriginalSignature}.
- if (renamedSignature.kind() == SignatureKind.METHOD) {
- for (MemberNaming memberNaming : methodMembers.values()) {
- if (memberNaming.getResidualSignatureInternal().equals(renamedSignature)) {
- return memberNaming;
- }
+ Collection<MemberNaming> memberNamings =
+ renamedSignature.kind() == SignatureKind.METHOD
+ ? methodMembers.values()
+ : fieldMembers.values();
+ for (MemberNaming memberNaming : memberNamings) {
+ if (memberNaming.getResidualSignature().equals(renamedSignature)) {
+ return memberNaming;
}
- return null;
- } else {
- assert renamedSignature.kind() == SignatureKind.FIELD;
- for (MemberNaming memberNaming : fieldMembers.values()) {
- if (memberNaming.getResidualSignatureInternal().equals(renamedSignature)) {
- return memberNaming;
- }
- }
- return null;
}
+ return null;
}
@Override
public MemberNaming lookupByOriginalSignature(Signature original) {
// As the key is inverted, this looks a lot like {@link ClassNamingForNameMapper#lookup}.
if (original.kind() == SignatureKind.METHOD) {
- return methodMembers.get(original);
+ return methodMembers.get(original.asMethodSignature());
} else {
assert original.kind() == SignatureKind.FIELD;
- return fieldMembers.get(original);
+ return fieldMembers.get(original.asFieldSignature());
}
}
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 8fb8ae6..0f09fdf 100644
--- a/src/main/java/com/android/tools/r8/naming/ClassNamingForNameMapper.java
+++ b/src/main/java/com/android/tools/r8/naming/ClassNamingForNameMapper.java
@@ -3,6 +3,8 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.naming;
+import static com.android.tools.r8.naming.MappedRangeUtils.addAllInlineFramesUntilOutermostCaller;
+
import com.android.tools.r8.naming.MemberNaming.FieldSignature;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.naming.MemberNaming.Signature;
@@ -11,9 +13,11 @@
import com.android.tools.r8.naming.mappinginformation.OutlineCallsiteMappingInformation;
import com.android.tools.r8.naming.mappinginformation.RewriteFrameMappingInformation;
import com.android.tools.r8.utils.ChainableStringConsumer;
+import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.ThrowingConsumer;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import java.util.ArrayList;
import java.util.Collection;
@@ -59,11 +63,11 @@
}
@Override
- public ClassNaming.Builder addMemberEntry(MemberNaming entry, Signature residualSignature) {
+ public ClassNaming.Builder addMemberEntry(MemberNaming entry) {
if (entry.isMethodNaming()) {
- methodMembers.put(residualSignature.asMethodSignature(), entry);
+ methodMembers.put(entry.getResidualSignature().asMethodSignature(), entry);
} else {
- fieldMembers.put(residualSignature.asFieldSignature(), entry);
+ fieldMembers.put(entry.getResidualSignature().asFieldSignature(), entry);
mappedFieldNamingsByName
.computeIfAbsent(entry.getRenamedName(), ignored -> new ArrayList<>())
.add(entry);
@@ -218,6 +222,48 @@
public int hashCode() {
return mappedRanges.hashCode();
}
+
+ public List<MappedRangesOfName> partitionOnMethodSignature() {
+ if (mappedRanges.size() <= 1) {
+ return Collections.singletonList(this);
+ }
+ List<MappedRangesOfName> partitionedMappings = new ArrayList<>();
+ int index = 0;
+ List<MappedRange> currentMappedRanges = new ArrayList<>();
+ index = addAllInlineFramesUntilOutermostCaller(mappedRanges, index, currentMappedRanges);
+ // Do a fast check to see if the last one is the same signature as the first one.
+ if (ListUtils.last(currentMappedRanges)
+ .getOriginalSignature()
+ .equals(ListUtils.last(mappedRanges).getOriginalSignature())) {
+ return Collections.singletonList(this);
+ }
+ // Otherwise the signature changes which means we have overloads.
+ while (index < mappedRanges.size()) {
+ List<MappedRange> newMappedRanges = new ArrayList<>();
+ index = addAllInlineFramesUntilOutermostCaller(mappedRanges, index, newMappedRanges);
+ if (!ListUtils.last(currentMappedRanges)
+ .getOriginalSignature()
+ .equals(ListUtils.last(newMappedRanges).getOriginalSignature())) {
+ partitionedMappings.add(new MappedRangesOfName(currentMappedRanges));
+ currentMappedRanges = new ArrayList<>();
+ }
+ currentMappedRanges.addAll(newMappedRanges);
+ }
+ partitionedMappings.add(new MappedRangesOfName(currentMappedRanges));
+ return partitionedMappings;
+ }
+
+ public MemberNaming getMemberNaming(
+ ClassNamingForNameMapper classNamingForNameMapper, boolean hasMultipleResults) {
+ MappedRange lastMappedRange = ListUtils.last(mappedRanges);
+ if (hasMultipleResults) {
+ return null;
+ }
+ MethodSignature signature = lastMappedRange.getResidualSignature();
+ MemberNaming memberNaming = classNamingForNameMapper.methodMembers.get(signature);
+ assert memberNaming != null;
+ return memberNaming;
+ }
}
static Builder builder(
@@ -425,7 +471,7 @@
mappedRangesSorted.sort(Comparator.comparingInt(range -> range.sequenceNumber));
for (MappedRange range : mappedRangesSorted) {
consumer.accept(" ").accept(range.toString()).accept("\n");
- for (MappingInformation info : range.additionalMappingInfo) {
+ for (MappingInformation info : range.getAdditionalMappingInformation()) {
consumer.accept(" # ").accept(info.serialize()).accept("\n");
}
}
@@ -499,13 +545,19 @@
private MethodSignature residualSignature = null;
+ private boolean hasComputedHashCode = false;
+
/**
* The sole purpose of {@link #sequenceNumber} is to preserve the order of members read from a
* Proguard-map.
*/
private final int sequenceNumber = getNextSequenceNumber();
- private List<MappingInformation> additionalMappingInfo = EMPTY_MAPPING_INFORMATION;
+ /**
+ * We never emit member namings for methods so mapped ranges has to account for both positional
+ * and referential mapping information.
+ */
+ private List<MappingInformation> additionalMappingInformation = EMPTY_MAPPING_INFORMATION;
MappedRange(
Range minifiedRange, MethodSignature signature, Range originalRange, String renamedName) {
@@ -522,40 +574,17 @@
public void addMappingInformation(
MappingInformation info, Consumer<MappingInformation> onProhibitedAddition) {
- if (additionalMappingInfo == EMPTY_MAPPING_INFORMATION) {
- additionalMappingInfo = new ArrayList<>();
+ if (additionalMappingInformation == EMPTY_MAPPING_INFORMATION) {
+ additionalMappingInformation = new ArrayList<>();
}
- for (MappingInformation existing : additionalMappingInfo) {
- if (!existing.allowOther(info)) {
- onProhibitedAddition.accept(existing);
- return;
- }
- }
- additionalMappingInfo.add(info);
+ MappingInformation.addMappingInformation(
+ additionalMappingInformation, info, onProhibitedAddition);
}
- public boolean isCompilerSynthesized() {
- for (MappingInformation info : additionalMappingInfo) {
- if (info.isCompilerSynthesizedMappingInformation() || info.isOutlineMappingInformation()) {
- return true;
- }
- }
- return false;
- }
-
- public boolean isOutlineFrame() {
- for (MappingInformation info : additionalMappingInfo) {
- if (info.isOutlineMappingInformation()) {
- return true;
- }
- }
- return false;
- }
-
- public <T> List<T> filter(
+ private <T> List<T> filter(
Predicate<MappingInformation> predicate, Function<MappingInformation, T> mapper) {
ImmutableList.Builder<T> builder = ImmutableList.builder();
- for (MappingInformation mappingInformation : additionalMappingInfo) {
+ for (MappingInformation mappingInformation : additionalMappingInformation) {
if (predicate.test(mappingInformation)) {
builder.add(mapper.apply(mappingInformation));
}
@@ -607,20 +636,41 @@
return signature;
}
- @Override
- public boolean hasResidualSignature() {
- return residualSignature != null;
+ public boolean isCompilerSynthesized() {
+ for (MappingInformation info : additionalMappingInformation) {
+ if (info.isCompilerSynthesizedMappingInformation() || info.isOutlineMappingInformation()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean isOutlineFrame() {
+ for (MappingInformation info : additionalMappingInformation) {
+ if (info.isOutlineMappingInformation()) {
+ return true;
+ }
+ }
+ return false;
}
@Override
- public MethodSignature getResidualSignatureInternal() {
- return residualSignature;
+ public boolean hasResidualSignatureMappingInformation() {
+ return Iterables.any(
+ additionalMappingInformation, MappingInformation::isResidualSignatureMappingInformation);
+ }
+
+ public void setResidualSignatureInternal(MethodSignature signature) {
+ assert !hasComputedHashCode;
+ this.residualSignature = signature;
}
@Override
- public void setResidualSignatureInternal(Signature residualSignature) {
- assert residualSignature.isMethodSignature();
- this.residualSignature = residualSignature.asMethodSignature();
+ public MethodSignature getResidualSignature() {
+ if (residualSignature != null) {
+ return residualSignature;
+ }
+ return signature.asRenamed(renamedName).asMethodSignature();
}
public int getLastPositionOfOriginalRange() {
@@ -662,7 +712,8 @@
&& Objects.equals(originalRange, that.originalRange)
&& signature.equals(that.signature)
&& renamedName.equals(that.renamedName)
- && Objects.equals(residualSignature, that.residualSignature);
+ && Objects.equals(residualSignature, that.residualSignature)
+ && Objects.equals(additionalMappingInformation, that.additionalMappingInformation);
}
@Override
@@ -673,11 +724,13 @@
result = 31 * result + signature.hashCode();
result = 31 * result + renamedName.hashCode();
result = 31 * result + Objects.hashCode(residualSignature);
+ result = 31 * result + Objects.hashCode(additionalMappingInformation);
+ hasComputedHashCode = true;
return result;
}
- public List<MappingInformation> getAdditionalMappingInfo() {
- return Collections.unmodifiableList(additionalMappingInfo);
+ public List<MappingInformation> getAdditionalMappingInformation() {
+ return Collections.unmodifiableList(additionalMappingInformation);
}
}
}
diff --git a/src/main/java/com/android/tools/r8/naming/ComposingBuilder.java b/src/main/java/com/android/tools/r8/naming/ComposingBuilder.java
index 5b3e838..cc7f927 100644
--- a/src/main/java/com/android/tools/r8/naming/ComposingBuilder.java
+++ b/src/main/java/com/android/tools/r8/naming/ComposingBuilder.java
@@ -4,6 +4,8 @@
package com.android.tools.r8.naming;
+import static com.android.tools.r8.naming.MappedRangeUtils.addAllInlineFramesUntilOutermostCaller;
+import static com.android.tools.r8.naming.MappedRangeUtils.isInlineMappedRange;
import static com.android.tools.r8.utils.FunctionUtils.ignoreArgument;
import com.android.tools.r8.naming.ClassNamingForNameMapper.MappedRange;
@@ -595,7 +597,8 @@
// Register mapping information that is dependent on the residual naming to allow updating
// later on.
for (MappedRange mappedRange : mappedRangesForThisInterval) {
- for (MappingInformation mappingInformation : mappedRange.getAdditionalMappingInfo()) {
+ for (MappingInformation mappingInformation :
+ mappedRange.getAdditionalMappingInformation()) {
if (mappingInformation.isRewriteFrameMappingInformation()) {
RewriteFrameMappingInformation rewriteFrameMappingInformation =
mappingInformation.asRewriteFrameMappingInformation();
@@ -631,16 +634,6 @@
seenMappedRanges);
}
- private int addAllInlineFramesUntilOutermostCaller(
- List<MappedRange> mappedRanges, int index, List<MappedRange> seenMappedRanges) {
- assert index < mappedRanges.size();
- while (isInlineMappedRange(mappedRanges, index)) {
- seenMappedRanges.add(mappedRanges.get(index++));
- }
- seenMappedRanges.add(mappedRanges.get(index++));
- return index;
- }
-
private List<MappedRange> composeMappedRangesForMethod(
List<MappedRange> existingRanges, List<MappedRange> newRanges)
throws MappingComposeException {
@@ -687,8 +680,8 @@
new MappedRange(
null, lastExistingRange.signature, originalRange.get(), newRange.renamedName);
composeMappingInformation(
- newComposedRange.getAdditionalMappingInfo(),
- lastExistingRange.getAdditionalMappingInfo(),
+ newComposedRange.getAdditionalMappingInformation(),
+ lastExistingRange.getAdditionalMappingInformation(),
info -> newComposedRange.addMappingInformation(info, ConsumerUtils.emptyConsumer()));
newComposedRanges.add(newComposedRange);
} else {
@@ -789,7 +782,7 @@
newOriginalRange,
lastExistingMappedRange.renamedName);
nonExistingMappedRange.setResidualSignatureInternal(
- lastExistingRange.getResidualSignatureInternal());
+ lastExistingRange.getResidualSignature());
lastExistingMappedRange = nonExistingMappedRange;
existingMappedRanges = Collections.singletonList(nonExistingMappedRange);
position += (endOriginalPosition - startOriginalPosition) - 1;
@@ -938,7 +931,7 @@
newMappedRange.renamedName);
List<MappingInformation> mappingInformationToCompose = new ArrayList<>();
existingMappedRange
- .getAdditionalMappingInfo()
+ .getAdditionalMappingInformation()
.forEach(
info -> {
if (info.isOutlineMappingInformation()) {
@@ -952,7 +945,7 @@
}
});
composeMappingInformation(
- computedRange.getAdditionalMappingInfo(),
+ computedRange.getAdditionalMappingInformation(),
mappingInformationToCompose,
info -> computedRange.addMappingInformation(info, ConsumerUtils.emptyConsumer()));
newComposedRanges.add(computedRange);
@@ -989,16 +982,6 @@
});
}
- private boolean isInlineMappedRange(List<MappedRange> mappedRanges, int index) {
- // We are comparing against the next entry so we need a buffer of one.
- if (index + 1 >= mappedRanges.size()) {
- return false;
- }
- MappedRange mappedRange = mappedRanges.get(index);
- return mappedRange.minifiedRange != null
- && mappedRange.minifiedRange.equals(mappedRanges.get(index + 1).minifiedRange);
- }
-
public void write(ChainableStringConsumer consumer) {
consumer.accept(originalName).accept(" -> ").accept(renamedName).accept(":\n");
additionalMappingInfo.forEach(info -> consumer.accept("# " + info.serialize()).accept("\n"));
@@ -1018,7 +1001,7 @@
methodsWithoutPosition.forEach(
(ignored, mapped) -> {
consumer.accept(INDENTATION).accept(mapped.toString()).accept("\n");
- for (MappingInformation info : mapped.getAdditionalMappingInfo()) {
+ for (MappingInformation info : mapped.getAdditionalMappingInformation()) {
consumer.accept(INDENTATION).accept("# ").accept(info.serialize()).accept("\n");
}
});
@@ -1043,7 +1026,7 @@
.forEach(
mappedRange -> {
consumer.accept(INDENTATION).accept(mappedRange.toString()).accept("\n");
- for (MappingInformation info : mappedRange.getAdditionalMappingInfo()) {
+ for (MappingInformation info : mappedRange.getAdditionalMappingInformation()) {
consumer.accept(INDENTATION).accept("# ").accept(info.serialize()).accept("\n");
}
});
diff --git a/src/main/java/com/android/tools/r8/naming/MappedRangeUtils.java b/src/main/java/com/android/tools/r8/naming/MappedRangeUtils.java
new file mode 100644
index 0000000..7dff280
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/naming/MappedRangeUtils.java
@@ -0,0 +1,31 @@
+// Copyright (c) 2022, 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.naming;
+
+import com.android.tools.r8.naming.ClassNamingForNameMapper.MappedRange;
+import java.util.List;
+
+public class MappedRangeUtils {
+
+ static int addAllInlineFramesUntilOutermostCaller(
+ List<MappedRange> mappedRanges, int index, List<MappedRange> listToAdd) {
+ assert index < mappedRanges.size();
+ while (isInlineMappedRange(mappedRanges, index)) {
+ listToAdd.add(mappedRanges.get(index++));
+ }
+ listToAdd.add(mappedRanges.get(index++));
+ return index;
+ }
+
+ static boolean isInlineMappedRange(List<MappedRange> mappedRanges, int index) {
+ // We are comparing against the next entry so we need a buffer of one.
+ if (index + 1 >= mappedRanges.size()) {
+ return false;
+ }
+ MappedRange mappedRange = mappedRanges.get(index);
+ return mappedRange.minifiedRange != null
+ && mappedRange.minifiedRange.equals(mappedRanges.get(index + 1).minifiedRange);
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/naming/MappingWithResidualInfo.java b/src/main/java/com/android/tools/r8/naming/MappingWithResidualInfo.java
index 7e7bcd0..77e145b 100644
--- a/src/main/java/com/android/tools/r8/naming/MappingWithResidualInfo.java
+++ b/src/main/java/com/android/tools/r8/naming/MappingWithResidualInfo.java
@@ -13,19 +13,16 @@
Signature getOriginalSignature();
- boolean hasResidualSignature();
+ boolean hasResidualSignatureMappingInformation();
- Signature getResidualSignatureInternal();
+ Signature getResidualSignature();
- void setResidualSignatureInternal(Signature signature);
-
+ /** Should be removed when R8 emits residual information for alpha renamed signatures. */
+ @Deprecated()
default Signature computeResidualSignature(Function<String, String> typeNameMapper) {
- if (hasResidualSignature()) {
- return getResidualSignatureInternal();
+ if (hasResidualSignatureMappingInformation()) {
+ return getResidualSignature();
}
- Signature residualSignature =
- getOriginalSignature().computeResidualSignature(getRenamedName(), typeNameMapper);
- setResidualSignatureInternal(residualSignature);
- return residualSignature;
+ return getOriginalSignature().computeResidualSignature(getRenamedName(), typeNameMapper);
}
}
diff --git a/src/main/java/com/android/tools/r8/naming/MemberNaming.java b/src/main/java/com/android/tools/r8/naming/MemberNaming.java
index 043bb4c..12606ff 100644
--- a/src/main/java/com/android/tools/r8/naming/MemberNaming.java
+++ b/src/main/java/com/android/tools/r8/naming/MemberNaming.java
@@ -13,6 +13,8 @@
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.naming.MemberNaming.Signature.SignatureKind;
+import com.android.tools.r8.naming.mappinginformation.MappingInformation;
+import com.android.tools.r8.naming.mappinginformation.MappingInformation.ReferentialMappingInformation;
import com.android.tools.r8.position.Position;
import com.android.tools.r8.references.FieldReference;
import com.android.tools.r8.references.MethodReference;
@@ -21,12 +23,16 @@
import com.android.tools.r8.utils.CollectionUtils;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.Iterables;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.Objects;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Consumer;
import java.util.function.Function;
import org.objectweb.asm.Type;
@@ -37,6 +43,9 @@
*/
public class MemberNaming implements MappingWithResidualInfo {
+ private static final List<ReferentialMappingInformation> EMPTY_MAPPING_INFORMATION =
+ Collections.emptyList();
+
@Override
public boolean equals(Object o) {
if (this == o) {
@@ -45,55 +54,41 @@
if (!(o instanceof MemberNaming)) {
return false;
}
-
MemberNaming that = (MemberNaming) o;
- return signature.equals(that.signature)
- && renamedName.equals(that.renamedName)
- && Objects.equals(residualSignature, that.residualSignature);
+ return signature.equals(that.signature) && residualSignature.equals(that.residualSignature);
}
@Override
public int hashCode() {
int result = signature.hashCode();
- result = 31 * result + renamedName.hashCode();
- result = 31 * result + Objects.hashCode(residualSignature);
+ result = 31 * result + residualSignature.hashCode();
return result;
}
/** Original signature of the member. */
private final Signature signature;
/** Residual signature where types and names could be changed. */
- private Signature residualSignature = null;
- /**
- * Renamed name in the mapping file. This value will always be present even if the residual
- * signature is not.
- */
- private final String renamedName;
+ private final Signature residualSignature;
/** Position of the member in the file. */
private final Position position;
- public MemberNaming(Signature signature, String renamedName) {
- this(signature, renamedName, Position.UNKNOWN);
- }
+ private List<ReferentialMappingInformation> additionalMappingInformation =
+ EMPTY_MAPPING_INFORMATION;
public MemberNaming(Signature signature, Signature residualSignature) {
- this(signature, residualSignature.getName(), Position.UNKNOWN);
- this.residualSignature = residualSignature;
+ this(signature, residualSignature, Position.UNKNOWN);
}
- public MemberNaming(Signature signature, String renamedName, Position position) {
+ public MemberNaming(Signature signature, Signature residualSignature, Position position) {
this.signature = signature;
- this.renamedName = renamedName;
+ this.residualSignature = residualSignature;
this.position = position;
}
/** This is used internally in google3. */
@Deprecated
public Signature getRenamedSignature() {
- if (residualSignature != null) {
- return residualSignature;
- }
- return getOriginalSignature().asRenamed(renamedName);
+ return residualSignature;
}
@Override
@@ -106,13 +101,14 @@
}
@Override
- public boolean hasResidualSignature() {
- return residualSignature != null;
+ public boolean hasResidualSignatureMappingInformation() {
+ return Iterables.any(
+ additionalMappingInformation, MappingInformation::isResidualSignatureMappingInformation);
}
@Override
public String getRenamedName() {
- return renamedName;
+ return residualSignature.getName();
}
public boolean isMethodNaming() {
@@ -129,17 +125,50 @@
@Override
public String toString() {
- return signature.toString() + " -> " + renamedName;
+ return signature.toString() + " -> " + residualSignature.getName();
}
@Override
- public Signature getResidualSignatureInternal() {
+ public Signature getResidualSignature() {
return residualSignature;
}
- @Override
- public void setResidualSignatureInternal(Signature signature) {
- this.residualSignature = signature;
+ public void addMappingInformation(
+ ReferentialMappingInformation info, Consumer<MappingInformation> onProhibitedAddition) {
+ if (additionalMappingInformation == EMPTY_MAPPING_INFORMATION) {
+ additionalMappingInformation = new ArrayList<>();
+ }
+ MappingInformation.addMappingInformation(
+ additionalMappingInformation, info, onProhibitedAddition);
+ }
+
+ void addAllMappingInformationInternal(List<ReferentialMappingInformation> otherInfo) {
+ if (additionalMappingInformation == EMPTY_MAPPING_INFORMATION) {
+ additionalMappingInformation = new ArrayList<>();
+ }
+ additionalMappingInformation.addAll(otherInfo);
+ }
+
+ public boolean isCompilerSynthesized() {
+ for (MappingInformation info : additionalMappingInformation) {
+ if (info.isCompilerSynthesizedMappingInformation() || info.isOutlineMappingInformation()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean isOutlineFrame() {
+ for (MappingInformation info : additionalMappingInformation) {
+ if (info.isOutlineMappingInformation()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public List<ReferentialMappingInformation> getAdditionalMappingInformation() {
+ return additionalMappingInformation;
}
public abstract static class Signature {
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 80cc8e6..cd8bd3f 100644
--- a/src/main/java/com/android/tools/r8/naming/ProguardMapReader.java
+++ b/src/main/java/com/android/tools/r8/naming/ProguardMapReader.java
@@ -12,11 +12,15 @@
import com.android.tools.r8.naming.PositionRangeAllocator.NonCardinalPositionRangeAllocator;
import com.android.tools.r8.naming.mappinginformation.MapVersionMappingInformation;
import com.android.tools.r8.naming.mappinginformation.MappingInformation;
+import com.android.tools.r8.naming.mappinginformation.MappingInformation.ReferentialMappingInformation;
import com.android.tools.r8.naming.mappinginformation.MappingInformationDiagnostics;
+import com.android.tools.r8.naming.mappinginformation.ResidualSignatureMappingInformation;
+import com.android.tools.r8.naming.mappinginformation.ResidualSignatureMappingInformation.ResidualFieldSignatureMappingInformation;
import com.android.tools.r8.naming.mappinginformation.ResidualSignatureMappingInformation.ResidualMethodSignatureMappingInformation;
import com.android.tools.r8.position.Position;
import com.android.tools.r8.utils.ArrayUtils;
import com.android.tools.r8.utils.BooleanBox;
+import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.IdentifierUtils;
import com.android.tools.r8.utils.StringUtils;
@@ -334,14 +338,20 @@
private void parseMemberMappings(
ProguardMap.Builder mapBuilder, ClassNaming.Builder classNamingBuilder) throws IOException {
MemberNaming lastAddedNaming = null;
- MemberNaming activeMemberNaming = null;
+ // To ensure we only commit a member if we have the residual signature, we delay creating the
+ // object and have the variables out here.
+ Signature previousOriginalSignature = null;
+ String previousRenamedName = null;
+ int previousLineNumber = -1;
+ Range previousRange = null;
+ Box<Signature> currentResidualSignature = new Box<>();
+ Box<List<ReferentialMappingInformation>> currentMappingInfoForMemberNaming = new Box<>();
MappedRange activeMappedRange = null;
- Range previousMappedRange = null;
do {
Range originalRange = null;
// Try to parse any information added in comments above member namings
if (isCommentLineWithJsonBrace()) {
- final MemberNaming currentMember = activeMemberNaming;
+ final String currentRenamedNameFinal = previousRenamedName;
final MappedRange currentRange = activeMappedRange;
// Reading global info should cause member mapping to return since we are now reading
// headers pertaining to what could be a concatinated file.
@@ -349,38 +359,44 @@
parseMappingInformation(
info -> {
readGlobalInfo.set(info.isGlobalMappingInformation());
- // TODO(b/242673239): Support additional information for fields.
- if (currentMember == null) {
+ if (currentRenamedNameFinal == null) {
classNamingBuilder.addMappingInformation(
info,
conflictingInfo ->
diagnosticsHandler.warning(
MappingInformationDiagnostics.notAllowedCombination(
info, conflictingInfo, lineNo)));
- } else if (currentRange != null) {
+ return;
+ }
+ // Always add information to the current range, this will ensure that additional
+ // information is always placed the same place.
+ if (currentRange != null) {
currentRange.addMappingInformation(
info,
conflictingInfo ->
diagnosticsHandler.warning(
MappingInformationDiagnostics.notAllowedCombination(
info, conflictingInfo, lineNo)));
- if (info.isResidualMethodSignatureMappingInformation()) {
- ResidualMethodSignatureMappingInformation residualSignatureInfo =
- info.asResidualMethodSignatureMappingInformation();
- MethodSignature residualSignature =
- new MethodSignature(
- currentMember.getRenamedName(),
- DescriptorUtils.descriptorToJavaType(
- residualSignatureInfo.getReturnType()),
- ArrayUtils.mapToStringArray(
- residualSignatureInfo.getParameters(),
- DescriptorUtils::descriptorToJavaType));
- residualSignature =
- signatureCache
- .computeIfAbsent(residualSignature, Function.identity())
- .asMethodSignature();
- currentMember.setResidualSignatureInternal(residualSignature);
- currentRange.setResidualSignatureInternal(residualSignature);
+ }
+ if (info.isReferentialMappingInformation()) {
+ ReferentialMappingInformation referentialMappingInformation =
+ info.asReferentialMappingInformation();
+ MappingInformation.addMappingInformation(
+ currentMappingInfoForMemberNaming.computeIfAbsent(ArrayList::new),
+ referentialMappingInformation,
+ conflictingInfo ->
+ diagnosticsHandler.warning(
+ MappingInformationDiagnostics.notAllowedCombination(
+ info, conflictingInfo, lineNo)));
+ if (info.isResidualSignatureMappingInformation()) {
+ Signature residualSignature =
+ getResidualSignatureFromMappingInformation(
+ info.asResidualSignatureMappingInformation(), currentRenamedNameFinal);
+ currentResidualSignature.set(residualSignature);
+ if (currentRange != null) {
+ currentRange.setResidualSignatureInternal(
+ residualSignature.asMethodSignature());
+ }
}
}
});
@@ -431,7 +447,7 @@
if (activeMappedRange != null
&& activeMappedRange.signature == signature
&& activeMappedRange.renamedName.equals(renamedName)) {
- residualSignature = activeMappedRange.getResidualSignatureInternal();
+ residualSignature = activeMappedRange.getResidualSignature();
}
activeMappedRange =
classNamingBuilder.addMappedRange(
@@ -442,51 +458,114 @@
}
assert mappedRange == null || signature.isMethodSignature();
-
- // If this line refers to a member that should be added to classNamingBuilder (as opposed to
- // an inner inlined callee) and it's different from the the previous activeMemberNaming, then
- // flush (add) the current activeMemberNaming.
- if (activeMemberNaming != null) {
- boolean changedName = !activeMemberNaming.getRenamedName().equals(renamedName);
- boolean changedMappedRange = !Objects.equals(previousMappedRange, mappedRange);
+ if (previousOriginalSignature != null) {
+ boolean changedName = !previousRenamedName.equals(renamedName);
+ boolean changedMappedRange =
+ previousRange == null || !Objects.equals(previousRange, mappedRange);
boolean originalRangeChange = originalRange == null || !originalRange.isCardinal;
- if (changedName
- || previousMappedRange == null
- || changedMappedRange
- || originalRangeChange) {
- if (lastAddedNaming == null
- || !lastAddedNaming
- .getOriginalSignature()
- .equals(activeMemberNaming.getOriginalSignature())) {
- classNamingBuilder.addMemberEntry(
- activeMemberNaming, getResidualSignatureForMemberNaming(activeMemberNaming));
- lastAddedNaming = activeMemberNaming;
- }
+ if (changedName || changedMappedRange || originalRangeChange) {
+ lastAddedNaming =
+ addMemberEntryOrCopyInformation(
+ lastAddedNaming,
+ previousOriginalSignature,
+ previousRenamedName,
+ previousLineNumber,
+ currentResidualSignature,
+ currentMappingInfoForMemberNaming,
+ previousRange,
+ classNamingBuilder);
}
}
- activeMemberNaming = new MemberNaming(signature, renamedName, getPosition());
- previousMappedRange = mappedRange;
+ previousOriginalSignature = signature;
+ previousRenamedName = renamedName;
+ previousLineNumber = lineNo;
+ previousRange = mappedRange;
} while (nextLine(mapBuilder));
- if (activeMemberNaming != null) {
- boolean notAdded =
- lastAddedNaming == null
- || !lastAddedNaming
- .getOriginalSignature()
- .equals(activeMemberNaming.getOriginalSignature());
- if (previousMappedRange == null || notAdded) {
- classNamingBuilder.addMemberEntry(
- activeMemberNaming, getResidualSignatureForMemberNaming(activeMemberNaming));
- }
+ if (previousOriginalSignature != null) {
+ addMemberEntryOrCopyInformation(
+ lastAddedNaming,
+ previousOriginalSignature,
+ previousRenamedName,
+ previousLineNumber,
+ currentResidualSignature,
+ currentMappingInfoForMemberNaming,
+ previousRange,
+ classNamingBuilder);
}
}
- private Signature getResidualSignatureForMemberNaming(MemberNaming memberNaming) {
- if (memberNaming.hasResidualSignature()) {
- return memberNaming.getResidualSignatureInternal();
+ private MemberNaming addMemberEntryOrCopyInformation(
+ MemberNaming lastAddedNaming,
+ Signature originalSignature,
+ String renamedName,
+ int lineNumber,
+ Box<Signature> residualSignature,
+ Box<List<ReferentialMappingInformation>> additionalMappingInformation,
+ Range previousMappedRange,
+ ClassNaming.Builder classNamingBuilder) {
+ // If this line refers to a member that should be added to classNamingBuilder (as opposed to
+ // an inner inlined callee) and it's different from the the previous activeMemberNaming, then
+ // flush (add) the current activeMemberNaming.
+ if (previousMappedRange == null
+ || lastAddedNaming == null
+ || !lastAddedNaming.getRenamedName().equals(renamedName)
+ || !lastAddedNaming.getOriginalSignature().equals(originalSignature)) {
+ MemberNaming newMemberNaming =
+ new MemberNaming(
+ originalSignature,
+ getResidualSignatureForMemberNaming(
+ residualSignature, originalSignature, renamedName),
+ new LinePosition(lineNumber));
+ if (additionalMappingInformation.isSet()) {
+ newMemberNaming.addAllMappingInformationInternal(additionalMappingInformation.get());
+ }
+ classNamingBuilder.addMemberEntry(newMemberNaming);
+ residualSignature.clear();
+ additionalMappingInformation.clear();
+ return newMemberNaming;
}
- Signature signature =
- memberNaming.getOriginalSignature().asRenamed(memberNaming.getRenamedName());
+ if (additionalMappingInformation.isSet()) {
+ lastAddedNaming.addAllMappingInformationInternal(additionalMappingInformation.get());
+ additionalMappingInformation.clear();
+ }
+ residualSignature.clear();
+ return lastAddedNaming;
+ }
+
+ private Signature getResidualSignatureFromMappingInformation(
+ ResidualSignatureMappingInformation mappingInformation, String renamedName) {
+ if (mappingInformation.isResidualMethodSignatureMappingInformation()) {
+ ResidualMethodSignatureMappingInformation residualSignatureInfo =
+ mappingInformation.asResidualMethodSignatureMappingInformation();
+ MethodSignature residualSignature =
+ new MethodSignature(
+ renamedName,
+ DescriptorUtils.descriptorToJavaType(residualSignatureInfo.getReturnType()),
+ ArrayUtils.mapToStringArray(
+ residualSignatureInfo.getParameters(), DescriptorUtils::descriptorToJavaType));
+ return signatureCache
+ .computeIfAbsent(residualSignature, Function.identity())
+ .asMethodSignature();
+ } else {
+ assert mappingInformation.isResidualFieldSignatureMappingInformation();
+ ResidualFieldSignatureMappingInformation residualSignatureInfo =
+ mappingInformation.asResidualFieldSignatureMappingInformation();
+ FieldSignature residualSignature =
+ new FieldSignature(
+ renamedName, DescriptorUtils.descriptorToJavaType(residualSignatureInfo.getType()));
+ return signatureCache
+ .computeIfAbsent(residualSignature, Function.identity())
+ .asFieldSignature();
+ }
+ }
+
+ private Signature getResidualSignatureForMemberNaming(
+ Box<Signature> residualSignature, Signature originalSignature, String renamedName) {
+ if (residualSignature.isSet()) {
+ return residualSignature.get();
+ }
+ Signature signature = originalSignature.asRenamed(renamedName);
signature = signatureCache.computeIfAbsent(signature, Function.identity());
return signature;
}
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 b1d1eff..8ddef2b 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
@@ -6,11 +6,12 @@
import com.android.tools.r8.naming.MapVersion;
import com.android.tools.r8.naming.MappingComposeException;
+import com.android.tools.r8.naming.mappinginformation.MappingInformation.ReferentialMappingInformation;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import java.util.function.Consumer;
-public class CompilerSynthesizedMappingInformation extends MappingInformation {
+public class CompilerSynthesizedMappingInformation extends ReferentialMappingInformation {
public static final MapVersion SUPPORTED_VERSION = MapVersion.MAP_VERSION_1_0;
public static final String ID = "com.android.tools.r8.synthesized";
@@ -55,7 +56,7 @@
@Override
public boolean allowOther(MappingInformation information) {
- return !information.isCompilerSynthesizedMappingInformation();
+ return true;
}
@Override
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 828b5d8..7535bd3 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
@@ -7,12 +7,13 @@
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.naming.MapVersion;
import com.android.tools.r8.naming.MappingComposeException;
+import com.android.tools.r8.naming.mappinginformation.MappingInformation.ReferentialMappingInformation;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import java.util.function.Consumer;
-public class FileNameInformation extends MappingInformation {
+public class FileNameInformation extends ReferentialMappingInformation {
private final String fileName;
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 c62d4e6..6680142 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
@@ -11,6 +11,7 @@
import com.android.tools.r8.naming.mappinginformation.ResidualSignatureMappingInformation.ResidualMethodSignatureMappingInformation;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
+import java.util.List;
import java.util.function.Consumer;
public abstract class MappingInformation {
@@ -89,6 +90,10 @@
return null;
}
+ public ResidualSignatureMappingInformation asResidualSignatureMappingInformation() {
+ return null;
+ }
+
public ResidualMethodSignatureMappingInformation asResidualMethodSignatureMappingInformation() {
return null;
}
@@ -177,6 +182,39 @@
}
}
+ public boolean isPositionalMappingInformation() {
+ return false;
+ }
+
+ public boolean isReferentialMappingInformation() {
+ return false;
+ }
+
+ public ReferentialMappingInformation asReferentialMappingInformation() {
+ return null;
+ }
+
+ public abstract static class ReferentialMappingInformation extends MappingInformation {
+
+ @Override
+ public boolean isReferentialMappingInformation() {
+ return true;
+ }
+
+ @Override
+ public ReferentialMappingInformation asReferentialMappingInformation() {
+ return this;
+ }
+ }
+
+ public abstract static class PositionalMappingInformation extends MappingInformation {
+
+ @Override
+ public boolean isPositionalMappingInformation() {
+ return true;
+ }
+ }
+
static JsonElement getJsonElementFromObject(
JsonObject object,
DiagnosticsHandler diagnosticsHandler,
@@ -190,4 +228,15 @@
}
return element;
}
+
+ public static <T extends MappingInformation> void addMappingInformation(
+ List<T> existingInfos, T newInfo, Consumer<MappingInformation> onProhibitedAddition) {
+ for (MappingInformation existing : existingInfos) {
+ if (!existing.allowOther(newInfo)) {
+ onProhibitedAddition.accept(existing);
+ return;
+ }
+ }
+ existingInfos.add(newInfo);
+ }
}
diff --git a/src/main/java/com/android/tools/r8/naming/mappinginformation/OutlineCallsiteMappingInformation.java b/src/main/java/com/android/tools/r8/naming/mappinginformation/OutlineCallsiteMappingInformation.java
index b38d707..238a9dd 100644
--- a/src/main/java/com/android/tools/r8/naming/mappinginformation/OutlineCallsiteMappingInformation.java
+++ b/src/main/java/com/android/tools/r8/naming/mappinginformation/OutlineCallsiteMappingInformation.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.naming.MapVersion;
import com.android.tools.r8.naming.MappingComposeException;
+import com.android.tools.r8.naming.mappinginformation.MappingInformation.PositionalMappingInformation;
import com.android.tools.r8.references.MethodReference;
import com.android.tools.r8.utils.MethodReferenceUtils;
import com.google.gson.JsonElement;
@@ -16,7 +17,7 @@
import it.unimi.dsi.fastutil.ints.Int2IntSortedMap;
import java.util.function.Consumer;
-public class OutlineCallsiteMappingInformation extends MappingInformation {
+public class OutlineCallsiteMappingInformation extends PositionalMappingInformation {
public static final MapVersion SUPPORTED_VERSION = MapVersion.MAP_VERSION_2_0;
public static final MapVersion SUPPORTED_WITH_OUTLINE_VERSION = MapVersion.MAP_VERSION_2_1;
diff --git a/src/main/java/com/android/tools/r8/naming/mappinginformation/OutlineMappingInformation.java b/src/main/java/com/android/tools/r8/naming/mappinginformation/OutlineMappingInformation.java
index 09c60d9..72b3b8f 100644
--- a/src/main/java/com/android/tools/r8/naming/mappinginformation/OutlineMappingInformation.java
+++ b/src/main/java/com/android/tools/r8/naming/mappinginformation/OutlineMappingInformation.java
@@ -6,11 +6,12 @@
import com.android.tools.r8.naming.MapVersion;
import com.android.tools.r8.naming.MappingComposeException;
+import com.android.tools.r8.naming.mappinginformation.MappingInformation.ReferentialMappingInformation;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import java.util.function.Consumer;
-public class OutlineMappingInformation extends MappingInformation {
+public class OutlineMappingInformation extends ReferentialMappingInformation {
public static final MapVersion SUPPORTED_VERSION = MapVersion.MAP_VERSION_2_0;
public static final String ID = "com.android.tools.r8.outline";
@@ -40,7 +41,7 @@
@Override
public boolean allowOther(MappingInformation information) {
- return !information.isOutlineMappingInformation();
+ return true;
}
@Override
diff --git a/src/main/java/com/android/tools/r8/naming/mappinginformation/ResidualSignatureMappingInformation.java b/src/main/java/com/android/tools/r8/naming/mappinginformation/ResidualSignatureMappingInformation.java
index 1c94da9..79c4023 100644
--- a/src/main/java/com/android/tools/r8/naming/mappinginformation/ResidualSignatureMappingInformation.java
+++ b/src/main/java/com/android/tools/r8/naming/mappinginformation/ResidualSignatureMappingInformation.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.naming.MapVersion;
import com.android.tools.r8.naming.MappingComposeException;
+import com.android.tools.r8.naming.mappinginformation.MappingInformation.ReferentialMappingInformation;
import com.android.tools.r8.utils.ArrayUtils;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.StringUtils;
@@ -20,7 +21,7 @@
import java.util.Arrays;
import java.util.function.Consumer;
-public abstract class ResidualSignatureMappingInformation extends MappingInformation {
+public abstract class ResidualSignatureMappingInformation extends ReferentialMappingInformation {
public static final MapVersion SUPPORTED_VERSION = MapVersion.MAP_VERSION_EXPERIMENTAL;
public static final String ID = "com.android.tools.r8.residualsignature";
@@ -41,11 +42,6 @@
protected abstract String serializeInternal();
- @Override
- public boolean allowOther(MappingInformation information) {
- return !information.isResidualSignatureMappingInformation();
- }
-
public static boolean isSupported(MapVersion version) {
return version.isGreaterThanOrEqualTo(SUPPORTED_VERSION);
}
@@ -67,6 +63,16 @@
}
}
+ @Override
+ public boolean isResidualSignatureMappingInformation() {
+ return true;
+ }
+
+ @Override
+ public ResidualSignatureMappingInformation asResidualSignatureMappingInformation() {
+ return this;
+ }
+
public static class ResidualMethodSignatureMappingInformation
extends ResidualSignatureMappingInformation {
@@ -122,6 +128,16 @@
assert existing.isResidualMethodSignatureMappingInformation();
return this;
}
+
+ @Override
+ public boolean allowOther(MappingInformation information) {
+ if (!information.isResidualMethodSignatureMappingInformation()) {
+ return true;
+ }
+ ResidualMethodSignatureMappingInformation other =
+ information.asResidualMethodSignatureMappingInformation();
+ return returnType.equals(other.returnType) && Arrays.equals(parameters, other.parameters);
+ }
}
public static class ResidualFieldSignatureMappingInformation
@@ -138,6 +154,10 @@
return new ResidualFieldSignatureMappingInformation(field.getType().toDescriptorString());
}
+ public String getType() {
+ return type;
+ }
+
@Override
protected String serializeInternal() {
return type;
@@ -163,5 +183,11 @@
assert existing.isResidualFieldSignatureMappingInformation();
return this;
}
+
+ @Override
+ public boolean allowOther(MappingInformation information) {
+ return !information.isResidualFieldSignatureMappingInformation()
+ || type.equals(information.asResidualFieldSignatureMappingInformation().getType());
+ }
}
}
diff --git a/src/main/java/com/android/tools/r8/naming/mappinginformation/RewriteFrameMappingInformation.java b/src/main/java/com/android/tools/r8/naming/mappinginformation/RewriteFrameMappingInformation.java
index da0c1f3..589a743 100644
--- a/src/main/java/com/android/tools/r8/naming/mappinginformation/RewriteFrameMappingInformation.java
+++ b/src/main/java/com/android/tools/r8/naming/mappinginformation/RewriteFrameMappingInformation.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.errors.Unimplemented;
import com.android.tools.r8.naming.MapVersion;
import com.android.tools.r8.naming.MappingComposeException;
+import com.android.tools.r8.naming.mappinginformation.MappingInformation.PositionalMappingInformation;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.retrace.internal.RetraceStackTraceContextImpl;
@@ -25,7 +26,7 @@
import java.util.List;
import java.util.function.Consumer;
-public class RewriteFrameMappingInformation extends MappingInformation {
+public class RewriteFrameMappingInformation extends PositionalMappingInformation {
public static final MapVersion SUPPORTED_VERSION = MapVersion.MAP_VERSION_2_0;
public static final String ID = "com.android.tools.r8.rewriteFrame";
diff --git a/src/main/java/com/android/tools/r8/naming/mappinginformation/UnknownJsonMappingInformation.java b/src/main/java/com/android/tools/r8/naming/mappinginformation/UnknownJsonMappingInformation.java
index 3348063..98699b2 100644
--- a/src/main/java/com/android/tools/r8/naming/mappinginformation/UnknownJsonMappingInformation.java
+++ b/src/main/java/com/android/tools/r8/naming/mappinginformation/UnknownJsonMappingInformation.java
@@ -6,10 +6,11 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.naming.MappingComposeException;
+import com.android.tools.r8.naming.mappinginformation.MappingInformation.PositionalMappingInformation;
import com.google.gson.JsonObject;
import java.util.function.Consumer;
-public class UnknownJsonMappingInformation extends MappingInformation {
+public class UnknownJsonMappingInformation extends PositionalMappingInformation {
private final String id;
private final String payload;
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/MemberNamingWithMappedRangesOfName.java b/src/main/java/com/android/tools/r8/retrace/internal/MemberNamingWithMappedRangesOfName.java
new file mode 100644
index 0000000..26d5a16
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/retrace/internal/MemberNamingWithMappedRangesOfName.java
@@ -0,0 +1,40 @@
+// Copyright (c) 2022, 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.retrace.internal;
+
+import com.android.tools.r8.naming.ClassNamingForNameMapper.MappedRange;
+import com.android.tools.r8.naming.ClassNamingForNameMapper.MappedRangesOfName;
+import com.android.tools.r8.naming.MemberNaming;
+import com.android.tools.r8.utils.ListUtils;
+import java.util.List;
+
+class MemberNamingWithMappedRangesOfName {
+
+ private final MappedRangesOfName mappedRangesOfName;
+ private final MemberNaming methodMemberNaming;
+
+ MemberNamingWithMappedRangesOfName(
+ MemberNaming methodMemberNaming, MappedRangesOfName mappedRangesOfName) {
+ this.methodMemberNaming = methodMemberNaming;
+ this.mappedRangesOfName = mappedRangesOfName;
+ }
+
+ List<MappedRange> allRangesForLine(int line) {
+ return mappedRangesOfName.allRangesForLine(line, false);
+ }
+
+ List<MappedRange> mappedRangesWithNoMinifiedRange() {
+ return ListUtils.filter(
+ mappedRangesOfName.getMappedRanges(), mappedRange -> mappedRange.minifiedRange == null);
+ }
+
+ List<MappedRange> getMappedRanges() {
+ return mappedRangesOfName.getMappedRanges();
+ }
+
+ public MemberNaming getMemberNaming() {
+ return methodMemberNaming;
+ }
+}
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 1b2be6a..411f8d7 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
@@ -8,9 +8,6 @@
import com.android.tools.r8.naming.ClassNamingForNameMapper;
import com.android.tools.r8.naming.ClassNamingForNameMapper.MappedRangesOfName;
import com.android.tools.r8.naming.MemberNaming;
-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.mappinginformation.MappingInformation;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.references.FieldReference;
@@ -23,8 +20,8 @@
import com.android.tools.r8.retrace.RetraceStackTraceContext;
import com.android.tools.r8.retrace.RetraceUnknownJsonMappingInformationResult;
import com.android.tools.r8.retrace.RetracedSourceFile;
+import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.Pair;
-import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.List;
import java.util.OptionalInt;
@@ -63,6 +60,23 @@
return lookupField(FieldDefinition.create(fieldReference));
}
+ private RetraceFieldResultImpl lookupField(FieldDefinition fieldDefinition) {
+ return lookup(
+ fieldDefinition,
+ RetraceClassResultImpl::lookupMemberNamingsForFieldDefinition,
+ RetraceFieldResultImpl::new);
+ }
+
+ private static List<MemberNaming> lookupMemberNamingsForFieldDefinition(
+ ClassNamingForNameMapper mapper, FieldDefinition fieldDefinition) {
+ List<MemberNaming> memberNamings =
+ mapper.mappedFieldNamingsByName.get(fieldDefinition.getName());
+ if (memberNamings == null || memberNamings.isEmpty()) {
+ return null;
+ }
+ return memberNamings;
+ }
+
@Override
public RetraceMethodResultImpl lookupMethod(String methodName) {
return lookupMethod(MethodDefinition.create(obfuscatedReference, methodName));
@@ -79,82 +93,52 @@
return lookupMethod(MethodDefinition.create(reference));
}
- private static MethodSignature getSignature(
- ClassNamingForNameMapper mapper, MethodDefinition definition) {
- if (mapper != null && definition.isFullMethodDefinition()) {
- MemberNaming lookup =
- mapper.lookup(
- MethodSignature.fromMethodReference(
- definition.asFullMethodDefinition().getMethodReference()));
- if (lookup != null) {
- return lookup.getOriginalSignature().asMethodSignature();
- }
- }
- return null;
- }
-
- private static FieldSignature getSignature(
- ClassNamingForNameMapper mapper, FieldDefinition definition) {
- if (mapper != null && definition.isFullFieldDefinition()) {
- MemberNaming lookup =
- mapper.lookup(
- FieldSignature.fromFieldReference(
- definition.asFullFieldDefinition().getFieldReference()));
- if (lookup != null) {
- return lookup.getOriginalSignature().asFieldSignature();
- }
- }
- return null;
- }
-
- private RetraceFieldResultImpl lookupField(FieldDefinition fieldDefinition) {
- return lookup(
- fieldDefinition,
- getSignature(mapper, fieldDefinition),
- (mapper, name) -> {
- List<MemberNaming> memberNamings = mapper.mappedFieldNamingsByName.get(name);
- if (memberNamings == null || memberNamings.isEmpty()) {
- return null;
- }
- return memberNamings;
- },
- RetraceFieldResultImpl::new);
- }
-
private RetraceMethodResultImpl lookupMethod(MethodDefinition methodDefinition) {
return lookup(
methodDefinition,
- getSignature(mapper, methodDefinition),
- (mapper, name) -> {
- MappedRangesOfName mappedRanges = mapper.mappedRangesByRenamedName.get(name);
- if (mappedRanges == null || mappedRanges.getMappedRanges().isEmpty()) {
- return null;
- }
- return mappedRanges.getMappedRanges();
- },
+ RetraceClassResultImpl::lookupMappedRangesForMethodDefinition,
RetraceMethodResultImpl::new);
}
- private <T, R, D extends Definition, S extends Signature> R lookup(
+ private static List<MemberNamingWithMappedRangesOfName> lookupMappedRangesForMethodDefinition(
+ ClassNamingForNameMapper mapper, MethodDefinition methodDefinition) {
+ MappedRangesOfName mappedRanges =
+ mapper.mappedRangesByRenamedName.get(methodDefinition.getName());
+ if (mappedRanges == null || mappedRanges.getMappedRanges().isEmpty()) {
+ return null;
+ }
+ List<MappedRangesOfName> partitions = mappedRanges.partitionOnMethodSignature();
+ boolean isAmbiguous = partitions.size() > 1;
+ return ListUtils.map(
+ partitions,
+ mappedRangesOfName ->
+ new MemberNamingWithMappedRangesOfName(
+ mappedRangesOfName.getMemberNaming(mapper, isAmbiguous), mappedRangesOfName));
+ }
+
+ private static <T, D extends Definition> void lookupElement(
+ RetraceClassElementImpl element,
D definition,
- S originalSignature,
- BiFunction<ClassNamingForNameMapper, String, T> lookupFunction,
- ResultConstructor<T, R, D, S> constructor) {
+ List<Pair<RetraceClassElementImpl, T>> mappings,
+ BiFunction<ClassNamingForNameMapper, D, T> lookupFunction) {
+ if (element.mapper != null) {
+ T mappedElements = lookupFunction.apply(element.mapper, definition);
+ if (mappedElements != null) {
+ mappings.add(new Pair<>(element, mappedElements));
+ return;
+ }
+ }
+ mappings.add(new Pair<>(element, null));
+ }
+
+ private <T, R, D extends Definition> R lookup(
+ D definition,
+ BiFunction<ClassNamingForNameMapper, D, T> lookupFunction,
+ ResultConstructor<T, R, D> constructor) {
List<Pair<RetraceClassElementImpl, T>> mappings = new ArrayList<>();
internalStream()
- .forEach(
- element -> {
- if (mapper != null) {
- assert element.mapper != null;
- T mappedElements = lookupFunction.apply(element.mapper, definition.getName());
- if (mappedElements != null) {
- mappings.add(new Pair<>(element, mappedElements));
- return;
- }
- }
- mappings.add(new Pair<>(element, null));
- });
- return constructor.create(this, mappings, definition, originalSignature, retracer);
+ .forEach(element -> lookupElement(element, definition, mappings, lookupFunction));
+ return constructor.create(this, mappings, definition, retracer);
}
@Override
@@ -212,12 +196,11 @@
mapper);
}
- private interface ResultConstructor<T, R, D, S> {
+ private interface ResultConstructor<T, R, D> {
R create(
RetraceClassResultImpl classResult,
List<Pair<RetraceClassElementImpl, T>> mappings,
D definition,
- S originalSignature,
RetracerImpl retracer);
}
@@ -271,14 +254,7 @@
private RetraceFieldResultImpl lookupField(FieldDefinition fieldDefinition) {
return lookup(
fieldDefinition,
- getSignature(mapper, fieldDefinition),
- (mapper, name) -> {
- List<MemberNaming> memberNamings = mapper.mappedFieldNamingsByName.get(name);
- if (memberNamings == null || memberNamings.isEmpty()) {
- return null;
- }
- return memberNamings;
- },
+ RetraceClassResultImpl::lookupMemberNamingsForFieldDefinition,
RetraceFieldResultImpl::new);
}
@@ -290,34 +266,17 @@
private RetraceMethodResultImpl lookupMethod(MethodDefinition methodDefinition) {
return lookup(
methodDefinition,
- getSignature(mapper, methodDefinition),
- (mapper, name) -> {
- MappedRangesOfName mappedRanges = mapper.mappedRangesByRenamedName.get(name);
- if (mappedRanges == null || mappedRanges.getMappedRanges().isEmpty()) {
- return null;
- }
- return mappedRanges.getMappedRanges();
- },
+ RetraceClassResultImpl::lookupMappedRangesForMethodDefinition,
RetraceMethodResultImpl::new);
}
- private <T, R, D extends Definition, S extends Signature> R lookup(
+ private <T, R, D extends Definition> R lookup(
D definition,
- S originalSignature,
- BiFunction<ClassNamingForNameMapper, String, T> lookupFunction,
- ResultConstructor<T, R, D, S> constructor) {
- List<Pair<RetraceClassElementImpl, T>> mappings = ImmutableList.of();
- if (mapper != null) {
- T result = lookupFunction.apply(mapper, definition.getName());
- if (result != null) {
- mappings = ImmutableList.of(new Pair<>(this, result));
- }
- }
- if (mappings.isEmpty()) {
- mappings = ImmutableList.of(new Pair<>(this, null));
- }
- return constructor.create(
- classResult, mappings, definition, originalSignature, classResult.retracer);
+ BiFunction<ClassNamingForNameMapper, D, T> lookupFunction,
+ ResultConstructor<T, R, D> constructor) {
+ List<Pair<RetraceClassElementImpl, T>> mappings = new ArrayList<>();
+ RetraceClassResultImpl.lookupElement(this, definition, mappings, lookupFunction);
+ return constructor.create(classResult, mappings, definition, classResult.retracer);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/RetraceFieldResultImpl.java b/src/main/java/com/android/tools/r8/retrace/internal/RetraceFieldResultImpl.java
index d1d7203..e87a2ea 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/RetraceFieldResultImpl.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/RetraceFieldResultImpl.java
@@ -23,19 +23,16 @@
private final RetraceClassResultImpl classResult;
private final List<Pair<RetraceClassElementImpl, List<MemberNaming>>> memberNamings;
private final FieldDefinition fieldDefinition;
- private final FieldSignature originalFieldSignature;
private final Retracer retracer;
RetraceFieldResultImpl(
RetraceClassResultImpl classResult,
List<Pair<RetraceClassElementImpl, List<MemberNaming>>> memberNamings,
FieldDefinition fieldDefinition,
- FieldSignature originalFieldSignature,
Retracer retracer) {
this.classResult = classResult;
this.memberNamings = memberNamings;
this.fieldDefinition = fieldDefinition;
- this.originalFieldSignature = originalFieldSignature;
this.retracer = retracer;
assert classResult != null;
assert !memberNamings.isEmpty();
@@ -55,7 +52,8 @@
classElement,
RetracedFieldReferenceImpl.create(
fieldDefinition.substituteHolder(
- classElement.getRetracedClass().getClassReference()))));
+ classElement.getRetracedClass().getClassReference())),
+ null));
}
return memberNamings.stream()
.map(
@@ -78,7 +76,8 @@
fieldSignature.isQualified()
? fieldSignature.toUnqualifiedName()
: fieldSignature.name,
- Reference.typeFromTypeName(fieldSignature.type))));
+ Reference.typeFromTypeName(fieldSignature.type))),
+ memberNaming);
});
});
}
@@ -105,14 +104,17 @@
private final RetracedFieldReferenceImpl fieldReference;
private final RetraceFieldResultImpl retraceFieldResult;
private final RetraceClassElementImpl classElement;
+ private final MemberNaming memberNaming;
private ElementImpl(
RetraceFieldResultImpl retraceFieldResult,
RetraceClassElementImpl classElement,
- RetracedFieldReferenceImpl fieldReference) {
+ RetracedFieldReferenceImpl fieldReference,
+ MemberNaming memberNaming) {
this.classElement = classElement;
this.fieldReference = fieldReference;
this.retraceFieldResult = retraceFieldResult;
+ this.memberNaming = memberNaming;
}
@Override
@@ -122,6 +124,7 @@
@Override
public boolean isUnknown() {
+ assert (memberNaming == null) == fieldReference.isUnknown();
return fieldReference.isUnknown();
}
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/RetraceFrameResultImpl.java b/src/main/java/com/android/tools/r8/retrace/internal/RetraceFrameResultImpl.java
index 9d22b04..cfaa06e 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/RetraceFrameResultImpl.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/RetraceFrameResultImpl.java
@@ -8,6 +8,7 @@
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.naming.ClassNamingForNameMapper.MappedRange;
+import com.android.tools.r8.naming.MemberNaming;
import com.android.tools.r8.naming.Range;
import com.android.tools.r8.references.MethodReference;
import com.android.tools.r8.retrace.RetraceFrameElement;
@@ -36,7 +37,8 @@
private final RetraceClassResultImpl classResult;
private final MethodDefinition methodDefinition;
private final OptionalInt obfuscatedPosition;
- private final List<Pair<RetraceClassElementImpl, List<MappedRange>>> mappedRanges;
+ private final List<Pair<RetraceClassElementImpl, List<MemberNamingWithMappedRangesOfName>>>
+ mappedRanges;
private final RetracerImpl retracer;
private final RetraceStackTraceContextImpl context;
@@ -44,7 +46,7 @@
public RetraceFrameResultImpl(
RetraceClassResultImpl classResult,
- List<Pair<RetraceClassElementImpl, List<MappedRange>>> mappedRanges,
+ List<Pair<RetraceClassElementImpl, List<MemberNamingWithMappedRangesOfName>>> mappedRanges,
MethodDefinition methodDefinition,
OptionalInt obfuscatedPosition,
RetracerImpl retracer,
@@ -55,35 +57,46 @@
this.mappedRanges = mappedRanges;
this.retracer = retracer;
this.context = context;
+ assert !mappedRanges.isEmpty();
}
@Override
public boolean isAmbiguous() {
if (isAmbiguousCache.isUnknown()) {
- if (mappedRanges.size() > 1) {
- isAmbiguousCache = OptionalBool.TRUE;
- return true;
- }
- List<MappedRange> methodRanges = mappedRanges.get(0).getSecond();
- if (methodRanges != null && !methodRanges.isEmpty()) {
- MappedRange initialRange = methodRanges.get(0);
- for (MappedRange mappedRange : methodRanges) {
- if (isMappedRangeAmbiguous(mappedRange)) {
- isAmbiguousCache = OptionalBool.TRUE;
- return true;
- }
- if (mappedRange != initialRange
- && (mappedRange.minifiedRange == null
- || !mappedRange.minifiedRange.equals(initialRange.minifiedRange))) {
- isAmbiguousCache = OptionalBool.TRUE;
- return true;
- }
+ isAmbiguousCache = OptionalBool.of(computeIsAmbiguous());
+ assert !isAmbiguousCache.isUnknown();
+ }
+ return isAmbiguousCache.isTrue();
+ }
+
+ private boolean computeIsAmbiguous() {
+ if (mappedRanges.size() > 1) {
+ return true;
+ }
+ List<MemberNamingWithMappedRangesOfName> memberNamingWithMappedRanges =
+ mappedRanges.get(0).getSecond();
+ if (memberNamingWithMappedRanges == null) {
+ return false;
+ }
+ if (memberNamingWithMappedRanges.size() > 1) {
+ return true;
+ }
+ assert !memberNamingWithMappedRanges.isEmpty();
+ List<MappedRange> methodRanges = memberNamingWithMappedRanges.get(0).getMappedRanges();
+ if (methodRanges != null && !methodRanges.isEmpty()) {
+ MappedRange initialRange = methodRanges.get(0);
+ for (MappedRange mappedRange : methodRanges) {
+ if (isMappedRangeAmbiguous(mappedRange)) {
+ return true;
+ }
+ if (mappedRange != initialRange
+ && (mappedRange.minifiedRange == null
+ || !mappedRange.minifiedRange.equals(initialRange.minifiedRange))) {
+ return true;
}
}
- isAmbiguousCache = OptionalBool.FALSE;
}
- assert !isAmbiguousCache.isUnknown();
- return isAmbiguousCache.isTrue();
+ return false;
}
private boolean isMappedRangeAmbiguous(MappedRange mappedRange) {
@@ -102,8 +115,10 @@
.flatMap(
mappedRangePair -> {
RetraceClassElementImpl classElement = mappedRangePair.getFirst();
- List<MappedRange> mappedRanges = mappedRangePair.getSecond();
- if (mappedRanges == null || mappedRanges.isEmpty()) {
+ List<MemberNamingWithMappedRangesOfName> memberNamingWithMappedRangesOfNames =
+ mappedRangePair.getSecond();
+ if (memberNamingWithMappedRangesOfNames == null
+ || memberNamingWithMappedRangesOfNames.isEmpty()) {
return Stream.of(
new ElementImpl(
this,
@@ -112,32 +127,46 @@
methodDefinition.substituteHolder(
classElement.getRetracedClass().getClassReference())),
ImmutableList.of(),
+ null,
obfuscatedPosition,
retracer));
}
// Iterate over mapped ranges that may have different positions than specified.
List<ElementImpl> ambiguousFrames = new ArrayList<>();
- Range minifiedRange = mappedRanges.get(0).minifiedRange;
- List<MappedRange> mappedRangesForElement = Lists.newArrayList(mappedRanges.get(0));
- for (int i = 1; i < mappedRanges.size(); i++) {
- MappedRange mappedRange = mappedRanges.get(i);
- if (minifiedRange == null || !minifiedRange.equals(mappedRange.minifiedRange)) {
- // This is a new frame
- separateAmbiguousOriginalPositions(
- classElement, mappedRangesForElement, ambiguousFrames);
- mappedRangesForElement = new ArrayList<>();
- minifiedRange = mappedRange.minifiedRange;
+ for (MemberNamingWithMappedRangesOfName memberNamingWithMappedRangesOfName :
+ memberNamingWithMappedRangesOfNames) {
+ List<MappedRange> mappedRangesForMemberNaming =
+ memberNamingWithMappedRangesOfName.getMappedRanges();
+ MappedRange firstMappedRange = mappedRangesForMemberNaming.get(0);
+ Range minifiedRange = firstMappedRange.minifiedRange;
+ List<MappedRange> mappedRangesForElement = Lists.newArrayList(firstMappedRange);
+ for (int i = 1; i < mappedRangesForMemberNaming.size(); i++) {
+ MappedRange mappedRange = mappedRangesForMemberNaming.get(i);
+ if (minifiedRange == null || !minifiedRange.equals(mappedRange.minifiedRange)) {
+ // This is a new frame
+ separateAmbiguousOriginalPositions(
+ classElement,
+ memberNamingWithMappedRangesOfName.getMemberNaming(),
+ mappedRangesForElement,
+ ambiguousFrames);
+ mappedRangesForElement = new ArrayList<>();
+ minifiedRange = mappedRange.minifiedRange;
+ }
+ mappedRangesForElement.add(mappedRange);
}
- mappedRangesForElement.add(mappedRange);
+ separateAmbiguousOriginalPositions(
+ classElement,
+ memberNamingWithMappedRangesOfName.getMemberNaming(),
+ mappedRangesForElement,
+ ambiguousFrames);
}
- separateAmbiguousOriginalPositions(
- classElement, mappedRangesForElement, ambiguousFrames);
return ambiguousFrames.stream();
});
}
private void separateAmbiguousOriginalPositions(
RetraceClassElementImpl classElement,
+ MemberNaming memberNaming,
List<MappedRange> frames,
List<ElementImpl> allAmbiguousElements) {
// We have a single list of frames where minified positional information may produce ambiguous
@@ -145,7 +174,7 @@
if (!isAmbiguous() || !isMappedRangeAmbiguous(frames.get(0))) {
allAmbiguousElements.add(
elementFromMappedRanges(
- ListUtils.map(frames, MappedRangeForFrame::create), classElement));
+ memberNaming, ListUtils.map(frames, MappedRangeForFrame::create), classElement));
return;
}
assert frames.size() > 0;
@@ -165,19 +194,19 @@
}
} else {
newFrames.forEach(
- ambiguousFrames -> {
- ambiguousFrames.add(MappedRangeForFrame.create(frame));
- });
+ ambiguousFrames -> ambiguousFrames.add(MappedRangeForFrame.create(frame)));
}
});
newFrames.forEach(
- ambiguousFrames -> {
- allAmbiguousElements.add(elementFromMappedRanges(ambiguousFrames, classElement));
- });
+ ambiguousFrames ->
+ allAmbiguousElements.add(
+ elementFromMappedRanges(memberNaming, ambiguousFrames, classElement)));
}
private ElementImpl elementFromMappedRanges(
- List<MappedRangeForFrame> mappedRangesForElement, RetraceClassElementImpl classElement) {
+ MemberNaming memberNaming,
+ List<MappedRangeForFrame> mappedRangesForElement,
+ RetraceClassElementImpl classElement) {
MappedRangeForFrame topFrame = mappedRangesForElement.get(0);
MethodReference methodReference =
methodReferenceFromMappedRange(
@@ -187,6 +216,7 @@
classElement,
getRetracedMethod(methodReference, topFrame, obfuscatedPosition),
mappedRangesForElement,
+ memberNaming,
obfuscatedPosition,
retracer);
}
@@ -221,7 +251,8 @@
@Override
public boolean isEmpty() {
- return mappedRanges.isEmpty();
+ List<MemberNamingWithMappedRangesOfName> mappedRangesOfNames = mappedRanges.get(0).getSecond();
+ return mappedRangesOfNames == null || mappedRangesOfNames.isEmpty();
}
public static class ElementImpl implements RetraceFrameElement {
@@ -230,6 +261,7 @@
private final RetraceFrameResultImpl retraceFrameResult;
private final RetraceClassElementImpl classElement;
private final List<MappedRangeForFrame> mappedRanges;
+ private final MemberNaming memberNaming;
private final OptionalInt obfuscatedPosition;
private final RetracerImpl retracer;
@@ -238,12 +270,14 @@
RetraceClassElementImpl classElement,
RetracedMethodReferenceImpl methodReference,
List<MappedRangeForFrame> mappedRanges,
+ MemberNaming memberNaming,
OptionalInt obfuscatedPosition,
RetracerImpl retracer) {
this.methodReference = methodReference;
this.retraceFrameResult = retraceFrameResult;
this.classElement = classElement;
this.mappedRanges = mappedRanges;
+ this.memberNaming = memberNaming;
this.obfuscatedPosition = obfuscatedPosition;
this.retracer = retracer;
}
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/RetraceMethodResultImpl.java b/src/main/java/com/android/tools/r8/retrace/internal/RetraceMethodResultImpl.java
index 19b2c15..1614e37 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/RetraceMethodResultImpl.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/RetraceMethodResultImpl.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.errors.Unimplemented;
import com.android.tools.r8.naming.ClassNamingForNameMapper.MappedRange;
import com.android.tools.r8.naming.ClassNamingForNameMapper.MappedRangesOfName;
+import com.android.tools.r8.naming.MemberNaming;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.naming.mappinginformation.OutlineCallsiteMappingInformation;
import com.android.tools.r8.references.MethodReference;
@@ -19,30 +20,26 @@
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.Pair;
import java.util.ArrayList;
-import java.util.HashSet;
import java.util.List;
import java.util.OptionalInt;
-import java.util.Set;
import java.util.stream.Stream;
public class RetraceMethodResultImpl implements RetraceMethodResult {
private final MethodDefinition methodDefinition;
- private final MethodSignature originalMethodSignature;
private final RetraceClassResultImpl classResult;
- private final List<Pair<RetraceClassElementImpl, List<MappedRange>>> mappedRanges;
+ private final List<Pair<RetraceClassElementImpl, List<MemberNamingWithMappedRangesOfName>>>
+ mappedRanges;
private final RetracerImpl retracer;
RetraceMethodResultImpl(
RetraceClassResultImpl classResult,
- List<Pair<RetraceClassElementImpl, List<MappedRange>>> mappedRanges,
+ List<Pair<RetraceClassElementImpl, List<MemberNamingWithMappedRangesOfName>>> mappedRanges,
MethodDefinition methodDefinition,
- MethodSignature originalMethodSignature,
RetracerImpl retracer) {
this.classResult = classResult;
this.mappedRanges = mappedRanges;
this.methodDefinition = methodDefinition;
- this.originalMethodSignature = originalMethodSignature;
this.retracer = retracer;
assert classResult != null;
assert !mappedRanges.isEmpty();
@@ -53,73 +50,71 @@
if (mappedRanges.size() > 1) {
return true;
}
- if (originalMethodSignature != null) {
- return false;
- }
- List<MappedRange> methodRanges = mappedRanges.get(0).getSecond();
- if (methodRanges == null || methodRanges.isEmpty()) {
- return false;
- }
- MappedRange lastRange = methodRanges.get(0);
- for (MappedRange mappedRange : methodRanges) {
- if (mappedRange != lastRange
- && (mappedRange.minifiedRange == null
- || !mappedRange.minifiedRange.equals(lastRange.minifiedRange))) {
- return true;
- }
- }
- return false;
+ List<MemberNamingWithMappedRangesOfName> mappedRangesOfNames = mappedRanges.get(0).getSecond();
+ return mappedRangesOfNames != null && mappedRangesOfNames.size() > 1;
}
@Override
public boolean isEmpty() {
- return mappedRanges == null || mappedRanges.isEmpty();
+ List<MemberNamingWithMappedRangesOfName> mappedRangesOfNames = mappedRanges.get(0).getSecond();
+ return mappedRangesOfNames == null || mappedRangesOfNames.isEmpty();
}
@Override
public RetraceFrameResultImpl narrowByPosition(
RetraceStackTraceContext context, OptionalInt position) {
- List<Pair<RetraceClassElementImpl, List<MappedRange>>> narrowedRanges = new ArrayList<>();
+ List<Pair<RetraceClassElementImpl, List<MemberNamingWithMappedRangesOfName>>> narrowedRanges =
+ new ArrayList<>();
RetraceStackTraceContextImpl stackTraceContext = null;
if (context instanceof RetraceStackTraceContextImpl) {
stackTraceContext = (RetraceStackTraceContextImpl) context;
}
- for (Pair<RetraceClassElementImpl, List<MappedRange>> mappedRange : mappedRanges) {
- if (mappedRange.getSecond() == null) {
+ for (Pair<RetraceClassElementImpl, List<MemberNamingWithMappedRangesOfName>> mappedRange :
+ mappedRanges) {
+ List<MemberNamingWithMappedRangesOfName> memberNamingWithMappedRanges =
+ mappedRange.getSecond();
+ if (memberNamingWithMappedRanges == null) {
narrowedRanges.add(new Pair<>(mappedRange.getFirst(), null));
continue;
}
- MappedRangesOfName mappedRangesOfElement = new MappedRangesOfName(mappedRange.getSecond());
- List<MappedRange> mappedRangesForPosition = null;
boolean hasPosition = position.isPresent() && position.getAsInt() >= 0;
- if (hasPosition) {
- mappedRangesForPosition =
- mappedRangesOfElement.allRangesForLine(position.getAsInt(), false);
- }
- if (mappedRangesForPosition == null || mappedRangesForPosition.isEmpty()) {
- mappedRangesForPosition =
- hasPosition
- ? ListUtils.filter(
- mappedRangesOfElement.getMappedRanges(), range -> range.minifiedRange == null)
- : mappedRangesOfElement.getMappedRanges();
- }
- if (mappedRangesForPosition != null && !mappedRangesForPosition.isEmpty()) {
- if (stackTraceContext != null && stackTraceContext.hasRewritePosition()) {
- List<OutlineCallsiteMappingInformation> outlineCallsiteInformation =
- ListUtils.last(mappedRangesForPosition).getOutlineCallsiteInformation();
- if (!outlineCallsiteInformation.isEmpty()) {
- assert outlineCallsiteInformation.size() == 1
- : "There can only be one outline entry for a line";
- return narrowByPosition(
- stackTraceContext.buildFromThis().clearRewritePosition().build(),
- OptionalInt.of(
- outlineCallsiteInformation
- .get(0)
- .rewritePosition(stackTraceContext.getRewritePosition())));
+ List<MemberNamingWithMappedRangesOfName> newMemberNamingsResult = new ArrayList<>();
+ for (MemberNamingWithMappedRangesOfName memberNamingWithMappedRange :
+ memberNamingWithMappedRanges) {
+ List<MappedRange> mappedRangesForPosition = null;
+ if (hasPosition) {
+ mappedRangesForPosition =
+ memberNamingWithMappedRange.allRangesForLine(position.getAsInt());
+ }
+ if (mappedRangesForPosition == null || mappedRangesForPosition.isEmpty()) {
+ mappedRangesForPosition =
+ hasPosition
+ ? memberNamingWithMappedRange.mappedRangesWithNoMinifiedRange()
+ : memberNamingWithMappedRange.getMappedRanges();
+ }
+ if (mappedRangesForPosition != null && !mappedRangesForPosition.isEmpty()) {
+ MemberNamingWithMappedRangesOfName newMemberNaming =
+ new MemberNamingWithMappedRangesOfName(
+ memberNamingWithMappedRange.getMemberNaming(),
+ new MappedRangesOfName(mappedRangesForPosition));
+ newMemberNamingsResult.add(newMemberNaming);
+ if (stackTraceContext != null && stackTraceContext.hasRewritePosition()) {
+ List<OutlineCallsiteMappingInformation> outlineCallsiteInformation =
+ ListUtils.last(mappedRangesForPosition).getOutlineCallsiteInformation();
+ if (!outlineCallsiteInformation.isEmpty()) {
+ assert outlineCallsiteInformation.size() == 1
+ : "There can only be one outline entry for a line";
+ return narrowByPosition(
+ stackTraceContext.buildFromThis().clearRewritePosition().build(),
+ OptionalInt.of(
+ outlineCallsiteInformation
+ .get(0)
+ .rewritePosition(stackTraceContext.getRewritePosition())));
+ }
}
}
- narrowedRanges.add(new Pair<>(mappedRange.getFirst(), mappedRangesForPosition));
}
+ narrowedRanges.add(new Pair<>(mappedRange.getFirst(), newMemberNamingsResult));
}
return new RetraceFrameResultImpl(
classResult,
@@ -132,48 +127,43 @@
@Override
public Stream<RetraceMethodElement> stream() {
- if (originalMethodSignature != null) {
- // Even if we know exactly the retraced residual definition, the class element
- // may still be ambiguous.
- return mappedRanges.stream()
- .map(
- mappedRangePair -> {
- RetraceClassElementImpl classElement = mappedRangePair.getFirst();
- MethodReference methodReference =
- RetraceUtils.methodReferenceFromMethodSignature(
- originalMethodSignature,
- classElement.getRetracedClass().getClassReference());
- return new ElementImpl(
- this, classElement, RetracedMethodReferenceImpl.create(methodReference));
- });
- }
return mappedRanges.stream()
.flatMap(
mappedRangePair -> {
RetraceClassElementImpl classElement = mappedRangePair.getFirst();
- List<MappedRange> mappedRanges = mappedRangePair.getSecond();
- if (mappedRanges == null || mappedRanges.isEmpty()) {
+ List<MemberNamingWithMappedRangesOfName> memberNamingsWithMappedRange =
+ mappedRangePair.getSecond();
+ if (memberNamingsWithMappedRange == null || memberNamingsWithMappedRange.isEmpty()) {
return Stream.of(
new ElementImpl(
this,
classElement,
RetracedMethodReferenceImpl.create(
methodDefinition.substituteHolder(
- classElement.getRetracedClass().getClassReference()))));
+ classElement.getRetracedClass().getClassReference())),
+ null));
}
- List<ElementImpl> results = new ArrayList<>();
- Set<MethodReference> seenMethodReferences = new HashSet<>();
- for (MappedRange mappedRange : mappedRanges) {
- MethodReference methodReference =
- RetraceUtils.methodReferenceFromMappedRange(
- mappedRange, classElement.getRetracedClass().getClassReference());
- if (seenMethodReferences.add(methodReference)) {
- results.add(
- new ElementImpl(
- this, classElement, RetracedMethodReferenceImpl.create(methodReference)));
- }
- }
- return results.stream();
+ return ListUtils.map(
+ memberNamingsWithMappedRange,
+ memberNamingWithMappedRangesOfName -> {
+ MemberNaming memberNaming =
+ memberNamingWithMappedRangesOfName.getMemberNaming();
+ MethodSignature originalSignature =
+ memberNaming != null
+ ? memberNaming.getOriginalSignature().asMethodSignature()
+ : ListUtils.last(memberNamingWithMappedRangesOfName.getMappedRanges())
+ .getOriginalSignature()
+ .asMethodSignature();
+ MethodReference methodReference =
+ RetraceUtils.methodReferenceFromMethodSignature(
+ originalSignature, classElement.getRetracedClass().getClassReference());
+ return new ElementImpl(
+ this,
+ classElement,
+ RetracedMethodReferenceImpl.create(methodReference),
+ memberNaming);
+ })
+ .stream();
});
}
@@ -182,14 +172,17 @@
private final RetracedMethodReferenceImpl methodReference;
private final RetraceMethodResultImpl retraceMethodResult;
private final RetraceClassElementImpl classElement;
+ private final MemberNaming memberNaming;
private ElementImpl(
RetraceMethodResultImpl retraceMethodResult,
RetraceClassElementImpl classElement,
- RetracedMethodReferenceImpl methodReference) {
+ RetracedMethodReferenceImpl methodReference,
+ MemberNaming memberNaming) {
this.classElement = classElement;
this.retraceMethodResult = retraceMethodResult;
this.methodReference = methodReference;
+ this.memberNaming = memberNaming;
}
@Override
diff --git a/src/main/java/com/android/tools/r8/utils/positions/MappedPositionToClassNameMapperBuilder.java b/src/main/java/com/android/tools/r8/utils/positions/MappedPositionToClassNameMapperBuilder.java
index b87a2b5..646e09e 100644
--- a/src/main/java/com/android/tools/r8/utils/positions/MappedPositionToClassNameMapperBuilder.java
+++ b/src/main/java/com/android/tools/r8/utils/positions/MappedPositionToClassNameMapperBuilder.java
@@ -179,7 +179,7 @@
FieldSignature.fromDexField(originalField, originalField.holder != originalType);
FieldSignature residualSignature = FieldSignature.fromDexField(residualField);
MemberNaming memberNaming = new MemberNaming(originalSignature, residualSignature);
- getBuilder().addMemberEntry(memberNaming, residualSignature);
+ getBuilder().addMemberEntry(memberNaming);
}
});
return this;
@@ -227,7 +227,7 @@
MethodSignature residualSignature = MethodSignature.fromDexMethod(residualMethod);
MemberNaming memberNaming = new MemberNaming(originalSignature, residualSignature);
- getBuilder().addMemberEntry(memberNaming, residualSignature);
+ getBuilder().addMemberEntry(memberNaming);
// Add simple "a() -> b" mapping if we won't have any other with concrete line numbers
if (mappedPositions.isEmpty()) {
diff --git a/src/test/java/com/android/tools/r8/classmerging/vertical/VerticalClassMergerTest.java b/src/test/java/com/android/tools/r8/classmerging/vertical/VerticalClassMergerTest.java
index da6cb32..1f9e6c7 100644
--- a/src/test/java/com/android/tools/r8/classmerging/vertical/VerticalClassMergerTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/vertical/VerticalClassMergerTest.java
@@ -53,7 +53,6 @@
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
-import java.util.function.Function;
import java.util.function.Predicate;
import org.junit.Assume;
import org.junit.Test;
@@ -540,7 +539,7 @@
.toString()
.equals("java.lang.String classmerging.ProguardFieldMapTest$A.f")
&& fieldNaming
- .computeResidualSignature(Function.identity())
+ .getResidualSignature()
.toString()
.equals("java.lang.String f")));
}
@@ -588,10 +587,7 @@
methodNaming
.getOriginalSignature()
.toString()
- .equals(
- methodNaming
- .computeResidualSignature(Function.identity())
- .toString())));
+ .equals(methodNaming.getResidualSignature().toString())));
// Try with vertical class merging.
Set<String> preservedClassNames =
@@ -624,7 +620,7 @@
.toString()
.equals("void classmerging.ProguardMethodMapTest$A.method()")
&& methodNaming
- .computeResidualSignature(Function.identity())
+ .getResidualSignature()
.toString()
.equals("void method$classmerging$ProguardMethodMapTest$A()")));
}
diff --git a/src/test/java/com/android/tools/r8/retrace/RenamedSignatureClashTest.java b/src/test/java/com/android/tools/r8/retrace/RenamedSignatureClashTest.java
new file mode 100644
index 0000000..183f4a1
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/retrace/RenamedSignatureClashTest.java
@@ -0,0 +1,71 @@
+// Copyright (c) 2022, 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.retrace;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.DiagnosticsHandler;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.errors.Unimplemented;
+import com.android.tools.r8.references.ClassReference;
+import com.android.tools.r8.references.MethodReference;
+import com.android.tools.r8.references.Reference;
+import com.android.tools.r8.utils.StringUtils;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class RenamedSignatureClashTest extends TestBase {
+
+ @Parameter() public TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withNoneRuntime().build();
+ }
+
+ private final ClassReference renamedHolder = Reference.classFromTypeName("A");
+ private final ClassReference originalHolder =
+ Reference.classFromTypeName("com.android.tools.r8.naming.retrace.Main");
+
+ private final String mapping =
+ StringUtils.lines(
+ originalHolder.getTypeName() + " -> " + renamedHolder.getTypeName() + ":",
+ " void some.moved.Method.someMethod(int) -> a",
+ " void methodWithRemovedArgument(int) -> a",
+ " # { id: 'com.android.tools.r8.synthesized' }");
+
+ @Test
+ public void testAmbiguousResult() {
+ Retracer retracer =
+ Retracer.createDefault(
+ ProguardMapProducer.fromString(mapping), new DiagnosticsHandler() {});
+ MethodReference methodReference =
+ Reference.methodFromDescriptor(renamedHolder.getDescriptor(), "a", "(I)V");
+ RetraceMethodResult retraceMethodResult = retracer.retraceMethod(methodReference);
+ assertTrue(retraceMethodResult.isAmbiguous());
+ retraceMethodResult.stream()
+ .forEach(
+ result -> {
+ String method = result.getRetracedMethod().asKnown().getMethodReference().toString();
+ if (method.equals("Lsome/moved/Method;someMethod(I)V")) {
+ // TODO(b/172014416): Fix when changed.
+ assertThrows(Unimplemented.class, result::isCompilerSynthesized);
+ } else {
+ // TODO(b/172014416): Fix when changed.
+ assertEquals(
+ originalHolder.getDescriptor() + "methodWithRemovedArgument(I)V", method);
+ assertThrows(Unimplemented.class, result::isCompilerSynthesized);
+ }
+ });
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/retrace/RetraceOutsideLineRangeTest.java b/src/test/java/com/android/tools/r8/retrace/RetraceOutsideLineRangeTest.java
index 234ab06..6817079 100644
--- a/src/test/java/com/android/tools/r8/retrace/RetraceOutsideLineRangeTest.java
+++ b/src/test/java/com/android/tools/r8/retrace/RetraceOutsideLineRangeTest.java
@@ -57,7 +57,7 @@
Retracer retracer =
Retracer.createDefault(
ProguardMapProducer.fromString(mapping), new DiagnosticsHandler() {});
- retraceClassMethodAndPosition(retracer, someClassRenamed, someClassOriginal, 2, 0);
+ retraceClassMethodAndPosition(retracer, someClassRenamed, someClassOriginal, 2, 1);
retraceClassMethodAndPosition(retracer, someOtherClassRenamed, someOtherClassOriginal, 1, 1);
}
diff --git a/src/test/java/com/android/tools/r8/retrace/api/RetraceApiResidualSignatureTest.java b/src/test/java/com/android/tools/r8/retrace/api/RetraceApiResidualSignatureTest.java
index 01a62b5..d66d77d 100644
--- a/src/test/java/com/android/tools/r8/retrace/api/RetraceApiResidualSignatureTest.java
+++ b/src/test/java/com/android/tools/r8/retrace/api/RetraceApiResidualSignatureTest.java
@@ -15,7 +15,10 @@
import com.android.tools.r8.retrace.RetraceFieldElement;
import com.android.tools.r8.retrace.RetraceMethodElement;
import com.android.tools.r8.retrace.Retracer;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import java.util.stream.Collectors;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -39,11 +42,9 @@
"# { id: 'com.android.tools.r8.mapping', version: 'experimental' }\n"
+ "some.Class -> a:\n"
+ " some.SuperType field -> a\n"
- + " # { id: 'com.android.tools.r8.residualsignature', signature: 'Ljava/lang/Object;'"
- + " }\n"
+ + " # { id:'com.android.tools.r8.residualsignature',signature:'Ljava/lang/Object;' }\n"
+ " some.SubType field -> a\n"
- + " # { id: 'com.android.tools.r8.residualsignature', signature: 'Lsome/SuperType;'"
- + " }\n"
+ + " # { id:'com.android.tools.r8.residualsignature',signature:'Lsome/SuperType;' }\n"
+ " void foo(int, int) -> x\n"
+ " # { id: 'com.android.tools.r8.residualsignature', signature: '(I)V' }\n"
+ " void foo(int) -> x\n"
@@ -61,17 +62,22 @@
List<RetraceMethodElement> fooWithTwoArgs =
retracer.retraceMethod(Reference.methodFromDescriptor(aClass, "x", "(I)V")).stream()
.collect(Collectors.toList());
- assertEquals(1, fooWithTwoArgs.size());
+ // TODO(b/169953605): Use the residual signature information to prune the result.
+ assertEquals(2, fooWithTwoArgs.size());
assertEquals(
- "Lsome/Class;foo(II)V",
- fooWithTwoArgs.get(0).getRetracedMethod().asKnown().getMethodReference().toString());
+ setOf("Lsome/Class;foo(II)V", "Lsome/Class;foo(I)V"),
+ fooWithTwoArgs.stream()
+ .map(result -> result.getRetracedMethod().asKnown().getMethodReference().toString())
+ .collect(Collectors.toSet()));
List<RetraceMethodElement> fooWithOneArg =
retracer.retraceMethod(Reference.methodFromDescriptor(aClass, "x", "()V")).stream()
.collect(Collectors.toList());
- assertEquals(1, fooWithOneArg.size());
+ assertEquals(2, fooWithOneArg.size());
assertEquals(
- "Lsome/Class;foo(I)V",
- fooWithOneArg.get(0).getRetracedMethod().asKnown().getMethodReference().toString());
+ setOf("Lsome/Class;foo(II)V", "Lsome/Class;foo(I)V"),
+ fooWithOneArg.stream()
+ .map(result -> result.getRetracedMethod().asKnown().getMethodReference().toString())
+ .collect(Collectors.toSet()));
List<RetraceFieldElement> fieldWithSuperType =
retracer
.retraceField(
@@ -80,14 +86,29 @@
.collect(Collectors.toList());
// TODO(b/169953605): Use the residual signature information to prune the result.
assertEquals(2, fieldWithSuperType.size());
+ assertEquals(
+ setOf("Lsome/Class;field:Lsome/SuperType;", "Lsome/Class;field:Lsome/SubType;"),
+ fieldWithSuperType.stream()
+ .map(result -> result.getField().asKnown().getFieldReference().toString())
+ .collect(Collectors.toSet()));
List<RetraceFieldElement> fieldWithSubType =
retracer
.retraceField(
Reference.field(aClass, "a", Reference.typeFromTypeName("some.SuperType")))
.stream()
.collect(Collectors.toList());
- // TODO(b/169953605): Use the residual signature information to prune the result.
assertEquals(2, fieldWithSubType.size());
+ assertEquals(
+ setOf("Lsome/Class;field:Lsome/SuperType;", "Lsome/Class;field:Lsome/SubType;"),
+ fieldWithSubType.stream()
+ .map(result -> result.getField().asKnown().getFieldReference().toString())
+ .collect(Collectors.toSet()));
+ }
+
+ private Set<Object> setOf(Object... objects) {
+ Set<Object> result = new HashSet<>();
+ Collections.addAll(result, objects);
+ return result;
}
}
}