Android Extensions: put new functionality under the flag
This commit is contained in:
+11
-5
@@ -18,8 +18,8 @@ package org.jetbrains.kotlin.android.synthetic
|
||||
|
||||
import com.intellij.mock.MockProject
|
||||
import com.intellij.openapi.extensions.Extensions
|
||||
import org.jetbrains.kotlin.android.synthetic.codegen.AndroidExpressionCodegenExtension
|
||||
import org.jetbrains.kotlin.android.synthetic.codegen.AndroidOnDestroyClassBuilderInterceptorExtension
|
||||
import org.jetbrains.kotlin.android.synthetic.codegen.CliAndroidExtensionsExpressionCodegenExtension
|
||||
import org.jetbrains.kotlin.android.synthetic.diagnostic.AndroidExtensionPropertiesCallChecker
|
||||
import org.jetbrains.kotlin.android.synthetic.diagnostic.DefaultErrorMessagesAndroid
|
||||
import org.jetbrains.kotlin.android.synthetic.res.AndroidLayoutXmlFileManager
|
||||
@@ -45,6 +45,7 @@ import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
|
||||
object AndroidConfigurationKeys {
|
||||
val VARIANT: CompilerConfigurationKey<List<String>> = CompilerConfigurationKey.create<List<String>>("Android build variant")
|
||||
val PACKAGE: CompilerConfigurationKey<String> = CompilerConfigurationKey.create<String>("application package fq name")
|
||||
val EXPERIMENTAL: CompilerConfigurationKey<String> = CompilerConfigurationKey.create<String>("enable experimental features")
|
||||
}
|
||||
|
||||
class AndroidCommandLineProcessor : CommandLineProcessor {
|
||||
@@ -53,36 +54,41 @@ class AndroidCommandLineProcessor : CommandLineProcessor {
|
||||
|
||||
val VARIANT_OPTION: CliOption = CliOption("variant", "<name;path>", "Android build variant", allowMultipleOccurrences = true)
|
||||
val PACKAGE_OPTION: CliOption = CliOption("package", "<fq name>", "Application package")
|
||||
val EXPERIMENTAL_OPTION: CliOption = CliOption("experimental", "true/false", "Enable experimental 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)
|
||||
}
|
||||
|
||||
override val pluginId: String = ANDROID_COMPILER_PLUGIN_ID
|
||||
|
||||
override val pluginOptions: Collection<CliOption> = listOf(VARIANT_OPTION, PACKAGE_OPTION)
|
||||
override val pluginOptions: Collection<CliOption> = listOf(VARIANT_OPTION, PACKAGE_OPTION, EXPERIMENTAL_OPTION)
|
||||
|
||||
override fun processOption(option: CliOption, value: String, configuration: CompilerConfiguration) {
|
||||
when (option) {
|
||||
VARIANT_OPTION -> configuration.appendList(AndroidConfigurationKeys.VARIANT, value)
|
||||
PACKAGE_OPTION -> configuration.put(AndroidConfigurationKeys.PACKAGE, value)
|
||||
EXPERIMENTAL_OPTION -> configuration.put(AndroidConfigurationKeys.EXPERIMENTAL, value)
|
||||
else -> throw CliOptionProcessingException("Unknown option: ${option.name}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AndroidComponentRegistrar : ComponentRegistrar {
|
||||
|
||||
override fun registerProjectComponents(project: MockProject, configuration: CompilerConfiguration) {
|
||||
val applicationPackage = configuration.get(AndroidConfigurationKeys.PACKAGE)
|
||||
val variants = configuration.get(AndroidConfigurationKeys.VARIANT)?.mapNotNull { parseVariant(it) } ?: emptyList()
|
||||
val isExperimental = configuration.get(AndroidConfigurationKeys.EXPERIMENTAL) == "true"
|
||||
|
||||
if (variants.isNotEmpty() && !applicationPackage.isNullOrBlank()) {
|
||||
val layoutXmlFileManager = CliAndroidLayoutXmlFileManager(project, applicationPackage!!, variants)
|
||||
project.registerService(AndroidLayoutXmlFileManager::class.java, layoutXmlFileManager)
|
||||
|
||||
ExpressionCodegenExtension.registerExtension(project, AndroidExpressionCodegenExtension())
|
||||
ExpressionCodegenExtension.registerExtension(project, CliAndroidExtensionsExpressionCodegenExtension(isExperimental))
|
||||
StorageComponentContainerContributor.registerExtension(project, AndroidExtensionPropertiesComponentContainerContributor())
|
||||
Extensions.getRootArea().getExtensionPoint(DefaultErrorMessages.Extension.EP_NAME).registerExtension(DefaultErrorMessagesAndroid())
|
||||
ClassBuilderInterceptorExtension.registerExtension(project, AndroidOnDestroyClassBuilderInterceptorExtension())
|
||||
PackageFragmentProviderExtension.registerExtension(project, CliAndroidPackageFragmentProviderExtension())
|
||||
PackageFragmentProviderExtension.registerExtension(project, CliAndroidPackageFragmentProviderExtension(isExperimental))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+12
-4
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.android.synthetic.codegen
|
||||
|
||||
import kotlinx.android.extensions.CacheImplementation.NO_CACHE
|
||||
import org.jetbrains.kotlin.android.synthetic.AndroidConst
|
||||
import org.jetbrains.kotlin.android.synthetic.codegen.AndroidContainerType.LAYOUT_CONTAINER
|
||||
import org.jetbrains.kotlin.android.synthetic.descriptors.ContainerOptionsProxy
|
||||
import org.jetbrains.kotlin.android.synthetic.descriptors.AndroidSyntheticPackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.android.synthetic.res.AndroidSyntheticFunction
|
||||
@@ -29,6 +30,7 @@ import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.psi.KtClass
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
@@ -42,7 +44,7 @@ import org.jetbrains.org.objectweb.asm.Opcodes.ACC_SYNTHETIC
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
class AndroidExpressionCodegenExtension : ExpressionCodegenExtension {
|
||||
abstract class AbstractAndroidExtensionsExpressionCodegenExtension : ExpressionCodegenExtension {
|
||||
companion object {
|
||||
val PROPERTY_NAME = "_\$_findViewCache"
|
||||
val CACHED_FIND_VIEW_BY_ID_METHOD_NAME = "_\$_findCachedViewById"
|
||||
@@ -61,6 +63,8 @@ class AndroidExpressionCodegenExtension : ExpressionCodegenExtension {
|
||||
val classOrObject: KtClassOrObject,
|
||||
val containerOptions: ContainerOptionsProxy)
|
||||
|
||||
protected abstract fun isExperimental(clazz: KtClassOrObject): Boolean
|
||||
|
||||
override fun applyProperty(receiver: StackValue, resolvedCall: ResolvedCall<*>, c: ExpressionCodegenExtension.Context): StackValue? {
|
||||
val resultingDescriptor = resolvedCall.resultingDescriptor
|
||||
return if (resultingDescriptor is PropertyDescriptor) {
|
||||
@@ -124,7 +128,7 @@ class AndroidExpressionCodegenExtension : ExpressionCodegenExtension {
|
||||
|
||||
override fun generateClassSyntheticParts(codegen: ImplementationBodyCodegen) {
|
||||
val classBuilder = codegen.v
|
||||
val targetClass = codegen.myClass as? KtClassOrObject ?: return
|
||||
val targetClass = codegen.myClass as? KtClass ?: return
|
||||
|
||||
val container = codegen.descriptor
|
||||
if (container.kind != ClassKind.CLASS || container.isInner || DescriptorUtils.isLocal(container)) return
|
||||
@@ -132,6 +136,10 @@ class AndroidExpressionCodegenExtension : ExpressionCodegenExtension {
|
||||
val containerOptions = ContainerOptionsProxy.create(container)
|
||||
if (containerOptions.cache == NO_CACHE) return
|
||||
|
||||
if (containerOptions.containerType == LAYOUT_CONTAINER && !isExperimental(targetClass)) {
|
||||
return
|
||||
}
|
||||
|
||||
val context = SyntheticPartsGenerateContext(classBuilder, codegen.state, container, targetClass, containerOptions)
|
||||
context.generateCachedFindViewByIdFunction()
|
||||
context.generateClearCacheFunction()
|
||||
@@ -239,8 +247,8 @@ class AndroidExpressionCodegenExtension : ExpressionCodegenExtension {
|
||||
loadId()
|
||||
iv.invokevirtual(containerType.internalClassName, "findViewById", "(I)Landroid/view/View;", false)
|
||||
}
|
||||
AndroidContainerType.FRAGMENT, AndroidContainerType.SUPPORT_FRAGMENT, AndroidContainerType.LAYOUT_CONTAINER -> {
|
||||
if (containerType == AndroidContainerType.LAYOUT_CONTAINER) {
|
||||
AndroidContainerType.FRAGMENT, AndroidContainerType.SUPPORT_FRAGMENT, LAYOUT_CONTAINER -> {
|
||||
if (containerType == LAYOUT_CONTAINER) {
|
||||
iv.invokeinterface(containerType.internalClassName, "getContainerView", "()Landroid/view/View;")
|
||||
} else {
|
||||
iv.invokevirtual(containerType.internalClassName, "getView", "()Landroid/view/View;", false)
|
||||
+4
-2
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.android.synthetic.codegen
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.android.synthetic.codegen.AbstractAndroidExtensionsExpressionCodegenExtension.Companion.ON_DESTROY_METHOD_NAME
|
||||
import org.jetbrains.kotlin.android.synthetic.descriptors.ContainerOptionsProxy
|
||||
import org.jetbrains.kotlin.codegen.ClassBuilder
|
||||
import org.jetbrains.kotlin.codegen.ClassBuilderFactory
|
||||
@@ -28,6 +29,7 @@ import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.org.objectweb.asm.*
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
import org.jetbrains.kotlin.android.synthetic.codegen.AbstractAndroidExtensionsExpressionCodegenExtension.Companion.CLEAR_CACHE_METHOD_NAME
|
||||
|
||||
class AndroidOnDestroyClassBuilderInterceptorExtension : ClassBuilderInterceptorExtension {
|
||||
|
||||
@@ -106,7 +108,7 @@ class AndroidOnDestroyClassBuilderInterceptorExtension : ClassBuilderInterceptor
|
||||
}
|
||||
|
||||
private fun generateClearCacheMethodCall() {
|
||||
if (name != AndroidExpressionCodegenExtension.ON_DESTROY_METHOD_NAME || currentClass == null) return
|
||||
if (name != ON_DESTROY_METHOD_NAME || currentClass == null) return
|
||||
if (Type.getArgumentTypes(desc).isNotEmpty()) return
|
||||
if (Type.getReturnType(desc) != Type.VOID_TYPE) return
|
||||
|
||||
@@ -118,7 +120,7 @@ class AndroidOnDestroyClassBuilderInterceptorExtension : ClassBuilderInterceptor
|
||||
|
||||
val iv = InstructionAdapter(this)
|
||||
iv.load(0, containerType)
|
||||
iv.invokevirtual(currentClassName, AndroidExpressionCodegenExtension.CLEAR_CACHE_METHOD_NAME, "()V", false)
|
||||
iv.invokevirtual(currentClassName, CLEAR_CACHE_METHOD_NAME, "()V", false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-4
@@ -20,6 +20,7 @@ import kotlinx.android.extensions.CacheImplementation
|
||||
import org.jetbrains.kotlin.android.synthetic.descriptors.ContainerOptionsProxy
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
import org.jetbrains.kotlin.android.synthetic.codegen.AbstractAndroidExtensionsExpressionCodegenExtension.Companion.PROPERTY_NAME
|
||||
|
||||
interface CacheMechanism {
|
||||
/** Push the cache object onto the stack. */
|
||||
@@ -62,7 +63,7 @@ internal class HashMapCacheMechanism(
|
||||
) : CacheMechanism {
|
||||
override fun loadCache() {
|
||||
iv.load(0, containerType)
|
||||
iv.getfield(containerType.internalName, AndroidExpressionCodegenExtension.PROPERTY_NAME, "Ljava/util/HashMap;")
|
||||
iv.getfield(containerType.internalName, PROPERTY_NAME, "Ljava/util/HashMap;")
|
||||
}
|
||||
|
||||
override fun initCache() {
|
||||
@@ -70,7 +71,7 @@ internal class HashMapCacheMechanism(
|
||||
iv.anew(Type.getType("Ljava/util/HashMap;"))
|
||||
iv.dup()
|
||||
iv.invokespecial("java/util/HashMap", "<init>", "()V", false)
|
||||
iv.putfield(containerType.internalName, AndroidExpressionCodegenExtension.PROPERTY_NAME, "Ljava/util/HashMap;")
|
||||
iv.putfield(containerType.internalName, PROPERTY_NAME, "Ljava/util/HashMap;")
|
||||
}
|
||||
|
||||
override fun clearCache() {
|
||||
@@ -96,7 +97,7 @@ internal class SparseArrayCacheMechanism(
|
||||
) : CacheMechanism {
|
||||
override fun loadCache() {
|
||||
iv.load(0, containerType)
|
||||
iv.getfield(containerType.internalName, AndroidExpressionCodegenExtension.PROPERTY_NAME, "Landroid/util/SparseArray;")
|
||||
iv.getfield(containerType.internalName, PROPERTY_NAME, "Landroid/util/SparseArray;")
|
||||
}
|
||||
|
||||
override fun initCache() {
|
||||
@@ -104,7 +105,7 @@ internal class SparseArrayCacheMechanism(
|
||||
iv.anew(Type.getType("Landroid/util/SparseArray;"))
|
||||
iv.dup()
|
||||
iv.invokespecial("android/util/SparseArray", "<init>", "()V", false)
|
||||
iv.putfield(containerType.internalName, AndroidExpressionCodegenExtension.PROPERTY_NAME, "Landroid/util/SparseArray;")
|
||||
iv.putfield(containerType.internalName, PROPERTY_NAME, "Landroid/util/SparseArray;")
|
||||
}
|
||||
|
||||
override fun clearCache() {
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.android.synthetic.codegen
|
||||
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
|
||||
class CliAndroidExtensionsExpressionCodegenExtension(val isExperimental: Boolean) : AbstractAndroidExtensionsExpressionCodegenExtension() {
|
||||
override fun isExperimental(clazz: KtClassOrObject) = isExperimental
|
||||
}
|
||||
+3
-2
@@ -17,7 +17,8 @@
|
||||
package org.jetbrains.kotlin.android.synthetic.codegen
|
||||
|
||||
import org.jetbrains.kotlin.android.synthetic.AndroidConst
|
||||
import org.jetbrains.kotlin.android.synthetic.codegen.AndroidExpressionCodegenExtension.Companion.shouldCacheResource
|
||||
import org.jetbrains.kotlin.android.synthetic.codegen.AbstractAndroidExtensionsExpressionCodegenExtension.Companion.shouldCacheResource
|
||||
import org.jetbrains.kotlin.android.synthetic.codegen.AbstractAndroidExtensionsExpressionCodegenExtension.Companion.CACHED_FIND_VIEW_BY_ID_METHOD_NAME
|
||||
import org.jetbrains.kotlin.android.synthetic.descriptors.ContainerOptionsProxy
|
||||
import org.jetbrains.kotlin.android.synthetic.res.AndroidSyntheticProperty
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
@@ -58,7 +59,7 @@ class ResourcePropertyStackValue(
|
||||
val packageName = resourceId.packageName ?: androidPackage
|
||||
v.getstatic(packageName.replace(".", "/") + "/R\$id", resourceId.name, "I")
|
||||
|
||||
v.invokevirtual(declarationDescriptorType.internalName, AndroidExpressionCodegenExtension.CACHED_FIND_VIEW_BY_ID_METHOD_NAME, "(I)Landroid/view/View;", false)
|
||||
v.invokevirtual(declarationDescriptorType.internalName, CACHED_FIND_VIEW_BY_ID_METHOD_NAME, "(I)Landroid/view/View;", false)
|
||||
}
|
||||
else {
|
||||
when (containerType) {
|
||||
|
||||
+3
-2
@@ -42,7 +42,8 @@ class AndroidSyntheticPackageFragmentDescriptor(
|
||||
fqName: FqName,
|
||||
val packageData: AndroidSyntheticPackageData,
|
||||
private val lazyContext: LazySyntheticElementResolveContext,
|
||||
private val storageManager: StorageManager
|
||||
private val storageManager: StorageManager,
|
||||
private val isExperimental: Boolean
|
||||
) : PackageFragmentDescriptorImpl(module, fqName) {
|
||||
private val scope = AndroidExtensionPropertiesScope()
|
||||
override fun getMemberScope(): MemberScope = scope
|
||||
@@ -52,7 +53,7 @@ class AndroidSyntheticPackageFragmentDescriptor(
|
||||
val packageFragmentDescriptor = this@AndroidSyntheticPackageFragmentDescriptor
|
||||
|
||||
val context = lazyContext()
|
||||
val widgetReceivers = context.getWidgetReceivers(packageData.forView)
|
||||
val widgetReceivers = context.getWidgetReceivers(packageData.forView, isExperimental)
|
||||
val fragmentTypes = context.fragmentTypes
|
||||
|
||||
val properties = ArrayList<PropertyDescriptor>(0)
|
||||
|
||||
+7
-2
@@ -77,6 +77,11 @@ internal class SyntheticElementResolveContext(
|
||||
receivers += WidgetReceiver(dialog, mayHaveCache = false)
|
||||
fragment?.let { receivers += WidgetReceiver(it, mayHaveCache = true) }
|
||||
supportFragment?.let { receivers += WidgetReceiver(it, mayHaveCache = true) }
|
||||
receivers
|
||||
}
|
||||
|
||||
private val experimentalWidgetReceivers by lazy {
|
||||
val receivers = widgetReceivers.toMutableList()
|
||||
layoutContainer?.let { receivers += WidgetReceiver(it, mayHaveCache = true) }
|
||||
receivers
|
||||
}
|
||||
@@ -97,9 +102,9 @@ internal class SyntheticElementResolveContext(
|
||||
}
|
||||
}
|
||||
|
||||
fun getWidgetReceivers(forView: Boolean): List<WidgetReceiver> {
|
||||
fun getWidgetReceivers(forView: Boolean, isExperimental: Boolean): List<WidgetReceiver> {
|
||||
if (forView) return listOf(WidgetReceiver(view, mayHaveCache = true))
|
||||
return widgetReceivers
|
||||
return if (isExperimental) experimentalWidgetReceivers else widgetReceivers
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+9
-2
@@ -31,6 +31,8 @@ import org.jetbrains.kotlin.storage.StorageManager
|
||||
abstract class AndroidPackageFragmentProviderExtension : PackageFragmentProviderExtension {
|
||||
protected abstract fun getLayoutXmlFileManager(project: Project, moduleInfo: ModuleInfo?): AndroidLayoutXmlFileManager?
|
||||
|
||||
protected abstract fun isExperimental(moduleInfo: ModuleInfo?): Boolean
|
||||
|
||||
override fun getPackageFragmentProvider(
|
||||
project: Project,
|
||||
module: ModuleDescriptor,
|
||||
@@ -38,6 +40,8 @@ abstract class AndroidPackageFragmentProviderExtension : PackageFragmentProvider
|
||||
trace: BindingTrace,
|
||||
moduleInfo: ModuleInfo?
|
||||
): PackageFragmentProvider? {
|
||||
val isExperimental = isExperimental(moduleInfo)
|
||||
|
||||
val layoutXmlFileManager = getLayoutXmlFileManager(project, moduleInfo) ?: return null
|
||||
|
||||
val moduleData = layoutXmlFileManager.getModuleData()
|
||||
@@ -54,7 +58,7 @@ abstract class AndroidPackageFragmentProviderExtension : PackageFragmentProvider
|
||||
val resources = layoutXmlFileManager.extractResources(AndroidLayoutGroupData(layoutName, layouts), module)
|
||||
val packageData = AndroidSyntheticPackageData(moduleData, forView, isDeprecated, resources)
|
||||
val packageDescriptor = AndroidSyntheticPackageFragmentDescriptor(
|
||||
module, FqName(fqName), packageData, lazyContext, storageManager)
|
||||
module, FqName(fqName), packageData, lazyContext, storageManager, isExperimental)
|
||||
packagesToLookupInCompletion += packageDescriptor
|
||||
allPackageDescriptors += packageDescriptor
|
||||
}
|
||||
@@ -79,7 +83,10 @@ abstract class AndroidPackageFragmentProviderExtension : PackageFragmentProvider
|
||||
// Package with clearFindViewByIdCache()
|
||||
AndroidConst.SYNTHETIC_SUBPACKAGES.last().let { s ->
|
||||
val packageDescriptor = PredefinedPackageFragmentDescriptor(s, module, storageManager, packagesToLookupInCompletion) { descriptor ->
|
||||
(lazyContext().getWidgetReceivers(forView = false) + lazyContext().getWidgetReceivers(forView = true))
|
||||
val widgetReceivers = lazyContext().getWidgetReceivers(forView = false, isExperimental = isExperimental) +
|
||||
lazyContext().getWidgetReceivers(forView = true, isExperimental = isExperimental)
|
||||
|
||||
widgetReceivers
|
||||
.filter { it.mayHaveCache }
|
||||
.map { genClearCacheFunction(descriptor, it.type) }
|
||||
}
|
||||
|
||||
+4
-1
@@ -17,10 +17,13 @@
|
||||
package org.jetbrains.kotlin.android.synthetic.res
|
||||
|
||||
import com.intellij.openapi.components.ServiceManager
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
||||
|
||||
class CliAndroidPackageFragmentProviderExtension : AndroidPackageFragmentProviderExtension() {
|
||||
class CliAndroidPackageFragmentProviderExtension(private val isExperimental: Boolean) : AndroidPackageFragmentProviderExtension() {
|
||||
override fun isExperimental(moduleInfo: ModuleInfo?): Boolean = isExperimental
|
||||
|
||||
override fun getLayoutXmlFileManager(project: Project, moduleInfo: ModuleInfo?): AndroidLayoutXmlFileManager? {
|
||||
return ServiceManager.getService(project, AndroidLayoutXmlFileManager::class.java)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user