Remove the unused JavaGenerator from the React Native Gradle Plugin.

Summary:
I'm removing the Java generation as we're not using it for now, and we're not maintaining it.
Moreover is not feature complete, and still needs `react-native-codegen` to generate the Makefile/CMake/C++ code.
We can still resort it if we decide to switch to AST based generation.

Changelog:
[Internal] [Changed] - Remove the unused JavaGenerator from the React Native Gradle Plugin

Reviewed By: cipolleschi

Differential Revision: D35930746

fbshipit-source-id: 624c411cdc678b270a647efc3cc8236b50018bef
This commit is contained in:
Nicola Corti 2022-04-28 02:34:07 -07:00 коммит произвёл Facebook GitHub Bot
Родитель 0c4c6ca319
Коммит 63acead781
46 изменённых файлов: 8 добавлений и 2149 удалений

Просмотреть файл

@ -1,106 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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 static java.nio.charset.StandardCharsets.UTF_8;
import com.facebook.react.codegen.generator.model.CodegenException;
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.TypeSpec;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.stream.Collectors;
/**
* Given a react-native-codegen JSON schema, generate a set of .java files for React Native. The
* generator is isolated to a single schema, and a single Java package output.
*/
public final class JavaGenerator {
public static final String LICENSE_HEADER =
"/*\n"
+ " * Copyright (c) Meta Platforms, Inc. and affiliates.\n"
+ " *\n"
+ " * This source code is licensed under the MIT license found in the\n"
+ " * LICENSE file in the root directory of this source tree.\n"
+ " *\n"
+ " * Generated by react-native-codegen JavaGenerator.\n"
+ " *\n"
+ " * @"
+ "generated\n"
+ " * @"
+ "nolint\n"
+ " */\n\n";
private final File mSchemaFile;
private final String mJavaPackageName;
private final File mOutputDir;
public JavaGenerator(final File schemaFile, final String javaPackageName, final File outputDir) {
mSchemaFile = schemaFile;
mJavaPackageName = javaPackageName;
mOutputDir = outputDir;
}
public void build() throws CodegenException, FileNotFoundException, IOException {
// Step 1: Given a schema JSON, collect all types.
final TypeData typeData = SchemaJsonParser.parse(mSchemaFile);
// Step 2: Resolve each type, then collect those that produce a class or interface (TypeSpec).
final List<TypeSpec> typeSpecsToWrite =
typeData.getAllTypes().stream()
.map(
t -> {
final ResolvedType resolvedType =
TypeResolver.resolveType(typeData.getType(t), typeData, false);
final TypeSpec spec = resolvedType.getGeneratedCode(mJavaPackageName);
return spec;
})
.filter(f -> f != null)
.collect(Collectors.toList());
// Step 3: Write all of the TypeSpec's into the output directory.
for (final TypeSpec typeSpec : typeSpecsToWrite) {
writeTypeSpecToFile(typeSpec);
}
}
private final void writeTypeSpecToFile(final TypeSpec typeSpec)
throws CodegenException, IOException {
JavaFile file = JavaFile.builder(mJavaPackageName, typeSpec).skipJavaLangImports(true).build();
// Instead of using JavaFile.writeTo() API, manage the output files ourselves because
// JavaFile.addFileComment() does not support "block comment" style.
// See https://github.com/square/javapoet/issues/682#issuecomment-512238075.
Path outputDirPath = new File(mOutputDir, "java").toPath();
if (Files.exists(outputDirPath) && !Files.isDirectory(outputDirPath)) {
throw new CodegenException(
"Output path " + outputDirPath + " exists but is not a directory.");
}
if (!mJavaPackageName.isEmpty()) {
for (String packageComponent : mJavaPackageName.split("\\.")) {
outputDirPath = outputDirPath.resolve(packageComponent);
}
Files.createDirectories(outputDirPath);
}
Path outputPath = outputDirPath.resolve(typeSpec.name + ".java");
try (Writer writer = new OutputStreamWriter(Files.newOutputStream(outputPath), UTF_8)) {
writer.write(LICENSE_HEADER + file.toString());
}
}
}

Просмотреть файл

