blob: 158549293353a5f2f0d0f0a469e89f6c02b6dd12 [file] [log] [blame]
// Copyright (c) 2017, 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.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.utils.ThrowingConsumer;
import com.google.common.collect.ImmutableMap;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Stores name information for a class.
* <p>
* This includes how the class was renamed and information on the classes members.
*/
public class ClassNamingForNameMapper implements ClassNaming {
public static class Builder extends ClassNaming.Builder {
private final String originalName;
private final String renamedName;
private final Map<MethodSignature, MemberNaming> methodMembers = new HashMap<>();
private final Map<FieldSignature, MemberNaming> fieldMembers = new HashMap<>();
private Builder(String renamedName, String originalName) {
this.originalName = originalName;
this.renamedName = renamedName;
}
@Override
ClassNaming.Builder addMemberEntry(MemberNaming entry) {
if (entry.isMethodNaming()) {
methodMembers.put((MethodSignature) entry.getRenamedSignature(), entry);
} else {
fieldMembers.put((FieldSignature) entry.getRenamedSignature(), entry);
}
return this;
}
@Override
ClassNamingForNameMapper build() {
return new ClassNamingForNameMapper(renamedName, originalName, methodMembers, fieldMembers);
}
}
static Builder builder(String renamedName, String originalName) {
return new Builder(renamedName, originalName);
}
public final String originalName;
private final String renamedName;
/**
* Mapping from the renamed signature to the naming information for a member.
* <p>
* A renamed signature is a signature where the member's name has been obfuscated but not the type
* information.
**/
private final ImmutableMap<MethodSignature, MemberNaming> methodMembers;
private final ImmutableMap<FieldSignature, MemberNaming> fieldMembers;
private ClassNamingForNameMapper(
String renamedName,
String originalName,
Map<MethodSignature, MemberNaming> methodMembers,
Map<FieldSignature, MemberNaming> fieldMembers) {
this.renamedName = renamedName;
this.originalName = originalName;
this.methodMembers = ImmutableMap.copyOf(methodMembers);
this.fieldMembers = ImmutableMap.copyOf(fieldMembers);
}
@Override
public MemberNaming lookup(Signature renamedSignature) {
if (renamedSignature.kind() == SignatureKind.METHOD) {
return methodMembers.get(renamedSignature);
} else {
assert renamedSignature.kind() == SignatureKind.FIELD;
return fieldMembers.get(renamedSignature);
}
}
@Override
public MemberNaming lookupByOriginalSignature(Signature original) {
if (original.kind() == SignatureKind.METHOD) {
for (MemberNaming memberNaming: methodMembers.values()) {
if (memberNaming.signature.equals(original)) {
return memberNaming;
}
}
return null;
} else {
assert original.kind() == SignatureKind.FIELD;
for (MemberNaming memberNaming : fieldMembers.values()) {
if (memberNaming.signature.equals(original)) {
return memberNaming;
}
}
return null;
}
}
public List<MemberNaming> lookupByOriginalName(String originalName) {
List<MemberNaming> result = new ArrayList<>();
for (MemberNaming naming : methodMembers.values()) {
if (naming.signature.name.equals(originalName)) {
result.add(naming);
}
}
for (MemberNaming naming : fieldMembers.values()) {
if (naming.signature.name.equals(originalName)) {
result.add(naming);
}
}
return result;
}
@Override
public <T extends Throwable> void forAllMemberNaming(
ThrowingConsumer<MemberNaming, T> consumer) throws T {
forAllFieldNaming(consumer);
forAllMethodNaming(consumer);
}
@Override
public <T extends Throwable> void forAllFieldNaming(
ThrowingConsumer<MemberNaming, T> consumer) throws T {
for (MemberNaming naming : fieldMembers.values()) {
consumer.accept(naming);
}
}
@Override
public <T extends Throwable> void forAllMethodNaming(
ThrowingConsumer<MemberNaming, T> consumer) throws T {
for (MemberNaming naming : methodMembers.values()) {
consumer.accept(naming);
}
}
void write(Writer writer, boolean collapseRanges) throws IOException {
writer.append(originalName);
writer.append(" -> ");
writer.append(renamedName);
writer.append(":\n");
forAllMemberNaming(memberNaming -> memberNaming.write(writer, collapseRanges, true));
}
@Override
public String toString() {
try {
StringWriter writer = new StringWriter();
write(writer, false);
return writer.toString();
} catch (IOException e) {
return e.toString();
}
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof ClassNamingForNameMapper)) {
return false;
}
ClassNamingForNameMapper that = (ClassNamingForNameMapper) o;
return originalName.equals(that.originalName)
&& renamedName.equals(that.renamedName)
&& methodMembers.equals(that.methodMembers)
&& fieldMembers.equals(that.fieldMembers);
}
@Override
public int hashCode() {
int result = originalName.hashCode();
result = 31 * result + renamedName.hashCode();
result = 31 * result + methodMembers.hashCode();
result = 31 * result + fieldMembers.hashCode();
return result;
}
}