mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Codegen: JavaGenerator [3] - parse aliases and reserved value types
Summary: This parses the JSON schema's aliases and reserved function valye types. It also assigns TypeId correctly now: * TypeId is an identifier for a specific type, that can be referred by others * This means only aliases should have TypeId.typeName. Properties' names are not typeNames * NativeModule spec's typeName is hardcoded to `Spec`, see T71955395 This way, whenever we encounter an `AliasType`, we can just lookup the actual Type by a quick Map lookup with TypeId as the key. Changelog: [Internal] Reviewed By: mdvacca Differential Revision: D23181432 fbshipit-source-id: 9d0ea17dbf601589d8f3fc1955e0c9406a80e244
This commit is contained in:
committed by
Facebook GitHub Bot
parent
4231551270
commit
eecb930222
@@ -20,7 +20,8 @@ gradlePlugin {
|
||||
|
||||
dependencies {
|
||||
implementation 'com.android.tools.build:gradle:3.5.3'
|
||||
implementation 'com.google.code.gson:gson:2.8.6'
|
||||
// Use the same Gson version that `com.android.tools.build:gradle` depends on.
|
||||
implementation 'com.google.code.gson:gson:2.8.5'
|
||||
implementation 'com.google.guava:guava:29.0-jre'
|
||||
implementation 'com.squareup:javapoet:1.13.0'
|
||||
}
|
||||
|
||||
+5
@@ -7,6 +7,7 @@
|
||||
|
||||
package com.facebook.react.codegen.generator;
|
||||
|
||||
import com.facebook.react.codegen.generator.model.RawSchema;
|
||||
import com.squareup.javapoet.JavaFile;
|
||||
import com.squareup.javapoet.MethodSpec;
|
||||
import com.squareup.javapoet.TypeSpec;
|
||||
@@ -28,6 +29,10 @@ public final class JavaGenerator {
|
||||
}
|
||||
|
||||
public void build() throws FileNotFoundException, IOException {
|
||||
final RawSchema rawSchema = SchemaJsonParser.parse(mSchemaFile);
|
||||
// TODO (T71663018): remove - this is for debugging
|
||||
System.out.println(rawSchema);
|
||||
|
||||
final MethodSpec main =
|
||||
MethodSpec.methodBuilder("main")
|
||||
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
||||
|
||||
+48
-29
@@ -37,7 +37,6 @@ import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -47,7 +46,7 @@ public final class SchemaJsonParser {
|
||||
final JsonParser parser = new JsonParser();
|
||||
final JsonElement rootElement = parser.parse(new FileReader(schemaFile));
|
||||
|
||||
final Map<String, List<NativeModuleType>> collection = new HashMap<>();
|
||||
final Map<String, Map<String, NativeModuleType>> collection = new HashMap<>();
|
||||
|
||||
if (rootElement.isJsonObject()) {
|
||||
final JsonObject root = rootElement.getAsJsonObject();
|
||||
@@ -67,13 +66,16 @@ public final class SchemaJsonParser {
|
||||
collection.put(
|
||||
jsModuleName,
|
||||
nativeModules.entrySet().stream()
|
||||
.map(
|
||||
nativeModuleEntry -> {
|
||||
return parseNativeModule(
|
||||
TypeId.of(jsModuleName, nativeModuleEntry.getKey()),
|
||||
nativeModuleEntry.getValue().getAsJsonObject());
|
||||
})
|
||||
.collect(Collectors.toList()));
|
||||
.collect(
|
||||
Collectors.toMap(
|
||||
Map.Entry::getKey,
|
||||
e -> {
|
||||
return parseNativeModule(
|
||||
// TODO (T71955395): NativeModule spec type name does not
|
||||
// exist in the schema. For now assume it's "Spec".
|
||||
TypeId.of(jsModuleName, "Spec"),
|
||||
e.getValue().getAsJsonObject());
|
||||
})));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -84,9 +86,21 @@ public final class SchemaJsonParser {
|
||||
final JsonObject aliases = json.getAsJsonObject("aliases");
|
||||
final JsonArray properties = json.getAsJsonArray("properties");
|
||||
|
||||
// TODO: parse aliases
|
||||
final ImmutableList<Type> collectedAliases =
|
||||
ImmutableList.copyOf(
|
||||
aliases.entrySet().stream()
|
||||
.map(
|
||||
entry -> {
|
||||
final String typeName = entry.getKey();
|
||||
final JsonObject typeAnnotation = entry.getValue().getAsJsonObject();
|
||||
// The alias name is the type name that other types can refer to.
|
||||
return parseTypeAnnotation(
|
||||
TypeId.of(typeId.moduleName, typeName), typeAnnotation);
|
||||
})
|
||||
.collect(Collectors.toList()));
|
||||
|
||||
ImmutableList.Builder<NativeModuleType.Property> methods = new ImmutableList.Builder<>();
|
||||
ImmutableList.Builder<NativeModuleType.Property> collectedPropertiesBuilder =
|
||||
new ImmutableList.Builder<>();
|
||||
properties.forEach(
|
||||
p -> {
|
||||
final JsonObject node = p.getAsJsonObject();
|
||||
@@ -94,13 +108,13 @@ public final class SchemaJsonParser {
|
||||
final JsonObject typeAnnotation = node.getAsJsonObject("typeAnnotation");
|
||||
// TODO (T71845349): "optional" field shouldn't be part of the Function's typeAnnotation.
|
||||
final boolean optional = typeAnnotation.get("optional").getAsBoolean();
|
||||
final TypeId propertyTypeId = TypeId.of(typeId.moduleName, name);
|
||||
methods.add(
|
||||
final TypeId propertyTypeId = TypeId.of(typeId.moduleName);
|
||||
collectedPropertiesBuilder.add(
|
||||
new NativeModuleType.Property(
|
||||
name, parseTypeAnnotation(propertyTypeId, typeAnnotation), optional));
|
||||
});
|
||||
|
||||
return new NativeModuleType(typeId, methods.build());
|
||||
return new NativeModuleType(typeId, collectedAliases, collectedPropertiesBuilder.build());
|
||||
}
|
||||
|
||||
// Parse type information from a JSON "typeAnnotation" node.
|
||||
@@ -115,8 +129,7 @@ public final class SchemaJsonParser {
|
||||
|
||||
switch (type) {
|
||||
case AliasType.TYPE_NAME:
|
||||
// TODO
|
||||
parsedType = new AliasType(typeId, typeId);
|
||||
parsedType = parseAliasTypeAnnotation(typeId, typeAnnotation);
|
||||
break;
|
||||
case AnyType.TYPE_NAME:
|
||||
parsedType = new AnyType(typeId);
|
||||
@@ -152,9 +165,8 @@ public final class SchemaJsonParser {
|
||||
parsedType = new PromiseType(typeId);
|
||||
break;
|
||||
case ReservedFunctionValueType.TYPE_NAME:
|
||||
// TODO
|
||||
parsedType =
|
||||
new ReservedFunctionValueType(typeId, ReservedFunctionValueType.ReservedName.RootTag);
|
||||
parsedType = parseReservedFunctionValueTypeAnnotation(typeId, typeAnnotation);
|
||||
break;
|
||||
case StringType.TYPE_NAME:
|
||||
parsedType = new StringType(typeId);
|
||||
break;
|
||||
@@ -167,19 +179,20 @@ public final class SchemaJsonParser {
|
||||
return maybeCreateNullableType(nullable, parsedType);
|
||||
}
|
||||
|
||||
private static Type parseAliasTypeAnnotation(
|
||||
final TypeId typeId, final JsonObject typeAnnotation) {
|
||||
// For now, assume the alias lives inside the same file.
|
||||
return new AliasType(
|
||||
typeId, TypeId.of(typeId.moduleName, typeAnnotation.get("name").getAsString()));
|
||||
}
|
||||
|
||||
private static Type parseArrayTypeAnnotation(
|
||||
final TypeId typeId, final JsonObject typeAnnotation) {
|
||||
final JsonObject elementTypeAnnotation = typeAnnotation.getAsJsonObject("elementType");
|
||||
// TODO (T71847026): Some array types are missing elementType annotation.
|
||||
final Type elementType =
|
||||
elementTypeAnnotation != null
|
||||
? parseTypeAnnotation(
|
||||
TypeId.of(
|
||||
typeId.moduleName,
|
||||
elementTypeAnnotation.has("name")
|
||||
? elementTypeAnnotation.get("name").getAsString()
|
||||
: null),
|
||||
elementTypeAnnotation)
|
||||
? parseTypeAnnotation(TypeId.of(typeId.moduleName), elementTypeAnnotation)
|
||||
: new AnyType(TypeId.of(typeId.moduleName));
|
||||
|
||||
return new ArrayType(typeId, elementType);
|
||||
@@ -201,8 +214,7 @@ public final class SchemaJsonParser {
|
||||
FunctionType.createArgument(
|
||||
name,
|
||||
parseTypeAnnotation(
|
||||
TypeId.of(typeId.moduleName, name),
|
||||
node.getAsJsonObject("typeAnnotation"))));
|
||||
TypeId.of(typeId.moduleName), node.getAsJsonObject("typeAnnotation"))));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -227,7 +239,7 @@ public final class SchemaJsonParser {
|
||||
final String name = node.has("name") ? node.get("name").getAsString() : null;
|
||||
final boolean optional = node.get("optional").getAsBoolean();
|
||||
final JsonObject propertyTypeAnnotation = node.getAsJsonObject("typeAnnotation");
|
||||
final TypeId propertyTypeId = TypeId.of(typeId.moduleName, name);
|
||||
final TypeId propertyTypeId = TypeId.of(typeId.moduleName);
|
||||
|
||||
// TODO (T67898313): Some object properties are missing typeAnnotation.
|
||||
final Type propertyType =
|
||||
@@ -241,6 +253,13 @@ public final class SchemaJsonParser {
|
||||
return new ObjectType(typeId, propertiesList.build());
|
||||
}
|
||||
|
||||
private static Type parseReservedFunctionValueTypeAnnotation(
|
||||
final TypeId typeId, final JsonObject typeAnnotation) {
|
||||
return new ReservedFunctionValueType(
|
||||
typeId,
|
||||
ReservedFunctionValueType.ReservedName.valueOf(typeAnnotation.get("name").getAsString()));
|
||||
}
|
||||
|
||||
private static Type maybeCreateNullableType(final boolean nullable, final Type original) {
|
||||
if (!nullable || original instanceof VoidType) {
|
||||
return original;
|
||||
|
||||
+5
-2
@@ -13,6 +13,7 @@ import java.util.List;
|
||||
public final class NativeModuleType extends Type {
|
||||
public static String TYPE_NAME = "<NONE>"; // Not an actual type in the schema.
|
||||
|
||||
public final List<Type> aliases;
|
||||
public final List<Property> properties;
|
||||
|
||||
public static class Property {
|
||||
@@ -33,13 +34,15 @@ public final class NativeModuleType extends Type {
|
||||
}
|
||||
}
|
||||
|
||||
public NativeModuleType(final TypeId typeId, final List<Property> properties) {
|
||||
public NativeModuleType(
|
||||
final TypeId typeId, final List<Type> aliases, final List<Property> properties) {
|
||||
super(typeId);
|
||||
this.aliases = Collections.unmodifiableList(aliases);
|
||||
this.properties = Collections.unmodifiableList(properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getTypeId() + " -> " + properties;
|
||||
return getTypeId() + "\n aliases: " + aliases + "\n properties: " + properties;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -7,16 +7,16 @@
|
||||
|
||||
package com.facebook.react.codegen.generator.model;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
/** Represents the parsed JSON schema without any type resolution. */
|
||||
public final class RawSchema {
|
||||
|
||||
public final Map<String, List<NativeModuleType>> modules;
|
||||
public final Map<String, Map<String, NativeModuleType>> modules;
|
||||
|
||||
public RawSchema(final Map<String, List<NativeModuleType>> modules) {
|
||||
this.modules = modules;
|
||||
public RawSchema(final Map<String, Map<String, NativeModuleType>> modules) {
|
||||
this.modules = Collections.unmodifiableMap(modules);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ public final class TypeId {
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"<moduleName = %s, typeName = %s>",
|
||||
moduleName, EMPTY_TYPE_NAME.equals(typeName) ? moduleName : typeName);
|
||||
moduleName, EMPTY_TYPE_NAME.equals(typeName) ? "\"\"" : typeName);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user