@ -1,275 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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.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;
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.ReservedFunctionValueType;
import com.facebook.react.codegen.generator.model.StringType;
import com.facebook.react.codegen.generator.model.Type;
import com.facebook.react.codegen.generator.model.TypeData;
import com.facebook.react.codegen.generator.model.TypeId;
import com.facebook.react.codegen.generator.model.VoidType;
import com.google.common.base.CaseFormat;
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.Map;
import java.util.stream.Collectors;
public final class SchemaJsonParser {
private final TypeData mTypeData = new TypeData();
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 CodegenException, FileNotFoundException, IOException {
final JsonParser parser = new JsonParser();
final JsonElement rootElement = parser.parse(new FileReader(schemaFile));
final Map<String, Map<String, NativeModuleType>> 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 String jsModuleType = jsModule.get("type").getAsString();
if (!"NativeModule".equals(jsModuleType)) {
return;
}
if (jsModule.has("excludedPlatforms")) {
final JsonArray excludedPlatforms = jsModule.getAsJsonArray("excludedPlatforms");
for (JsonElement p : excludedPlatforms) {
if (p.getAsString().equals("android")) {
// This module is not for Android.
return;
}
}
}
final Type parsedType =
parseNativeModule(
// TODO (T71955395): NativeModule spec type name does not
// exist in the schema. For now assume it's "Spec".
// The final type name will be the output class name.
TypeId.of(jsModuleName, jsModuleName + "Spec"), jsModule);
mTypeData.addType(parsedType);
});
}
return mTypeData;
}
// Parse type information from a JSON "typeAnnotation" node.
private Type parseTypeAnnotation(final TypeId typeId, final JsonObject originalTypeAnnotation) {
JsonObject typeAnnotation = originalTypeAnnotation;
String type = typeAnnotation.get("type").getAsString();
boolean nullable = false;
Type parsedType = null;
if (type.equals(NullableType.TYPE_NAME)) {
nullable = true;
typeAnnotation = typeAnnotation.get("typeAnnotation").getAsJsonObject();
type = typeAnnotation.get("type").getAsString();
}
switch (type) {
case AliasType.TYPE_NAME:
parsedType = parseAliasTypeAnnotation(typeId, typeAnnotation);
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:
// Use double type for generic numbers.
parsedType = new DoubleType(typeId);
break;
case ObjectType.TYPE_NAME:
parsedType = parseObjectTypeAnnotation(typeId, typeAnnotation);
break;
case PromiseType.TYPE_NAME:
parsedType = new PromiseType(typeId);
break;
case ReservedFunctionValueType.TYPE_NAME:
parsedType = parseReservedFunctionValueTypeAnnotation(typeId, typeAnnotation);
break;
case StringType.TYPE_NAME:
parsedType = new StringType(typeId);
break;
case VoidType.TYPE_NAME:
return VoidType.VOID;
default:
throw new CodegenException("Found invalid type annotation: " + type);
}
final Type finalType = maybeCreateNullableType(nullable, parsedType);
mTypeData.addType(finalType);
return finalType;
}
private NativeModuleType parseNativeModule(final TypeId typeId, final JsonObject json) {
final JsonObject aliases = json.getAsJsonObject("aliases");
final JsonArray properties = json.getAsJsonObject("spec").getAsJsonArray("properties");
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> collectedPropertiesBuilder =
new ImmutableList.Builder<>();
properties.forEach(
p -> {
final JsonObject node = p.getAsJsonObject();
final String name = node.get("name").getAsString();
final JsonObject typeAnnotation = node.getAsJsonObject("typeAnnotation");
final boolean optional = node.get("optional").getAsBoolean();
final TypeId propertyTypeId =
TypeId.expandOf(typeId, CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, name));
collectedPropertiesBuilder.add(
new NativeModuleType.Property(
name, parseTypeAnnotation(propertyTypeId, typeAnnotation), optional));
});
return new NativeModuleType(typeId, collectedAliases, collectedPropertiesBuilder.build());
}
private 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 Type parseArrayTypeAnnotation(final TypeId typeId, final JsonObject typeAnnotation) {
final JsonObject elementTypeAnnotation = typeAnnotation.getAsJsonObject("elementType");
final TypeId elementTypeId = TypeId.expandOf(typeId, "ElementType");
// TODO (T71847026): Some array types are missing elementType annotation.
final Type elementType =
elementTypeAnnotation != null
? parseTypeAnnotation(elementTypeId, elementTypeAnnotation)
: new AnyType(elementTypeId);
return new ArrayType(typeId, elementType);
}
private Type parseFunctionTypeAnnotation(final TypeId typeId, final JsonObject typeAnnotation) {
final JsonArray params = typeAnnotation.getAsJsonArray("params");
ImmutableList.Builder<FunctionType.ArgumentType> paramsList = new ImmutableList.Builder<>();
for (int i = 0; i < params.size(); i++) {
final JsonElement p = params.get(i);
final JsonObject node = p.getAsJsonObject();
final String name = node.get("name").getAsString();
paramsList.add(
FunctionType.createArgument(
name,
parseTypeAnnotation(
TypeId.expandOf(typeId, CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, name)),
node.getAsJsonObject("typeAnnotation"))));
}
final JsonObject returnTypeAnnotation = typeAnnotation.getAsJsonObject("returnTypeAnnotation");
final Type returnType =
parseTypeAnnotation(TypeId.expandOf(typeId, "ReturnType"), returnTypeAnnotation);
return new FunctionType(typeId, paramsList.build(), returnType);
}
private Type parseObjectTypeAnnotation(final TypeId typeId, final JsonObject typeAnnotation) {
final JsonArray properties = typeAnnotation.getAsJsonArray("properties");
ImmutableList.Builder<ObjectType.Property> propertiesList = new ImmutableList.Builder<>();
properties.forEach(
p -> {
final JsonObject node = p.getAsJsonObject();
final String name = node.get("name").getAsString();
final boolean optional = node.get("optional").getAsBoolean();
final JsonObject propertyTypeAnnotation = node.getAsJsonObject("typeAnnotation");
final TypeId propertyTypeId =
TypeId.expandOf(typeId, CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, name));
final Type propertyType = parseTypeAnnotation(propertyTypeId, propertyTypeAnnotation);
propertiesList.add(new ObjectType.Property(name, propertyType, optional));
});
return new ObjectType(typeId, propertiesList.build());
}
private Type parseReservedFunctionValueTypeAnnotation(
final TypeId typeId, final JsonObject typeAnnotation) {
return new ReservedFunctionValueType(
typeId,
ReservedFunctionValueType.ReservedName.valueOf(typeAnnotation.get("name").getAsString()));
}
private Type maybeCreateNullableType(final boolean nullable, final Type original) {
if (!nullable || original instanceof VoidType) {
return original;
}
return new NullableType(TypeId.of(original.getTypeId()), original);
}
}

Просмотреть файл

@ -1,19 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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 AliasType extends Type {
public static final String TYPE_NAME = "TypeAliasTypeAnnotation";
public final TypeId referredTypeId;
public AliasType(final TypeId typeId, final TypeId referredTypeId) {
super(typeId);
this.referredTypeId = referredTypeId;
}
}

Просмотреть файл

