Minor: Android Extensions compiler plugin refactoring
This commit is contained in:
+2
-6
@@ -22,7 +22,6 @@ import org.xml.sax.helpers.DefaultHandler
|
|||||||
import java.util.HashMap
|
import java.util.HashMap
|
||||||
|
|
||||||
class AndroidXmlHandler(private val elementCallback: (ResourceIdentifier, String) -> Unit) : DefaultHandler() {
|
class AndroidXmlHandler(private val elementCallback: (ResourceIdentifier, String) -> Unit) : DefaultHandler() {
|
||||||
|
|
||||||
override fun startDocument() {
|
override fun startDocument() {
|
||||||
super.startDocument()
|
super.startDocument()
|
||||||
}
|
}
|
||||||
@@ -40,13 +39,10 @@ class AndroidXmlHandler(private val elementCallback: (ResourceIdentifier, String
|
|||||||
if (name != null) elementCallback(name, widgetType)
|
if (name != null) elementCallback(name, widgetType)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun endElement(uri: String?, localName: String, qName: String) {
|
override fun endElement(uri: String?, localName: String, qName: String) {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Attributes.toMap(): HashMap<String, String> {
|
private fun Attributes.toMap(): HashMap<String, String> {
|
||||||
val res = HashMap<String, String>()
|
val res = HashMap<String, String>()
|
||||||
for (index in 0..length - 1) {
|
for (index in 0..length - 1) {
|
||||||
val attrName = getLocalName(index)!!
|
val attrName = getLocalName(index)!!
|
||||||
|
|||||||
+68
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* 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.android.synthetic.AndroidConst
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||||
|
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
|
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor
|
||||||
|
|
||||||
|
enum class AndroidClassType(className: String, val supportsCache: Boolean = false, val fragment: Boolean = false) {
|
||||||
|
ACTIVITY(AndroidConst.ACTIVITY_FQNAME, supportsCache = true),
|
||||||
|
FRAGMENT(AndroidConst.FRAGMENT_FQNAME, supportsCache = true, fragment = true),
|
||||||
|
DIALOG(AndroidConst.DIALOG_FQNAME, supportsCache = false),
|
||||||
|
SUPPORT_FRAGMENT_ACTIVITY(AndroidConst.SUPPORT_FRAGMENT_ACTIVITY_FQNAME, supportsCache = true),
|
||||||
|
SUPPORT_FRAGMENT(AndroidConst.SUPPORT_FRAGMENT_FQNAME, supportsCache = true, fragment = true),
|
||||||
|
VIEW(AndroidConst.VIEW_FQNAME),
|
||||||
|
UNKNOWN("");
|
||||||
|
|
||||||
|
val internalClassName: String = className.replace('.', '/')
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun getClassType(descriptor: ClassifierDescriptor): AndroidClassType {
|
||||||
|
fun getClassTypeInternal(name: String): AndroidClassType? = when (name) {
|
||||||
|
AndroidConst.ACTIVITY_FQNAME -> AndroidClassType.ACTIVITY
|
||||||
|
AndroidConst.FRAGMENT_FQNAME -> AndroidClassType.FRAGMENT
|
||||||
|
AndroidConst.DIALOG_FQNAME -> AndroidClassType.DIALOG
|
||||||
|
AndroidConst.SUPPORT_FRAGMENT_ACTIVITY_FQNAME -> AndroidClassType.SUPPORT_FRAGMENT_ACTIVITY
|
||||||
|
AndroidConst.SUPPORT_FRAGMENT_FQNAME -> AndroidClassType.SUPPORT_FRAGMENT
|
||||||
|
AndroidConst.VIEW_FQNAME -> AndroidClassType.VIEW
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (descriptor is LazyJavaClassDescriptor) {
|
||||||
|
val androidClassType = getClassTypeInternal(DescriptorUtils.getFqName(descriptor).asString())
|
||||||
|
if (androidClassType != null) return androidClassType
|
||||||
|
}
|
||||||
|
else if (descriptor is LazyClassDescriptor) { // For tests (FakeActivity)
|
||||||
|
val androidClassType = getClassTypeInternal(DescriptorUtils.getFqName(descriptor).toString())
|
||||||
|
if (androidClassType != null) return androidClassType
|
||||||
|
}
|
||||||
|
|
||||||
|
for (supertype in descriptor.typeConstructor.supertypes) {
|
||||||
|
val declarationDescriptor = supertype.constructor.declarationDescriptor
|
||||||
|
if (declarationDescriptor != null) {
|
||||||
|
val androidClassType = getClassType(declarationDescriptor)
|
||||||
|
if (androidClassType != AndroidClassType.UNKNOWN) return androidClassType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return AndroidClassType.UNKNOWN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+34
-156
@@ -26,18 +26,14 @@ import org.jetbrains.kotlin.codegen.ImplementationBodyCodegen
|
|||||||
import org.jetbrains.kotlin.codegen.StackValue
|
import org.jetbrains.kotlin.codegen.StackValue
|
||||||
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
|
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaClassDescriptor
|
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
|
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
|
||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor
|
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||||
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
|
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
|
||||||
import org.jetbrains.kotlin.types.lowerIfFlexible
|
|
||||||
import org.jetbrains.org.objectweb.asm.Label
|
import org.jetbrains.org.objectweb.asm.Label
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes.ACC_PRIVATE
|
import org.jetbrains.org.objectweb.asm.Opcodes.ACC_PRIVATE
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes.ACC_PUBLIC
|
import org.jetbrains.org.objectweb.asm.Opcodes.ACC_PUBLIC
|
||||||
@@ -45,64 +41,23 @@ import org.jetbrains.org.objectweb.asm.Opcodes.ACC_SYNTHETIC
|
|||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
|
|
||||||
enum class AndroidClassType(className: String, val supportsCache: Boolean = false, val fragment: Boolean = false) {
|
|
||||||
ACTIVITY(AndroidConst.ACTIVITY_FQNAME, supportsCache = true),
|
|
||||||
FRAGMENT(AndroidConst.FRAGMENT_FQNAME, supportsCache = true, fragment = true),
|
|
||||||
DIALOG(AndroidConst.DIALOG_FQNAME, supportsCache = false),
|
|
||||||
SUPPORT_FRAGMENT_ACTIVITY(AndroidConst.SUPPORT_FRAGMENT_ACTIVITY_FQNAME, supportsCache = true),
|
|
||||||
SUPPORT_FRAGMENT(AndroidConst.SUPPORT_FRAGMENT_FQNAME, supportsCache = true, fragment = true),
|
|
||||||
VIEW(AndroidConst.VIEW_FQNAME),
|
|
||||||
UNKNOWN("");
|
|
||||||
|
|
||||||
val internalClassName: String = className.replace('.', '/')
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun getClassType(descriptor: ClassifierDescriptor): AndroidClassType {
|
|
||||||
fun getClassTypeInternal(name: String): AndroidClassType? = when (name) {
|
|
||||||
AndroidConst.ACTIVITY_FQNAME -> AndroidClassType.ACTIVITY
|
|
||||||
AndroidConst.FRAGMENT_FQNAME -> AndroidClassType.FRAGMENT
|
|
||||||
AndroidConst.DIALOG_FQNAME -> AndroidClassType.DIALOG
|
|
||||||
AndroidConst.SUPPORT_FRAGMENT_ACTIVITY_FQNAME -> AndroidClassType.SUPPORT_FRAGMENT_ACTIVITY
|
|
||||||
AndroidConst.SUPPORT_FRAGMENT_FQNAME -> AndroidClassType.SUPPORT_FRAGMENT
|
|
||||||
AndroidConst.VIEW_FQNAME -> AndroidClassType.VIEW
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
|
|
||||||
if (descriptor is LazyJavaClassDescriptor) {
|
|
||||||
val androidClassType = getClassTypeInternal(DescriptorUtils.getFqName(descriptor).asString())
|
|
||||||
if (androidClassType != null) return androidClassType
|
|
||||||
}
|
|
||||||
else if (descriptor is LazyClassDescriptor) { // For tests (FakeActivity)
|
|
||||||
val androidClassType = getClassTypeInternal(DescriptorUtils.getFqName(descriptor).toString())
|
|
||||||
if (androidClassType != null) return androidClassType
|
|
||||||
}
|
|
||||||
|
|
||||||
for (supertype in descriptor.typeConstructor.supertypes) {
|
|
||||||
val declarationDescriptor = supertype.constructor.declarationDescriptor
|
|
||||||
if (declarationDescriptor != null) {
|
|
||||||
val androidClassType = getClassType(declarationDescriptor)
|
|
||||||
if (androidClassType != AndroidClassType.UNKNOWN) return androidClassType
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return AndroidClassType.UNKNOWN
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class AndroidExpressionCodegenExtension : ExpressionCodegenExtension {
|
class AndroidExpressionCodegenExtension : ExpressionCodegenExtension {
|
||||||
companion object {
|
companion object {
|
||||||
private val PROPERTY_NAME = "_\$_findViewCache"
|
private val PROPERTY_NAME = "_\$_findViewCache"
|
||||||
private val CACHED_FIND_VIEW_BY_ID_METHOD_NAME = "_\$_findCachedViewById"
|
val CACHED_FIND_VIEW_BY_ID_METHOD_NAME = "_\$_findCachedViewById"
|
||||||
val CLEAR_CACHE_METHOD_NAME = "_\$_clearFindViewByIdCache"
|
val CLEAR_CACHE_METHOD_NAME = "_\$_clearFindViewByIdCache"
|
||||||
val ON_DESTROY_METHOD_NAME = "onDestroyView"
|
val ON_DESTROY_METHOD_NAME = "onDestroyView"
|
||||||
|
|
||||||
fun isCacheSupported(receiverDescriptor: ClassDescriptor, descriptor: PropertyDescriptor? = null): Boolean {
|
fun doesContainerSupportCache(container: ClassDescriptor): Boolean {
|
||||||
val receiverIsKotlinClass = receiverDescriptor.source is KotlinSourceElement
|
return container.source is KotlinSourceElement
|
||||||
return receiverIsKotlinClass && when (descriptor) {
|
}
|
||||||
is AndroidSyntheticProperty -> descriptor.cacheView
|
|
||||||
else -> true
|
fun shouldCacheResource(container: ClassDescriptor, resource: PropertyDescriptor): Boolean {
|
||||||
|
if (!doesContainerSupportCache(container)) {
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (resource as? AndroidSyntheticProperty)?.shouldBeCached ?: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,43 +71,45 @@ class AndroidExpressionCodegenExtension : ExpressionCodegenExtension {
|
|||||||
override fun applyProperty(receiver: StackValue, resolvedCall: ResolvedCall<*>, c: ExpressionCodegenExtension.Context): StackValue? {
|
override fun applyProperty(receiver: StackValue, resolvedCall: ResolvedCall<*>, c: ExpressionCodegenExtension.Context): StackValue? {
|
||||||
val resultingDescriptor = resolvedCall.resultingDescriptor
|
val resultingDescriptor = resolvedCall.resultingDescriptor
|
||||||
return if (resultingDescriptor is PropertyDescriptor) {
|
return if (resultingDescriptor is PropertyDescriptor) {
|
||||||
return generateSyntheticPropertyCall(receiver, resolvedCall, c, resultingDescriptor)
|
return generateResourcePropertyCall(receiver, resolvedCall, c, resultingDescriptor)
|
||||||
}
|
}
|
||||||
else null
|
else null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun applyFunction(receiver: StackValue, resolvedCall: ResolvedCall<*>, c: ExpressionCodegenExtension.Context): StackValue? {
|
override fun applyFunction(receiver: StackValue, resolvedCall: ResolvedCall<*>, c: ExpressionCodegenExtension.Context): StackValue? {
|
||||||
val resultingDescriptor = resolvedCall.resultingDescriptor
|
val targetCallable = resolvedCall.resultingDescriptor
|
||||||
return if (resultingDescriptor is FunctionDescriptor) {
|
resolvedCall.resultingDescriptor as? AndroidSyntheticFunction ?: return null
|
||||||
return generateSyntheticFunctionCall(receiver, resolvedCall, c, resultingDescriptor)
|
|
||||||
|
return if (targetCallable.name.asString() == AndroidConst.CLEAR_FUNCTION_NAME) {
|
||||||
|
val container = resolvedCall.getReceiverDeclarationDescriptor() as? ClassDescriptor ?: return null
|
||||||
|
generateClearFindViewByIdCacheFunctionCall(receiver, container, c)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
null
|
||||||
}
|
}
|
||||||
else null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateSyntheticFunctionCall(
|
private fun generateClearFindViewByIdCacheFunctionCall(
|
||||||
receiver: StackValue,
|
receiver: StackValue,
|
||||||
resolvedCall: ResolvedCall<*>,
|
container: ClassDescriptor,
|
||||||
c: ExpressionCodegenExtension.Context,
|
c: ExpressionCodegenExtension.Context
|
||||||
functionDescriptor: FunctionDescriptor
|
|
||||||
): StackValue? {
|
): StackValue? {
|
||||||
if (functionDescriptor !is AndroidSyntheticFunction) return null
|
if (!doesContainerSupportCache(container)) {
|
||||||
if (functionDescriptor.name.asString() != AndroidConst.CLEAR_FUNCTION_NAME) return null
|
return StackValue.functionCall(Type.VOID_TYPE) {}
|
||||||
|
}
|
||||||
|
|
||||||
val receiverDescriptor = resolvedCall.getReceiverDeclarationDescriptor() as? ClassDescriptor ?: return null
|
val androidClassType = AndroidClassType.getClassType(container)
|
||||||
if (!isCacheSupported(receiverDescriptor)) return StackValue.functionCall(Type.VOID_TYPE) {}
|
|
||||||
|
|
||||||
val androidClassType = AndroidClassType.getClassType(receiverDescriptor)
|
|
||||||
if (androidClassType == AndroidClassType.UNKNOWN) return null
|
if (androidClassType == AndroidClassType.UNKNOWN) return null
|
||||||
|
|
||||||
return StackValue.functionCall(Type.VOID_TYPE) {
|
return StackValue.functionCall(Type.VOID_TYPE) {
|
||||||
val bytecodeClassName = c.typeMapper.mapType(receiverDescriptor).internalName
|
val bytecodeClassName = c.typeMapper.mapType(container).internalName
|
||||||
|
|
||||||
receiver.put(c.typeMapper.mapType(receiverDescriptor), it)
|
receiver.put(c.typeMapper.mapType(container), it)
|
||||||
it.invokevirtual(bytecodeClassName, CLEAR_CACHE_METHOD_NAME, "()V", false)
|
it.invokevirtual(bytecodeClassName, CLEAR_CACHE_METHOD_NAME, "()V", false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateSyntheticPropertyCall(
|
private fun generateResourcePropertyCall(
|
||||||
receiver: StackValue,
|
receiver: StackValue,
|
||||||
resolvedCall: ResolvedCall<*>,
|
resolvedCall: ResolvedCall<*>,
|
||||||
c: ExpressionCodegenExtension.Context,
|
c: ExpressionCodegenExtension.Context,
|
||||||
@@ -164,84 +121,7 @@ class AndroidExpressionCodegenExtension : ExpressionCodegenExtension {
|
|||||||
val receiverDescriptor = resolvedCall.getReceiverDeclarationDescriptor() as? ClassDescriptor ?: return null
|
val receiverDescriptor = resolvedCall.getReceiverDeclarationDescriptor() as? ClassDescriptor ?: return null
|
||||||
val androidClassType = AndroidClassType.getClassType(receiverDescriptor)
|
val androidClassType = AndroidClassType.getClassType(receiverDescriptor)
|
||||||
|
|
||||||
return SyntheticProperty(receiver, c.typeMapper, descriptor, receiverDescriptor, androidClassType, androidPackage)
|
return ResourcePropertyStackValue(receiver, c.typeMapper, descriptor, receiverDescriptor, androidClassType, androidPackage)
|
||||||
}
|
|
||||||
|
|
||||||
private class SyntheticProperty(
|
|
||||||
val receiver: StackValue,
|
|
||||||
val typeMapper: KotlinTypeMapper,
|
|
||||||
val propertyDescriptor: PropertyDescriptor,
|
|
||||||
val receiverDescriptor: ClassDescriptor,
|
|
||||||
val androidClassType: AndroidClassType,
|
|
||||||
val androidPackage: String
|
|
||||||
) : StackValue(typeMapper.mapType(propertyDescriptor.returnType!!)) {
|
|
||||||
|
|
||||||
override fun putSelector(type: Type, v: InstructionAdapter) {
|
|
||||||
val returnTypeString = typeMapper.mapType(propertyDescriptor.type.lowerIfFlexible()).className
|
|
||||||
if (AndroidConst.FRAGMENT_FQNAME == returnTypeString || AndroidConst.SUPPORT_FRAGMENT_FQNAME == returnTypeString) {
|
|
||||||
return putSelectorForFragment(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
val syntheticProperty = propertyDescriptor as AndroidSyntheticProperty
|
|
||||||
|
|
||||||
if (androidClassType.supportsCache && isCacheSupported(receiverDescriptor, propertyDescriptor)) {
|
|
||||||
val declarationDescriptorType = typeMapper.mapType(receiverDescriptor)
|
|
||||||
receiver.put(declarationDescriptorType, v)
|
|
||||||
|
|
||||||
val resourceId = syntheticProperty.resource.id
|
|
||||||
val packageName = resourceId.packageName ?: androidPackage
|
|
||||||
v.getstatic(packageName.replace(".", "/") + "/R\$id", resourceId.name, "I")
|
|
||||||
|
|
||||||
v.invokevirtual(declarationDescriptorType.internalName, CACHED_FIND_VIEW_BY_ID_METHOD_NAME, "(I)Landroid/view/View;", false)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
when (androidClassType) {
|
|
||||||
AndroidClassType.ACTIVITY, AndroidClassType.SUPPORT_FRAGMENT_ACTIVITY, AndroidClassType.VIEW, AndroidClassType.DIALOG -> {
|
|
||||||
receiver.put(Type.getType("L${androidClassType.internalClassName};"), v)
|
|
||||||
getResourceId(v)
|
|
||||||
v.invokevirtual(androidClassType.internalClassName, "findViewById", "(I)Landroid/view/View;", false)
|
|
||||||
}
|
|
||||||
AndroidClassType.FRAGMENT, AndroidClassType.SUPPORT_FRAGMENT -> {
|
|
||||||
receiver.put(Type.getType("L${androidClassType.internalClassName};"), v)
|
|
||||||
v.invokevirtual(androidClassType.internalClassName, "getView", "()Landroid/view/View;", false)
|
|
||||||
getResourceId(v)
|
|
||||||
v.invokevirtual("android/view/View", "findViewById", "(I)Landroid/view/View;", false)
|
|
||||||
}
|
|
||||||
else -> throw IllegalStateException("Invalid Android class type: $androidClassType") // Should never occur
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
v.checkcast(this.type)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun putSelectorForFragment(v: InstructionAdapter) {
|
|
||||||
receiver.put(Type.getType("L${androidClassType.internalClassName};"), v)
|
|
||||||
|
|
||||||
when (androidClassType) {
|
|
||||||
AndroidClassType.ACTIVITY, AndroidClassType.FRAGMENT -> {
|
|
||||||
v.invokevirtual(androidClassType.internalClassName, "getFragmentManager", "()Landroid/app/FragmentManager;", false)
|
|
||||||
getResourceId(v)
|
|
||||||
v.invokevirtual("android/app/FragmentManager", "findFragmentById", "(I)Landroid/app/Fragment;", false)
|
|
||||||
}
|
|
||||||
AndroidClassType.SUPPORT_FRAGMENT -> {
|
|
||||||
v.invokevirtual(androidClassType.internalClassName, "getFragmentManager", "()Landroid/support/v4/app/FragmentManager;", false)
|
|
||||||
getResourceId(v)
|
|
||||||
v.invokevirtual("android/support/v4/app/FragmentManager", "findFragmentById", "(I)Landroid/support/v4/app/Fragment;", false)
|
|
||||||
}
|
|
||||||
AndroidClassType.SUPPORT_FRAGMENT_ACTIVITY -> {
|
|
||||||
v.invokevirtual(androidClassType.internalClassName, "getSupportFragmentManager", "()Landroid/support/v4/app/FragmentManager;", false)
|
|
||||||
getResourceId(v)
|
|
||||||
v.invokevirtual("android/support/v4/app/FragmentManager", "findFragmentById", "(I)Landroid/support/v4/app/Fragment;", false)
|
|
||||||
}
|
|
||||||
else -> throw IllegalStateException("Invalid Android class type: $androidClassType") // Should never occur
|
|
||||||
}
|
|
||||||
|
|
||||||
v.checkcast(this.type)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getResourceId(v: InstructionAdapter) {
|
|
||||||
v.getstatic(androidPackage.replace(".", "/") + "/R\$id", propertyDescriptor.name.asString(), "I")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ResolvedCall<*>.getReceiverDeclarationDescriptor(): ClassifierDescriptor? {
|
private fun ResolvedCall<*>.getReceiverDeclarationDescriptor(): ClassifierDescriptor? {
|
||||||
@@ -250,18 +130,16 @@ class AndroidExpressionCodegenExtension : ExpressionCodegenExtension {
|
|||||||
|
|
||||||
override fun generateClassSyntheticParts(codegen: ImplementationBodyCodegen) {
|
override fun generateClassSyntheticParts(codegen: ImplementationBodyCodegen) {
|
||||||
val classBuilder = codegen.v
|
val classBuilder = codegen.v
|
||||||
val state = codegen.state
|
val targetClass = codegen.myClass as? KtClassOrObject ?: return
|
||||||
val classOrObject = codegen.myClass
|
|
||||||
val descriptor = codegen.descriptor
|
|
||||||
|
|
||||||
|
val descriptor = codegen.descriptor
|
||||||
if (descriptor.kind != ClassKind.CLASS || descriptor.isInner || DescriptorUtils.isLocal(descriptor)) return
|
if (descriptor.kind != ClassKind.CLASS || descriptor.isInner || DescriptorUtils.isLocal(descriptor)) return
|
||||||
if (classOrObject !is KtClassOrObject) return // works only only on physical classes, not synthetic ones
|
|
||||||
|
|
||||||
// Do not generate anything if class is not supported
|
// Do not generate anything if class is not supported
|
||||||
val androidClassType = AndroidClassType.getClassType(descriptor)
|
val androidClassType = AndroidClassType.getClassType(descriptor)
|
||||||
if (androidClassType == AndroidClassType.UNKNOWN) return
|
if (androidClassType == AndroidClassType.UNKNOWN) return
|
||||||
|
|
||||||
val context = SyntheticPartsGenerateContext(classBuilder, state, descriptor, classOrObject, androidClassType)
|
val context = SyntheticPartsGenerateContext(classBuilder, codegen.state, descriptor, targetClass, androidClassType)
|
||||||
context.generateCachedFindViewByIdFunction()
|
context.generateCachedFindViewByIdFunction()
|
||||||
context.generateClearCacheFunction()
|
context.generateClearCacheFunction()
|
||||||
|
|
||||||
|
|||||||
+2
-3
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.codegen.ClassBuilder
|
|||||||
import org.jetbrains.kotlin.codegen.ClassBuilderFactory
|
import org.jetbrains.kotlin.codegen.ClassBuilderFactory
|
||||||
import org.jetbrains.kotlin.codegen.DelegatingClassBuilder
|
import org.jetbrains.kotlin.codegen.DelegatingClassBuilder
|
||||||
import org.jetbrains.kotlin.codegen.extensions.ClassBuilderInterceptorExtension
|
import org.jetbrains.kotlin.codegen.extensions.ClassBuilderInterceptorExtension
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||||
import org.jetbrains.kotlin.psi.KtClass
|
import org.jetbrains.kotlin.psi.KtClass
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
@@ -107,12 +106,12 @@ class AndroidOnDestroyClassBuilderInterceptorExtension : ClassBuilderInterceptor
|
|||||||
|
|
||||||
private fun generateClearCacheMethodCall() {
|
private fun generateClearCacheMethodCall() {
|
||||||
if (name != AndroidExpressionCodegenExtension.ON_DESTROY_METHOD_NAME || currentClass == null) return
|
if (name != AndroidExpressionCodegenExtension.ON_DESTROY_METHOD_NAME || currentClass == null) return
|
||||||
if (Type.getArgumentTypes(desc).size != 0) return
|
if (Type.getArgumentTypes(desc).isNotEmpty()) return
|
||||||
if (Type.getReturnType(desc) != Type.VOID_TYPE) return
|
if (Type.getReturnType(desc) != Type.VOID_TYPE) return
|
||||||
|
|
||||||
val classType = currentClassName?.let { Type.getObjectType(it) } ?: return
|
val classType = currentClassName?.let { Type.getObjectType(it) } ?: return
|
||||||
|
|
||||||
val descriptor = bindingContext.get(BindingContext.CLASS, currentClass) as? ClassDescriptor ?: return
|
val descriptor = bindingContext.get(BindingContext.CLASS, currentClass) ?: return
|
||||||
val androidClassType = AndroidClassType.getClassType(descriptor)
|
val androidClassType = AndroidClassType.getClassType(descriptor)
|
||||||
if (!androidClassType.fragment) return
|
if (!androidClassType.fragment) return
|
||||||
|
|
||||||
|
|||||||
+104
@@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* 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.android.synthetic.AndroidConst
|
||||||
|
import org.jetbrains.kotlin.android.synthetic.res.AndroidSyntheticProperty
|
||||||
|
import org.jetbrains.kotlin.codegen.StackValue
|
||||||
|
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
|
import org.jetbrains.kotlin.types.lowerIfFlexible
|
||||||
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
|
|
||||||
|
class ResourcePropertyStackValue(
|
||||||
|
val receiver: StackValue,
|
||||||
|
val typeMapper: KotlinTypeMapper,
|
||||||
|
val propertyDescriptor: PropertyDescriptor,
|
||||||
|
val receiverDescriptor: ClassDescriptor,
|
||||||
|
val androidClassType: AndroidClassType,
|
||||||
|
val androidPackage: String
|
||||||
|
) : StackValue(typeMapper.mapType(propertyDescriptor.returnType!!)) {
|
||||||
|
|
||||||
|
override fun putSelector(type: Type, v: InstructionAdapter) {
|
||||||
|
val returnTypeString = typeMapper.mapType(propertyDescriptor.type.lowerIfFlexible()).className
|
||||||
|
if (AndroidConst.FRAGMENT_FQNAME == returnTypeString || AndroidConst.SUPPORT_FRAGMENT_FQNAME == returnTypeString) {
|
||||||
|
return putSelectorForFragment(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
val syntheticProperty = propertyDescriptor as AndroidSyntheticProperty
|
||||||
|
|
||||||
|
if (androidClassType.supportsCache && AndroidExpressionCodegenExtension.shouldCacheResource(receiverDescriptor, propertyDescriptor)) {
|
||||||
|
val declarationDescriptorType = typeMapper.mapType(receiverDescriptor)
|
||||||
|
receiver.put(declarationDescriptorType, v)
|
||||||
|
|
||||||
|
val resourceId = syntheticProperty.resource.id
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
when (androidClassType) {
|
||||||
|
AndroidClassType.ACTIVITY, AndroidClassType.SUPPORT_FRAGMENT_ACTIVITY, AndroidClassType.VIEW, AndroidClassType.DIALOG -> {
|
||||||
|
receiver.put(Type.getType("L${androidClassType.internalClassName};"), v)
|
||||||
|
getResourceId(v)
|
||||||
|
v.invokevirtual(androidClassType.internalClassName, "findViewById", "(I)Landroid/view/View;", false)
|
||||||
|
}
|
||||||
|
AndroidClassType.FRAGMENT, AndroidClassType.SUPPORT_FRAGMENT -> {
|
||||||
|
receiver.put(Type.getType("L${androidClassType.internalClassName};"), v)
|
||||||
|
v.invokevirtual(androidClassType.internalClassName, "getView", "()Landroid/view/View;", false)
|
||||||
|
getResourceId(v)
|
||||||
|
v.invokevirtual("android/view/View", "findViewById", "(I)Landroid/view/View;", false)
|
||||||
|
}
|
||||||
|
else -> throw IllegalStateException("Invalid Android class type: $androidClassType") // Should never occur
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
v.checkcast(this.type)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun putSelectorForFragment(v: InstructionAdapter) {
|
||||||
|
receiver.put(Type.getType("L${androidClassType.internalClassName};"), v)
|
||||||
|
|
||||||
|
when (androidClassType) {
|
||||||
|
AndroidClassType.ACTIVITY, AndroidClassType.FRAGMENT -> {
|
||||||
|
v.invokevirtual(androidClassType.internalClassName, "getFragmentManager", "()Landroid/app/FragmentManager;", false)
|
||||||
|
getResourceId(v)
|
||||||
|
v.invokevirtual("android/app/FragmentManager", "findFragmentById", "(I)Landroid/app/Fragment;", false)
|
||||||
|
}
|
||||||
|
AndroidClassType.SUPPORT_FRAGMENT -> {
|
||||||
|
v.invokevirtual(androidClassType.internalClassName, "getFragmentManager", "()Landroid/support/v4/app/FragmentManager;", false)
|
||||||
|
getResourceId(v)
|
||||||
|
v.invokevirtual("android/support/v4/app/FragmentManager", "findFragmentById", "(I)Landroid/support/v4/app/Fragment;", false)
|
||||||
|
}
|
||||||
|
AndroidClassType.SUPPORT_FRAGMENT_ACTIVITY -> {
|
||||||
|
v.invokevirtual(androidClassType.internalClassName, "getSupportFragmentManager", "()Landroid/support/v4/app/FragmentManager;", false)
|
||||||
|
getResourceId(v)
|
||||||
|
v.invokevirtual("android/support/v4/app/FragmentManager", "findFragmentById", "(I)Landroid/support/v4/app/Fragment;", false)
|
||||||
|
}
|
||||||
|
else -> throw IllegalStateException("Invalid Android class type: $androidClassType") // Should never occur
|
||||||
|
}
|
||||||
|
|
||||||
|
v.checkcast(this.type)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getResourceId(v: InstructionAdapter) {
|
||||||
|
v.getstatic(androidPackage.replace(".", "/") + "/R\$id", propertyDescriptor.name.asString(), "I")
|
||||||
|
}
|
||||||
|
}
|
||||||
-1
@@ -32,7 +32,6 @@ import org.jetbrains.kotlin.utils.Printer
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class AndroidSyntheticPackageData(
|
class AndroidSyntheticPackageData(
|
||||||
val layoutName: String,
|
|
||||||
val moduleData: AndroidModuleData,
|
val moduleData: AndroidModuleData,
|
||||||
val forView: Boolean,
|
val forView: Boolean,
|
||||||
val isDeprecated: Boolean,
|
val isDeprecated: Boolean,
|
||||||
|
|||||||
+8
-6
@@ -41,18 +41,20 @@ class PredefinedPackageFragmentDescriptor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val scope = PredefinedScope()
|
private val scope = PredefinedScope()
|
||||||
|
|
||||||
override fun getMemberScope() = scope
|
override fun getMemberScope() = scope
|
||||||
|
|
||||||
inner class PredefinedScope : MemberScopeImpl() {
|
inner class PredefinedScope : MemberScopeImpl() {
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
override fun getContributedVariables(name: Name, location: LookupLocation) = emptyList<PropertyDescriptor>()
|
override fun getContributedVariables(name: Name, location: LookupLocation) = emptyList<PropertyDescriptor>()
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
override fun getContributedFunctions(name: Name, location: LookupLocation) = calculatedFunctions().filter { it.name == name }
|
||||||
override fun getContributedFunctions(name: Name, location: LookupLocation) =
|
|
||||||
calculatedFunctions().filter { it.name == name }
|
|
||||||
|
|
||||||
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean) =
|
override fun getContributedDescriptors(
|
||||||
calculatedFunctions().filter { nameFilter(it.name) && kindFilter.accepts(it) }
|
kindFilter: DescriptorKindFilter,
|
||||||
|
nameFilter: (Name) -> Boolean
|
||||||
|
): List<SimpleFunctionDescriptor> {
|
||||||
|
return calculatedFunctions().filter { nameFilter(it.name) && kindFilter.accepts(it) }
|
||||||
|
}
|
||||||
|
|
||||||
override fun printScopeStructure(p: Printer) {
|
override fun printScopeStructure(p: Printer) {
|
||||||
p.println(this::class.java.simpleName)
|
p.println(this::class.java.simpleName)
|
||||||
|
|||||||
+1
@@ -20,6 +20,7 @@ import com.intellij.psi.PsiElement
|
|||||||
import org.jetbrains.kotlin.android.synthetic.descriptors.AndroidSyntheticPackageFragmentDescriptor
|
import org.jetbrains.kotlin.android.synthetic.descriptors.AndroidSyntheticPackageFragmentDescriptor
|
||||||
import org.jetbrains.kotlin.android.synthetic.diagnostic.ErrorsAndroid.*
|
import org.jetbrains.kotlin.android.synthetic.diagnostic.ErrorsAndroid.*
|
||||||
import org.jetbrains.kotlin.android.synthetic.res.AndroidSyntheticProperty
|
import org.jetbrains.kotlin.android.synthetic.res.AndroidSyntheticProperty
|
||||||
|
import org.jetbrains.kotlin.android.synthetic.res.isErrorType
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||||
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
|
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
|
||||||
|
|||||||
+34
-36
@@ -29,15 +29,17 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class AndroidVariantData(val variant: AndroidVariant, private val layouts: Map<String, List<PsiFile>>): Map<String, List<PsiFile>> by layouts
|
class AndroidVariantData(val variant: AndroidVariant, val layouts: Map<String, List<PsiFile>>)
|
||||||
class AndroidModuleData(val module: AndroidModule, private val variants: List<AndroidVariantData>): Iterable<AndroidVariantData> by variants {
|
|
||||||
|
class AndroidModuleData(val module: AndroidModule, val variants: List<AndroidVariantData>) {
|
||||||
companion object {
|
companion object {
|
||||||
val EMPTY = AndroidModuleData(AndroidModule("android", listOf()), listOf())
|
val EMPTY = AndroidModuleData(AndroidModule("android", listOf()), listOf())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class AndroidLayoutXmlFileManager(val project: Project) {
|
data class AndroidLayoutGroupData(val name: String, val layouts: List<PsiFile>)
|
||||||
|
|
||||||
|
abstract class AndroidLayoutXmlFileManager(val project: Project) {
|
||||||
abstract val androidModule: AndroidModule?
|
abstract val androidModule: AndroidModule?
|
||||||
|
|
||||||
open fun propertyToXmlAttributes(propertyDescriptor: PropertyDescriptor): List<PsiElement> = listOf()
|
open fun propertyToXmlAttributes(propertyDescriptor: PropertyDescriptor): List<PsiElement> = listOf()
|
||||||
@@ -47,7 +49,7 @@ abstract class AndroidLayoutXmlFileManager(val project: Project) {
|
|||||||
return AndroidModuleData(androidModule, androidModule.variants.map { getVariantData(it) })
|
return AndroidModuleData(androidModule, androidModule.variants.map { getVariantData(it) })
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getVariantData(variant: AndroidVariant): AndroidVariantData {
|
private fun getVariantData(variant: AndroidVariant): AndroidVariantData {
|
||||||
val psiManager = PsiManager.getInstance(project)
|
val psiManager = PsiManager.getInstance(project)
|
||||||
val fileManager = VirtualFileManager.getInstance()
|
val fileManager = VirtualFileManager.getInstance()
|
||||||
|
|
||||||
@@ -84,11 +86,11 @@ abstract class AndroidLayoutXmlFileManager(val project: Project) {
|
|||||||
return AndroidVariantData(variant, layoutNameToXmlFiles)
|
return AndroidVariantData(variant, layoutNameToXmlFiles)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun extractResources(files: List<PsiFile>, module: ModuleDescriptor): List<AndroidResource> {
|
fun extractResources(layoutGroupFiles: AndroidLayoutGroupData, module: ModuleDescriptor): List<AndroidResource> {
|
||||||
return filterDuplicates(doExtractResources(files, module))
|
return filterDuplicates(doExtractResources(layoutGroupFiles, module))
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract fun doExtractResources(files: List<PsiFile>, module: ModuleDescriptor): List<AndroidLayoutGroup>
|
protected abstract fun doExtractResources(layoutGroup: AndroidLayoutGroupData, module: ModuleDescriptor): AndroidLayoutGroup
|
||||||
|
|
||||||
protected fun parseAndroidResource(id: ResourceIdentifier, tag: String, sourceElement: PsiElement?): AndroidResource {
|
protected fun parseAndroidResource(id: ResourceIdentifier, tag: String, sourceElement: PsiElement?): AndroidResource {
|
||||||
return when (tag) {
|
return when (tag) {
|
||||||
@@ -98,41 +100,39 @@ abstract class AndroidLayoutXmlFileManager(val project: Project) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun filterDuplicates(layoutGroups: List<AndroidLayoutGroup>): List<AndroidResource> {
|
private fun filterDuplicates(layoutGroup: AndroidLayoutGroup): List<AndroidResource> {
|
||||||
val resourceMap = linkedMapOf<String, AndroidResource>()
|
val resourceMap = linkedMapOf<String, AndroidResource>()
|
||||||
val resourcesToExclude = hashSetOf<String>()
|
val resourcesToExclude = hashSetOf<String>()
|
||||||
|
|
||||||
for (layoutGroup in layoutGroups) {
|
val resourcesByName = layoutGroup.layouts.flatMap { it.resources }.groupBy {
|
||||||
val resources = layoutGroup.layouts.flatMap { it.resources }.groupBy {
|
val id = it.id
|
||||||
val id = it.id
|
if (id.packageName == null) id.name else id.packageName + "/" + id.name
|
||||||
if (id.packageName == null) id.name else id.packageName + "/" + id.name
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (resources in resources.values) {
|
for (resources in resourcesByName.values) {
|
||||||
val isPartiallyDefined = resources.size < layoutGroup.layouts.size
|
val isPartiallyDefined = resources.size < layoutGroup.layouts.size
|
||||||
|
|
||||||
for (res in resources) {
|
for (res in resources) {
|
||||||
if (resourceMap.contains(res.id.name)) {
|
if (res.id.name in resourceMap) {
|
||||||
val existing = resourceMap[res.id.name]!!
|
val existing = resourceMap[res.id.name]!!
|
||||||
|
|
||||||
if (!res.sameClass(existing) || res.id.packageName != existing.id.packageName) {
|
if (!res.sameClass(existing) || res.id.packageName != existing.id.packageName) {
|
||||||
resourcesToExclude.add(res.id.name)
|
resourcesToExclude.add(res.id.name)
|
||||||
}
|
}
|
||||||
else if (res is AndroidResource.Widget && existing is AndroidResource.Widget) {
|
else if (res is AndroidResource.Widget && existing is AndroidResource.Widget) {
|
||||||
// Widgets with the same id but different types exist.
|
// Widgets with the same id but different types exist.
|
||||||
if (res.xmlType != existing.xmlType && existing.xmlType != AndroidConst.VIEW_FQNAME) {
|
if (res.xmlType != existing.xmlType && existing.xmlType != AndroidConst.VIEW_FQNAME) {
|
||||||
val mergedWidget = AndroidResource.Widget(
|
val mergedWidget = AndroidResource.Widget(
|
||||||
res.id, AndroidConst.VIEW_FQNAME, res.sourceElement, isPartiallyDefined)
|
res.id, AndroidConst.VIEW_FQNAME, res.sourceElement, isPartiallyDefined)
|
||||||
resourceMap.put(res.id.name, mergedWidget)
|
resourceMap.put(res.id.name, mergedWidget)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (isPartiallyDefined) {
|
}
|
||||||
resourceMap.put(res.id.name, res.partiallyDefined())
|
else if (isPartiallyDefined) {
|
||||||
}
|
resourceMap.put(res.id.name, res.partiallyDefined())
|
||||||
else {
|
}
|
||||||
resourceMap.put(res.id.name, res)
|
else {
|
||||||
}
|
resourceMap.put(res.id.name, res)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -141,12 +141,10 @@ abstract class AndroidLayoutXmlFileManager(val project: Project) {
|
|||||||
return resourceMap.values.toList()
|
return resourceMap.values.toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun getInstance(module: Module): AndroidLayoutXmlFileManager? {
|
fun getInstance(module: Module): AndroidLayoutXmlFileManager? {
|
||||||
val service = ModuleServiceManager.getService(module, AndroidLayoutXmlFileManager::class.java)
|
val service = ModuleServiceManager.getService(module, AndroidLayoutXmlFileManager::class.java)
|
||||||
return service ?: module.getComponent(AndroidLayoutXmlFileManager::class.java)
|
return service ?: module.getComponent(AndroidLayoutXmlFileManager::class.java)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-14
@@ -48,11 +48,11 @@ abstract class AndroidPackageFragmentProviderExtension : PackageFragmentProvider
|
|||||||
val packagesToLookupInCompletion = arrayListOf<PackageFragmentDescriptor>()
|
val packagesToLookupInCompletion = arrayListOf<PackageFragmentDescriptor>()
|
||||||
|
|
||||||
// Packages with synthetic properties
|
// Packages with synthetic properties
|
||||||
for (variantData in moduleData) {
|
for (variantData in moduleData.variants) {
|
||||||
for ((layoutName, layouts) in variantData) {
|
for ((layoutName, layouts) in variantData.layouts) {
|
||||||
fun createPackageFragment(fqName: String, forView: Boolean, isDeprecated: Boolean = false) {
|
fun createPackageFragment(fqName: String, forView: Boolean, isDeprecated: Boolean = false) {
|
||||||
val resources = layoutXmlFileManager.extractResources(layouts, module)
|
val resources = layoutXmlFileManager.extractResources(AndroidLayoutGroupData(layoutName, layouts), module)
|
||||||
val packageData = AndroidSyntheticPackageData(layoutName, moduleData, forView, isDeprecated, resources)
|
val packageData = AndroidSyntheticPackageData(moduleData, forView, isDeprecated, resources)
|
||||||
val packageDescriptor = AndroidSyntheticPackageFragmentDescriptor(
|
val packageDescriptor = AndroidSyntheticPackageFragmentDescriptor(
|
||||||
module, FqName(fqName), packageData, lazyContext, storageManager)
|
module, FqName(fqName), packageData, lazyContext, storageManager)
|
||||||
packagesToLookupInCompletion += packageDescriptor
|
packagesToLookupInCompletion += packageDescriptor
|
||||||
@@ -71,7 +71,7 @@ abstract class AndroidPackageFragmentProviderExtension : PackageFragmentProvider
|
|||||||
allPackageDescriptors += PredefinedPackageFragmentDescriptor(s, module, storageManager)
|
allPackageDescriptors += PredefinedPackageFragmentDescriptor(s, module, storageManager)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (variantData in moduleData) {
|
for (variantData in moduleData.variants) {
|
||||||
val fqName = AndroidConst.SYNTHETIC_PACKAGE + '.' + variantData.variant.name
|
val fqName = AndroidConst.SYNTHETIC_PACKAGE + '.' + variantData.variant.name
|
||||||
allPackageDescriptors += PredefinedPackageFragmentDescriptor(fqName, module, storageManager)
|
allPackageDescriptors += PredefinedPackageFragmentDescriptor(fqName, module, storageManager)
|
||||||
}
|
}
|
||||||
@@ -79,7 +79,9 @@ abstract class AndroidPackageFragmentProviderExtension : PackageFragmentProvider
|
|||||||
// Package with clearFindViewByIdCache()
|
// Package with clearFindViewByIdCache()
|
||||||
AndroidConst.SYNTHETIC_SUBPACKAGES.last().let { s ->
|
AndroidConst.SYNTHETIC_SUBPACKAGES.last().let { s ->
|
||||||
val packageDescriptor = PredefinedPackageFragmentDescriptor(s, module, storageManager, packagesToLookupInCompletion) { descriptor ->
|
val packageDescriptor = PredefinedPackageFragmentDescriptor(s, module, storageManager, packagesToLookupInCompletion) { descriptor ->
|
||||||
lazyContext().getWidgetReceivers(false).filter { it.mayHaveCache }.map { genClearCacheFunction(descriptor, it.type) }
|
lazyContext().getWidgetReceivers(false)
|
||||||
|
.filter { it.mayHaveCache }
|
||||||
|
.map { genClearCacheFunction(descriptor, it.type) }
|
||||||
}
|
}
|
||||||
packagesToLookupInCompletion += packageDescriptor
|
packagesToLookupInCompletion += packageDescriptor
|
||||||
allPackageDescriptors += packageDescriptor
|
allPackageDescriptors += packageDescriptor
|
||||||
@@ -89,14 +91,13 @@ abstract class AndroidPackageFragmentProviderExtension : PackageFragmentProvider
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AndroidSyntheticPackageFragmentProvider(
|
class AndroidSyntheticPackageFragmentProvider(val packageFragments: Collection<PackageFragmentDescriptor>) : PackageFragmentProvider {
|
||||||
val packageFragments: Collection<PackageFragmentDescriptor>
|
|
||||||
) : PackageFragmentProvider {
|
|
||||||
override fun getPackageFragments(fqName: FqName) = packageFragments.filter { it.fqName == fqName }
|
override fun getPackageFragments(fqName: FqName) = packageFragments.filter { it.fqName == fqName }
|
||||||
|
|
||||||
override fun getSubPackagesOf(fqName: FqName, nameFilter: (Name) -> Boolean) =
|
override fun getSubPackagesOf(fqName: FqName, nameFilter: (Name) -> Boolean): List<FqName> {
|
||||||
packageFragments.asSequence()
|
return packageFragments.asSequence()
|
||||||
.map { it.fqName }
|
.map { it.fqName }
|
||||||
.filter { !it.isRoot && it.parent() == fqName }
|
.filter { !it.isRoot && it.parent() == fqName }
|
||||||
.toList()
|
.toList()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-15
@@ -17,7 +17,6 @@
|
|||||||
package org.jetbrains.kotlin.android.synthetic.res
|
package org.jetbrains.kotlin.android.synthetic.res
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.psi.PsiFile
|
|
||||||
import org.jetbrains.kotlin.android.synthetic.AndroidXmlHandler
|
import org.jetbrains.kotlin.android.synthetic.AndroidXmlHandler
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
import java.io.ByteArrayInputStream
|
import java.io.ByteArrayInputStream
|
||||||
@@ -33,24 +32,19 @@ class CliAndroidLayoutXmlFileManager(
|
|||||||
|
|
||||||
private val saxParser: SAXParser = initSAX()
|
private val saxParser: SAXParser = initSAX()
|
||||||
|
|
||||||
override fun doExtractResources(files: List<PsiFile>, module: ModuleDescriptor): List<AndroidLayoutGroup> {
|
override fun doExtractResources(layoutGroup: AndroidLayoutGroupData, module: ModuleDescriptor): AndroidLayoutGroup {
|
||||||
val layoutGroupFiles = files.groupBy { it.name }
|
val layouts = layoutGroup.layouts.map { layout ->
|
||||||
val layoutGroups = mutableListOf<AndroidLayoutGroup>()
|
val resources = arrayListOf<AndroidResource>()
|
||||||
|
|
||||||
for ((name, layouts) in layoutGroupFiles) {
|
val inputStream = ByteArrayInputStream(layout.virtualFile.contentsToByteArray())
|
||||||
layoutGroups += AndroidLayoutGroup(name, layouts.map { layout ->
|
saxParser.parse(inputStream, AndroidXmlHandler { id, tag ->
|
||||||
val resources = arrayListOf<AndroidResource>()
|
resources += parseAndroidResource(id, tag, null)
|
||||||
|
|
||||||
val inputStream = ByteArrayInputStream(layout.virtualFile.contentsToByteArray())
|
|
||||||
saxParser.parse(inputStream, AndroidXmlHandler { id, tag ->
|
|
||||||
resources += parseAndroidResource(id, tag, null)
|
|
||||||
})
|
|
||||||
|
|
||||||
AndroidLayout(resources)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
AndroidLayout(resources)
|
||||||
}
|
}
|
||||||
|
|
||||||
return layoutGroups
|
return AndroidLayoutGroup(layoutGroup.name, layouts)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initSAX(): SAXParser {
|
private fun initSAX(): SAXParser {
|
||||||
|
|||||||
+30
-16
@@ -61,11 +61,14 @@ internal fun genPropertyForWidget(
|
|||||||
val classDescriptor = resolvedWidget.viewClassDescriptor
|
val classDescriptor = resolvedWidget.viewClassDescriptor
|
||||||
val type = classDescriptor?.let {
|
val type = classDescriptor?.let {
|
||||||
val defaultType = classDescriptor.defaultType
|
val defaultType = classDescriptor.defaultType
|
||||||
if (defaultType.constructor.parameters.isEmpty())
|
|
||||||
|
if (defaultType.constructor.parameters.isEmpty()) {
|
||||||
defaultType
|
defaultType
|
||||||
else
|
}
|
||||||
KotlinTypeFactory.simpleNotNullType(Annotations.EMPTY, classDescriptor,
|
else {
|
||||||
defaultType.constructor.parameters.map(::StarProjectionImpl))
|
KotlinTypeFactory.simpleNotNullType(
|
||||||
|
Annotations.EMPTY, classDescriptor, defaultType.constructor.parameters.map(::StarProjectionImpl))
|
||||||
|
}
|
||||||
} ?: context.viewType
|
} ?: context.viewType
|
||||||
|
|
||||||
return genProperty(resolvedWidget.widget, receiverType, type, packageFragmentDescriptor, sourceEl, resolvedWidget.errorType)
|
return genProperty(resolvedWidget.widget, receiverType, type, packageFragmentDescriptor, sourceEl, resolvedWidget.errorType)
|
||||||
@@ -89,8 +92,6 @@ private fun genProperty(
|
|||||||
sourceElement: SourceElement,
|
sourceElement: SourceElement,
|
||||||
errorType: String?
|
errorType: String?
|
||||||
): PropertyDescriptor {
|
): PropertyDescriptor {
|
||||||
val cacheView = type.constructor.declarationDescriptor?.fqNameUnsafe?.asString() != AndroidConst.VIEWSTUB_FQNAME
|
|
||||||
|
|
||||||
val property = object : AndroidSyntheticProperty, PropertyDescriptorImpl(
|
val property = object : AndroidSyntheticProperty, PropertyDescriptorImpl(
|
||||||
containingDeclaration,
|
containingDeclaration,
|
||||||
null,
|
null,
|
||||||
@@ -101,7 +102,7 @@ private fun genProperty(
|
|||||||
Name.identifier(resource.id.name),
|
Name.identifier(resource.id.name),
|
||||||
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
||||||
sourceElement,
|
sourceElement,
|
||||||
/* lateinit = */ false,
|
/* lateInit = */ false,
|
||||||
/* isConst = */ false,
|
/* isConst = */ false,
|
||||||
/* isHeader = */ false,
|
/* isHeader = */ false,
|
||||||
/* isImpl = */ false,
|
/* isImpl = */ false,
|
||||||
@@ -109,7 +110,7 @@ private fun genProperty(
|
|||||||
/* isDelegated = */ false
|
/* isDelegated = */ false
|
||||||
) {
|
) {
|
||||||
override val errorType = errorType
|
override val errorType = errorType
|
||||||
override val cacheView = cacheView
|
override val shouldBeCached = type.shouldBeCached
|
||||||
override val resource = resource
|
override val resource = resource
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,11 +127,11 @@ private fun genProperty(
|
|||||||
Annotations.EMPTY,
|
Annotations.EMPTY,
|
||||||
Modality.FINAL,
|
Modality.FINAL,
|
||||||
Visibilities.PUBLIC,
|
Visibilities.PUBLIC,
|
||||||
false,
|
/* isDefault = */ false,
|
||||||
false,
|
/* isExternal = */ false,
|
||||||
false,
|
/* isInline = */ false,
|
||||||
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
||||||
null,
|
/* original = */ null,
|
||||||
SourceElement.NO_SOURCE
|
SourceElement.NO_SOURCE
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -141,13 +142,26 @@ private fun genProperty(
|
|||||||
return property
|
return property
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val SimpleType.shouldBeCached: Boolean
|
||||||
|
get() {
|
||||||
|
val viewClassFqName = constructor.declarationDescriptor?.fqNameUnsafe?.asString() ?: return false
|
||||||
|
return when (viewClassFqName) {
|
||||||
|
AndroidConst.VIEWSTUB_FQNAME -> false
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
interface AndroidSyntheticFunction
|
interface AndroidSyntheticFunction
|
||||||
|
|
||||||
interface AndroidSyntheticProperty {
|
interface AndroidSyntheticProperty {
|
||||||
val errorType: String?
|
|
||||||
val cacheView: Boolean
|
|
||||||
val resource: AndroidResource
|
val resource: AndroidResource
|
||||||
|
|
||||||
val isErrorType: Boolean
|
val errorType: String?
|
||||||
get() = errorType != null
|
|
||||||
|
// True if the View should be cached.
|
||||||
|
// Some views (such as ViewStub) should not be cached.
|
||||||
|
val shouldBeCached: Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val AndroidSyntheticProperty.isErrorType: Boolean
|
||||||
|
get() = errorType != null
|
||||||
-1
@@ -33,7 +33,6 @@ import org.jetbrains.kotlin.resolve.BindingContext
|
|||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
|
|
||||||
class AndroidGotoDeclarationHandler : GotoDeclarationHandler {
|
class AndroidGotoDeclarationHandler : GotoDeclarationHandler {
|
||||||
|
|
||||||
override fun getGotoDeclarationTargets(sourceElement: PsiElement?, offset: Int, editor: Editor?): Array<PsiElement>? {
|
override fun getGotoDeclarationTargets(sourceElement: PsiElement?, offset: Int, editor: Editor?): Array<PsiElement>? {
|
||||||
if (sourceElement is LeafPsiElement && sourceElement.parent is KtSimpleNameExpression) {
|
if (sourceElement is LeafPsiElement && sourceElement.parent is KtSimpleNameExpression) {
|
||||||
val simpleNameExpression = sourceElement.parent as? KtSimpleNameExpression ?: return null
|
val simpleNameExpression = sourceElement.parent as? KtSimpleNameExpression ?: return null
|
||||||
|
|||||||
+18
-27
@@ -21,7 +21,6 @@ import com.android.tools.idea.gradle.AndroidGradleModel
|
|||||||
import com.intellij.openapi.module.Module
|
import com.intellij.openapi.module.Module
|
||||||
import com.intellij.openapi.roots.ProjectRootModificationTracker
|
import com.intellij.openapi.roots.ProjectRootModificationTracker
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiFile
|
|
||||||
import com.intellij.psi.impl.PsiTreeChangePreprocessor
|
import com.intellij.psi.impl.PsiTreeChangePreprocessor
|
||||||
import com.intellij.psi.util.CachedValue
|
import com.intellij.psi.util.CachedValue
|
||||||
import com.intellij.psi.util.CachedValueProvider
|
import com.intellij.psi.util.CachedValueProvider
|
||||||
@@ -33,10 +32,11 @@ import org.jetbrains.kotlin.android.synthetic.res.*
|
|||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
|
||||||
|
|
||||||
class IDEAndroidLayoutXmlFileManager(val module: Module) : AndroidLayoutXmlFileManager(module.project) {
|
class IDEAndroidLayoutXmlFileManager(val module: Module) : AndroidLayoutXmlFileManager(module.project) {
|
||||||
override val androidModule: AndroidModule?
|
override val androidModule: AndroidModule?
|
||||||
get() = module.androidFacet?.toAndroidModuleInfo()
|
get() = AndroidFacet.getInstance(module)?.let { getAndroidModuleInfo(it) }
|
||||||
|
|
||||||
@Volatile
|
@Volatile
|
||||||
private var _moduleData: CachedValue<AndroidModuleData>? = null
|
private var _moduleData: CachedValue<AndroidModuleData>? = null
|
||||||
@@ -58,27 +58,21 @@ class IDEAndroidLayoutXmlFileManager(val module: Module) : AndroidLayoutXmlFileM
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getPsiTreeChangePreprocessor(): PsiTreeChangePreprocessor {
|
private fun getPsiTreeChangePreprocessor(): PsiTreeChangePreprocessor {
|
||||||
return project.getExtensions(PsiTreeChangePreprocessor.EP_NAME).first { it is AndroidPsiTreeChangePreprocessor }
|
return project.getExtensions(PsiTreeChangePreprocessor.EP_NAME).firstIsInstance<AndroidPsiTreeChangePreprocessor>()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun doExtractResources(files: List<PsiFile>, module: ModuleDescriptor): List<AndroidLayoutGroup> {
|
override fun doExtractResources(layoutGroup: AndroidLayoutGroupData, module: ModuleDescriptor): AndroidLayoutGroup {
|
||||||
val layoutGroupFiles = files.groupBy { it.name }
|
val layouts = layoutGroup.layouts.map { layout ->
|
||||||
val layoutGroups = mutableListOf<AndroidLayoutGroup>()
|
val resources = arrayListOf<AndroidResource>()
|
||||||
|
layout.accept(AndroidXmlVisitor { id, widgetType, attribute ->
|
||||||
for ((name, layouts) in layoutGroupFiles) {
|
resources += parseAndroidResource(id, widgetType, attribute.valueElement)
|
||||||
layoutGroups += AndroidLayoutGroup(name, layouts.map { layout ->
|
|
||||||
val resources = arrayListOf<AndroidResource>()
|
|
||||||
layout.accept(AndroidXmlVisitor { id, widgetType, attribute ->
|
|
||||||
resources += parseAndroidResource(id, widgetType, attribute.valueElement)
|
|
||||||
})
|
|
||||||
AndroidLayout(resources)
|
|
||||||
})
|
})
|
||||||
|
AndroidLayout(resources)
|
||||||
}
|
}
|
||||||
|
|
||||||
return layoutGroups
|
return AndroidLayoutGroup(layoutGroup.name, layouts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun propertyToXmlAttributes(propertyDescriptor: PropertyDescriptor): List<PsiElement> {
|
override fun propertyToXmlAttributes(propertyDescriptor: PropertyDescriptor): List<PsiElement> {
|
||||||
val fqPath = propertyDescriptor.fqNameUnsafe.pathSegments()
|
val fqPath = propertyDescriptor.fqNameUnsafe.pathSegments()
|
||||||
if (fqPath.size <= SYNTHETIC_PACKAGE_PATH_LENGTH) return listOf()
|
if (fqPath.size <= SYNTHETIC_PACKAGE_PATH_LENGTH) return listOf()
|
||||||
@@ -87,7 +81,7 @@ class IDEAndroidLayoutXmlFileManager(val module: Module) : AndroidLayoutXmlFileM
|
|||||||
val layoutNamePosition = SYNTHETIC_PACKAGE_PATH_LENGTH + (if (defaultVariant) 0 else 1)
|
val layoutNamePosition = SYNTHETIC_PACKAGE_PATH_LENGTH + (if (defaultVariant) 0 else 1)
|
||||||
val layoutName = fqPath[layoutNamePosition].asString()
|
val layoutName = fqPath[layoutNamePosition].asString()
|
||||||
|
|
||||||
val layoutFiles = variantData[layoutName] ?: return null
|
val layoutFiles = variantData.layouts[layoutName] ?: return null
|
||||||
if (layoutFiles.isEmpty()) return null
|
if (layoutFiles.isEmpty()) return null
|
||||||
|
|
||||||
val propertyName = propertyDescriptor.name.asString()
|
val propertyName = propertyDescriptor.name.asString()
|
||||||
@@ -101,7 +95,7 @@ class IDEAndroidLayoutXmlFileManager(val module: Module) : AndroidLayoutXmlFileM
|
|||||||
return attributes
|
return attributes
|
||||||
}
|
}
|
||||||
|
|
||||||
for (variantData in getModuleData()) {
|
for (variantData in getModuleData().variants) {
|
||||||
if (variantData.variant.isMainVariant && fqPath.size == SYNTHETIC_PACKAGE_PATH_LENGTH + 2) {
|
if (variantData.variant.isMainVariant && fqPath.size == SYNTHETIC_PACKAGE_PATH_LENGTH + 2) {
|
||||||
handle(variantData, true)?.let { return it }
|
handle(variantData, true)?.let { return it }
|
||||||
}
|
}
|
||||||
@@ -115,16 +109,13 @@ class IDEAndroidLayoutXmlFileManager(val module: Module) : AndroidLayoutXmlFileM
|
|||||||
|
|
||||||
private fun SourceProvider.toVariant() = AndroidVariant(name, resDirectories.map { it.canonicalPath })
|
private fun SourceProvider.toVariant() = AndroidVariant(name, resDirectories.map { it.canonicalPath })
|
||||||
|
|
||||||
private val Module.androidFacet: AndroidFacet?
|
private fun getAndroidModuleInfo(androidFacet: AndroidFacet): AndroidModule? {
|
||||||
get() = AndroidFacet.getInstance(this)
|
val applicationPackage = androidFacet.manifest?.`package`?.toString() ?: return null
|
||||||
|
|
||||||
private fun AndroidFacet.toAndroidModuleInfo(): AndroidModule? {
|
val allResDirectories = androidFacet.getAppResources(true)?.resourceDirs.orEmpty().mapNotNull { it.canonicalPath }
|
||||||
val applicationPackage = manifest?.`package`?.toString() ?: return null
|
|
||||||
|
|
||||||
val allResDirectories = getAppResources(true)?.resourceDirs.orEmpty().mapNotNull { it.canonicalPath }
|
val resDirectoriesForMainVariant = androidFacet.run {
|
||||||
|
val resDirsFromSourceProviders = AndroidGradleModel.get(this.module)?.allSourceProviders.orEmpty()
|
||||||
val resDirectoriesForMainVariant = run {
|
|
||||||
val resDirsFromSourceProviders = AndroidGradleModel.get(module)?.allSourceProviders.orEmpty()
|
|
||||||
.filter { it.name != "main" }
|
.filter { it.name != "main" }
|
||||||
.flatMap { it.resDirectories }
|
.flatMap { it.resDirectories }
|
||||||
.map { it.canonicalPath }
|
.map { it.canonicalPath }
|
||||||
@@ -134,7 +125,7 @@ class IDEAndroidLayoutXmlFileManager(val module: Module) : AndroidLayoutXmlFileM
|
|||||||
|
|
||||||
val variants = mutableListOf(AndroidVariant("main", resDirectoriesForMainVariant))
|
val variants = mutableListOf(AndroidVariant("main", resDirectoriesForMainVariant))
|
||||||
|
|
||||||
AndroidGradleModel.get(module)?.let { androidGradleModel ->
|
AndroidGradleModel.get(androidFacet.module)?.let { androidGradleModel ->
|
||||||
androidGradleModel.activeSourceProviders.filter { it.name != "main" }.forEach { sourceProvider ->
|
androidGradleModel.activeSourceProviders.filter { it.name != "main" }.forEach { sourceProvider ->
|
||||||
variants += sourceProvider.toVariant()
|
variants += sourceProvider.toVariant()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user