From 8fc1646c75c86f1aaa77417245e664fa070bf8cd Mon Sep 17 00:00:00 2001 From: Kevin Gozali Date: Tue, 25 Aug 2020 10:34:41 -0700 Subject: [PATCH] Codegen: JavaGenerator [6] - resolve individual types into their generated code Summary: For each resolved type, define how to process its own type and whether it should produce generated code/file, minus the NativeModuleResolvedType (will be in the next commit). Changelog: [Internal] Reviewed By: mdvacca Differential Revision: D23307961 fbshipit-source-id: 87af09867aace7a5ff060a33a00b141048630eda --- .../codegen/generator/JavaGenerator.java | 35 ++++++-------- .../codegen/generator/SchemaJsonParser.java | 15 +++--- .../generator/model/CodegenException.java | 16 +++++++ .../codegen/generator/model/NullableType.java | 6 +-- .../codegen/generator/model/NumberType.java | 2 +- .../model/ReservedFunctionValueType.java | 5 ++ .../generator/resolver/AliasResolvedType.java | 15 ++++-- .../generator/resolver/AnyResolvedType.java | 18 ++++---- .../generator/resolver/ArrayResolvedType.java | 31 ++++++++----- .../resolver/BooleanResolvedType.java | 11 +---- .../resolver/FunctionResolvedType.java | 36 ++++++++++----- .../resolver/GenericObjectResolvedType.java | 20 ++++---- .../resolver/NativeModuleResolvedType.java | 46 ++++++++++++++++--- .../resolver/NullableResolvedType.java | 9 ++-- .../resolver/NumberResolvedType.java | 24 ++++++---- .../resolver/ObjectResolvedType.java | 42 ++++++++++++++--- .../resolver/PromiseResolvedType.java | 11 +---- .../generator/resolver/ReactClassNames.java | 39 ++++++++++++++++ .../ReservedFunctionValueResolvedType.java | 18 ++++++-- .../resolver/StringResolvedType.java | 12 +---- .../generator/resolver/TypeResolver.java | 1 - .../codegen/generator/resolver/TypeUtils.java | 42 +++++++++++++++++ .../generator/resolver/VoidResolvedType.java | 4 +- 23 files changed, 312 insertions(+), 146 deletions(-) create mode 100644 packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/CodegenException.java create mode 100644 packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/ReactClassNames.java create mode 100644 packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/TypeUtils.java 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 d6f759e01dd..8f8a7b2bf8d 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 @@ -8,14 +8,13 @@ package com.facebook.react.codegen.generator; import com.facebook.react.codegen.generator.model.TypeData; +import com.facebook.react.codegen.generator.resolver.ResolvedType; import com.facebook.react.codegen.generator.resolver.TypeResolver; 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; // TODO: Implement proper generator - this is a sample usage of JavaPoet public final class JavaGenerator { @@ -35,26 +34,18 @@ public final class JavaGenerator { .getAllTypes() .forEach( t -> { - // TODO: Ask each resolved type to produce its own code if it supports it. - TypeResolver.resolveType(typeData.getType(t), typeData, false); + ResolvedType resolvedType = + TypeResolver.resolveType(typeData.getType(t), typeData, false); + TypeSpec spec = resolvedType.getGeneratedCode(mJavaPackageName); + if (spec != null) { + final JavaFile javaFile = JavaFile.builder(mJavaPackageName, spec).build(); + System.out.println(javaFile.toString()); + try { + javaFile.writeTo(mOutputDir); + } catch (IOException ex) { + // TODO: Handle this in a different way. + } + } }); - - final MethodSpec main = - MethodSpec.methodBuilder("main") - .addModifiers(Modifier.PUBLIC, Modifier.STATIC) - .returns(void.class) - .addParameter(String[].class, "args") - .addStatement("$T.out.println($S)", System.class, "Hello, JavaPoet!") - .build(); - - final TypeSpec helloWorld = - TypeSpec.classBuilder("ReactNativeCodegen") - .addModifiers(Modifier.PUBLIC, Modifier.FINAL) - .addMethod(main) - .build(); - - final JavaFile javaFile = JavaFile.builder(mJavaPackageName, helloWorld).build(); - - 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 index 45d254cd16d..0b44b62826d 100644 --- 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 @@ -11,6 +11,7 @@ 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.CodegenException; import com.facebook.react.codegen.generator.model.DoubleType; import com.facebook.react.codegen.generator.model.FloatType; import com.facebook.react.codegen.generator.model.FunctionType; @@ -44,12 +45,14 @@ import java.util.stream.Collectors; public final class SchemaJsonParser { private final TypeData mTypeData = new TypeData(); - public static TypeData parse(final File schemaFile) throws FileNotFoundException, IOException { + public static TypeData parse(final File schemaFile) + throws CodegenException, FileNotFoundException, IOException { final SchemaJsonParser parser = new SchemaJsonParser(); return parser.buildTypeData(schemaFile); } - private TypeData buildTypeData(final File schemaFile) throws FileNotFoundException, IOException { + private TypeData buildTypeData(final File schemaFile) + throws CodegenException, FileNotFoundException, IOException { final JsonParser parser = new JsonParser(); final JsonElement rootElement = parser.parse(new FileReader(schemaFile)); @@ -90,8 +93,7 @@ public final class SchemaJsonParser { } // Parse type information from a JSON "typeAnnotation" node. - private Type parseTypeAnnotation(final TypeId typeId, final JsonObject typeAnnotation) - throws IllegalStateException { + private Type parseTypeAnnotation(final TypeId typeId, final JsonObject typeAnnotation) { final String type = typeAnnotation.get("type").getAsString(); // TODO (T71824250): Support NullableTypeAnnotation in the schema instead of a field here. final boolean nullable = @@ -128,7 +130,8 @@ public final class SchemaJsonParser { parsedType = new Int32Type(typeId); break; case NumberType.TYPE_NAME: - parsedType = new NumberType(typeId); + // Use double type for generic numbers. + parsedType = new DoubleType(typeId); break; case ObjectType.TYPE_NAME: parsedType = parseObjectTypeAnnotation(typeId, typeAnnotation); @@ -145,7 +148,7 @@ public final class SchemaJsonParser { case VoidType.TYPE_NAME: return VoidType.VOID; default: - throw new IllegalStateException("Found invalid type annotation: " + type); + throw new CodegenException("Found invalid type annotation: " + type); } final Type finalType = maybeCreateNullableType(nullable, parsedType); diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/CodegenException.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/CodegenException.java new file mode 100644 index 00000000000..0b0ff3c8680 --- /dev/null +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/model/CodegenException.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 class CodegenException extends RuntimeException { + private static final long serialVersionUID = 1L; + + public CodegenException(final String message) { + super(message); + } +} 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 index 5b85bb28cb0..51809250d20 100644 --- 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 @@ -10,10 +10,10 @@ 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 final Type innerType; - public NullableType(final TypeId typeId, final Type referredType) { + public NullableType(final TypeId typeId, final Type innerType) { super(typeId); - this.referredType = referredType; + this.innerType = innerType; } } 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 e31df14556b..382e06846d6 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 @@ -7,7 +7,7 @@ package com.facebook.react.codegen.generator.model; -public class NumberType extends Type { +public abstract class NumberType extends Type { public static final String TYPE_NAME = "NumberTypeAnnotation"; public NumberType(final TypeId typeId) { 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 c8a6d132aa8..c1f755ed118 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 @@ -20,4 +20,9 @@ public final class ReservedFunctionValueType extends Type { super(typeId); this.reservedName = reservedName; } + + @Override + public String toString() { + return mTypeId + "(" + reservedName.toString() + ")"; + } } diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/AliasResolvedType.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/AliasResolvedType.java index 2f6d3d5bbd0..6720ef76e38 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/AliasResolvedType.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/AliasResolvedType.java @@ -8,6 +8,8 @@ package com.facebook.react.codegen.generator.resolver; import com.facebook.react.codegen.generator.model.AliasType; +import com.facebook.react.codegen.generator.model.AnyType; +import com.facebook.react.codegen.generator.model.Type; import com.facebook.react.codegen.generator.model.TypeData; import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeSpec; @@ -17,22 +19,25 @@ public final class AliasResolvedType extends ResolvedType { private AliasResolvedType(final AliasType type, final boolean nullable) { super(type, nullable); + throw new UnsupportedOperationException(); } - public static AliasResolvedType create( + public static ResolvedType create( final AliasType type, final TypeData typeData, final boolean nullable) { - return new AliasResolvedType(type, nullable); + Type referredType = typeData.getType(type.referredTypeId); + if (referredType != null) { + return resolveType(referredType, typeData, nullable); + } + return resolveType(new AnyType(type.getTypeId()), typeData, nullable); } @Override public TypeName getNativeType(final NativeTypeContext typeContext) { - // TODO - return TypeName.VOID; + throw new UnsupportedOperationException(); } @Override public @Nullable TypeSpec getGeneratedCode(final String packageName) { - // TODO throw new UnsupportedOperationException(); } } diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/AnyResolvedType.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/AnyResolvedType.java index 203cd1150bd..e9fc8dc335b 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/AnyResolvedType.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/AnyResolvedType.java @@ -10,8 +10,6 @@ package com.facebook.react.codegen.generator.resolver; import com.facebook.react.codegen.generator.model.AnyType; import com.facebook.react.codegen.generator.model.TypeData; import com.squareup.javapoet.TypeName; -import com.squareup.javapoet.TypeSpec; -import javax.annotation.Nullable; public final class AnyResolvedType extends ResolvedType { @@ -26,13 +24,13 @@ public final class AnyResolvedType extends ResolvedType { @Override public TypeName getNativeType(final NativeTypeContext typeContext) { - // TODO - return TypeName.VOID; - } - - @Override - public @Nullable TypeSpec getGeneratedCode(final String packageName) { - // TODO - throw new UnsupportedOperationException(); + switch (typeContext) { + case FUNCTION_ARGUMENT: + return TypeUtils.makeNullable(ReactClassNames.REACT_READABLE_MAP, mNullable); + case FUNCTION_RETURN: + return TypeUtils.makeNullable(ReactClassNames.REACT_WRITABLE_MAP, mNullable); + default: + return TypeUtils.makeNullable(TypeName.OBJECT, mNullable); + } } } diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/ArrayResolvedType.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/ArrayResolvedType.java index e6d08108dd5..b6a7d3b7854 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/ArrayResolvedType.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/ArrayResolvedType.java @@ -9,30 +9,37 @@ package com.facebook.react.codegen.generator.resolver; import com.facebook.react.codegen.generator.model.ArrayType; import com.facebook.react.codegen.generator.model.TypeData; +import com.squareup.javapoet.ArrayTypeName; import com.squareup.javapoet.TypeName; -import com.squareup.javapoet.TypeSpec; -import javax.annotation.Nullable; public final class ArrayResolvedType extends ResolvedType { - private ArrayResolvedType(final ArrayType type, final boolean nullable) { + private final ResolvedType mElementResolvedType; + + private ArrayResolvedType(final ArrayType type, final TypeData typeData, final boolean nullable) { super(type, nullable); + mElementResolvedType = resolveType(mType.elementType, typeData, nullable); } public static ArrayResolvedType create( final ArrayType type, final TypeData typeData, final boolean nullable) { - return new ArrayResolvedType(type, nullable); + return new ArrayResolvedType(type, typeData, nullable); + } + + public ResolvedType getElementResolvedType() { + return mElementResolvedType; } @Override public TypeName getNativeType(final NativeTypeContext typeContext) { - // TODO - return TypeName.VOID; - } - - @Override - public @Nullable TypeSpec getGeneratedCode(final String packageName) { - // TODO - throw new UnsupportedOperationException(); + switch (typeContext) { + case FUNCTION_ARGUMENT: + return TypeUtils.makeNullable(ReactClassNames.REACT_READABLE_ARRAY, mNullable); + case FUNCTION_RETURN: + return TypeUtils.makeNullable(ReactClassNames.REACT_WRITABLE_ARRAY, mNullable); + default: + return TypeUtils.makeNullable( + ArrayTypeName.of(mElementResolvedType.getNativeType(typeContext)), mNullable); + } } } diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/BooleanResolvedType.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/BooleanResolvedType.java index 48cc67dc280..75ac0a77ce5 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/BooleanResolvedType.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/BooleanResolvedType.java @@ -10,8 +10,6 @@ package com.facebook.react.codegen.generator.resolver; import com.facebook.react.codegen.generator.model.BooleanType; import com.facebook.react.codegen.generator.model.TypeData; import com.squareup.javapoet.TypeName; -import com.squareup.javapoet.TypeSpec; -import javax.annotation.Nullable; public final class BooleanResolvedType extends ResolvedType { @@ -26,13 +24,6 @@ public final class BooleanResolvedType extends ResolvedType { @Override public TypeName getNativeType(final NativeTypeContext typeContext) { - // TODO - return TypeName.VOID; - } - - @Override - public @Nullable TypeSpec getGeneratedCode(final String packageName) { - // TODO - throw new UnsupportedOperationException(); + return TypeUtils.makeNullable(TypeName.BOOLEAN, mNullable); } } diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/FunctionResolvedType.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/FunctionResolvedType.java index 19d0dde4637..495070afa2b 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/FunctionResolvedType.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/FunctionResolvedType.java @@ -10,29 +10,41 @@ package com.facebook.react.codegen.generator.resolver; import com.facebook.react.codegen.generator.model.FunctionType; import com.facebook.react.codegen.generator.model.TypeData; import com.squareup.javapoet.TypeName; -import com.squareup.javapoet.TypeSpec; -import javax.annotation.Nullable; +import java.util.Collections; +import java.util.Map; +import java.util.stream.Collectors; public final class FunctionResolvedType extends ResolvedType { + private final Map mResolvedArgTypes; + private final ResolvedType mResolvedReturnType; - private FunctionResolvedType(final FunctionType type, final boolean nullable) { + private FunctionResolvedType( + final FunctionType type, final TypeData typeData, final boolean nullable) { super(type, nullable); + mResolvedReturnType = resolveType(type.returnType, typeData, nullable); + mResolvedArgTypes = + Collections.unmodifiableMap( + type.parameters.stream() + .collect( + Collectors.toMap( + item -> item.name, item -> resolveType(item.type, typeData, false)))); } public static FunctionResolvedType create( final FunctionType type, final TypeData typeData, final boolean nullable) { - return new FunctionResolvedType(type, nullable); + return new FunctionResolvedType(type, typeData, nullable); + } + + public ResolvedType getResolvedReturnType() { + return mResolvedReturnType; + } + + public Map getResolvedArgTypes() { + return mResolvedArgTypes; } @Override public TypeName getNativeType(final NativeTypeContext typeContext) { - // TODO - return TypeName.VOID; - } - - @Override - public @Nullable TypeSpec getGeneratedCode(final String packageName) { - // TODO - throw new UnsupportedOperationException(); + return TypeUtils.makeNullable(ReactClassNames.REACT_CALLBACK, mNullable); } } diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/GenericObjectResolvedType.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/GenericObjectResolvedType.java index c2dd1635402..84b98eb9698 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/GenericObjectResolvedType.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/GenericObjectResolvedType.java @@ -7,11 +7,10 @@ package com.facebook.react.codegen.generator.resolver; +import com.facebook.react.codegen.generator.model.CodegenException; import com.facebook.react.codegen.generator.model.GenericObjectType; import com.facebook.react.codegen.generator.model.TypeData; import com.squareup.javapoet.TypeName; -import com.squareup.javapoet.TypeSpec; -import javax.annotation.Nullable; public final class GenericObjectResolvedType extends ResolvedType { @@ -26,13 +25,16 @@ public final class GenericObjectResolvedType extends ResolvedType { + private final Map mResolvedAliasTypes; + private final Map mResolvedPropertyTypes; - private NativeModuleResolvedType(final NativeModuleType type, final boolean nullable) { + private NativeModuleResolvedType( + final NativeModuleType type, final TypeData typeData, final boolean nullable) { super(type, nullable); + mResolvedAliasTypes = + Collections.unmodifiableMap( + type.aliases.stream() + .collect( + Collectors.toMap( + item -> item.getTypeId().typeName, + item -> resolveType(item, typeData, false)))); + mResolvedPropertyTypes = + Collections.unmodifiableMap( + type.properties.stream() + .collect( + Collectors.toMap( + item -> item.name, + // TODO: Optional Object property is not necessarily nullable. + item -> resolveType(item.type, typeData, item.optional)))); } public static NativeModuleResolvedType create( final NativeModuleType type, final TypeData typeData, final boolean nullable) { - return new NativeModuleResolvedType(type, nullable); + return new NativeModuleResolvedType(type, typeData, nullable); } @Override public TypeName getNativeType(final NativeTypeContext typeContext) { - // TODO - return TypeName.VOID; + throw new UnsupportedOperationException( + "NativeModuleType cannot be referred to by other types."); } @Override public @Nullable TypeSpec getGeneratedCode(final String packageName) { - // TODO - throw new UnsupportedOperationException(); + // TODO: Remove this placeholder implementation. + final MethodSpec main = + MethodSpec.methodBuilder("main") + .addModifiers(Modifier.PUBLIC, Modifier.STATIC) + .returns(void.class) + .addParameter(String[].class, "args") + .addStatement("$T.out.println($S)", System.class, "Hello, JavaPoet!") + .build(); + + return TypeSpec.classBuilder(mType.getTypeId().typeName) + .addModifiers(Modifier.PUBLIC, Modifier.FINAL) + .addMethod(main) + .build(); } } diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/NullableResolvedType.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/NullableResolvedType.java index 0ffe587ade2..b5dd2fee1ea 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/NullableResolvedType.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/NullableResolvedType.java @@ -17,22 +17,21 @@ public final class NullableResolvedType extends ResolvedType { private NullableResolvedType(final NullableType type, final boolean nullable) { super(type, nullable); + throw new UnsupportedOperationException(); } - public static NullableResolvedType create( + public static ResolvedType create( final NullableType type, final TypeData typeData, final boolean nullable) { - return new NullableResolvedType(type, nullable); + return resolveType(type.innerType, typeData, true); } @Override public TypeName getNativeType(final NativeTypeContext typeContext) { - // TODO - return TypeName.VOID; + throw new UnsupportedOperationException(); } @Override public @Nullable TypeSpec getGeneratedCode(final String packageName) { - // TODO throw new UnsupportedOperationException(); } } diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/NumberResolvedType.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/NumberResolvedType.java index 8b241ddeed7..6a9576efe7c 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/NumberResolvedType.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/NumberResolvedType.java @@ -7,11 +7,13 @@ package com.facebook.react.codegen.generator.resolver; +import com.facebook.react.codegen.generator.model.CodegenException; +import com.facebook.react.codegen.generator.model.DoubleType; +import com.facebook.react.codegen.generator.model.FloatType; +import com.facebook.react.codegen.generator.model.Int32Type; import com.facebook.react.codegen.generator.model.NumberType; import com.facebook.react.codegen.generator.model.TypeData; import com.squareup.javapoet.TypeName; -import com.squareup.javapoet.TypeSpec; -import javax.annotation.Nullable; public final class NumberResolvedType extends ResolvedType { @@ -26,13 +28,15 @@ public final class NumberResolvedType extends ResolvedType { @Override public TypeName getNativeType(final NativeTypeContext typeContext) { - // TODO - return TypeName.VOID; - } - - @Override - public @Nullable TypeSpec getGeneratedCode(final String packageName) { - // TODO - throw new UnsupportedOperationException(); + if (mType instanceof Int32Type) { + return TypeUtils.makeNullable(TypeName.INT, mNullable); + } + if (mType instanceof FloatType) { + return TypeUtils.makeNullable(TypeName.FLOAT, mNullable); + } + if (mType instanceof DoubleType) { + return TypeUtils.makeNullable(TypeName.DOUBLE, mNullable); + } + throw new CodegenException("Unsupported NumberType: " + mType.getClass()); } } diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/ObjectResolvedType.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/ObjectResolvedType.java index 5f57fab1091..54a9cb09eee 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/ObjectResolvedType.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/ObjectResolvedType.java @@ -7,32 +7,62 @@ package com.facebook.react.codegen.generator.resolver; +import com.facebook.react.codegen.generator.model.CodegenException; import com.facebook.react.codegen.generator.model.ObjectType; import com.facebook.react.codegen.generator.model.TypeData; import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeSpec; +import java.util.Collections; +import java.util.Map; +import java.util.stream.Collectors; import javax.annotation.Nullable; public final class ObjectResolvedType extends ResolvedType { + private final Map mResolvedPropertyTypes; - private ObjectResolvedType(final ObjectType type, final boolean nullable) { + private ObjectResolvedType( + final ObjectType type, final TypeData typeData, final boolean nullable) { super(type, nullable); + mResolvedPropertyTypes = + Collections.unmodifiableMap( + type.properties.stream() + .collect( + Collectors.toMap( + item -> item.name, + // TODO: Optional Object property is not necessarily nullable. + item -> resolveType(item.type, typeData, item.optional)))); } public static ObjectResolvedType create( final ObjectType type, final TypeData typeData, final boolean nullable) { - return new ObjectResolvedType(type, nullable); + return new ObjectResolvedType(type, typeData, nullable); + } + + public Map getResolvedPropertyTypes() { + return mResolvedPropertyTypes; } @Override public TypeName getNativeType(final NativeTypeContext typeContext) { - // TODO - return TypeName.VOID; + // TODO: It should return its own class type. + // However, the NativeModule system only supports built-in ReadableMap/WritableMap for now. + switch (typeContext) { + case FUNCTION_ARGUMENT: + return TypeUtils.makeNullable(ReactClassNames.REACT_READABLE_MAP, mNullable); + case FUNCTION_RETURN: + return TypeUtils.makeNullable(ReactClassNames.REACT_WRITABLE_MAP, mNullable); + default: + break; + } + + throw new CodegenException( + "Unsupported ObjectType: " + mType + " - typeContext: " + typeContext); } @Override public @Nullable TypeSpec getGeneratedCode(final String packageName) { - // TODO - throw new UnsupportedOperationException(); + // TODO: Object type should produce is own class to represent its shape. + // However, the NativeModule system only supports built-in ReadableMap/WritableMap for now. + return null; } } diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/PromiseResolvedType.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/PromiseResolvedType.java index 9c34e59eadc..0c575ff08a2 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/PromiseResolvedType.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/PromiseResolvedType.java @@ -10,8 +10,6 @@ package com.facebook.react.codegen.generator.resolver; import com.facebook.react.codegen.generator.model.PromiseType; import com.facebook.react.codegen.generator.model.TypeData; import com.squareup.javapoet.TypeName; -import com.squareup.javapoet.TypeSpec; -import javax.annotation.Nullable; public final class PromiseResolvedType extends ResolvedType { @@ -26,13 +24,6 @@ public final class PromiseResolvedType extends ResolvedType { @Override public TypeName getNativeType(final NativeTypeContext typeContext) { - // TODO - return TypeName.VOID; - } - - @Override - public @Nullable TypeSpec getGeneratedCode(final String packageName) { - // TODO - throw new UnsupportedOperationException(); + return TypeUtils.makeNullable(ReactClassNames.REACT_PROMISE, mNullable); } } diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/ReactClassNames.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/ReactClassNames.java new file mode 100644 index 00000000000..2fca4df5dfd --- /dev/null +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/ReactClassNames.java @@ -0,0 +1,39 @@ +/* + * 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.resolver; + +import com.squareup.javapoet.ClassName; + +/** Names of React-specific Java classes required by generated code. */ +public class ReactClassNames { + + public static final ClassName REACT_APPLICATION_CONTEXT = + ClassName.bestGuess("com.facebook.react.bridge.ReactApplicationContext"); + public static final ClassName REACT_CALLBACK = + ClassName.bestGuess("com.facebook.react.bridge.Callback"); + public static final ClassName REACT_CONTEXT_BASE_JAVA_MODULE = + ClassName.bestGuess("com.facebook.react.bridge.ReactContextBaseJavaModule"); + public static final ClassName REACT_METHOD = + ClassName.bestGuess("com.facebook.react.bridge.ReactMethod"); + public static final ClassName REACT_MODULE_WITH_SPEC = + ClassName.bestGuess("com.facebook.react.bridge.ReactModuleWithSpec"); + public static final ClassName REACT_PROMISE = + ClassName.bestGuess("com.facebook.react.bridge.Promise"); + public static final ClassName REACT_READABLE_ARRAY = + ClassName.bestGuess("com.facebook.react.bridge.ReadableArray"); + public static final ClassName REACT_READABLE_MAP = + ClassName.bestGuess("com.facebook.react.bridge.ReadableMap"); + public static final ClassName REACT_WRITABLE_ARRAY = + ClassName.bestGuess("com.facebook.react.bridge.WritableArray"); + public static final ClassName REACT_WRITABLE_MAP = + ClassName.bestGuess("com.facebook.react.bridge.WritableMap"); + public static final ClassName REACT_BUILD_CONFIG = + ClassName.bestGuess("com.facebook.react.common.build.ReactBuildConfig"); + public static final ClassName REACT_TURBOMODULE = + ClassName.bestGuess("com.facebook.react.turbomodule.core.interfaces.TurboModule"); +} diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/ReservedFunctionValueResolvedType.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/ReservedFunctionValueResolvedType.java index 67991dc47b8..3cd677cc70e 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/ReservedFunctionValueResolvedType.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/ReservedFunctionValueResolvedType.java @@ -7,6 +7,8 @@ package com.facebook.react.codegen.generator.resolver; +import com.facebook.react.codegen.generator.model.CodegenException; +import com.facebook.react.codegen.generator.model.DoubleType; import com.facebook.react.codegen.generator.model.ReservedFunctionValueType; import com.facebook.react.codegen.generator.model.TypeData; import com.squareup.javapoet.TypeName; @@ -19,22 +21,28 @@ public final class ReservedFunctionValueResolvedType private ReservedFunctionValueResolvedType( final ReservedFunctionValueType type, final boolean nullable) { super(type, nullable); + throw new UnsupportedOperationException(); } - public static ReservedFunctionValueResolvedType create( + public static ResolvedType create( final ReservedFunctionValueType type, final TypeData typeData, final boolean nullable) { - return new ReservedFunctionValueResolvedType(type, nullable); + switch (type.reservedName) { + case RootTag: + return resolveType(new DoubleType(type.getTypeId()), typeData, nullable); + default: + break; + } + + throw new CodegenException("Unsupported ReservedFunctionValueType: " + type); } @Override public TypeName getNativeType(final NativeTypeContext typeContext) { - // TODO - return TypeName.VOID; + throw new UnsupportedOperationException(); } @Override public @Nullable TypeSpec getGeneratedCode(final String packageName) { - // TODO throw new UnsupportedOperationException(); } } diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/StringResolvedType.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/StringResolvedType.java index 199968c567b..7a24e39be6b 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/StringResolvedType.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/StringResolvedType.java @@ -9,9 +9,8 @@ package com.facebook.react.codegen.generator.resolver; import com.facebook.react.codegen.generator.model.StringType; import com.facebook.react.codegen.generator.model.TypeData; +import com.squareup.javapoet.ClassName; import com.squareup.javapoet.TypeName; -import com.squareup.javapoet.TypeSpec; -import javax.annotation.Nullable; public final class StringResolvedType extends ResolvedType { @@ -26,13 +25,6 @@ public final class StringResolvedType extends ResolvedType { @Override public TypeName getNativeType(final NativeTypeContext typeContext) { - // TODO - return TypeName.VOID; - } - - @Override - public @Nullable TypeSpec getGeneratedCode(final String packageName) { - // TODO - throw new UnsupportedOperationException(); + return TypeUtils.makeNullable(ClassName.get(String.class), mNullable); } } diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/TypeResolver.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/TypeResolver.java index e20534b3ba8..6b9b533876e 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/TypeResolver.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/TypeResolver.java @@ -27,7 +27,6 @@ import com.facebook.react.codegen.generator.model.VoidType; public final class TypeResolver { public static ResolvedType resolveType( final Type type, final TypeData typeData, final boolean nullable) { - System.out.println("Resolving: " + type); if (type instanceof AliasType) { return AliasResolvedType.create((AliasType) type, typeData, nullable); diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/TypeUtils.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/TypeUtils.java new file mode 100644 index 00000000000..4c45f76889e --- /dev/null +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/TypeUtils.java @@ -0,0 +1,42 @@ +/* + * 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.resolver; + +import com.squareup.javapoet.AnnotationSpec; +import com.squareup.javapoet.ParameterizedTypeName; +import com.squareup.javapoet.TypeName; +import com.squareup.javapoet.TypeVariableName; +import javax.annotation.Nullable; + +public class TypeUtils { + + public static class Annotations { + public static final AnnotationSpec OVERRIDE = AnnotationSpec.builder(Override.class).build(); + public static final AnnotationSpec NULLABLE = AnnotationSpec.builder(Nullable.class).build(); + } + + public static TypeName getNativeClassName(TypeName className) { + while (className instanceof ParameterizedTypeName) { + className = ((ParameterizedTypeName) className).rawType; + } + + return (className instanceof TypeVariableName) ? TypeName.OBJECT : className.box(); + } + + public static TypeName makeNullable(TypeName typeName, boolean isNullable) { + if (isNullable) { + if (typeName.isPrimitive()) { + return typeName.box(); + } + if (!typeName.annotations.contains(Annotations.NULLABLE)) { + return typeName.annotated(Annotations.NULLABLE); + } + } + return typeName; + } +} diff --git a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/VoidResolvedType.java b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/VoidResolvedType.java index 2d8deebb63c..4a4e0c823de 100644 --- a/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/VoidResolvedType.java +++ b/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/src/main/java/com/facebook/react/codegen/generator/resolver/VoidResolvedType.java @@ -26,13 +26,11 @@ public final class VoidResolvedType extends ResolvedType { @Override public TypeName getNativeType(final NativeTypeContext typeContext) { - // TODO - return TypeName.VOID; + return TypeUtils.makeNullable(TypeName.VOID, mNullable); } @Override public @Nullable TypeSpec getGeneratedCode(final String packageName) { - // TODO throw new UnsupportedOperationException(); } }