@ -1,16 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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 AnyType extends Type {
public static final String TYPE_NAME = "AnyTypeAnnotation";
public AnyType(final TypeId typeId) {
super(typeId);
}
}

Просмотреть файл

@ -1,19 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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 ArrayType extends Type {
public static final String TYPE_NAME = "ArrayTypeAnnotation";
public final Type elementType;
public ArrayType(final TypeId typeId, final Type elementType) {
super(typeId);
this.elementType = elementType;
}
}

Просмотреть файл

@ -1,16 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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 BooleanType extends Type {
public static final String TYPE_NAME = "BooleanTypeAnnotation";
public BooleanType(final TypeId typeId) {
super(typeId);
}
}

Просмотреть файл

@ -1,16 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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);
}
}

Просмотреть файл

@ -1,16 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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 DoubleType extends NumberType {
public static final String TYPE_NAME = "DoubleTypeAnnotation";
public DoubleType(final TypeId typeId) {
super(typeId);
}
}

Просмотреть файл

@ -1,16 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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 FloatType extends NumberType {
public static final String TYPE_NAME = "FloatTypeAnnotation";
public FloatType(final TypeId typeId) {
super(typeId);
}
}

Просмотреть файл

@ -1,89 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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;
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;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ArgumentType that = (ArgumentType) o;
return Objects.equals(this.name, that.name) && Objects.equals(this.type, that.type);
}
@Override
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<ArgumentType> parameters;
public final Type returnType;
public FunctionType(
final TypeId typeId, final List<ArgumentType> parameters, final Type returnType) {
super(typeId);
this.parameters = Collections.unmodifiableList(parameters);
this.returnType = returnType;
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass() || !super.equals(o)) {
return false;
}
final FunctionType that = (FunctionType) o;
return Objects.equals(this.parameters, that.parameters)
&& Objects.equals(this.returnType, that.returnType);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), parameters, returnType);
}
@Override
public String toString() {
return "(" + returnType + ")" + this.getTypeId() + "(" + parameters + ")";
}
}

Просмотреть файл

@ -1,16 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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 GenericObjectType extends Type {
public static final String TYPE_NAME = "GenericObjectTypeAnnotation";
public GenericObjectType(final TypeId typeId) {
super(typeId);
}
}

Просмотреть файл

@ -1,16 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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 Int32Type extends NumberType {
public static final String TYPE_NAME = "Int32TypeAnnotation";
public Int32Type(final TypeId typeId) {
super(typeId);
}
}

Просмотреть файл

@ -1,48 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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 = "<NONE>"; // Not an actual type in the schema.
public final List<Type> aliases;
public final List<Property> 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<Type> aliases, final List<Property> properties) {
super(typeId);
this.aliases = Collections.unmodifiableList(aliases);
this.properties = Collections.unmodifiableList(properties);
}
@Override
public String toString() {
return getTypeId() + "\n aliases: " + aliases + "\n properties: " + properties;
}
}

Просмотреть файл

@ -1,19 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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 innerType;
public NullableType(final TypeId typeId, final Type innerType) {
super(typeId);
this.innerType = innerType;
}
}

Просмотреть файл

@ -1,16 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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 abstract class NumberType extends Type {
public static final String TYPE_NAME = "NumberTypeAnnotation";
public NumberType(final TypeId typeId) {
super(typeId);
}
}

Просмотреть файл

@ -1,44 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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 ObjectType extends Type {
public static final String TYPE_NAME = "ObjectTypeAnnotation";
public static class Property {
public final String name;
public final Type type;
public final boolean optional;
public Property(String name, Type type, boolean optional) {
this.name = name;
this.type = type;
this.optional = optional;
}
@Override
public String toString() {
return (optional ? "?" : "") + name + ": " + type;
}
}
public final List<Property> properties;
public ObjectType(final TypeId typeId, final List<Property> properties) {
super(typeId);
this.properties = Collections.unmodifiableList(properties);
}
@Override
public String toString() {
return getTypeId() + " -> " + properties;
}
}

Просмотреть файл

@ -1,16 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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 = "PromiseTypeAnnotation";
public PromiseType(final TypeId typeId) {
super(typeId);
}
}

Просмотреть файл

@ -1,28 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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 ReservedFunctionValueType extends Type {
public static final String TYPE_NAME = "ReservedFunctionValueTypeAnnotation";
public enum ReservedName {
RootTag,
}
public ReservedName reservedName;
public ReservedFunctionValueType(final TypeId typeId, ReservedName reservedName) {
super(typeId);
this.reservedName = reservedName;
}
@Override
public String toString() {
return mTypeId + "(" + reservedName.toString() + ")";
}
}

Просмотреть файл

@ -1,16 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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 StringType extends Type {
public static final String TYPE_NAME = "StringTypeAnnotation";
public StringType(final TypeId typeId) {
super(typeId);
}
}

Просмотреть файл

@ -1,54 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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.Objects;
public abstract class Type {
public static String TYPE_NAME = "<NONE>";
protected final TypeId mTypeId;
public static <T extends Type> void assertType(
final Type type, final Class<T> expectedTypeClass) {
if (!expectedTypeClass.isInstance(type)) {
throw new IllegalStateException(
"Expected: " + expectedTypeClass.getName() + " but found: " + type.getClass().getName());
}
}
public Type(final TypeId typeId) {
mTypeId = typeId;
}
public TypeId getTypeId() {
return mTypeId;
}
@Override
public String toString() {
return mTypeId.toString();
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final Type type = (Type) o;
return Objects.equals(mTypeId, type.mTypeId);
}
@Override
public int hashCode() {
return Objects.hash(mTypeId);
}
}

Просмотреть файл

