@granite-js/screen 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/GraniteScreen.podspec +25 -0
- package/LICENSE +202 -0
- package/android/CMakeLists.txt +62 -0
- package/android/build.gradle +63 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/cpp/BundleEvaluator.cpp +27 -0
- package/android/src/main/cpp/BundleEvaluator.h +17 -0
- package/android/src/main/cpp/onLoad.cpp +6 -0
- package/android/src/main/kotlin/run/granite/BundleEvaluator.kt +50 -0
- package/android/src/main/kotlin/run/granite/BundleLoader.kt +40 -0
- package/android/src/main/kotlin/run/granite/DefaultBundleLoader.kt +20 -0
- package/android/src/main/kotlin/run/granite/DefaultErrorView.kt +58 -0
- package/android/src/main/kotlin/run/granite/DefaultLoadingView.kt +51 -0
- package/android/src/main/kotlin/run/granite/GraniteReactDelegate.kt +76 -0
- package/android/src/main/kotlin/run/granite/GraniteReactDelegateImpl.kt +448 -0
- package/android/src/main/kotlin/run/granite/GraniteReactHost.kt +113 -0
- package/android/src/main/kotlin/run/granite/ReactHostFactory.kt +106 -0
- package/gradle-plugin/LICENSE +201 -0
- package/gradle-plugin/README.md +578 -0
- package/gradle-plugin/build.gradle.kts +97 -0
- package/gradle-plugin/gradle/libs.versions.toml +17 -0
- package/gradle-plugin/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/gradle-plugin/gradle/wrapper/gradle-wrapper.properties +7 -0
- package/gradle-plugin/gradle.properties +12 -0
- package/gradle-plugin/gradlew +248 -0
- package/gradle-plugin/gradlew.bat +93 -0
- package/gradle-plugin/settings.gradle.kts +1 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/GraniteExtension.kt +225 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/GranitePlugin.kt +784 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/GraniteRootExtension.kt +107 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/GraniteRootProjectPlugin.kt +290 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/config/BuildConfigConfigurator.kt +69 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/config/DependencyConfigurator.kt +232 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/config/DependencyCoordinates.kt +29 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/config/DevServerResourceConfigurator.kt +101 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/config/JniPackagingConfigurator.kt +160 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/config/NdkConfigurator.kt +135 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/config/RepositoryConfigurator.kt +148 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/config/ResourceConfigurator.kt +56 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/generators/CMakeGenerator.kt +105 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/generators/CppAutolinkingGenerator.kt +152 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/generators/EntryPointGenerator.kt +100 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/models/AndroidDependencyConfig.kt +23 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/models/AutolinkingConfig.kt +89 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/models/CMakeEntry.kt +47 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/models/NativeModule.kt +177 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/tasks/AssetPackagingTask.kt +194 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/tasks/AutolinkingTask.kt +431 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/tasks/BundleTask.kt +275 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/tasks/CodegenArtifactsTask.kt +218 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/tasks/CodegenSchemaTask.kt +186 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/utils/AutolinkingParser.kt +128 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/utils/ConflictDetector.kt +121 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/utils/JdkValidator.kt +73 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/utils/NodeExecutableFinder.kt +43 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/utils/ReactNativeVersionReader.kt +329 -0
- package/gradle-plugin/src/main/kotlin/run/granite/gradle/utils/TaskDependencyValidator.kt +198 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/GraniteExtensionTest.kt +191 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/GranitePluginTest.kt +156 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/GraniteRootProjectPluginTest.kt +87 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/config/BuildConfigConfiguratorTest.kt +115 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/config/DependencyConfiguratorTest.kt +338 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/config/DevServerResourceConfiguratorTest.kt +205 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/config/ResourceConfiguratorTest.kt +131 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/fixtures/NativeModuleFixtures.kt +67 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/generators/CMakeGeneratorTest.kt +71 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/generators/CppAutolinkingGeneratorTest.kt +344 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/generators/EntryPointGeneratorTest.kt +40 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/models/AutolinkingConfigTest.kt +350 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/models/CMakeEntryTest.kt +200 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/models/NativeModuleTest.kt +562 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/tasks/AssetPackagingTaskTest.kt +318 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/tasks/AutolinkingTaskTest.kt +89 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/tasks/BundleTaskTest.kt +68 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/tasks/CodegenTasksTest.kt +410 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/utils/AutolinkingParserTest.kt +335 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/utils/ConflictDetectorTest.kt +75 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/utils/JdkValidatorTest.kt +88 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/utils/ReactNativeVersionReaderTest.kt +585 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/utils/TaskDependencyValidatorTest.kt +123 -0
- package/gradle-plugin/src/test/kotlin/run/granite/gradle/utils/TaskTestUtils.kt +88 -0
- package/gradle-plugin/src/test/resources/fixtures/sample-rn-config.json +45 -0
- package/ios/BundleLoader/BundleEvaluator.h +16 -0
- package/ios/BundleLoader/BundleEvaluator.mm +76 -0
- package/ios/BundleLoader/BundleLoadable.swift +91 -0
- package/ios/GraniteBundleLoaderTypes.swift +7 -0
- package/ios/GraniteScreen.h +12 -0
- package/ios/ReactNativeHosting/DefaultViews.swift +138 -0
- package/ios/ReactNativeHosting/GraniteDefaultModuleProvider.h +24 -0
- package/ios/ReactNativeHosting/GraniteDefaultModuleProvider.mm +22 -0
- package/ios/ReactNativeHosting/GraniteHostingHelper.swift +103 -0
- package/ios/ReactNativeHosting/GraniteNativeFactory.swift +35 -0
- package/ios/ReactNativeHosting/GraniteNativeFactoryDelegateImpl.swift +30 -0
- package/ios/ReactNativeHosting/GraniteNativeFactoryImpl.swift +24 -0
- package/ios/ReactNativeHosting/GraniteReactHost.swift +39 -0
- package/ios/ReactNativeHosting/GraniteScreen-Bridging-Header.h +12 -0
- package/package.json +59 -0
- package/react-native.config.js +8 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
package run.granite.gradle.fixtures
|
|
2
|
+
|
|
3
|
+
import run.granite.gradle.models.NativeModule
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Test fixtures for NativeModule instances.
|
|
7
|
+
* Used for testing autolinking generation with various module configurations.
|
|
8
|
+
*/
|
|
9
|
+
object NativeModuleFixtures {
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Creates a module with includesGeneratedCode: true.
|
|
13
|
+
*
|
|
14
|
+
* This represents the brick-module package with:
|
|
15
|
+
* - libraryName: "BrickModuleSpec" (from package.json codegenConfig)
|
|
16
|
+
* - Java TurboModule implementation
|
|
17
|
+
* - No C++ implementation (Java only)
|
|
18
|
+
* - PackageList integration
|
|
19
|
+
* - includesGeneratedCode: true (uses brick-codegen instead of react-native-codegen)
|
|
20
|
+
*/
|
|
21
|
+
fun createModuleWithCustomCodegen(): NativeModule = NativeModule(
|
|
22
|
+
name = "custom-codegen-module",
|
|
23
|
+
packageImportPath = "com.example.CustomCodegenPackage",
|
|
24
|
+
packageInstance = "new CustomCodegenPackage()",
|
|
25
|
+
dependencyConfiguration = null,
|
|
26
|
+
buildTypes = emptyList(),
|
|
27
|
+
libraryName = "CustomCodegenSpec",
|
|
28
|
+
componentDescriptors = emptyList(),
|
|
29
|
+
cmakeListsPath = "node_modules/custom-codegen-module/android/build/generated/source/codegen/jni/CMakeLists.txt",
|
|
30
|
+
cxxModuleCMakeListsPath = null,
|
|
31
|
+
cxxModuleCMakeListsModuleName = null,
|
|
32
|
+
cxxModuleHeaderName = null,
|
|
33
|
+
isPureCxxDependency = false,
|
|
34
|
+
includesGeneratedCode = true, // brick-module uses brick-codegen
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Creates a standard module that uses react-native-codegen.
|
|
39
|
+
*
|
|
40
|
+
* This represents a typical React Native module that should be included in autolinking.
|
|
41
|
+
*/
|
|
42
|
+
fun createStandardModule(): NativeModule = NativeModule(
|
|
43
|
+
name = "react-native-example",
|
|
44
|
+
packageImportPath = "com.example.ExamplePackage",
|
|
45
|
+
packageInstance = "new ExamplePackage()",
|
|
46
|
+
dependencyConfiguration = null,
|
|
47
|
+
buildTypes = emptyList(),
|
|
48
|
+
libraryName = "ExampleSpec",
|
|
49
|
+
componentDescriptors = emptyList(),
|
|
50
|
+
cmakeListsPath = "node_modules/react-native-example/android/build/generated/source/codegen/jni/CMakeLists.txt",
|
|
51
|
+
cxxModuleCMakeListsPath = null,
|
|
52
|
+
cxxModuleCMakeListsModuleName = null,
|
|
53
|
+
cxxModuleHeaderName = null,
|
|
54
|
+
isPureCxxDependency = false,
|
|
55
|
+
includesGeneratedCode = false,
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Creates a list with both standard and custom codegen modules.
|
|
60
|
+
*
|
|
61
|
+
* Useful for testing filtering behavior.
|
|
62
|
+
*/
|
|
63
|
+
fun createMixedModules(): List<NativeModule> = listOf(
|
|
64
|
+
createModuleWithCustomCodegen(),
|
|
65
|
+
createStandardModule(),
|
|
66
|
+
)
|
|
67
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
package run.granite.gradle.generators
|
|
2
|
+
|
|
3
|
+
import org.assertj.core.api.Assertions.assertThat
|
|
4
|
+
import org.junit.jupiter.api.Test
|
|
5
|
+
import org.junit.jupiter.api.io.TempDir
|
|
6
|
+
import run.granite.gradle.models.NativeModule
|
|
7
|
+
import java.io.File
|
|
8
|
+
|
|
9
|
+
class CMakeGeneratorTest {
|
|
10
|
+
|
|
11
|
+
@TempDir
|
|
12
|
+
lateinit var tempDir: File
|
|
13
|
+
|
|
14
|
+
@Test
|
|
15
|
+
fun `generate with CMake modules creates REACTNATIVE_MERGED_SO and add_subdirectory commands`() {
|
|
16
|
+
// Create actual directory for the test
|
|
17
|
+
val androidDir = File(tempDir, "android")
|
|
18
|
+
androidDir.mkdirs()
|
|
19
|
+
|
|
20
|
+
val module = createModuleWithCMake("test-module", "TestLib", "android/CMakeLists.txt")
|
|
21
|
+
|
|
22
|
+
val generated = CMakeGenerator.generate(listOf(module), tempDir)
|
|
23
|
+
|
|
24
|
+
assertThat(generated).contains("set(REACTNATIVE_MERGED_SO true)")
|
|
25
|
+
assertThat(generated).contains("add_subdirectory(")
|
|
26
|
+
assertThat(generated).contains("TestLib_autolinked_build")
|
|
27
|
+
assertThat(generated).contains("set(AUTOLINKED_LIBRARIES")
|
|
28
|
+
assertThat(generated).contains("react_codegen_TestLib")
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@Test
|
|
32
|
+
fun `generate with no CMake modules creates empty file`() {
|
|
33
|
+
val module = createJavaOnlyModule()
|
|
34
|
+
|
|
35
|
+
val generated = CMakeGenerator.generate(listOf(module), tempDir)
|
|
36
|
+
|
|
37
|
+
assertThat(generated).contains("# No native modules with CMake configuration found")
|
|
38
|
+
assertThat(generated).contains("set(REACTNATIVE_MERGED_SO true)")
|
|
39
|
+
assertThat(generated).contains("set(AUTOLINKED_LIBRARIES)")
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
private fun createModuleWithCMake(name: String, libraryName: String, cmakePath: String): NativeModule = NativeModule(
|
|
43
|
+
name = name,
|
|
44
|
+
packageImportPath = null,
|
|
45
|
+
packageInstance = null,
|
|
46
|
+
dependencyConfiguration = null,
|
|
47
|
+
buildTypes = emptyList(),
|
|
48
|
+
libraryName = libraryName,
|
|
49
|
+
componentDescriptors = emptyList(),
|
|
50
|
+
cmakeListsPath = cmakePath,
|
|
51
|
+
cxxModuleCMakeListsPath = null,
|
|
52
|
+
cxxModuleCMakeListsModuleName = null,
|
|
53
|
+
cxxModuleHeaderName = null,
|
|
54
|
+
isPureCxxDependency = false,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
private fun createJavaOnlyModule(): NativeModule = NativeModule(
|
|
58
|
+
name = "java-module",
|
|
59
|
+
packageImportPath = "com.example.Package",
|
|
60
|
+
packageInstance = "new Package()",
|
|
61
|
+
dependencyConfiguration = null,
|
|
62
|
+
buildTypes = emptyList(),
|
|
63
|
+
libraryName = "JavaLib",
|
|
64
|
+
componentDescriptors = emptyList(),
|
|
65
|
+
cmakeListsPath = null,
|
|
66
|
+
cxxModuleCMakeListsPath = null,
|
|
67
|
+
cxxModuleCMakeListsModuleName = null,
|
|
68
|
+
cxxModuleHeaderName = null,
|
|
69
|
+
isPureCxxDependency = false,
|
|
70
|
+
)
|
|
71
|
+
}
|
package/gradle-plugin/src/test/kotlin/run/granite/gradle/generators/CppAutolinkingGeneratorTest.kt
ADDED
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
package run.granite.gradle.generators
|
|
2
|
+
|
|
3
|
+
import org.assertj.core.api.Assertions.assertThat
|
|
4
|
+
import org.junit.jupiter.api.Test
|
|
5
|
+
import run.granite.gradle.fixtures.NativeModuleFixtures
|
|
6
|
+
import run.granite.gradle.models.NativeModule
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Unit tests for CppAutolinkingGenerator core generation logic.
|
|
10
|
+
* Tests C++ code generation with various module configurations.
|
|
11
|
+
*/
|
|
12
|
+
class CppAutolinkingGeneratorTest {
|
|
13
|
+
|
|
14
|
+
@Test
|
|
15
|
+
fun `generate with no modules creates empty implementations`() {
|
|
16
|
+
val modules = emptyList<NativeModule>()
|
|
17
|
+
|
|
18
|
+
val generated = CppAutolinkingGenerator.generate(modules)
|
|
19
|
+
|
|
20
|
+
// Should contain auto-generated comment
|
|
21
|
+
assertThat(generated).contains("Generated by Granite Gradle Plugin - DO NOT EDIT")
|
|
22
|
+
|
|
23
|
+
// Should include autolinking.h
|
|
24
|
+
assertThat(generated).contains("#include <autolinking.h>")
|
|
25
|
+
|
|
26
|
+
// Should have namespace
|
|
27
|
+
assertThat(generated).contains("namespace facebook::react {")
|
|
28
|
+
|
|
29
|
+
// Should have registerProviders with "no Fabric components" comment
|
|
30
|
+
assertThat(generated).contains("void autolinking_registerProviders(")
|
|
31
|
+
assertThat(generated).contains("// No autolinked Fabric components found")
|
|
32
|
+
|
|
33
|
+
// Should have cxxModuleProvider returning nullptr
|
|
34
|
+
assertThat(generated).contains("std::shared_ptr<TurboModule> autolinking_cxxModuleProvider(")
|
|
35
|
+
assertThat(generated).contains("// No autolinked C++ TurboModules found")
|
|
36
|
+
assertThat(generated).contains("return nullptr;")
|
|
37
|
+
|
|
38
|
+
// Should have ModuleProvider returning nullptr
|
|
39
|
+
assertThat(generated).contains("std::shared_ptr<TurboModule> autolinking_ModuleProvider(")
|
|
40
|
+
assertThat(generated).contains("// No autolinked Java TurboModules found")
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@Test
|
|
44
|
+
fun `generate with Java-only module includes module provider call`() {
|
|
45
|
+
val modules = listOf(
|
|
46
|
+
NativeModule(
|
|
47
|
+
name = "react-native-webview",
|
|
48
|
+
packageImportPath = "com.example.Package",
|
|
49
|
+
packageInstance = "new Package()",
|
|
50
|
+
dependencyConfiguration = null,
|
|
51
|
+
buildTypes = emptyList(),
|
|
52
|
+
libraryName = "RNCWebView",
|
|
53
|
+
componentDescriptors = emptyList(),
|
|
54
|
+
cmakeListsPath = null,
|
|
55
|
+
cxxModuleCMakeListsPath = null,
|
|
56
|
+
cxxModuleCMakeListsModuleName = null,
|
|
57
|
+
cxxModuleHeaderName = null,
|
|
58
|
+
isPureCxxDependency = false,
|
|
59
|
+
),
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
val generated = CppAutolinkingGenerator.generate(modules)
|
|
63
|
+
|
|
64
|
+
// Should have Java module provider call
|
|
65
|
+
assertThat(generated).contains("auto module_react_native_webview = RNCWebView_ModuleProvider(moduleName, params);")
|
|
66
|
+
assertThat(generated).contains("if (module_react_native_webview != nullptr) {")
|
|
67
|
+
assertThat(generated).contains("return module_react_native_webview;")
|
|
68
|
+
|
|
69
|
+
// Should not have C++ module headers or checks
|
|
70
|
+
assertThat(generated).doesNotContain("// C++ TurboModule headers")
|
|
71
|
+
assertThat(generated).contains("// No autolinked C++ TurboModules found")
|
|
72
|
+
|
|
73
|
+
// Should have "no Fabric components" comment
|
|
74
|
+
assertThat(generated).contains("// No autolinked Fabric components found")
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
@Test
|
|
78
|
+
fun `generate with C++ module includes header and provider check`() {
|
|
79
|
+
val modules = listOf(
|
|
80
|
+
NativeModule(
|
|
81
|
+
name = "cxx-module",
|
|
82
|
+
packageImportPath = null,
|
|
83
|
+
packageInstance = null,
|
|
84
|
+
dependencyConfiguration = null,
|
|
85
|
+
buildTypes = emptyList(),
|
|
86
|
+
libraryName = "CxxModule",
|
|
87
|
+
componentDescriptors = emptyList(),
|
|
88
|
+
cmakeListsPath = null,
|
|
89
|
+
cxxModuleCMakeListsPath = null,
|
|
90
|
+
cxxModuleCMakeListsModuleName = null,
|
|
91
|
+
cxxModuleHeaderName = "CxxModule",
|
|
92
|
+
isPureCxxDependency = true,
|
|
93
|
+
),
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
val generated = CppAutolinkingGenerator.generate(modules)
|
|
97
|
+
|
|
98
|
+
// Should include C++ module header
|
|
99
|
+
assertThat(generated).contains("// C++ TurboModule headers")
|
|
100
|
+
assertThat(generated).contains("#include <CxxModule.h>")
|
|
101
|
+
|
|
102
|
+
// Should have C++ module provider check
|
|
103
|
+
assertThat(generated).contains("// Check C++ TurboModules (early-return pattern)")
|
|
104
|
+
assertThat(generated).contains("if (moduleName == CxxModule::kModuleName) {")
|
|
105
|
+
assertThat(generated).contains("return std::make_shared<CxxModule>(jsInvoker);")
|
|
106
|
+
|
|
107
|
+
// Should not have Java module provider
|
|
108
|
+
assertThat(generated).contains("// No autolinked Java TurboModules found")
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
@Test
|
|
112
|
+
fun `generate with Fabric module includes component descriptor header and registration`() {
|
|
113
|
+
val modules = listOf(
|
|
114
|
+
NativeModule(
|
|
115
|
+
name = "fabric-module",
|
|
116
|
+
packageImportPath = null,
|
|
117
|
+
packageInstance = null,
|
|
118
|
+
dependencyConfiguration = null,
|
|
119
|
+
buildTypes = emptyList(),
|
|
120
|
+
libraryName = "FabricModule",
|
|
121
|
+
componentDescriptors = listOf("MyComponentDescriptor", "AnotherComponentDescriptor"),
|
|
122
|
+
cmakeListsPath = null,
|
|
123
|
+
cxxModuleCMakeListsPath = null,
|
|
124
|
+
cxxModuleCMakeListsModuleName = null,
|
|
125
|
+
cxxModuleHeaderName = null,
|
|
126
|
+
isPureCxxDependency = false,
|
|
127
|
+
),
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
val generated = CppAutolinkingGenerator.generate(modules)
|
|
131
|
+
|
|
132
|
+
// Should include Fabric headers
|
|
133
|
+
assertThat(generated).contains("// Fabric component descriptor headers")
|
|
134
|
+
assertThat(generated).contains("<react/renderer/components/FabricModule/ComponentDescriptors.h>")
|
|
135
|
+
assertThat(generated).contains("<react/renderer/components/FabricModule/MyComponentDescriptor.h>")
|
|
136
|
+
|
|
137
|
+
// Should register codegen components + custom component descriptors
|
|
138
|
+
assertThat(generated).contains("FabricModule_registerComponentDescriptorsFromCodegen(registry);")
|
|
139
|
+
assertThat(generated).contains("registry->add(concreteComponentDescriptorProvider<MyComponentDescriptor>());")
|
|
140
|
+
assertThat(generated).contains("registry->add(concreteComponentDescriptorProvider<AnotherComponentDescriptor>());")
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
@Test
|
|
144
|
+
fun `generate with mixed modules includes TurboModule providers and Fabric registration`() {
|
|
145
|
+
// Handle modules with both Java and C++ implementations
|
|
146
|
+
val modules = listOf(
|
|
147
|
+
createJavaModule("java-module", "JavaLib"),
|
|
148
|
+
createCxxModule("cxx-module", "CxxLib", "CxxModule"),
|
|
149
|
+
createFabricModule("fabric-module", "FabricLib", listOf("FabricComponent")),
|
|
150
|
+
createMixedModule("mixed-module", "MixedLib", "MixedModule", listOf("MixedComponent")),
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
val generated = CppAutolinkingGenerator.generate(modules)
|
|
154
|
+
|
|
155
|
+
// Should have C++ TurboModule headers
|
|
156
|
+
assertThat(generated).contains("// C++ TurboModule headers")
|
|
157
|
+
|
|
158
|
+
// Should have Fabric component headers or registration
|
|
159
|
+
assertThat(generated).contains("// Fabric component descriptor headers")
|
|
160
|
+
assertThat(generated).contains("registry->add(concreteComponentDescriptorProvider<FabricComponent>());")
|
|
161
|
+
assertThat(generated).contains("registry->add(concreteComponentDescriptorProvider<MixedComponent>());")
|
|
162
|
+
|
|
163
|
+
// Should have C++ provider checks
|
|
164
|
+
assertThat(generated).contains("if (moduleName == CxxModule::kModuleName) {")
|
|
165
|
+
assertThat(generated).contains("if (moduleName == MixedModule::kModuleName) {")
|
|
166
|
+
|
|
167
|
+
// Should have Java provider calls
|
|
168
|
+
assertThat(generated).contains("auto module_java_module = JavaLib_ModuleProvider(moduleName, params);")
|
|
169
|
+
assertThat(generated).contains("auto module_mixed_module = MixedLib_ModuleProvider(moduleName, params);")
|
|
170
|
+
assertThat(generated).contains("FabricLib_registerComponentDescriptorsFromCodegen(registry);")
|
|
171
|
+
assertThat(generated).contains("MixedLib_registerComponentDescriptorsFromCodegen(registry);")
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
@Test
|
|
175
|
+
fun `generate uses sanitized names for variables`() {
|
|
176
|
+
// C++ identifier sanitization
|
|
177
|
+
val modules = listOf(
|
|
178
|
+
NativeModule(
|
|
179
|
+
name = "module-with-hyphens",
|
|
180
|
+
packageImportPath = "com.example.Package",
|
|
181
|
+
packageInstance = "new Package()",
|
|
182
|
+
dependencyConfiguration = null,
|
|
183
|
+
buildTypes = emptyList(),
|
|
184
|
+
libraryName = "ModuleLib",
|
|
185
|
+
componentDescriptors = emptyList(),
|
|
186
|
+
cmakeListsPath = null,
|
|
187
|
+
cxxModuleCMakeListsPath = null,
|
|
188
|
+
cxxModuleCMakeListsModuleName = null,
|
|
189
|
+
cxxModuleHeaderName = null,
|
|
190
|
+
isPureCxxDependency = false,
|
|
191
|
+
),
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
val generated = CppAutolinkingGenerator.generate(modules)
|
|
195
|
+
|
|
196
|
+
// Should use sanitized name (hyphens -> underscores)
|
|
197
|
+
assertThat(generated).contains("auto module_module_with_hyphens = ModuleLib_ModuleProvider(moduleName, params);")
|
|
198
|
+
assertThat(generated).contains("if (module_module_with_hyphens != nullptr) {")
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
@Test
|
|
202
|
+
fun `generate follows early-return pattern for multiple Java modules`() {
|
|
203
|
+
// Early-return pattern
|
|
204
|
+
val modules = listOf(
|
|
205
|
+
createJavaModule("module1", "Lib1"),
|
|
206
|
+
createJavaModule("module2", "Lib2"),
|
|
207
|
+
createJavaModule("module3", "Lib3"),
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
val generated = CppAutolinkingGenerator.generate(modules)
|
|
211
|
+
|
|
212
|
+
// Should check each module and return early if found
|
|
213
|
+
assertThat(generated).contains("auto module_module1 = Lib1_ModuleProvider(moduleName, params);")
|
|
214
|
+
assertThat(generated).contains("if (module_module1 != nullptr) {")
|
|
215
|
+
assertThat(generated).contains("return module_module1;")
|
|
216
|
+
|
|
217
|
+
assertThat(generated).contains("auto module_module2 = Lib2_ModuleProvider(moduleName, params);")
|
|
218
|
+
assertThat(generated).contains("if (module_module2 != nullptr) {")
|
|
219
|
+
assertThat(generated).contains("return module_module2;")
|
|
220
|
+
|
|
221
|
+
assertThat(generated).contains("auto module_module3 = Lib3_ModuleProvider(moduleName, params);")
|
|
222
|
+
|
|
223
|
+
// Should return nullptr at the end
|
|
224
|
+
val lines = generated.lines()
|
|
225
|
+
val returnNullptrIndex = lines.indexOfLast { it.contains("return nullptr;") }
|
|
226
|
+
assertThat(returnNullptrIndex).isGreaterThan(-1)
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
@Test
|
|
230
|
+
fun `generate follows early-return pattern for multiple C++ modules`() {
|
|
231
|
+
// Early-return pattern
|
|
232
|
+
val modules = listOf(
|
|
233
|
+
createCxxModule("module1", "Lib1", "Module1"),
|
|
234
|
+
createCxxModule("module2", "Lib2", "Module2"),
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
val generated = CppAutolinkingGenerator.generate(modules)
|
|
238
|
+
|
|
239
|
+
// Should check each module and return early if found
|
|
240
|
+
assertThat(generated).contains("if (moduleName == Module1::kModuleName) {")
|
|
241
|
+
assertThat(generated).contains("return std::make_shared<Module1>(jsInvoker);")
|
|
242
|
+
|
|
243
|
+
assertThat(generated).contains("if (moduleName == Module2::kModuleName) {")
|
|
244
|
+
assertThat(generated).contains("return std::make_shared<Module2>(jsInvoker);")
|
|
245
|
+
|
|
246
|
+
// Should return nullptr at the end
|
|
247
|
+
assertThat(generated).contains("return nullptr;")
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
@Test
|
|
251
|
+
fun `generate closes namespace correctly`() {
|
|
252
|
+
val modules = emptyList<NativeModule>()
|
|
253
|
+
|
|
254
|
+
val generated = CppAutolinkingGenerator.generate(modules)
|
|
255
|
+
|
|
256
|
+
assertThat(generated).contains("} // namespace facebook::react")
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
@Test
|
|
260
|
+
fun `generate includes modules with includesGeneratedCode flag`() {
|
|
261
|
+
// includesGeneratedCode indicates the library ships generated files; it should still be autolinked.
|
|
262
|
+
val modules = listOf(NativeModuleFixtures.createModuleWithCustomCodegen())
|
|
263
|
+
|
|
264
|
+
val generated = CppAutolinkingGenerator.generate(modules)
|
|
265
|
+
|
|
266
|
+
// Should call *_ModuleProvider for the module
|
|
267
|
+
assertThat(generated).contains("CustomCodegenSpec_ModuleProvider")
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
@Test
|
|
271
|
+
fun `generate includes standard modules and includesGeneratedCode modules`() {
|
|
272
|
+
// Mixed list: one standard module, one that ships generated code
|
|
273
|
+
val modules = NativeModuleFixtures.createMixedModules()
|
|
274
|
+
|
|
275
|
+
val generated = CppAutolinkingGenerator.generate(modules)
|
|
276
|
+
|
|
277
|
+
// Standard module should be included
|
|
278
|
+
assertThat(generated).contains("ExampleSpec_ModuleProvider")
|
|
279
|
+
|
|
280
|
+
// includesGeneratedCode module should also be included
|
|
281
|
+
assertThat(generated).contains("CustomCodegenSpec_ModuleProvider")
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// Helper methods for creating test modules
|
|
285
|
+
private fun createJavaModule(name: String, libraryName: String): NativeModule = NativeModule(
|
|
286
|
+
name = name,
|
|
287
|
+
packageImportPath = "com.example.$name.Package",
|
|
288
|
+
packageInstance = "new Package()",
|
|
289
|
+
dependencyConfiguration = null,
|
|
290
|
+
buildTypes = emptyList(),
|
|
291
|
+
libraryName = libraryName,
|
|
292
|
+
componentDescriptors = emptyList(),
|
|
293
|
+
cmakeListsPath = null,
|
|
294
|
+
cxxModuleCMakeListsPath = null,
|
|
295
|
+
cxxModuleCMakeListsModuleName = null,
|
|
296
|
+
cxxModuleHeaderName = null,
|
|
297
|
+
isPureCxxDependency = false,
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
private fun createCxxModule(name: String, libraryName: String, headerName: String): NativeModule = NativeModule(
|
|
301
|
+
name = name,
|
|
302
|
+
packageImportPath = null,
|
|
303
|
+
packageInstance = null,
|
|
304
|
+
dependencyConfiguration = null,
|
|
305
|
+
buildTypes = emptyList(),
|
|
306
|
+
libraryName = libraryName,
|
|
307
|
+
componentDescriptors = emptyList(),
|
|
308
|
+
cmakeListsPath = null,
|
|
309
|
+
cxxModuleCMakeListsPath = null,
|
|
310
|
+
cxxModuleCMakeListsModuleName = null,
|
|
311
|
+
cxxModuleHeaderName = headerName,
|
|
312
|
+
isPureCxxDependency = true,
|
|
313
|
+
)
|
|
314
|
+
|
|
315
|
+
private fun createFabricModule(name: String, libraryName: String, descriptors: List<String>): NativeModule = NativeModule(
|
|
316
|
+
name = name,
|
|
317
|
+
packageImportPath = null,
|
|
318
|
+
packageInstance = null,
|
|
319
|
+
dependencyConfiguration = null,
|
|
320
|
+
buildTypes = emptyList(),
|
|
321
|
+
libraryName = libraryName,
|
|
322
|
+
componentDescriptors = descriptors,
|
|
323
|
+
cmakeListsPath = null,
|
|
324
|
+
cxxModuleCMakeListsPath = null,
|
|
325
|
+
cxxModuleCMakeListsModuleName = null,
|
|
326
|
+
cxxModuleHeaderName = null,
|
|
327
|
+
isPureCxxDependency = false,
|
|
328
|
+
)
|
|
329
|
+
|
|
330
|
+
private fun createMixedModule(name: String, libraryName: String, headerName: String, descriptors: List<String>): NativeModule = NativeModule(
|
|
331
|
+
name = name,
|
|
332
|
+
packageImportPath = "com.example.$name.Package",
|
|
333
|
+
packageInstance = "new Package()",
|
|
334
|
+
dependencyConfiguration = null,
|
|
335
|
+
buildTypes = emptyList(),
|
|
336
|
+
libraryName = libraryName,
|
|
337
|
+
componentDescriptors = descriptors,
|
|
338
|
+
cmakeListsPath = null,
|
|
339
|
+
cxxModuleCMakeListsPath = null,
|
|
340
|
+
cxxModuleCMakeListsModuleName = null,
|
|
341
|
+
cxxModuleHeaderName = headerName,
|
|
342
|
+
isPureCxxDependency = false,
|
|
343
|
+
)
|
|
344
|
+
}
|
package/gradle-plugin/src/test/kotlin/run/granite/gradle/generators/EntryPointGeneratorTest.kt
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
package run.granite.gradle.generators
|
|
2
|
+
|
|
3
|
+
import org.assertj.core.api.Assertions.assertThat
|
|
4
|
+
import org.assertj.core.api.Assertions.assertThatThrownBy
|
|
5
|
+
import org.junit.jupiter.api.Test
|
|
6
|
+
|
|
7
|
+
class EntryPointGeneratorTest {
|
|
8
|
+
|
|
9
|
+
@Test
|
|
10
|
+
fun `generate creates ReactNativeApplicationEntryPoint class with loadReactNative method`() {
|
|
11
|
+
val generated = EntryPointGenerator.generate("com.example.test")
|
|
12
|
+
|
|
13
|
+
assertThat(generated).contains("package com.facebook.react")
|
|
14
|
+
assertThat(generated).contains("public class ReactNativeApplicationEntryPoint")
|
|
15
|
+
assertThat(generated).contains("public static void loadReactNative(Context context)")
|
|
16
|
+
assertThat(generated).contains("SoLoader.init(context, OpenSourceMergedSoMapping.INSTANCE)")
|
|
17
|
+
assertThat(generated).contains("if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED)")
|
|
18
|
+
assertThat(generated).contains("DefaultNewArchitectureEntryPoint.load()")
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@Test
|
|
22
|
+
fun `generate throws IllegalArgumentException when packageName is null`() {
|
|
23
|
+
assertThatThrownBy {
|
|
24
|
+
EntryPointGenerator.generate(null)
|
|
25
|
+
}
|
|
26
|
+
.isInstanceOf(IllegalArgumentException::class.java)
|
|
27
|
+
.hasMessageContaining("Android package name not found")
|
|
28
|
+
.hasMessageContaining("Ensure project has valid android configuration")
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@Test
|
|
32
|
+
fun `generate includes RuntimeException handling for SoLoader failure`() {
|
|
33
|
+
val generated = EntryPointGenerator.generate("com.example.test")
|
|
34
|
+
|
|
35
|
+
assertThat(generated).contains("try {")
|
|
36
|
+
assertThat(generated).contains("SoLoader.init")
|
|
37
|
+
assertThat(generated).contains("} catch (Exception e) {")
|
|
38
|
+
assertThat(generated).contains("throw new RuntimeException(\"Failed to initialize SoLoader\", e)")
|
|
39
|
+
}
|
|
40
|
+
}
|