@callstack/react-native-brownfield 3.12.0 → 3.13.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 +15 -0
- package/gradle-plugin/brownfield/build.gradle.kts +134 -0
- package/gradle-plugin/brownfield/config/detekt/detekt.yml +936 -0
- package/gradle-plugin/brownfield/gradle/libs.versions.toml +19 -0
- package/gradle-plugin/brownfield/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/gradle-plugin/brownfield/gradle/wrapper/gradle-wrapper.properties +7 -0
- package/gradle-plugin/brownfield/gradle.properties +14 -0
- package/gradle-plugin/brownfield/gradlew +249 -0
- package/gradle-plugin/brownfield/gradlew.bat +92 -0
- package/gradle-plugin/brownfield/settings.gradle +7 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/ArtifactsResolver.kt +132 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/exceptions/NameSpaceNotFound.kt +4 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/exceptions/TaskNotFound.kt +4 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/expo/ExpoPublishingHelper.kt +432 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/expo/utils/BrownfieldPrimitives.kt +31 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/expo/utils/ExpoProjectionPrimitives.kt +22 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/expo/utils/LocalMavenUtils.kt +83 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/expo/utils/ReflectionUtils.kt +79 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/expo/utils/VersionMediatingDependencySet.kt +100 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/CustomDependencyResolver.kt +50 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/ProjectConfigurations.kt +107 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RClassTransformer.kt +131 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt +171 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNSourceSets.kt +149 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/AssetTaskProcessor.kt +29 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ExplodeTaskProvider.kt +63 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/JNILibsProcessor.kt +165 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ManifestTaskProcessor.kt +74 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/MergeProcessor.kt +55 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ProguardProcessor.kt +61 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ResourceTaskProcessor.kt +26 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantHelper.kt +61 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantPackagesProperty.kt +21 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantTaskProvider.kt +103 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/BaseProject.kt +17 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/BundleTaskProvider.kt +46 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/Constants.kt +58 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ExplodeAarTask.kt +72 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/GradleILogger.kt +59 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/Logging.kt +24 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ModuleInfo.kt +22 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/AndroidArchiveLibrary.kt +77 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/DirectoryManager.kt +20 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/Extension.kt +44 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/StringExtensions.kt +5 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/StringMatcher.kt +21 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/Utils.kt +59 -0
- package/ios/Expo/ExpoHostRuntime.swift +3 -2
- package/ios/ReactNativeBrownfield.swift +1 -1
- package/ios/Vanilla/ReactNativeHostRuntime.swift +5 -2
- package/ios/swiftpm/Sources/BrownfieldBundleSupport/BrownfieldBundleURLResolver.swift +11 -5
- package/ios/swiftpm/Tests/BrownfieldBundleSupportTests/BrownfieldBundleURLResolverTests.swift +17 -5
- package/lib/commonjs/expo-config-plugin/ios/xcodeHelpers.js +2 -1
- package/lib/commonjs/expo-config-plugin/ios/xcodeHelpers.js.map +1 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/expo-config-plugin/ios/xcodeHelpers.js +2 -1
- package/lib/module/expo-config-plugin/ios/xcodeHelpers.js.map +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/commonjs/src/expo-config-plugin/ios/xcodeHelpers.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/index.d.ts +1 -0
- package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
- package/lib/typescript/module/src/expo-config-plugin/ios/xcodeHelpers.d.ts.map +1 -1
- package/lib/typescript/module/src/index.d.ts +1 -0
- package/lib/typescript/module/src/index.d.ts.map +1 -1
- package/package.json +6 -4
- package/scripts/sync-gradle-plugin-source.js +58 -0
- package/src/expo-config-plugin/ios/xcodeHelpers.ts +14 -0
- package/src/index.ts +2 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
package com.callstack.react.brownfield.expo.utils
|
|
2
|
+
|
|
3
|
+
import io.github.g00fy2.versioncompare.Version
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A set that stores DependencyInfo objects based only on their groupId and artifactId.
|
|
7
|
+
* When adding a new dependency with the same groupId and artifactId,
|
|
8
|
+
* it compares the versions and keeps the one with the higher version.
|
|
9
|
+
*/
|
|
10
|
+
open class VersionMediatingDependencySet : Iterable<DependencyInfo> {
|
|
11
|
+
private var backingMap =
|
|
12
|
+
mutableMapOf<Pair<String, String>, DependencyInfo>()
|
|
13
|
+
|
|
14
|
+
val size: Int get() = backingMap.size
|
|
15
|
+
|
|
16
|
+
fun contains(element: DependencyInfo): Boolean {
|
|
17
|
+
return backingMap.containsKey(element.groupId to element.artifactId)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
fun add(element: DependencyInfo): Boolean {
|
|
21
|
+
val key = element.groupId to element.artifactId
|
|
22
|
+
val existing = backingMap[key]
|
|
23
|
+
|
|
24
|
+
if (existing == null) {
|
|
25
|
+
backingMap[key] = element
|
|
26
|
+
return true
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// compare versions - replace if new version is greater (behavior of Gradle itself)
|
|
30
|
+
val existingVersion = existing.version
|
|
31
|
+
val newVersion = element.version
|
|
32
|
+
|
|
33
|
+
if (newVersion != null && (
|
|
34
|
+
existingVersion == null || compareVersions(
|
|
35
|
+
newVersion,
|
|
36
|
+
existingVersion,
|
|
37
|
+
) > 0
|
|
38
|
+
)
|
|
39
|
+
) {
|
|
40
|
+
backingMap[key] = element
|
|
41
|
+
return true
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return false
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
fun forEach(action: (DependencyInfo) -> Unit) {
|
|
48
|
+
backingMap.values.forEach(action)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
fun filter(predicate: (DependencyInfo) -> Boolean): VersionMediatingDependencySet {
|
|
52
|
+
backingMap =
|
|
53
|
+
backingMap.filter {
|
|
54
|
+
predicate(it.value)
|
|
55
|
+
}.toMutableMap()
|
|
56
|
+
|
|
57
|
+
return this
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
fun addAll(elements: Iterable<DependencyInfo>): Boolean {
|
|
61
|
+
var modified = false
|
|
62
|
+
elements.forEach { if (add(it)) modified = true }
|
|
63
|
+
return modified
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
fun removeAll(predicate: (it: DependencyInfo) -> Boolean): List<DependencyInfo?> {
|
|
67
|
+
val keysToBeRemoved = mutableSetOf<Pair<String, String>>()
|
|
68
|
+
|
|
69
|
+
forEach {
|
|
70
|
+
if (predicate(it)) {
|
|
71
|
+
keysToBeRemoved.add(it.groupId to it.artifactId)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return keysToBeRemoved.map {
|
|
76
|
+
backingMap.remove(it)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
private fun compareVersions(
|
|
81
|
+
version1: String,
|
|
82
|
+
version2: String,
|
|
83
|
+
): Int {
|
|
84
|
+
return Version(version1).compareTo(Version(version2))
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
override fun iterator(): Iterator<DependencyInfo> {
|
|
88
|
+
return backingMap.values.iterator()
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
companion object {
|
|
92
|
+
fun from(source: Iterable<DependencyInfo>): VersionMediatingDependencySet {
|
|
93
|
+
val instance = VersionMediatingDependencySet()
|
|
94
|
+
|
|
95
|
+
instance.addAll(source)
|
|
96
|
+
|
|
97
|
+
return instance
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
package com.callstack.react.brownfield.plugin
|
|
2
|
+
|
|
3
|
+
import org.gradle.api.Project
|
|
4
|
+
import org.gradle.api.artifacts.Configuration
|
|
5
|
+
import org.gradle.api.artifacts.DependencyResolutionListener
|
|
6
|
+
import org.gradle.api.artifacts.ResolvableDependencies
|
|
7
|
+
import org.gradle.api.internal.artifacts.dependencies.DefaultProjectDependency
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The goal of this class is to find the project dependencies
|
|
11
|
+
* either local or remote and link to the Aar for code hints and supports.
|
|
12
|
+
*
|
|
13
|
+
* It does not embed anything to the Aar.
|
|
14
|
+
*/
|
|
15
|
+
class CustomDependencyResolver(
|
|
16
|
+
private val project: Project,
|
|
17
|
+
private val configuration: Configuration,
|
|
18
|
+
) : DependencyResolutionListener {
|
|
19
|
+
private fun getCompileOnlyConfigName(configurationName: String): String {
|
|
20
|
+
val configSuffix = ProjectConfigurations.CONFIG_SUFFIX
|
|
21
|
+
if (configurationName.endsWith(configSuffix)) {
|
|
22
|
+
val configName = configurationName.dropLast(configSuffix.length)
|
|
23
|
+
return "${configName}CompileOnly"
|
|
24
|
+
} else {
|
|
25
|
+
return "compileOnly"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
override fun beforeResolve(dependencies: ResolvableDependencies) {
|
|
30
|
+
val configName = getCompileOnlyConfigName(configuration.name)
|
|
31
|
+
configuration.dependencies.forEach { dependency ->
|
|
32
|
+
if (dependency is DefaultProjectDependency) {
|
|
33
|
+
if (dependency.targetConfiguration == null) {
|
|
34
|
+
dependency.targetConfiguration = "default"
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
val dependencyClone = dependency.copy()
|
|
38
|
+
dependencyClone.targetConfiguration = null
|
|
39
|
+
|
|
40
|
+
project.dependencies.add(configName, dependencyClone)
|
|
41
|
+
} else {
|
|
42
|
+
project.dependencies.add(configName, dependency)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
override fun afterResolve(dependencies: ResolvableDependencies) {
|
|
48
|
+
project.gradle.removeListener(this)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
package com.callstack.react.brownfield.plugin
|
|
2
|
+
|
|
3
|
+
import com.android.build.api.variant.LibraryAndroidComponentsExtension
|
|
4
|
+
import com.android.build.gradle.LibraryExtension
|
|
5
|
+
import com.callstack.react.brownfield.shared.Logging
|
|
6
|
+
import com.callstack.react.brownfield.utils.capitalized
|
|
7
|
+
import org.gradle.api.Project
|
|
8
|
+
import org.gradle.api.artifacts.Configuration
|
|
9
|
+
import org.gradle.api.attributes.Attribute
|
|
10
|
+
import org.gradle.api.attributes.AttributeContainer
|
|
11
|
+
|
|
12
|
+
class ProjectConfigurations(private val project: Project) {
|
|
13
|
+
private val configurations: MutableCollection<Configuration> = mutableListOf()
|
|
14
|
+
|
|
15
|
+
companion object {
|
|
16
|
+
const val CONFIG_NAME = "embed"
|
|
17
|
+
const val CONFIG_SUFFIX = "Embed"
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
fun getConfigurations(): MutableCollection<Configuration> {
|
|
21
|
+
return configurations
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Handles setting up the configuration for the project.
|
|
26
|
+
* It operates in the following manner:
|
|
27
|
+
*
|
|
28
|
+
* 1. creates main config
|
|
29
|
+
* 2. creates configs for buildTypes
|
|
30
|
+
* 3. creates configs for flavours
|
|
31
|
+
* 4. creates configs for flavours with buildTypes
|
|
32
|
+
*/
|
|
33
|
+
fun configure() {
|
|
34
|
+
// create main configuration
|
|
35
|
+
createConfiguration(CONFIG_NAME)
|
|
36
|
+
val androidExtension = project.extensions.getByName("android") as LibraryExtension
|
|
37
|
+
createBuildTypesConfiguration(androidExtension)
|
|
38
|
+
createFlavorConfigurations(androidExtension)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* creates configs for buildTypes
|
|
43
|
+
*/
|
|
44
|
+
private fun createBuildTypesConfiguration(androidExtension: LibraryExtension) {
|
|
45
|
+
androidExtension.buildTypes.all { buildType ->
|
|
46
|
+
createConfiguration(getConfigName(buildType.name))
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* 1. creates configs for flavours
|
|
52
|
+
* 2. creates configs for flavours with buildTypes
|
|
53
|
+
*/
|
|
54
|
+
private fun createFlavorConfigurations(androidExtension: LibraryExtension) {
|
|
55
|
+
androidExtension.productFlavors.all { flavor ->
|
|
56
|
+
createConfiguration(getConfigName(flavor.name))
|
|
57
|
+
|
|
58
|
+
androidExtension.buildTypes.all { buildType ->
|
|
59
|
+
val variantName = "${flavor.name}${buildType.name.capitalized()}"
|
|
60
|
+
createConfiguration(getConfigName(variantName))
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* creates configuration based on `configName`. Also attaches a resolution listener.
|
|
67
|
+
*/
|
|
68
|
+
private fun createConfiguration(configName: String) {
|
|
69
|
+
Logging.log("creating configuration $configName ⌛️")
|
|
70
|
+
val configuration = project.configurations.create(configName)
|
|
71
|
+
|
|
72
|
+
configuration.extendsFrom(project.configurations.getByName("implementation"))
|
|
73
|
+
configuration.isVisible = false
|
|
74
|
+
configuration.isTransitive = false
|
|
75
|
+
|
|
76
|
+
val androidComponents = project.extensions.getByType(LibraryAndroidComponentsExtension::class.java)
|
|
77
|
+
androidComponents.onVariants { variant ->
|
|
78
|
+
|
|
79
|
+
val runtimeAttributes = variant.runtimeConfiguration.attributes
|
|
80
|
+
runtimeAttributes.keySet().forEach { key ->
|
|
81
|
+
copyAttribute(
|
|
82
|
+
key,
|
|
83
|
+
runtimeAttributes,
|
|
84
|
+
configuration.attributes,
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
project.gradle.addListener(CustomDependencyResolver(project, configuration))
|
|
90
|
+
configurations.add(configuration)
|
|
91
|
+
Logging.log("created configuration $configName ✅")
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
private fun <T : Any> copyAttribute(
|
|
95
|
+
key: Attribute<T>,
|
|
96
|
+
from: AttributeContainer,
|
|
97
|
+
into: AttributeContainer,
|
|
98
|
+
) {
|
|
99
|
+
from.getAttribute(key)?.let {
|
|
100
|
+
into.attribute(key, it)
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
private fun getConfigName(prefix: String): String {
|
|
105
|
+
return "${prefix}$CONFIG_SUFFIX"
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
package com.callstack.react.brownfield.plugin
|
|
2
|
+
|
|
3
|
+
import com.android.build.api.instrumentation.AsmClassVisitorFactory
|
|
4
|
+
import com.android.build.api.instrumentation.ClassContext
|
|
5
|
+
import com.android.build.api.instrumentation.ClassData
|
|
6
|
+
import com.android.build.api.instrumentation.FramesComputationMode
|
|
7
|
+
import com.android.build.api.instrumentation.InstrumentationParameters
|
|
8
|
+
import com.android.build.api.instrumentation.InstrumentationScope
|
|
9
|
+
import com.android.build.api.variant.AndroidComponentsExtension
|
|
10
|
+
import com.callstack.react.brownfield.processors.VariantPackagesProperty
|
|
11
|
+
import com.callstack.react.brownfield.shared.BaseProject
|
|
12
|
+
import org.gradle.api.provider.ListProperty
|
|
13
|
+
import org.gradle.api.provider.Property
|
|
14
|
+
import org.gradle.api.tasks.Input
|
|
15
|
+
import org.gradle.api.tasks.Optional
|
|
16
|
+
import org.objectweb.asm.ClassVisitor
|
|
17
|
+
import org.objectweb.asm.commons.ClassRemapper
|
|
18
|
+
import org.objectweb.asm.commons.Remapper
|
|
19
|
+
import java.util.Collections
|
|
20
|
+
import java.util.stream.Collectors
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Transforms R classes of all modules into a single
|
|
24
|
+
* R class. This avoid duplicates issues as each module
|
|
25
|
+
* can have it's own R class, so this redirects all
|
|
26
|
+
* references to a single R class.
|
|
27
|
+
*/
|
|
28
|
+
object RClassTransformer : BaseProject() {
|
|
29
|
+
fun registerASMTransformation() {
|
|
30
|
+
val components = project.extensions.getByType(AndroidComponentsExtension::class.java)
|
|
31
|
+
val variantPackagesProperty = VariantPackagesProperty.getVariantPackagesProperty()
|
|
32
|
+
|
|
33
|
+
components.onVariants(components.selector().all()) { variant ->
|
|
34
|
+
variant.instrumentation.transformClassesWith(
|
|
35
|
+
RClassAsmTransformerFactory::class.java,
|
|
36
|
+
InstrumentationScope.PROJECT,
|
|
37
|
+
) { params ->
|
|
38
|
+
params.namespace.set(variant.namespace)
|
|
39
|
+
params.libraryNamespaces.set(
|
|
40
|
+
variantPackagesProperty.getting(variant.name)
|
|
41
|
+
.map { list -> list.toList() },
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
variant.instrumentation.setAsmFramesComputationMode(FramesComputationMode.COPY_FRAMES)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* transforms R class into bytecode
|
|
51
|
+
*/
|
|
52
|
+
abstract class RClassAsmTransformerFactory :
|
|
53
|
+
AsmClassVisitorFactory<RClassAsmTransformerFactory.Params> {
|
|
54
|
+
interface Params : InstrumentationParameters {
|
|
55
|
+
@get:Input
|
|
56
|
+
val namespace: Property<String>
|
|
57
|
+
|
|
58
|
+
@get:Input
|
|
59
|
+
@get:Optional
|
|
60
|
+
val libraryNamespaces: ListProperty<String>
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Creates a class that remaps R class and its subclasses.
|
|
65
|
+
*/
|
|
66
|
+
override fun createClassVisitor(
|
|
67
|
+
classContext: ClassContext,
|
|
68
|
+
nextClassVisitor: ClassVisitor,
|
|
69
|
+
): ClassVisitor {
|
|
70
|
+
val params = parameters.get()
|
|
71
|
+
val namespace = params.namespace.get()
|
|
72
|
+
val libraryNamespaces = params.libraryNamespaces.orElse(Collections.emptyList()).get()
|
|
73
|
+
|
|
74
|
+
if (libraryNamespaces.isEmpty()) {
|
|
75
|
+
return nextClassVisitor
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return ClassRemapper(nextClassVisitor, getRemapper(libraryNamespaces, namespace))
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
private fun getRemapper(
|
|
82
|
+
libraryNamespaces: List<String>,
|
|
83
|
+
namespace: String,
|
|
84
|
+
): Remapper {
|
|
85
|
+
val formattedNameSpace = namespace.replace(".", "/")
|
|
86
|
+
val targetRClass = "$formattedNameSpace/R"
|
|
87
|
+
val targetRSubclass = "$formattedNameSpace/R$"
|
|
88
|
+
|
|
89
|
+
val libraryRClasses = getLibraryRClasses(libraryNamespaces)
|
|
90
|
+
val libraryRSubclasses = getLibraryRSubclasses(libraryNamespaces)
|
|
91
|
+
|
|
92
|
+
val remapper =
|
|
93
|
+
object : Remapper() {
|
|
94
|
+
override fun map(internalName: String?): String? {
|
|
95
|
+
if (internalName == null) {
|
|
96
|
+
return null
|
|
97
|
+
}
|
|
98
|
+
if (libraryRClasses.contains(internalName)) {
|
|
99
|
+
return targetRClass
|
|
100
|
+
}
|
|
101
|
+
for (libraryRSubclass in libraryRSubclasses) {
|
|
102
|
+
if (internalName.startsWith(libraryRSubclass)) {
|
|
103
|
+
return internalName.replaceFirst(libraryRSubclass, targetRSubclass, false)
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return super.map(internalName)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return remapper
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
private fun getLibraryRClasses(libraryNamespaces: List<String>): Set<String> {
|
|
113
|
+
return libraryNamespaces.stream()
|
|
114
|
+
.map { it.replace(".", "/") + "/R" }
|
|
115
|
+
.collect(Collectors.toSet())
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
private fun getLibraryRSubclasses(libraryNamespaces: List<String>): List<String> {
|
|
119
|
+
return libraryNamespaces.stream()
|
|
120
|
+
.map { it.replace(".", "/") + "/R$" }
|
|
121
|
+
.collect(Collectors.toList())
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Determines if the class can be checked for transformation.
|
|
126
|
+
*/
|
|
127
|
+
override fun isInstrumentable(classData: ClassData): Boolean {
|
|
128
|
+
return true
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
package com.callstack.react.brownfield.plugin
|
|
2
|
+
|
|
3
|
+
import com.android.build.gradle.LibraryExtension
|
|
4
|
+
import com.android.build.gradle.api.LibraryVariant
|
|
5
|
+
import com.callstack.react.brownfield.artifacts.ArtifactsResolver
|
|
6
|
+
import com.callstack.react.brownfield.expo.ExpoPublishingHelper
|
|
7
|
+
import com.callstack.react.brownfield.expo.utils.ExpoGradleProjectProjection
|
|
8
|
+
import com.callstack.react.brownfield.processors.AssetTaskProcessor
|
|
9
|
+
import com.callstack.react.brownfield.processors.ExplodeTaskProvider
|
|
10
|
+
import com.callstack.react.brownfield.processors.JNILibsProcessor
|
|
11
|
+
import com.callstack.react.brownfield.processors.ManifestTaskProcessor
|
|
12
|
+
import com.callstack.react.brownfield.processors.ProguardProcessor
|
|
13
|
+
import com.callstack.react.brownfield.processors.ResourceTaskProcessor
|
|
14
|
+
import com.callstack.react.brownfield.processors.VariantPackagesProperty
|
|
15
|
+
import com.callstack.react.brownfield.processors.VariantTaskProvider
|
|
16
|
+
import com.callstack.react.brownfield.shared.BaseProject
|
|
17
|
+
import com.callstack.react.brownfield.shared.Constants.PROJECT_ID
|
|
18
|
+
import com.callstack.react.brownfield.shared.Logging
|
|
19
|
+
import com.callstack.react.brownfield.shared.UnresolvedArtifactInfo
|
|
20
|
+
import com.callstack.react.brownfield.utils.AndroidArchiveLibrary
|
|
21
|
+
import com.callstack.react.brownfield.utils.DirectoryManager
|
|
22
|
+
import com.callstack.react.brownfield.utils.Extension
|
|
23
|
+
import com.callstack.react.brownfield.utils.Utils
|
|
24
|
+
import org.gradle.api.Plugin
|
|
25
|
+
import org.gradle.api.Project
|
|
26
|
+
import org.gradle.api.ProjectConfigurationException
|
|
27
|
+
|
|
28
|
+
class RNBrownfieldPlugin : Plugin<Project> {
|
|
29
|
+
private lateinit var extension: Extension
|
|
30
|
+
private lateinit var project: Project
|
|
31
|
+
|
|
32
|
+
private val isExpoProject: Boolean
|
|
33
|
+
get() = Utils.isExpoProject(project)
|
|
34
|
+
|
|
35
|
+
override fun apply(project: Project) {
|
|
36
|
+
verifyAndroidPluginApplied(project)
|
|
37
|
+
|
|
38
|
+
this.project = project
|
|
39
|
+
initializers()
|
|
40
|
+
|
|
41
|
+
val projectConfigurations = ProjectConfigurations(project)
|
|
42
|
+
projectConfigurations.configure()
|
|
43
|
+
RNSourceSets.configure(project, extension)
|
|
44
|
+
RClassTransformer.registerASMTransformation()
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Must run before processDefaultDependencies: ArtifactsResolver reads :expo's api configuration,
|
|
48
|
+
* which is only populated after the expo project is evaluated.
|
|
49
|
+
*/
|
|
50
|
+
if (this.isExpoProject) {
|
|
51
|
+
project.evaluationDependsOn(EXPO_PROJECT_LOCATOR)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
var expoProjects = listOf<ExpoGradleProjectProjection>()
|
|
55
|
+
if (this.isExpoProject) {
|
|
56
|
+
val expoPublishingHelper = ExpoPublishingHelper(brownfieldAppProject = project)
|
|
57
|
+
expoProjects = expoPublishingHelper.configure()
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* curates a list of artifacts that we need to bundle with the Aar
|
|
62
|
+
*/
|
|
63
|
+
val artifactsResolver = ArtifactsResolver(project, isExpoProject)
|
|
64
|
+
val artifacts = artifactsResolver.processDefaultDependencies(expoProjects)
|
|
65
|
+
|
|
66
|
+
val variantTaskProvider = VariantTaskProvider(project)
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Configure Tasks
|
|
70
|
+
*/
|
|
71
|
+
project.extensions.getByType(LibraryExtension::class.java).libraryVariants.all { variant ->
|
|
72
|
+
configureTasks(variant, artifacts, variantTaskProvider)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
companion object {
|
|
77
|
+
const val EXPO_PROJECT_LOCATOR = ":expo"
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
private fun initializers() {
|
|
81
|
+
RClassTransformer.project = project
|
|
82
|
+
Logging.project = project
|
|
83
|
+
val baseProject = BaseProject()
|
|
84
|
+
baseProject.project = project
|
|
85
|
+
DirectoryManager.project = project
|
|
86
|
+
|
|
87
|
+
this.extension = project.extensions.create(Extension.NAME, Extension::class.java)
|
|
88
|
+
VariantPackagesProperty.setVariantPackagesProperty(project)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Verifies and throws error if `com.android.library` plugin is not applied
|
|
93
|
+
*/
|
|
94
|
+
private fun verifyAndroidPluginApplied(project: Project) {
|
|
95
|
+
if (!project.plugins.hasPlugin("com.android.library")) {
|
|
96
|
+
throw ProjectConfigurationException(
|
|
97
|
+
"$PROJECT_ID must be applied to an android library project",
|
|
98
|
+
Throwable("Apply $PROJECT_ID"),
|
|
99
|
+
)
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
private fun getAarLibraries(
|
|
104
|
+
artifacts: List<UnresolvedArtifactInfo>,
|
|
105
|
+
variantName: String,
|
|
106
|
+
): List<AndroidArchiveLibrary> {
|
|
107
|
+
val aarLibraries = mutableListOf<AndroidArchiveLibrary>()
|
|
108
|
+
artifacts.forEach { art ->
|
|
109
|
+
val archiveLibrary =
|
|
110
|
+
AndroidArchiveLibrary(
|
|
111
|
+
this.project,
|
|
112
|
+
art,
|
|
113
|
+
variantName,
|
|
114
|
+
)
|
|
115
|
+
aarLibraries.add(archiveLibrary)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return aarLibraries
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
private fun configureTasks(
|
|
122
|
+
variant: LibraryVariant,
|
|
123
|
+
artifacts: List<UnresolvedArtifactInfo>,
|
|
124
|
+
variantTaskProvider: VariantTaskProvider,
|
|
125
|
+
) {
|
|
126
|
+
val variantName = variant.name
|
|
127
|
+
val capitalizedVariantName = variantName.replaceFirstChar(Char::titlecase)
|
|
128
|
+
|
|
129
|
+
/** ======= EXPLODE AAR =========*/
|
|
130
|
+
val explodeTask = ExplodeTaskProvider.getTask(variant, project, artifacts)
|
|
131
|
+
|
|
132
|
+
/** ======= Pre<Variant>Build =========*/
|
|
133
|
+
variantTaskProvider.preBuildTaskByVariant(
|
|
134
|
+
variantName,
|
|
135
|
+
variant.buildType.name,
|
|
136
|
+
variant.buildType.isDebuggable,
|
|
137
|
+
explodeTask,
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
val aarLibraries = getAarLibraries(artifacts, variantName)
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Flat IDs to be put into the variant property, required for RClass Transformer
|
|
144
|
+
*/
|
|
145
|
+
val packageIDs = aarLibraries.map { it.getPackageName() }
|
|
146
|
+
VariantPackagesProperty.getVariantPackagesProperty().put(variantName, packageIDs)
|
|
147
|
+
|
|
148
|
+
/** ======= MANIFEST MERGER =========*/
|
|
149
|
+
ManifestTaskProcessor.process(variant, project, aarLibraries)
|
|
150
|
+
|
|
151
|
+
/** ======= GENERATE RESOURCES =========*/
|
|
152
|
+
ResourceTaskProcessor.process(variant, project, aarLibraries)
|
|
153
|
+
|
|
154
|
+
/** ======= GENERATE ASSETS ========= */
|
|
155
|
+
AssetTaskProcessor.process(variant, project, aarLibraries)
|
|
156
|
+
|
|
157
|
+
/** ===== jniLibsProcessor ===== */
|
|
158
|
+
val jniLibsProcessor = JNILibsProcessor(project)
|
|
159
|
+
jniLibsProcessor.processJniLibs(aarLibraries, variantName)
|
|
160
|
+
|
|
161
|
+
/** ===== proguardProcessor ===== */
|
|
162
|
+
val proguardProcessor = ProguardProcessor(project)
|
|
163
|
+
val proguardRules = aarLibraries.map { it.getProguardRules() }
|
|
164
|
+
proguardProcessor.processConsumerFiles(proguardRules, capitalizedVariantName)
|
|
165
|
+
proguardProcessor.processGeneratedFiles(proguardRules, capitalizedVariantName)
|
|
166
|
+
|
|
167
|
+
/** ===== processDataBinding ===== */
|
|
168
|
+
val bundleTask = variantTaskProvider.bundleTaskProvider(project, variantName)
|
|
169
|
+
variantTaskProvider.processDataBinding(bundleTask, aarLibraries, variantName)
|
|
170
|
+
}
|
|
171
|
+
}
|