@ -1,48 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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.HashMap;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
/** A collection of all types information based on the parsed schema. */
public final class TypeData {
private final Map<TypeId, Type> mTypes = new HashMap<>();
public void addType(final TypeId typeId, final Type type) throws IllegalStateException {
if (getType(typeId) != null) {
throw new IllegalStateException("Found duplicated TypeId: " + typeId + " for: " + type);
}
mTypes.put(typeId, type);
}
public void addType(final Type type) {
addType(type.getTypeId(), type);
}
public @Nullable Type getType(final TypeId typeId) {
return mTypes.get(typeId);
}
public Set<TypeId> getAllTypes() {
return mTypes.keySet();
}
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
mTypes.forEach(
(k, v) -> {
builder.append(v.toString());
builder.append("\n");
});
return builder.toString();
}
}

Просмотреть файл

@ -1,74 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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.Objects;
import javax.annotation.Nullable;
/** Represents the fully qualified name for a Flow type. */
public final class TypeId {
public final String moduleName;
public final String typeName;
private static final String EMPTY_TYPE_NAME = "";
private TypeId(final String moduleName, final String typeName) {
this.moduleName = moduleName;
this.typeName = typeName;
}
public static TypeId of(final String moduleName) {
return new TypeId(moduleName, EMPTY_TYPE_NAME);
}
public static TypeId of(final String moduleName, @Nullable final String typeName) {
if (typeName == null) {
return TypeId.of(moduleName);
}
if (moduleName.equals(typeName)) {
return TypeId.of(moduleName);
}
return new TypeId(moduleName, typeName);
}
public static TypeId of(final TypeId typeId) {
return of(typeId.moduleName, typeId.typeName);
}
public static TypeId expandOf(final TypeId typeId, String suffix) {
return of(typeId.moduleName, typeId.typeName + suffix);
}
@Override
public String toString() {
return String.format(
"<moduleName = %s, typeName = %s>",
moduleName, EMPTY_TYPE_NAME.equals(typeName) ? "\"\"" : typeName);
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final TypeId typeId = (TypeId) o;
return Objects.equals(moduleName, typeId.moduleName)
&& Objects.equals(typeName, typeId.typeName);
}
@Override
public int hashCode() {
return Objects.hash(moduleName, typeName);
}
}

Просмотреть файл

@ -1,17 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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 VoidType extends Type {
public static final String TYPE_NAME = "VoidTypeAnnotation";
public static final VoidType VOID = new VoidType(TypeId.of(""));
private VoidType(final TypeId typeId) {
super(typeId);
}
}

Просмотреть файл

@ -1,43 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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.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;
import javax.annotation.Nullable;
public final class AliasResolvedType extends ResolvedType<AliasType> {
private AliasResolvedType(final AliasType type, final boolean nullable) {
super(type, nullable);
throw new UnsupportedOperationException();
}
public static ResolvedType create(
final AliasType type, final TypeData typeData, final boolean 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) {
throw new UnsupportedOperationException();
}
@Override
public @Nullable TypeSpec getGeneratedCode(final String packageName) {
throw new UnsupportedOperationException();
}
}

Просмотреть файл

@ -1,16 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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 javax.annotation.Nullable;
public class Annotations {
public static final AnnotationSpec OVERRIDE = AnnotationSpec.builder(Override.class).build();
public static final AnnotationSpec NULLABLE = AnnotationSpec.builder(Nullable.class).build();
}

Просмотреть файл

@ -1,36 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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.facebook.react.codegen.generator.model.AnyType;
import com.facebook.react.codegen.generator.model.TypeData;
import com.squareup.javapoet.TypeName;
public final class AnyResolvedType extends ResolvedType<AnyType> {
private AnyResolvedType(final AnyType type, final boolean nullable) {
super(type, nullable);
}
public static AnyResolvedType create(
final AnyType type, final TypeData typeData, final boolean nullable) {
return new AnyResolvedType(type, nullable);
}
@Override
public TypeName getNativeType(final NativeTypeContext typeContext) {
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);
}
}
}

Просмотреть файл

@ -1,45 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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.facebook.react.codegen.generator.model.ArrayType;
import com.facebook.react.codegen.generator.model.TypeData;
import com.squareup.javapoet.ArrayTypeName;
import com.squareup.javapoet.TypeName;
public final class ArrayResolvedType extends ResolvedType<ArrayType> {
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, typeData, nullable);
}
public ResolvedType getElementResolvedType() {
return mElementResolvedType;
}
@Override
public TypeName getNativeType(final NativeTypeContext typeContext) {
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);
}
}
}

Просмотреть файл

@ -1,29 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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.facebook.react.codegen.generator.model.BooleanType;
import com.facebook.react.codegen.generator.model.TypeData;
import com.squareup.javapoet.TypeName;
public final class BooleanResolvedType extends ResolvedType<BooleanType> {
private BooleanResolvedType(final BooleanType type, final boolean nullable) {
super(type, nullable);
}
public static BooleanResolvedType create(
final BooleanType type, final TypeData typeData, final boolean nullable) {
return new BooleanResolvedType(type, nullable);
}
@Override
public TypeName getNativeType(final NativeTypeContext typeContext) {
return TypeUtils.makeNullable(TypeName.BOOLEAN, mNullable);
}
}

Просмотреть файл

@ -1,23 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import java.util.Map;
/** Names of Java classes required by generated code. */
public class ClassNames {
// Java standard classes
public static final TypeName STRING = ClassName.get(String.class);
public static final ParameterizedTypeName CONSTANTS_MAP =
ParameterizedTypeName.get(ClassName.get(Map.class), ClassNames.STRING, ClassName.OBJECT);
}

Просмотреть файл

