Skip to content

Commit

Permalink
RNGP - Remove enableCodegenInApps and infer it from package.json (#35083
Browse files Browse the repository at this point in the history
)

Summary:
Pull Request resolved: #35083

We don't need to `enableCodegenInApps` keys but we can instead rely on the
existence of the `codegenConfig` key inside the `package.json` to decide if
Codegen should run in App modules or not.

Changelog:
[Internal] [Changed] - RNGP - Remove enableCodegenInApps and infer it from package.json

Reviewed By: cipolleschi

Differential Revision: D40687079

fbshipit-source-id: cd4a6c67caa19c1d199ae75388a0551339f876a0
  • Loading branch information
cortinico authored and facebook-github-bot committed Oct 26, 2022
1 parent 0627cd6 commit 7d61b9d
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -156,11 +156,4 @@ abstract class ReactExtension @Inject constructor(project: Project) {
*/
val codegenJavaPackageName: Property<String> =
objects.property(String::class.java).convention("com.facebook.fbreact.specs")

/**
* Toggles the Codegen for App modules. By default we enable the codegen only for library modules.
* If you want to enable codegen in your app, you will have to set this to true. Default: false
*/
val enableCodegenInApps: Property<Boolean> =
objects.property(Boolean::class.java).convention(false)
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import com.facebook.react.utils.DependencyUtils.configureRepositories
import com.facebook.react.utils.DependencyUtils.readVersionString
import com.facebook.react.utils.JsonUtils
import com.facebook.react.utils.NdkConfiguratorUtils.configureReactNativeNdk
import com.facebook.react.utils.ProjectUtils.needsCodegenFromPackageJson
import com.facebook.react.utils.findPackageJsonFile
import java.io.File
import kotlin.system.exitProcess
Expand Down Expand Up @@ -91,7 +92,11 @@ class ReactPlugin : Plugin<Project> {
it.codegenDir.set(extension.codegenDir)
val bashWindowsHome = project.findProperty("REACT_WINDOWS_BASH") as String?
it.bashWindowsHome.set(bashWindowsHome)
it.onlyIf { isLibrary || extension.enableCodegenInApps.get() }

// Please note that appNeedsCodegen is triggering a read of the package.json at
// configuration time as we need to feed the onlyIf condition of this task.
// Therefore, the appNeedsCodegen needs to be invoked inside this lambda.
it.onlyIf { isLibrary || project.needsCodegenFromPackageJson(extension) }
}

// We create the task to produce schema from JS files.
Expand All @@ -102,10 +107,9 @@ class ReactPlugin : Plugin<Project> {
it.nodeExecutableAndArgs.set(extension.nodeExecutableAndArgs)
it.codegenDir.set(extension.codegenDir)
it.generatedSrcDir.set(generatedSrcDir)
it.onlyIf { isLibrary || extension.enableCodegenInApps.get() }

// We're reading the package.json at configuration time to properly feed
// the `jsRootDir` @Input property of this task. Therefore, the
// the `jsRootDir` @Input property of this task & the onlyIf. Therefore, the
// parsePackageJson should be invoked inside this lambda.
val packageJson = findPackageJsonFile(project, extension)
val parsedPackageJson = packageJson?.let { JsonUtils.fromCodegenJson(it) }
Expand All @@ -116,6 +120,7 @@ class ReactPlugin : Plugin<Project> {
} else {
it.jsRootDir.set(extension.jsRootDir)
}
it.onlyIf { isLibrary || project.needsCodegenFromPackageJson(parsedPackageJson) }
}

// We create the task to generate Java code from schema.
Expand All @@ -130,7 +135,11 @@ class ReactPlugin : Plugin<Project> {
it.packageJsonFile.set(findPackageJsonFile(project, extension))
it.codegenJavaPackageName.set(extension.codegenJavaPackageName)
it.libraryName.set(extension.libraryName)
it.onlyIf { isLibrary || extension.enableCodegenInApps.get() }

// Please note that appNeedsCodegen is triggering a read of the package.json at
// configuration time as we need to feed the onlyIf condition of this task.
// Therefore, the appNeedsCodegen needs to be invoked inside this lambda.
it.onlyIf { isLibrary || project.needsCodegenFromPackageJson(extension) }
}

// We update the android configuration to include the generated sources.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
package com.facebook.react.utils

import com.facebook.react.ReactExtension
import com.facebook.react.model.ModelPackageJson
import java.io.File
import org.gradle.api.Project

Expand Down Expand Up @@ -206,6 +207,19 @@ internal fun findPackageJsonFile(project: Project, extension: ReactExtension): F
extension.root.file("package.json").orNull?.asFile
}

/**
* Function to look for the `package.json` and parse it. It returns a [ModelPackageJson] if found or
* null others.
*
* Please note that this function access the [ReactExtension] field properties and calls .get() on
* them, so calling this during apply() of the ReactPlugin is not recommended. It should be invoked
* inside lazy lambdas or at execution time.
*/
internal fun readPackageJsonFile(project: Project, extension: ReactExtension): ModelPackageJson? {
val packageJson = findPackageJsonFile(project, extension)
return packageJson?.let { JsonUtils.fromCodegenJson(it) }
}

private const val HERMESC_IN_REACT_NATIVE_DIR = "node_modules/react-native/sdks/hermesc/%OS-BIN%/"
private const val HERMESC_BUILT_FROM_SOURCE_DIR =
"node_modules/react-native/ReactAndroid/hermes-engine/build/hermes/bin/"
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

package com.facebook.react.utils

import com.facebook.react.ReactExtension
import com.facebook.react.model.ModelPackageJson
import org.gradle.api.Project

