Android Extensions: Allow to disable specific features of Android Extensions (#KT-23244)

This commit is contained in:
Yan Zhulanow
2018-05-18 22:29:22 +03:00
parent a70707b72b
commit 614003ad70
15 changed files with 226 additions and 19 deletions
@@ -54,6 +54,12 @@ object AndroidConfigurationKeys {
val PACKAGE = CompilerConfigurationKey.create<String>("application package fq name")
val EXPERIMENTAL = CompilerConfigurationKey.create<String>("enable experimental features")
val DEFAULT_CACHE_IMPL = CompilerConfigurationKey.create<String>("default cache implementation")
val FEATURES = CompilerConfigurationKey.create<Set<AndroidExtensionsFeature>>("enabled features")
}
enum class AndroidExtensionsFeature(val featureName: String) {
VIEWS("views"),
PARCELIZE("parcelize")
}
class AndroidCommandLineProcessor : CommandLineProcessor {
@@ -68,6 +74,9 @@ class AndroidCommandLineProcessor : CommandLineProcessor {
val DEFAULT_CACHE_IMPL_OPTION = CliOption(
"defaultCacheImplementation", "hashMap/sparseArray/none", "Default cache implementation for module", required = false)
val FEATURES_OPTION = CliOption(
"features", AndroidExtensionsFeature.values().joinToString(" | "), "Enabled features", required = false)
/* This option is just for saving Android Extensions status in Kotlin facet. It should not be supported from CLI. */
val ENABLED_OPTION: CliOption = CliOption("enabled", "true/false", "Enable Android Extensions", required = false)
}
@@ -75,7 +84,7 @@ class AndroidCommandLineProcessor : CommandLineProcessor {
override val pluginId: String = ANDROID_COMPILER_PLUGIN_ID
override val pluginOptions: Collection<CliOption>
= listOf(VARIANT_OPTION, PACKAGE_OPTION, EXPERIMENTAL_OPTION, DEFAULT_CACHE_IMPL_OPTION, CONFIGURATION)
= listOf(VARIANT_OPTION, PACKAGE_OPTION, EXPERIMENTAL_OPTION, DEFAULT_CACHE_IMPL_OPTION, CONFIGURATION, FEATURES_OPTION)
override fun processOption(option: CliOption, value: String, configuration: CompilerConfiguration) {
when (option) {
@@ -84,6 +93,12 @@ class AndroidCommandLineProcessor : CommandLineProcessor {
EXPERIMENTAL_OPTION -> configuration.put(AndroidConfigurationKeys.EXPERIMENTAL, value)
DEFAULT_CACHE_IMPL_OPTION -> configuration.put(AndroidConfigurationKeys.DEFAULT_CACHE_IMPL, value)
CONFIGURATION -> configuration.applyOptionsFrom(decodePluginOptions(value), pluginOptions)
FEATURES_OPTION -> {
val features = value.split(',').mapNotNullTo(mutableSetOf()) {
name -> AndroidExtensionsFeature.values().firstOrNull { it.featureName == name }
}
configuration.put(AndroidConfigurationKeys.FEATURES, features)
}
else -> throw CliOptionProcessingException("Unknown option: ${option.name}")
}
}
@@ -97,6 +112,37 @@ class AndroidComponentRegistrar : ComponentRegistrar {
ClassBuilderInterceptorExtension.registerExtension(project, ParcelableClinitClassBuilderInterceptorExtension())
}
private fun parseVariant(s: String): AndroidVariant? {
val parts = s.split(';')
if (parts.size < 2) return null
return AndroidVariant(parts[0], parts.drop(1))
}
fun registerViewExtensions(configuration: CompilerConfiguration, isExperimental: Boolean, project: MockProject) {
val applicationPackage = configuration.get(AndroidConfigurationKeys.PACKAGE) ?: return
val variants = configuration.get(AndroidConfigurationKeys.VARIANT)?.mapNotNull { parseVariant(it) } ?: return
val globalCacheImpl = parseCacheImplementationType(configuration.get(AndroidConfigurationKeys.DEFAULT_CACHE_IMPL))
if (variants.isEmpty() || applicationPackage.isEmpty()) {
return
}
val layoutXmlFileManager = CliAndroidLayoutXmlFileManager(project, applicationPackage, variants)
project.registerService(AndroidLayoutXmlFileManager::class.java, layoutXmlFileManager)
ExpressionCodegenExtension.registerExtension(project,
CliAndroidExtensionsExpressionCodegenExtension(isExperimental, globalCacheImpl))
StorageComponentContainerContributor.registerExtension(project,
AndroidExtensionPropertiesComponentContainerContributor())
ClassBuilderInterceptorExtension.registerExtension(project,
CliAndroidOnDestroyClassBuilderInterceptorExtension(globalCacheImpl))
PackageFragmentProviderExtension.registerExtension(project,
CliAndroidPackageFragmentProviderExtension(isExperimental))
}
fun parseCacheImplementationType(s: String?): CacheImplementation = when (s) {
"sparseArray" -> CacheImplementation.SPARSE_ARRAY
"none" -> CacheImplementation.NO_CACHE
@@ -105,31 +151,17 @@ class AndroidComponentRegistrar : ComponentRegistrar {
}
override fun registerProjectComponents(project: MockProject, configuration: CompilerConfiguration) {
val applicationPackage = configuration.get(AndroidConfigurationKeys.PACKAGE) ?: return
val variants = configuration.get(AndroidConfigurationKeys.VARIANT)?.mapNotNull { parseVariant(it) } ?: return
val features = configuration.get(AndroidConfigurationKeys.FEATURES) ?: AndroidExtensionsFeature.values().toSet()
val isExperimental = configuration.get(AndroidConfigurationKeys.EXPERIMENTAL) == "true"
val globalCacheImpl = parseCacheImplementationType(configuration.get(AndroidConfigurationKeys.DEFAULT_CACHE_IMPL))
if (isExperimental) {
if (isExperimental && AndroidExtensionsFeature.PARCELIZE in features) {
registerParcelExtensions(project)
}
if (variants.isNotEmpty() && !applicationPackage.isNullOrBlank()) {
val layoutXmlFileManager = CliAndroidLayoutXmlFileManager(project, applicationPackage!!, variants)
project.registerService(AndroidLayoutXmlFileManager::class.java, layoutXmlFileManager)
ExpressionCodegenExtension.registerExtension(project, CliAndroidExtensionsExpressionCodegenExtension(isExperimental, globalCacheImpl))
StorageComponentContainerContributor.registerExtension(project, AndroidExtensionPropertiesComponentContainerContributor())
ClassBuilderInterceptorExtension.registerExtension(project, CliAndroidOnDestroyClassBuilderInterceptorExtension(globalCacheImpl))
PackageFragmentProviderExtension.registerExtension(project, CliAndroidPackageFragmentProviderExtension(isExperimental))
if (AndroidExtensionsFeature.VIEWS in features) {
registerViewExtensions(configuration, isExperimental, project)
}
}
private fun parseVariant(s: String): AndroidVariant? {
val parts = s.split(';')
if (parts.size < 2) return null
return AndroidVariant(parts[0], parts.drop(1))
}
}
class AndroidExtensionPropertiesComponentContainerContributor : StorageComponentContainerContributor {