@ -1,125 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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.facebook.react.codegen.generator.model.FunctionType;
import com.facebook.react.codegen.generator.model.TypeData;
import com.squareup.javapoet.AnnotationSpec;
import com.squareup.javapoet.CodeBlock;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.TypeName;
import java.util.Collections;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import javax.lang.model.element.Modifier;
public final class FunctionResolvedType extends ResolvedType<FunctionType> {
private final Map<String, ResolvedType> mResolvedArgTypes;
private final ResolvedType mResolvedReturnType;
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, typeData, nullable);
}
public ResolvedType getResolvedReturnType() {
return mResolvedReturnType;
}
public Map<String, ResolvedType> getResolvedArgTypes() {
return mResolvedArgTypes;
}
@Override
public TypeName getNativeType(final NativeTypeContext typeContext) {
return TypeUtils.makeNullable(ReactClassNames.REACT_CALLBACK, mNullable);
}
public MethodSpec getGeneratedMethodWithReactAnnotation(String methodName) {
TypeName resolvedReturnTypeName =
mResolvedReturnType.getNativeType(NativeTypeContext.FUNCTION_RETURN);
boolean isReturnTypePromise = resolvedReturnTypeName == ReactClassNames.REACT_PROMISE;
TypeName returnTypeName = isReturnTypePromise ? TypeName.VOID : resolvedReturnTypeName;
MethodSpec.Builder methodBuilder =
MethodSpec.methodBuilder(methodName).addModifiers(Modifier.PUBLIC);
methodBuilder.returns(returnTypeName);
if (!mNullable) {
methodBuilder.addModifiers(Modifier.ABSTRACT);
} else {
String returnStatement = getFalsyReturnStatement(returnTypeName);
if (returnStatement != null) {
CodeBlock.Builder methodBody = CodeBlock.builder();
methodBody.addStatement(returnStatement);
methodBuilder.addCode(methodBody.build());
}
}
mResolvedArgTypes
.entrySet()
.forEach(
e -> {
String argName = e.getKey();
ResolvedType argResolvedType = e.getValue();
methodBuilder.addParameter(
ParameterSpec.builder(
argResolvedType.getNativeType(NativeTypeContext.FUNCTION_ARGUMENT),
argName)
.build());
});
AnnotationSpec.Builder annotationBuilder = AnnotationSpec.builder(ReactClassNames.REACT_METHOD);
// Special case: Promise inserts additional method arg at the end.
if (isReturnTypePromise) {
methodBuilder.addParameter(
ParameterSpec.builder(ReactClassNames.REACT_PROMISE, "promise").build());
} else if (!TypeName.VOID.equals(returnTypeName)) {
// A non-promise non-void return type means the method is synchronous.
annotationBuilder.addMember("isBlockingSynchronousMethod", "$L", true);
}
// React methods need special `@ReactMethod` annotation for now.
methodBuilder.addAnnotation(annotationBuilder.build());
// TODO(T82242829) Add @DoNotStrip annotation
return methodBuilder.build();
}
private static @Nullable String getFalsyReturnStatement(TypeName returnType) {
// TODO: Handle nullable falsy return.
if (returnType == TypeName.BOOLEAN) {
return "return false";
} else if (returnType == TypeName.DOUBLE) {
return "return 0.0";
} else if (returnType == ClassNames.STRING
|| returnType == ReactClassNames.REACT_WRITABLE_ARRAY
|| returnType == ReactClassNames.REACT_WRITABLE_MAP) {
return "return null";
}
return null;
}
}

Просмотреть файл

@ -1,40 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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.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;
public final class GenericObjectResolvedType extends ResolvedType<GenericObjectType> {
private GenericObjectResolvedType(final GenericObjectType type, final boolean nullable) {
super(type, nullable);
}
public static GenericObjectResolvedType create(
final GenericObjectType type, final TypeData typeData, final boolean nullable) {
return new GenericObjectResolvedType(type, nullable);
}
@Override
public TypeName getNativeType(final NativeTypeContext typeContext) {
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 GenericObjectType: " + mType + " - typeContext: " + typeContext);
}
}

Просмотреть файл

