Add default constructor information to libraryinfo file.
J2CL will soon remove empty constructor. For RTA correctness, we need to add to the call graph the default constructor, otherwise we might miss the call to the constructor for the super class.
@@ -44,6 +44,8 @@ import java.util.stream.Collectors;
/** Traverse types and gather execution flow information for building call graph. */
public final class LibraryInfoBuilder {
+ public static final String CONSTRUCTOR_METHOD_NAME = "constructor";
+
/** Serialize a LibraryInfo object into a JSON string. */
public static String toJson(LibraryInfo.Builder libraryInfo, Problems problems) {
try {
@@ -117,6 +119,11 @@ public final class LibraryInfoBuilder {
collectReferencedTypesAndMethodInvocations(member, builder);
}
+ // Add the default constructor if there is no other constructor defined, So when the type is
+ // instantiated, it ensures that RTA see a call to the possible super type constructor.
+ memberInfoBuilderByName.computeIfAbsent(
+ CONSTRUCTOR_METHOD_NAME, m -> createDefaultConstructorMember(type));
+
return typeInfoBuilder
.addAllMember(
memberInfoBuilderByName.values().stream()
@@ -125,6 +132,32 @@ public final class LibraryInfoBuilder {
.build();
}
+ private static MemberInfo.Builder createDefaultConstructorMember(Type type) {
+ if (type.isInterface()) {
+ return null;
+ }
+
+ MemberInfo.Builder builder =
+ MemberInfo.newBuilder().setName(CONSTRUCTOR_METHOD_NAME).setPublic(true);
+
+ DeclaredTypeDescriptor superTypeDescriptor = type.getSuperTypeDescriptor();
+ if (superTypeDescriptor != null
+ && !superTypeDescriptor.getTypeDeclaration().isStarOrUnknown()) {
+ String superTypeId = getTypeId(superTypeDescriptor.getTypeDeclaration());
+
+ // add method invocation to super constructor.
+ builder
+ .addInvokedMethods(
+ MethodInvocation.newBuilder()
+ .setMethod(CONSTRUCTOR_METHOD_NAME)
+ .setEnclosingType(superTypeId)
+ .setKind(InvocationKind.STATIC))
+ .addReferencedTypes(superTypeId);
+ }
+
+ return builder;
+ }
+
private static SourcePosition createSourcePosition(
com.google.j2cl.common.SourcePosition position) {
return SourcePosition.newBuilder()
