blob: 01e6c75b35b7716430eb45c7b840b35d76830a36 [file] [log] [blame]
// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.synthesis;
import com.android.tools.r8.ProgramResource.Kind;
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.graph.ClassAccessFlags;
import com.android.tools.r8.graph.ClassKind;
import com.android.tools.r8.graph.DexAnnotationSet;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DexTypeList;
import com.android.tools.r8.graph.EnclosingMethodAttribute;
import com.android.tools.r8.graph.GenericSignature.ClassSignature;
import com.android.tools.r8.graph.InnerClassAttribute;
import com.android.tools.r8.graph.NestHostClassAttribute;
import com.android.tools.r8.graph.NestMemberClassAttribute;
import com.android.tools.r8.origin.Origin;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
abstract class SyntheticClassBuilder<B extends SyntheticClassBuilder<B, C>, C extends DexClass> {
private final DexItemFactory factory;
private final DexType type;
private final Origin origin;
private Kind originKind;
private DexType superType;
private DexTypeList interfaces = DexTypeList.empty();
private List<DexEncodedField> staticFields = new ArrayList<>();
private List<DexEncodedField> instanceFields = new ArrayList<>();
private List<DexEncodedMethod> directMethods = new ArrayList<>();
private List<DexEncodedMethod> virtualMethods = new ArrayList<>();
private List<SyntheticMethodBuilder> methods = new ArrayList<>();
SyntheticClassBuilder(DexType type, SynthesizingContext context, DexItemFactory factory) {
this.factory = factory;
this.type = type;
this.origin = context.getInputContextOrigin();
this.superType = factory.objectType;
}
public abstract B self();
public abstract ClassKind<C> getClassKind();
public DexItemFactory getFactory() {
return factory;
}
public DexType getType() {
return type;
}
public B setInterfaces(List<DexType> interfaces) {
this.interfaces =
interfaces.isEmpty()
? DexTypeList.empty()
: new DexTypeList(interfaces.toArray(DexType.EMPTY_ARRAY));
return self();
}
public B setOriginKind(Kind originKind) {
this.originKind = originKind;
return self();
}
public B setStaticFields(List<DexEncodedField> fields) {
staticFields.clear();
staticFields.addAll(fields);
return self();
}
public B setInstanceFields(List<DexEncodedField> fields) {
instanceFields.clear();
instanceFields.addAll(fields);
return self();
}
public B setDirectMethods(Iterable<DexEncodedMethod> methods) {
directMethods.clear();
methods.forEach(directMethods::add);
return self();
}
public B setVirtualMethods(Iterable<DexEncodedMethod> methods) {
virtualMethods.clear();
methods.forEach(virtualMethods::add);
return self();
}
public B addMethod(Consumer<SyntheticMethodBuilder> fn) {
SyntheticMethodBuilder method = new SyntheticMethodBuilder(this);
fn.accept(method);
methods.add(method);
return self();
}
public C build() {
ClassAccessFlags accessFlags =
ClassAccessFlags.fromSharedAccessFlags(
Constants.ACC_FINAL | Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC);
DexString sourceFile = null;
NestHostClassAttribute nestHost = null;
List<NestMemberClassAttribute> nestMembers = Collections.emptyList();
EnclosingMethodAttribute enclosingMembers = null;
List<InnerClassAttribute> innerClasses = Collections.emptyList();
for (SyntheticMethodBuilder builder : methods) {
DexEncodedMethod method = builder.build();
if (method.isNonPrivateVirtualMethod()) {
virtualMethods.add(method);
} else {
directMethods.add(method);
}
}
long checksum =
7 * (long) directMethods.hashCode()
+ 11 * (long) virtualMethods.hashCode()
+ 13 * (long) staticFields.hashCode()
+ 17 * (long) instanceFields.hashCode();
return getClassKind()
.create(
type,
originKind,
origin,
accessFlags,
superType,
interfaces,
sourceFile,
nestHost,
nestMembers,
enclosingMembers,
innerClasses,
ClassSignature.noSignature(),
DexAnnotationSet.empty(),
staticFields.toArray(DexEncodedField.EMPTY_ARRAY),
instanceFields.toArray(DexEncodedField.EMPTY_ARRAY),
directMethods.toArray(DexEncodedMethod.EMPTY_ARRAY),
virtualMethods.toArray(DexEncodedMethod.EMPTY_ARRAY),
factory.getSkipNameValidationForTesting(),
c -> checksum);
}
}