@ -1,260 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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.facebook.react.codegen.generator.model.NativeModuleType;
import com.facebook.react.codegen.generator.model.TypeData;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import javax.lang.model.element.Modifier;
public final class NativeModuleResolvedType extends ResolvedType<NativeModuleType> {
private final Map<String, ResolvedType> mResolvedAliasTypes;
private final Map<String, FunctionResolvedType> mResolvedPropertyTypes;
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 -> {
final ResolvedType resolvedType =
resolveType(item.type, typeData, item.optional);
TypeUtils.assertCondition(
resolvedType instanceof FunctionResolvedType,
"NativeModules can only contain methods. Constants like '"
+ item.name
+ "' must be declared in the return type of the 'getConstants()' method.");
return (FunctionResolvedType) resolvedType;
})));
}
public static NativeModuleResolvedType create(
final NativeModuleType type, final TypeData typeData, final boolean nullable) {
return new NativeModuleResolvedType(type, typeData, nullable);
}
@Override
public TypeName getNativeType(final NativeTypeContext typeContext) {
throw new UnsupportedOperationException(
"NativeModuleType cannot be referred to by other types.");
}
@Override
public @Nullable TypeSpec getGeneratedCode(final String packageName) {
final TypeSpec.Builder classBuilder =
TypeSpec.classBuilder(mType.getTypeId().typeName)
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
.superclass(ReactClassNames.REACT_CONTEXT_BASE_JAVA_MODULE)
.addSuperinterface(ReactClassNames.REACT_MODULE_WITH_SPEC)
.addSuperinterface(ReactClassNames.REACT_TURBOMODULE);
final MethodSpec.Builder constructorBuilder =
MethodSpec.constructorBuilder()
.addModifiers(Modifier.PUBLIC)
.addParameter(
ParameterSpec.builder(ReactClassNames.REACT_APPLICATION_CONTEXT, "reactContext")
.build())
.addStatement("super($N)", "reactContext");
classBuilder.addMethod(constructorBuilder.build());
mResolvedPropertyTypes.forEach(
(name, resolvedType) -> {
if (name.equals("getConstants")) {
classBuilder.addMethod(generateGetTypedExportedConstantsMethod());
classBuilder.addMethod(generateGetConstantsMethod(resolvedType));
} else {
classBuilder.addMethod(
((FunctionResolvedType) resolvedType).getGeneratedMethodWithReactAnnotation(name));
}
});
return classBuilder.build();
}
// For now, getConstants() needs a runtime check to ensure the object return value has the
// required properties. In the future, the method should return the specific object type that
// can be verified during build time.
private static MethodSpec generateGetConstantsMethod(final FunctionResolvedType resolvedType) {
final ResolvedType resolvedReturnType = resolvedType.getResolvedReturnType();
TypeUtils.assertCondition(
resolvedReturnType instanceof ObjectResolvedType,
"getConstants() method must return an exact object. Found: " + resolvedType.mType);
final ParameterizedTypeName returnType =
ParameterizedTypeName.get(ClassName.get(Map.class), ClassNames.STRING, ClassName.OBJECT);
return MethodSpec.methodBuilder("getConstants")
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
.addAnnotation(Annotations.OVERRIDE)
.returns(returnType.annotated(Annotations.NULLABLE))
.addCode(
getConstantsMethodBody(
returnType, ((ObjectResolvedType) resolvedReturnType).getResolvedPropertyTypes()))
.build();
}
private static MethodSpec generateGetTypedExportedConstantsMethod() {
return MethodSpec.methodBuilder("getTypedExportedConstants")
.addModifiers(Modifier.PROTECTED, Modifier.ABSTRACT)
.returns(ClassNames.CONSTANTS_MAP)
.build();
}
private static CodeBlock getConstantsMethodBody(
final ParameterizedTypeName returnType, final Map<String, ResolvedType> constantsTypes) {
final CodeBlock.Builder methodBody = CodeBlock.builder();
final Map<Boolean, List<Map.Entry<String, ResolvedType>>> constantsByNullability =
constantsTypes.entrySet().stream()
.collect(Collectors.partitioningBy(entry -> entry.getValue().mNullable));
final String constantsVariableName = "constants";
final String obligatoryFlowConstantsVariableName = "obligatoryFlowConstants";
final String optionalFlowConstantsVariableName = "optionalFlowConstants";
final TypeName setOfStringsType =
ParameterizedTypeName.get(ClassName.get(Set.class), ClassNames.STRING);
final TypeName hashsetType = ClassName.get(HashSet.class);
methodBody.addStatement(
"$T $N = $N()",
returnType,
constantsVariableName,
generateGetTypedExportedConstantsMethod().name);
// Enable all of this for internal (debug) builds only.
methodBody.beginControlFlow(
"if ($1T.DEBUG || $1T.IS_INTERNAL_BUILD)", ReactClassNames.REACT_BUILD_CONFIG);
{
final List<String> obligatoryConstants =
constantsByNullability.get(false).stream()
.map(Map.Entry::getKey)
.sorted()
.collect(Collectors.toList());
addVariableDeclaration(
methodBody,
obligatoryFlowConstantsVariableName,
obligatoryConstants,
setOfStringsType,
hashsetType);
final List<String> optionalConstants =
constantsByNullability.get(true).stream()
.map(Map.Entry::getKey)
.sorted()
.collect(Collectors.toList());
addVariableDeclaration(
methodBody,
optionalFlowConstantsVariableName,
optionalConstants,
setOfStringsType,
hashsetType);
final String undeclaredConstantsVariableName = "undeclaredConstants";
methodBody
.addStatement(
"$T $N = new $T<>($N.keySet())",
setOfStringsType,
undeclaredConstantsVariableName,
hashsetType,
constantsVariableName)
.addStatement(
"$N.removeAll($N)",
undeclaredConstantsVariableName,
obligatoryFlowConstantsVariableName)
.addStatement(
"$N.removeAll($N)",
undeclaredConstantsVariableName,
optionalFlowConstantsVariableName);
methodBody.add(
checkForConstantsFulfillmentBlock(
undeclaredConstantsVariableName,
"Native Module Flow doesn\'t declare constants: %s"));
methodBody
.addStatement(
"$N = $N", undeclaredConstantsVariableName, obligatoryFlowConstantsVariableName)
.addStatement(
"$N.removeAll($N.keySet())", undeclaredConstantsVariableName, constantsVariableName);
methodBody.add(
checkForConstantsFulfillmentBlock(
undeclaredConstantsVariableName, "Native Module doesn\'t fill in constants: %s"));
}
methodBody.endControlFlow();
methodBody.addStatement("return $N", constantsVariableName);
return methodBody.build();
}
private static void addVariableDeclaration(
final CodeBlock.Builder builder,
final String variableName,
final List<String> values,
final TypeName varType,
final TypeName actualType) {
if (values.isEmpty()) {
builder.addStatement("$T $N = new $T<>()", varType, variableName, actualType);
} else {
builder.add(
"$T $N = new $T<>($T.asList(\n",
varType,
variableName,
actualType,
ClassName.get(Arrays.class));
builder.indent().indent();
int constantsToAdd = values.size();
for (final String constantName : values) {
builder.add("\"$L\"", constantName);
if (--constantsToAdd > 0) {
builder.add(",");
}
builder.add("\n");
}
builder.unindent().unindent();
builder.addStatement("))");
}
}
private static CodeBlock checkForConstantsFulfillmentBlock(
final String undeclaredConstantsVariableName, final String formatString) {
return CodeBlock.builder()
.beginControlFlow("if (!$N.isEmpty())", undeclaredConstantsVariableName)
.addStatement(
"throw new IllegalStateException(String.format(\"" + formatString + "\", $N))",
undeclaredConstantsVariableName)
.endControlFlow()
.build();
}
}