internal object ProjectUtils {
Expand All @@ -32,4 +34,13 @@ internal object ProjectUtils {
} else {
HERMES_FALLBACK
}

internal fun Project.needsCodegenFromPackageJson(extension: ReactExtension): Boolean {
val parsedPackageJson = readPackageJsonFile(this, extension)
return needsCodegenFromPackageJson(parsedPackageJson)
}

internal fun Project.needsCodegenFromPackageJson(model: ModelPackageJson?): Boolean {
return model?.codegenConfig != null
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import com.facebook.react.tests.OS
import com.facebook.react.tests.OsRule
import com.facebook.react.tests.WithOs
import java.io.File
import java.io.FileNotFoundException
import org.gradle.testfixtures.ProjectBuilder
import org.junit.Assert.*
import org.junit.Assume.assumeTrue
Expand Down Expand Up @@ -299,4 +300,60 @@ class PathUtilsTest {

assertEquals(localFile, findPackageJsonFile(project, extension))
}

@Test(expected = FileNotFoundException::class)
fun readPackageJsonFile_withMissingFile_returnsNull() {
val moduleFolder = tempFolder.newFolder("awesome-module")
val project = ProjectBuilder.builder().withProjectDir(moduleFolder).build()
project.plugins.apply("com.android.library")
project.plugins.apply("com.facebook.react")
val extension =
project.extensions.getByType(ReactExtension::class.java).apply { root.set(moduleFolder) }

val actual = readPackageJsonFile(project, extension)

assertNull(actual)
}

@Test
fun readPackageJsonFile_withFileConfiguredInExtension_andMissingCodegenConfig_returnsNullCodegenConfig() {
val moduleFolder = tempFolder.newFolder("awesome-module")
File(moduleFolder, "package.json").apply { writeText("{}") }
val project = ProjectBuilder.builder().withProjectDir(moduleFolder).build()
project.plugins.apply("com.android.library")
project.plugins.apply("com.facebook.react")
val extension =
project.extensions.getByType(ReactExtension::class.java).apply { root.set(moduleFolder) }

val actual = readPackageJsonFile(project, extension)

assertNotNull(actual)
assertNull(actual!!.codegenConfig)
}

@Test
fun readPackageJsonFile_withFileConfiguredInExtension_andHavingCodegenConfig_returnsValidCodegenConfig() {
val moduleFolder = tempFolder.newFolder("awesome-module")
File(moduleFolder, "package.json").apply {
writeText(
// language=json
"""
{
"name": "a-library",
"codegenConfig": {}
}
"""
.trimIndent())
}
val project = ProjectBuilder.builder().withProjectDir(moduleFolder).build()
project.plugins.apply("com.android.library")
project.plugins.apply("com.facebook.react")
val extension =
project.extensions.getByType(ReactExtension::class.java).apply { root.set(moduleFolder) }

val actual = readPackageJsonFile(project, extension)

assertNotNull(actual)
assertNotNull(actual!!.codegenConfig)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,24 @@

package com.facebook.react.utils

import com.facebook.react.TestReactExtension
import com.facebook.react.model.ModelCodegenConfig
import com.facebook.react.model.ModelPackageJson
import com.facebook.react.tests.createProject
import com.facebook.react.utils.ProjectUtils.isHermesEnabled
import com.facebook.react.utils.ProjectUtils.isNewArchEnabled
import com.facebook.react.utils.ProjectUtils.needsCodegenFromPackageJson
import java.io.File
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TemporaryFolder

class ProjectUtilsTest {

@get:Rule val tempFolder = TemporaryFolder()

@Test
fun isNewArchEnabled_returnsFalseByDefault() {
assertFalse(createProject().isNewArchEnabled)
Expand Down Expand Up @@ -99,4 +108,57 @@ class ProjectUtilsTest {
project.extensions.extraProperties.set("react", extMap)
assertTrue(project.isHermesEnabled)
}

@Test
fun needsCodegenFromPackageJson_withCodegenConfigInPackageJson_returnsTrue() {
val project = createProject()
val extension = TestReactExtension(project)
File(tempFolder.root, "package.json").apply {
writeText(
// language=json
"""
{
"name": "a-library",
"codegenConfig": {}
}
"""
.trimIndent())
}
extension.root.set(tempFolder.root)
assertTrue(project.needsCodegenFromPackageJson(extension))
}

@Test
fun needsCodegenFromPackageJson_withMissingCodegenConfigInPackageJson_returnsFalse() {
val project = createProject()
val extension = TestReactExtension(project)
File(tempFolder.root, "package.json").apply {
writeText(
// language=json
"""
{
"name": "a-library"
}
"""
.trimIndent())
}
extension.root.set(tempFolder.root)
assertFalse(project.needsCodegenFromPackageJson(extension))
}

@Test
fun needsCodegenFromPackageJson_withCodegenConfigInModel_returnsTrue() {
val project = createProject()
val model = ModelPackageJson(ModelCodegenConfig(null, null, null, null))

assertTrue(project.needsCodegenFromPackageJson(model))
}

@Test
fun needsCodegenFromPackageJson_withMissingCodegenConfigInModel_returnsFalse() {
val project = createProject()
val model = ModelPackageJson(null)

assertFalse(project.needsCodegenFromPackageJson(model))
}
}
1 change: 0 additions & 1 deletion packages/rn-tester/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ react {
// Codegen Configs
reactNativeDir = rootDir
codegenDir = new File(rootDir, "node_modules/react-native-codegen")
enableCodegenInApps = true
}

/**
Expand Down

0 comments on commit 7d61b9d

Please sign in to comment.