From e26dd1c35d781d6f1e5fc15c7cefe42aade2bede Mon Sep 17 00:00:00 2001 From: Kevin Gozali Date: Mon, 17 Aug 2020 14:08:06 -0700 Subject: [PATCH] Codegen: JavaGenerator [2] - parse JSON schema into Java typed representation Summary: This parses the output JSON schema into Java Type's, without any alias resolution. Some parts of the schema have incomplete information, hence a bunch of TODOs in the code expressing the issues. Notes: * The type structure here could be implemented in other codegen generators as well (including the RNCodegen.js' generators) for better type safety and correctness. With this exercise, I was able to catch a few issues mentioned above. * This commit does not produce any Java code with JavaPoet yet, just parsing the schema. Changelog: [Internal] Reviewed By: mdvacca Differential Revision: D23152891 fbshipit-source-id: 9f774dd98975f7202d3faf11c3fbfb83d4c97f5a --- .../gradlePlugin/build.gradle | 1 + .../codegen/generator/JavaGenerator.java | 5 +- .../codegen/generator/SchemaJsonParser.java | 250 ++++++++++++++++++ .../codegen/generator/model/AliasType.java | 1 + .../codegen/generator/model/AnyType.java | 1 + .../codegen/generator/model/ArrayType.java | 1 + .../codegen/generator/model/BooleanType.java | 1 + .../codegen/generator/model/DoubleType.java | 1 + .../codegen/generator/model/FloatType.java | 1 + .../codegen/generator/model/FunctionType.java | 24 +- .../generator/model/GenericObjectType.java | 1 + .../codegen/generator/model/Int32Type.java | 1 + .../generator/model/NativeModuleType.java | 45 ++++ .../codegen/generator/model/NullableType.java | 19 ++ .../codegen/generator/model/NumberType.java | 1 + .../codegen/generator/model/ObjectType.java | 28 +- .../codegen/generator/model/PromiseType.java | 16 ++ .../codegen/generator/model/RawSchema.java | 26 ++ .../model/ReservedFunctionValueType.java | 2 + .../codegen/generator/model/StringType.java | 1 + .../react/codegen/generator/model/Type.java | 10 + .../react/codegen/generator/model/TypeId.java | 4 + .../codegen/generator/model/VoidType.java | 4 +- .../react/codegen/plugin/CodegenPlugin.java | 6 +- 24 files changed, 432 insertions(+), 18 deletions(-) create mode 100644 packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/SchemaJsonParser.java create mode 100644 packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/NativeModuleType.java create mode 100644 packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/NullableType.java create mode 100644 packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/PromiseType.java create mode 100644 packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/RawSchema.java diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/build.gradle b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/build.gradle index 88e87904e0d..5bd9f4d416f 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/build.gradle +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/build.gradle @@ -20,6 +20,7 @@ gradlePlugin { dependencies { implementation 'com.android.tools.build:gradle:3.5.3' + implementation 'com.google.code.gson:gson:2.8.6' implementation 'com.google.guava:guava:29.0-jre' implementation 'com.squareup:javapoet:1.13.0' } diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/JavaGenerator.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/JavaGenerator.java index 885c14aef2b..05aa1e9bb4b 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/JavaGenerator.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/JavaGenerator.java @@ -11,6 +11,7 @@ import com.squareup.javapoet.JavaFile; import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.TypeSpec; import java.io.File; +import java.io.FileNotFoundException; import java.io.IOException; import javax.lang.model.element.Modifier; @@ -26,7 +27,7 @@ public final class JavaGenerator { mOutputDir = outputDir; } - public void build() throws IOException { + public void build() throws FileNotFoundException, IOException { final MethodSpec main = MethodSpec.methodBuilder("main") .addModifiers(Modifier.PUBLIC, Modifier.STATIC) @@ -43,8 +44,6 @@ public final class JavaGenerator { final JavaFile javaFile = JavaFile.builder(mJavaPackageName, helloWorld).build(); - System.out.println(javaFile.toString()); - javaFile.writeTo(mOutputDir); } } diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/SchemaJsonParser.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/SchemaJsonParser.java new file mode 100644 index 00000000000..526c3134c3e --- /dev/null +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/SchemaJsonParser.java @@ -0,0 +1,250 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.codegen.generator; + +import com.facebook.react.codegen.generator.model.AliasType; +import com.facebook.react.codegen.generator.model.AnyType; +import com.facebook.react.codegen.generator.model.ArrayType; +import com.facebook.react.codegen.generator.model.BooleanType; +import com.facebook.react.codegen.generator.model.DoubleType; +import com.facebook.react.codegen.generator.model.FloatType; +import com.facebook.react.codegen.generator.model.FunctionType; +import com.facebook.react.codegen.generator.model.GenericObjectType; +import com.facebook.react.codegen.generator.model.Int32Type; +import com.facebook.react.codegen.generator.model.NativeModuleType; +import com.facebook.react.codegen.generator.model.NullableType; +import com.facebook.react.codegen.generator.model.NumberType; +import com.facebook.react.codegen.generator.model.ObjectType; +import com.facebook.react.codegen.generator.model.PromiseType; +import com.facebook.react.codegen.generator.model.RawSchema; +import com.facebook.react.codegen.generator.model.ReservedFunctionValueType; +import com.facebook.react.codegen.generator.model.StringType; +import com.facebook.react.codegen.generator.model.Type; +import com.facebook.react.codegen.generator.model.TypeId; +import com.facebook.react.codegen.generator.model.VoidType; +import com.google.common.collect.ImmutableList; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import java.io.File; +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; + +public final class SchemaJsonParser { + + public static RawSchema parse(final File schemaFile) throws FileNotFoundException, IOException { + final JsonParser parser = new JsonParser(); + final JsonElement rootElement = parser.parse(new FileReader(schemaFile)); + + final Map> collection = new HashMap<>(); + + if (rootElement.isJsonObject()) { + final JsonObject root = rootElement.getAsJsonObject(); + final JsonObject modules = root.getAsJsonObject("modules"); + modules + .entrySet() + .forEach( + entry -> { + final String jsModuleName = entry.getKey(); + final JsonObject jsModule = entry.getValue().getAsJsonObject(); + final JsonObject nativeModules = jsModule.getAsJsonObject("nativeModules"); + if (nativeModules == null) { + // TODO: Handle components-related sections. + return; + } + + collection.put( + jsModuleName, + nativeModules.entrySet().stream() + .map( + nativeModuleEntry -> { + return parseNativeModule( + TypeId.of(jsModuleName, nativeModuleEntry.getKey()), + nativeModuleEntry.getValue().getAsJsonObject()); + }) + .collect(Collectors.toList())); + }); + } + + return new RawSchema(collection); + } + + private static NativeModuleType parseNativeModule(final TypeId typeId, final JsonObject json) { + final JsonObject aliases = json.getAsJsonObject("aliases"); + final JsonArray properties = json.getAsJsonArray("properties"); + + // TODO: parse aliases + + ImmutableList.Builder methods = new ImmutableList.Builder<>(); + properties.forEach( + p -> { + final JsonObject node = p.getAsJsonObject(); + final String name = node.has("name") ? node.get("name").getAsString() : null; + 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( + new NativeModuleType.Property( + name, parseTypeAnnotation(propertyTypeId, typeAnnotation), optional)); + }); + + return new NativeModuleType(typeId, methods.build()); + } + + // Parse type information from a JSON "typeAnnotation" node. + private static Type parseTypeAnnotation(final TypeId typeId, final JsonObject typeAnnotation) + throws IllegalStateException { + final String type = typeAnnotation.get("type").getAsString(); + // TODO (T71824250): Support NullableTypeAnnotation in the schema instead of a field here. + final boolean nullable = + typeAnnotation.has("nullable") ? typeAnnotation.get("nullable").getAsBoolean() : false; + + Type parsedType = null; + + switch (type) { + case AliasType.TYPE_NAME: + // TODO + parsedType = new AliasType(typeId, typeId); + break; + case AnyType.TYPE_NAME: + parsedType = new AnyType(typeId); + break; + case ArrayType.TYPE_NAME: + parsedType = parseArrayTypeAnnotation(typeId, typeAnnotation); + break; + case BooleanType.TYPE_NAME: + parsedType = new BooleanType(typeId); + break; + case DoubleType.TYPE_NAME: + parsedType = new DoubleType(typeId); + break; + case FloatType.TYPE_NAME: + parsedType = new FloatType(typeId); + break; + case FunctionType.TYPE_NAME: + parsedType = parseFunctionTypeAnnotation(typeId, typeAnnotation); + break; + case GenericObjectType.TYPE_NAME: + parsedType = new GenericObjectType(typeId); + break; + case Int32Type.TYPE_NAME: + parsedType = new Int32Type(typeId); + break; + case NumberType.TYPE_NAME: + parsedType = new NumberType(typeId); + break; + case ObjectType.TYPE_NAME: + parsedType = parseObjectTypeAnnotation(typeId, typeAnnotation); + break; + case PromiseType.TYPE_NAME: + parsedType = new PromiseType(typeId); + break; + case ReservedFunctionValueType.TYPE_NAME: + // TODO + parsedType = + new ReservedFunctionValueType(typeId, ReservedFunctionValueType.ReservedName.RootTag); + case StringType.TYPE_NAME: + parsedType = new StringType(typeId); + break; + case VoidType.TYPE_NAME: + return VoidType.VOID; + default: + throw new IllegalStateException("Found invalid type annotation: " + type); + } + + return maybeCreateNullableType(nullable, parsedType); + } + + 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) + : new AnyType(TypeId.of(typeId.moduleName)); + + return new ArrayType(typeId, elementType); + } + + private static Type parseFunctionTypeAnnotation( + final TypeId typeId, final JsonObject typeAnnotation) { + final JsonArray params = typeAnnotation.getAsJsonArray("params"); + + ImmutableList.Builder paramsList = new ImmutableList.Builder<>(); + + // TODO (T71846321): Some functions are missing params specification. + if (params != null) { + params.forEach( + p -> { + final JsonObject node = p.getAsJsonObject(); + final String name = node.has("name") ? node.get("name").getAsString() : null; + paramsList.add( + FunctionType.createArgument( + name, + parseTypeAnnotation( + TypeId.of(typeId.moduleName, name), + node.getAsJsonObject("typeAnnotation")))); + }); + } + + // TODO (T71846321): Some functions are missing a return type. + final JsonObject returnTypeAnnotation = typeAnnotation.getAsJsonObject("returnTypeAnnotation"); + final Type returnType = + returnTypeAnnotation != null + ? parseTypeAnnotation(TypeId.of(typeId.moduleName), returnTypeAnnotation) + : VoidType.VOID; + + return new FunctionType(typeId, paramsList.build(), returnType); + } + + private static Type parseObjectTypeAnnotation( + final TypeId typeId, final JsonObject typeAnnotation) { + final JsonArray properties = typeAnnotation.getAsJsonArray("properties"); + + ImmutableList.Builder propertiesList = new ImmutableList.Builder<>(); + properties.forEach( + p -> { + final JsonObject node = p.getAsJsonObject(); + 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); + + // TODO (T67898313): Some object properties are missing typeAnnotation. + final Type propertyType = + propertyTypeAnnotation != null + ? parseTypeAnnotation(propertyTypeId, propertyTypeAnnotation) + : new AnyType(propertyTypeId); + + propertiesList.add(new ObjectType.Property(name, propertyType, optional)); + }); + + return new ObjectType(typeId, propertiesList.build()); + } + + private static Type maybeCreateNullableType(final boolean nullable, final Type original) { + if (!nullable || original instanceof VoidType) { + return original; + } + return new NullableType(TypeId.of(original.getTypeId()), original); + } +} diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/AliasType.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/AliasType.java index 2915cdabdf9..4114dc52c83 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/AliasType.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/AliasType.java @@ -8,6 +8,7 @@ package com.facebook.react.codegen.generator.model; public final class AliasType extends Type { + public static final String TYPE_NAME = "TypeAliasTypeAnnotation"; public final TypeId referredTypeId; diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/AnyType.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/AnyType.java index d26fd527e77..ce22b204475 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/AnyType.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/AnyType.java @@ -8,6 +8,7 @@ package com.facebook.react.codegen.generator.model; public final class AnyType extends Type { + public static final String TYPE_NAME = "AnyTypeAnnotation"; public AnyType(final TypeId typeId) { super(typeId); diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/ArrayType.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/ArrayType.java index 58af1236956..536a082e5a8 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/ArrayType.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/ArrayType.java @@ -8,6 +8,7 @@ package com.facebook.react.codegen.generator.model; public final class ArrayType extends Type { + public static final String TYPE_NAME = "ArrayTypeAnnotation"; public final Type elementType; diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/BooleanType.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/BooleanType.java index ae5de917064..c5f8b9be17b 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/BooleanType.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/BooleanType.java @@ -8,6 +8,7 @@ package com.facebook.react.codegen.generator.model; public final class BooleanType extends Type { + public static final String TYPE_NAME = "BooleanTypeAnnotation"; public BooleanType(final TypeId typeId) { super(typeId); diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/DoubleType.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/DoubleType.java index 2cb8aa08c98..ddfa0616334 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/DoubleType.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/DoubleType.java @@ -8,6 +8,7 @@ package com.facebook.react.codegen.generator.model; public final class DoubleType extends NumberType { + public static final String TYPE_NAME = "DoubleTypeAnnotation"; public DoubleType(final TypeId typeId) { super(typeId); diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/FloatType.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/FloatType.java index 198872f227c..6698735501c 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/FloatType.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/FloatType.java @@ -8,6 +8,7 @@ package com.facebook.react.codegen.generator.model; public final class FloatType extends NumberType { + public static final String TYPE_NAME = "FloatTypeAnnotation"; public FloatType(final TypeId typeId) { super(typeId); diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/FunctionType.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/FunctionType.java index bc40e8d9c88..d664d747534 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/FunctionType.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/FunctionType.java @@ -12,11 +12,14 @@ import java.util.List; import java.util.Objects; public final class FunctionType extends Type { + public static final String TYPE_NAME = "FunctionTypeAnnotation"; public static class ArgumentType { public final String name; public final Type type; + // Note: Function argument is not optional. + // TODO (T71926678): Revisit if optional should be supported. private ArgumentType(String name, Type type) { this.name = name; this.type = type; @@ -39,19 +42,29 @@ public final class FunctionType extends Type { public int hashCode() { return Objects.hash(name, type); } + + @Override + public String toString() { + return name + ": " + type; + } + } + + public static ArgumentType createArgument(String name, Type type) { + return new ArgumentType(name, type); } public final List parameters; public final Type returnType; - public FunctionType(final TypeId typeId, List parameters, Type returnType) { + public FunctionType( + final TypeId typeId, final List parameters, final Type returnType) { super(typeId); this.parameters = Collections.unmodifiableList(parameters); this.returnType = returnType; } @Override - public boolean equals(Object o) { + public boolean equals(final Object o) { if (this == o) { return true; } @@ -59,7 +72,7 @@ public final class FunctionType extends Type { return false; } - FunctionType that = (FunctionType) o; + final FunctionType that = (FunctionType) o; return Objects.equals(this.parameters, that.parameters) && Objects.equals(this.returnType, that.returnType); } @@ -68,4 +81,9 @@ public final class FunctionType extends Type { public int hashCode() { return Objects.hash(super.hashCode(), parameters, returnType); } + + @Override + public String toString() { + return "(" + returnType + ")" + this.getTypeId() + "(" + parameters + ")"; + } } diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/GenericObjectType.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/GenericObjectType.java index f9995a68f2e..ce4a2b05eef 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/GenericObjectType.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/GenericObjectType.java @@ -8,6 +8,7 @@ package com.facebook.react.codegen.generator.model; public final class GenericObjectType extends Type { + public static final String TYPE_NAME = "GenericObjectTypeAnnotation"; public GenericObjectType(final TypeId typeId) { super(typeId); diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/Int32Type.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/Int32Type.java index 72afa7c8d85..4639d392397 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/Int32Type.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/Int32Type.java @@ -8,6 +8,7 @@ package com.facebook.react.codegen.generator.model; public final class Int32Type extends NumberType { + public static final String TYPE_NAME = "Int32TypeAnnotation"; public Int32Type(final TypeId typeId) { super(typeId); diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/NativeModuleType.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/NativeModuleType.java new file mode 100644 index 00000000000..b529e0e1178 --- /dev/null +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/NativeModuleType.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.codegen.generator.model; + +import java.util.Collections; +import java.util.List; + +public final class NativeModuleType extends Type { + public static String TYPE_NAME = ""; // Not an actual type in the schema. + + public final List properties; + + public static class Property { + public final String name; + public final FunctionType type; + public final boolean optional; + + public Property(final String name, final Type type, final boolean optional) { + assertType(type, FunctionType.class); + this.name = name; + this.type = (FunctionType) type; + this.optional = optional; + } + + @Override + public String toString() { + return name + ": " + (this.optional ? "?" : "") + type; + } + } + + public NativeModuleType(final TypeId typeId, final List properties) { + super(typeId); + this.properties = Collections.unmodifiableList(properties); + } + + @Override + public String toString() { + return getTypeId() + " -> " + properties; + } +} diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/NullableType.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/NullableType.java new file mode 100644 index 00000000000..5b85bb28cb0 --- /dev/null +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/NullableType.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.codegen.generator.model; + +public final class NullableType extends Type { + public static final String TYPE_NAME = "NullableTypeAnnotation"; + + public final Type referredType; + + public NullableType(final TypeId typeId, final Type referredType) { + super(typeId); + this.referredType = referredType; + } +} diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/NumberType.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/NumberType.java index 11770f829fe..e31df14556b 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/NumberType.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/NumberType.java @@ -8,6 +8,7 @@ package com.facebook.react.codegen.generator.model; public class NumberType extends Type { + public static final String TYPE_NAME = "NumberTypeAnnotation"; public NumberType(final TypeId typeId) { super(typeId); diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/ObjectType.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/ObjectType.java index 940cdd5a9c4..3c1fcabd512 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/ObjectType.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/ObjectType.java @@ -7,26 +7,38 @@ package com.facebook.react.codegen.generator.model; -public final class ObjectType extends Type { +import java.util.Collections; +import java.util.List; - public ObjectType(final TypeId typeId) { - super(typeId); - } +public final class ObjectType extends Type { + public static final String TYPE_NAME = "ObjectTypeAnnotation"; public static class Property { - public final String propertyName; + public final String name; public final Type type; public final boolean optional; - public Property(String propertyName, Type type, boolean optional) { - this.propertyName = propertyName; + public Property(String name, Type type, boolean optional) { + this.name = name; this.type = type; this.optional = optional; } @Override public String toString() { - return propertyName + " " + type; + return (optional ? "?" : "") + name + ": " + type; } } + + public final List properties; + + public ObjectType(final TypeId typeId, final List properties) { + super(typeId); + this.properties = Collections.unmodifiableList(properties); + } + + @Override + public String toString() { + return getTypeId() + " -> " + properties; + } } diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/PromiseType.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/PromiseType.java new file mode 100644 index 00000000000..b4051ac81d7 --- /dev/null +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/PromiseType.java @@ -0,0 +1,16 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.codegen.generator.model; + +public final class PromiseType extends Type { + public static final String TYPE_NAME = "GenericPromiseTypeAnnotation"; + + public PromiseType(final TypeId typeId) { + super(typeId); + } +} diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/RawSchema.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/RawSchema.java new file mode 100644 index 00000000000..76fff67e1e0 --- /dev/null +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/RawSchema.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.codegen.generator.model; + +import java.util.List; +import java.util.Map; + +/** Represents the parsed JSON schema without any type resolution. */ +public final class RawSchema { + + public final Map> modules; + + public RawSchema(final Map> modules) { + this.modules = modules; + } + + @Override + public String toString() { + return modules.toString(); + } +} diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/ReservedFunctionValueType.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/ReservedFunctionValueType.java index 8664fd10df1..c8a6d132aa8 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/ReservedFunctionValueType.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/ReservedFunctionValueType.java @@ -8,6 +8,8 @@ package com.facebook.react.codegen.generator.model; public final class ReservedFunctionValueType extends Type { + public static final String TYPE_NAME = "ReservedFunctionValueTypeAnnotation"; + public enum ReservedName { RootTag, } diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/StringType.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/StringType.java index 897e8d9fef7..39ba374a0fc 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/StringType.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/StringType.java @@ -8,6 +8,7 @@ package com.facebook.react.codegen.generator.model; public final class StringType extends Type { + public static final String TYPE_NAME = "StringTypeAnnotation"; public StringType(final TypeId typeId) { super(typeId); diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/Type.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/Type.java index bf1b6d087b5..b6151d20ed9 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/Type.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/Type.java @@ -10,8 +10,18 @@ package com.facebook.react.codegen.generator.model; import java.util.Objects; public abstract class Type { + public static String TYPE_NAME = ""; + protected final TypeId mTypeId; + public static void assertType( + final Type type, final Class expectedTypeClass) { + if (!expectedTypeClass.isInstance(type)) { + throw new IllegalStateException( + "Expected: " + expectedTypeClass.getName() + " but found: " + type.getClass().getName()); + } + } + public Type(final TypeId typeId) { mTypeId = typeId; } diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/TypeId.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/TypeId.java index bbec7886106..5a24bec9f73 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/TypeId.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/TypeId.java @@ -38,6 +38,10 @@ public final class TypeId { return new TypeId(moduleName, typeName); } + public static TypeId of(final TypeId typeId) { + return of(typeId.moduleName, typeId.typeName); + } + @Override public String toString() { return String.format( diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/VoidType.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/VoidType.java index 1e6f7d460c5..29ea494d7f2 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/VoidType.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/VoidType.java @@ -8,8 +8,10 @@ package com.facebook.react.codegen.generator.model; public final class VoidType extends Type { + public static final String TYPE_NAME = "VoidTypeAnnotation"; + public static final VoidType VOID = new VoidType(TypeId.of("")); - public VoidType(final TypeId typeId) { + private VoidType(final TypeId typeId) { super(typeId); } } diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/plugin/CodegenPlugin.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/plugin/CodegenPlugin.java index 1d355efd002..055bcff1b6f 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/plugin/CodegenPlugin.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/plugin/CodegenPlugin.java @@ -12,7 +12,7 @@ import com.facebook.react.codegen.generator.JavaGenerator; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import java.io.File; -import java.io.IOException; +import org.gradle.api.GradleException; import org.gradle.api.Plugin; import org.gradle.api.Project; import org.gradle.api.Task; @@ -159,8 +159,8 @@ public class CodegenPlugin implements Plugin { final JavaGenerator generator = new JavaGenerator(schemaFile, javaPackageName, outputDir); try { generator.build(); - } catch (final IOException e) { - // Ignore for now. + } catch (final Exception ex) { + throw new GradleException("Failed to generate Java from schema.", ex); } } }