Просмотреть файл

@ -1,37 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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.facebook.react.codegen.generator.model.NullableType;
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 NullableResolvedType extends ResolvedType<NullableType> {
private NullableResolvedType(final NullableType type, final boolean nullable) {
super(type, nullable);
throw new UnsupportedOperationException();
}
public static ResolvedType create(
final NullableType type, final TypeData typeData, final boolean nullable) {
return resolveType(type.innerType, typeData, true);
}
@Override
public TypeName getNativeType(final NativeTypeContext typeContext) {
throw new UnsupportedOperationException();
}
@Override
public @Nullable TypeSpec getGeneratedCode(final String packageName) {
throw new UnsupportedOperationException();
}
}

Просмотреть файл

@ -1,42 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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.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;
public final class NumberResolvedType extends ResolvedType<NumberType> {
private NumberResolvedType(final NumberType type, final boolean nullable) {
super(type, nullable);
}
public static NumberResolvedType create(
final NumberType type, final TypeData typeData, final boolean nullable) {
return new NumberResolvedType(type, nullable);
}
@Override
public TypeName getNativeType(final NativeTypeContext typeContext) {
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());
}
}

Просмотреть файл

@ -1,68 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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.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<ObjectType> {
private final Map<String, ResolvedType> mResolvedPropertyTypes;
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, typeData, nullable);
}
public Map<String, ResolvedType> getResolvedPropertyTypes() {
return mResolvedPropertyTypes;
}
@Override
public TypeName getNativeType(final NativeTypeContext typeContext) {
// 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: 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;
}
}

Просмотреть файл

@ -1,29 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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.facebook.react.codegen.generator.model.PromiseType;
import com.facebook.react.codegen.generator.model.TypeData;
import com.squareup.javapoet.TypeName;
public final class PromiseResolvedType extends ResolvedType<PromiseType> {
private PromiseResolvedType(final PromiseType type, final boolean nullable) {
super(type, nullable);
}
public static PromiseResolvedType create(
final PromiseType type, final TypeData typeData, final boolean nullable) {
return new PromiseResolvedType(type, nullable);
}
@Override
public TypeName getNativeType(final NativeTypeContext typeContext) {
return TypeUtils.makeNullable(ReactClassNames.REACT_PROMISE, mNullable);
}
}

Просмотреть файл

@ -1,39 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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");
}

Просмотреть файл

@ -1,48 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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.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;
import com.squareup.javapoet.TypeSpec;
import javax.annotation.Nullable;
public final class ReservedFunctionValueResolvedType
extends ResolvedType<ReservedFunctionValueType> {
private ReservedFunctionValueResolvedType(
final ReservedFunctionValueType type, final boolean nullable) {
super(type, nullable);
throw new UnsupportedOperationException();
}
public static ResolvedType create(
final ReservedFunctionValueType type, final TypeData typeData, final boolean 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) {
throw new UnsupportedOperationException();
}
@Override
public @Nullable TypeSpec getGeneratedCode(final String packageName) {
throw new UnsupportedOperationException();
}
}

Просмотреть файл

@ -1,52 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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.facebook.react.codegen.generator.model.Type;
import com.facebook.react.codegen.generator.model.TypeData;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import javax.annotation.Nullable;
public abstract class ResolvedType<T extends Type> {
/** Contexts native types can appear in. */
public enum NativeTypeContext {
FUNCTION_ARGUMENT,
FUNCTION_RETURN,
DEFAULT,
}
protected final T mType;
protected final boolean mNullable;
protected ResolvedType(final T type, final boolean nullable) {
mType = type;
mNullable = nullable;
}
protected static ResolvedType resolveType(
final Type type, final TypeData typeData, final boolean nullable) {
return TypeResolver.resolveType(type, typeData, nullable);
}
public T getType() {
return mType;
}
public boolean isNullable() {
return mNullable;
}
/** The Java type generated for this type */
public abstract TypeName getNativeType(NativeTypeContext typeContext);
/** Generate code for this type itself, if applicable. */
public @Nullable TypeSpec getGeneratedCode(final String packageName) {
return null;
}
}

Просмотреть файл

@ -1,29 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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.facebook.react.codegen.generator.model.StringType;
import com.facebook.react.codegen.generator.model.TypeData;
import com.squareup.javapoet.TypeName;
public final class StringResolvedType extends ResolvedType<StringType> {
private StringResolvedType(final StringType type, final boolean nullable) {
super(type, nullable);
}
public static StringResolvedType create(
final StringType type, final TypeData typeData, final boolean nullable) {
return new StringResolvedType(type, nullable);
}
@Override
public TypeName getNativeType(final NativeTypeContext typeContext) {
return TypeUtils.makeNullable(ClassNames.STRING, mNullable);
}
}

Просмотреть файл

@ -1,90 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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.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.FunctionType;
import com.facebook.react.codegen.generator.model.GenericObjectType;
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.ReservedFunctionValueType;
import com.facebook.react.codegen.generator.model.StringType;
import com.facebook.react.codegen.generator.model.Type;
import com.facebook.react.codegen.generator.model.TypeData;
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) {
if (type instanceof AliasType) {
return AliasResolvedType.create((AliasType) type, typeData, nullable);
}
if (type instanceof AnyType) {
return AnyResolvedType.create((AnyType) type, typeData, nullable);
}
if (type instanceof ArrayType) {
return ArrayResolvedType.create((ArrayType) type, typeData, nullable);
}
if (type instanceof BooleanType) {
return BooleanResolvedType.create((BooleanType) type, typeData, nullable);
}
if (type instanceof FunctionType) {
return FunctionResolvedType.create((FunctionType) type, typeData, nullable);
}
if (type instanceof GenericObjectType) {
return GenericObjectResolvedType.create((GenericObjectType) type, typeData, nullable);
}
if (type instanceof NativeModuleType) {
return NativeModuleResolvedType.create((NativeModuleType) type, typeData, nullable);
}
if (type instanceof NullableType) {
return NullableResolvedType.create((NullableType) type, typeData, nullable);
}
if (type instanceof NumberType) {
return NumberResolvedType.create((NumberType) type, typeData, nullable);
}
if (type instanceof ObjectType) {
return ObjectResolvedType.create((ObjectType) type, typeData, nullable);
}
if (type instanceof PromiseType) {
return PromiseResolvedType.create((PromiseType) type, typeData, nullable);
}
if (type instanceof ReservedFunctionValueType) {
return ReservedFunctionValueResolvedType.create(
(ReservedFunctionValueType) type, typeData, nullable);
}
if (type instanceof StringType) {
return StringResolvedType.create((StringType) type, typeData, nullable);
}
if (type instanceof VoidType) {
return VoidResolvedType.create((VoidType) type, typeData, nullable);
}
throw new IllegalArgumentException("Unable to resolve unsupported type: " + type.getClass());
}
}

Просмотреть файл

@ -1,43 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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.facebook.react.codegen.generator.model.CodegenException;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeVariableName;
public class TypeUtils {
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(final TypeName typeName, final boolean isNullable) {
if (isNullable) {
if (typeName.isPrimitive()) {
return typeName.box();
}
if (!typeName.annotations.contains(Annotations.NULLABLE)) {
return typeName.annotated(Annotations.NULLABLE);
}
}
return typeName;
}
public static void assertCondition(final boolean condition, final String errorMessage)
throws CodegenException {
if (!condition) {
throw new CodegenException(errorMessage);
}
}
}

Просмотреть файл

@ -1,36 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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.facebook.react.codegen.generator.model.TypeData;
import com.facebook.react.codegen.generator.model.VoidType;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import javax.annotation.Nullable;
public final class VoidResolvedType extends ResolvedType<VoidType> {
private VoidResolvedType(final VoidType type, final boolean nullable) {
super(type, nullable);
}
public static VoidResolvedType create(
final VoidType type, final TypeData typeData, final boolean nullable) {
return new VoidResolvedType(type, nullable);
}
@Override
public TypeName getNativeType(final NativeTypeContext typeContext) {
return TypeName.VOID;
}
@Override
public @Nullable TypeSpec getGeneratedCode(final String packageName) {
throw new UnsupportedOperationException();
}
}

Просмотреть файл

@ -228,7 +228,14 @@ abstract class ReactExtension @Inject constructor(project: Project) {
val codegenJavaPackageName: Property<String> =
objects.property(String::class.java).convention("com.facebook.fbreact.specs")
/** Whether the Java Generator (based on Javapoet) should be used or not. Default: false */
/**
* Whether the Java Generator (based on Javapoet) should be used or not. Please note that this is
* currently deprecated as the Java generator is not supported anymore. Default: false
*/
@Deprecated(
level = DeprecationLevel.ERROR,
message =
"Please note that this is deprecated as the Java generator is not supported and react-native-codegen should be used instead.")
val useJavaGenerator: Property<Boolean> = objects.property(Boolean::class.java).convention(false)
/**

Просмотреть файл

@ -100,7 +100,6 @@ class ReactPlugin : Plugin<Project> {
it.deprecatedReactRoot.set(extension.reactRoot)
it.nodeExecutableAndArgs.set(extension.nodeExecutableAndArgs)
it.codegenDir.set(extension.codegenDir)
it.useJavaGenerator.set(extension.useJavaGenerator)
it.codegenJavaPackageName.set(extension.codegenJavaPackageName)
it.libraryName.set(extension.libraryName)
it.generatedSrcDir.set(generatedSrcDir)

Просмотреть файл

@ -7,9 +7,7 @@
package com.facebook.react.tasks
import com.facebook.react.codegen.generator.JavaGenerator
import com.facebook.react.utils.windowsAwareCommandLine
import org.gradle.api.GradleException
import org.gradle.api.file.Directory
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.file.RegularFile
@ -28,8 +26,6 @@ abstract class GenerateCodegenArtifactsTask : Exec() {
@get:Input abstract val nodeExecutableAndArgs: ListProperty<String>
@get:Input abstract val useJavaGenerator: Property<Boolean>
@get:Input abstract val codegenJavaPackageName: Property<String>
@get:Input abstract val libraryName: Property<String>
@ -52,19 +48,6 @@ abstract class GenerateCodegenArtifactsTask : Exec() {
checkForDeprecatedProperty()
setupCommandLine()
super.exec()
if (useJavaGenerator.getOrElse(false)) {
// Use Java-based generator implementation to produce the source files,
// this will override the JS-based generator output (for the Java files only).
try {
JavaGenerator(
generatedSchemaFile.get().asFile,
codegenJavaPackageName.get(),
generatedSrcDir.get().asFile)
.build()
} catch (e: Exception) {
throw GradleException("Failed to generate Java from schema.", e)
}
}
}
private fun checkForDeprecatedProperty() {