Android Extensions: Make AndroidPackageFragmentProviderExtension lazy
This commit is contained in:
+15
-3
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.android.synthetic.descriptors
|
||||
|
||||
import com.intellij.openapi.util.ClearableLazyValue
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
@@ -30,16 +31,27 @@ import org.jetbrains.kotlin.storage.StorageManager
|
||||
import org.jetbrains.kotlin.utils.Printer
|
||||
|
||||
class PredefinedPackageFragmentDescriptor(
|
||||
fqName: String,
|
||||
fqName: FqName,
|
||||
module: ModuleDescriptor,
|
||||
storageManager: StorageManager,
|
||||
val subpackages: List<PackageFragmentDescriptor> = emptyList(),
|
||||
val lazySubpackages: List<LazyAndroidExtensionsPackageFragmentDescriptor> = emptyList(),
|
||||
private val functions: (PredefinedPackageFragmentDescriptor) -> Collection<SimpleFunctionDescriptor> = { emptyList() }
|
||||
) : PackageFragmentDescriptorImpl(module, FqName(fqName)) {
|
||||
) : PackageFragmentDescriptorImpl(module, fqName) {
|
||||
class LazyAndroidExtensionsPackageFragmentDescriptor(
|
||||
val descriptor: ClearableLazyValue<PackageFragmentDescriptor>,
|
||||
val isDeprecated: Boolean
|
||||
)
|
||||
|
||||
private val calculatedFunctions = storageManager.createLazyValue {
|
||||
functions(this)
|
||||
}
|
||||
|
||||
// Left for compatibility with Android Studio
|
||||
@Deprecated("Use lazySubpackages instead.", ReplaceWith("lazySubpackages"))
|
||||
@Suppress("unused")
|
||||
val subpackages: List<PackageFragmentDescriptor>
|
||||
get() = lazySubpackages.map { it.descriptor() }
|
||||
|
||||
private val scope = PredefinedScope()
|
||||
|
||||
override fun getMemberScope() = scope
|
||||
|
||||
+47
-30
@@ -17,12 +17,14 @@
|
||||
package org.jetbrains.kotlin.android.synthetic.res
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.ClearableLazyValue
|
||||
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
||||
import org.jetbrains.kotlin.android.synthetic.AndroidConst
|
||||
import org.jetbrains.kotlin.android.synthetic.descriptors.AndroidSyntheticPackageData
|
||||
import org.jetbrains.kotlin.android.synthetic.descriptors.AndroidSyntheticPackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.android.synthetic.descriptors.LazySyntheticElementResolveContext
|
||||
import org.jetbrains.kotlin.android.synthetic.descriptors.PredefinedPackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.android.synthetic.descriptors.PredefinedPackageFragmentDescriptor.LazyAndroidExtensionsPackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.android.synthetic.forEachUntilLast
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||
@@ -55,22 +57,27 @@ abstract class AndroidPackageFragmentProviderExtension : PackageFragmentProvider
|
||||
|
||||
val lazyContext = LazySyntheticElementResolveContext(module, storageManager)
|
||||
|
||||
val allPackageDescriptors = arrayListOf<PackageFragmentDescriptor>()
|
||||
val packagesToLookupInCompletion = arrayListOf<PackageFragmentDescriptor>()
|
||||
val packages = mutableMapOf<FqName, ClearableLazyValue<PackageFragmentDescriptor>>()
|
||||
val packagesToLookupInCompletion = mutableListOf<LazyAndroidExtensionsPackageFragmentDescriptor>()
|
||||
|
||||
// Packages with synthetic properties
|
||||
for (variantData in moduleData.variants) {
|
||||
for ((layoutName, layouts) in variantData.layouts) {
|
||||
fun createPackageFragment(fqName: String, forView: Boolean, isDeprecated: Boolean = false) {
|
||||
val packageData = AndroidSyntheticPackageData(moduleData, forView, isDeprecated) {
|
||||
layoutXmlFileManager.extractResources(AndroidLayoutGroupData(layoutName, layouts), module)
|
||||
}
|
||||
val packageDescriptor = AndroidSyntheticPackageFragmentDescriptor(
|
||||
module, FqName(fqName), packageData, lazyContext, storageManager, isExperimental,
|
||||
fun createPackageFragment(fqNameString: String, forView: Boolean, isDeprecated: Boolean = false) {
|
||||
val fqName = FqName(fqNameString)
|
||||
|
||||
val lazyPackageDescriptor = ClearableLazyValue.create<PackageFragmentDescriptor> {
|
||||
val packageData = AndroidSyntheticPackageData(moduleData, forView, isDeprecated) {
|
||||
layoutXmlFileManager.extractResources(AndroidLayoutGroupData(layoutName, layouts), module)
|
||||
}
|
||||
|
||||
AndroidSyntheticPackageFragmentDescriptor(
|
||||
module, fqName, packageData, lazyContext, storageManager, isExperimental,
|
||||
lookupTracker, layoutName
|
||||
)
|
||||
packagesToLookupInCompletion += packageDescriptor
|
||||
allPackageDescriptors += packageDescriptor
|
||||
)
|
||||
}
|
||||
packages[fqName] = lazyPackageDescriptor
|
||||
packagesToLookupInCompletion += LazyAndroidExtensionsPackageFragmentDescriptor(lazyPackageDescriptor, isDeprecated)
|
||||
}
|
||||
|
||||
val packageFqName = AndroidConst.SYNTHETIC_PACKAGE + '.' + variantData.variant.name + '.' + layoutName
|
||||
@@ -81,40 +88,50 @@ abstract class AndroidPackageFragmentProviderExtension : PackageFragmentProvider
|
||||
}
|
||||
|
||||
// Empty middle packages
|
||||
AndroidConst.SYNTHETIC_SUBPACKAGES.forEachUntilLast { s ->
|
||||
allPackageDescriptors += PredefinedPackageFragmentDescriptor(s, module, storageManager)
|
||||
AndroidConst.SYNTHETIC_SUBPACKAGES.forEachUntilLast { fqNameString ->
|
||||
val fqName = FqName(fqNameString)
|
||||
packages[fqName] = ClearableLazyValue.create<PackageFragmentDescriptor> {
|
||||
PredefinedPackageFragmentDescriptor(fqName, module, storageManager)
|
||||
}
|
||||
}
|
||||
|
||||
for (variantData in moduleData.variants) {
|
||||
val fqName = AndroidConst.SYNTHETIC_PACKAGE + '.' + variantData.variant.name
|
||||
allPackageDescriptors += PredefinedPackageFragmentDescriptor(fqName, module, storageManager)
|
||||
val fqName = FqName(AndroidConst.SYNTHETIC_PACKAGE + '.' + variantData.variant.name)
|
||||
packages[fqName] = ClearableLazyValue.create<PackageFragmentDescriptor> {
|
||||
PredefinedPackageFragmentDescriptor(fqName, module, storageManager)
|
||||
}
|
||||
}
|
||||
|
||||
// Package with clearFindViewByIdCache()
|
||||
AndroidConst.SYNTHETIC_SUBPACKAGES.last().let { s ->
|
||||
val packageDescriptor = PredefinedPackageFragmentDescriptor(s, module, storageManager, packagesToLookupInCompletion) { descriptor ->
|
||||
val widgetReceivers = lazyContext().getWidgetReceivers(forView = false, isExperimental = isExperimental) +
|
||||
lazyContext().getWidgetReceivers(forView = true, isExperimental = isExperimental)
|
||||
AndroidConst.SYNTHETIC_SUBPACKAGES.last().let { fqNameString ->
|
||||
val fqName = FqName(fqNameString)
|
||||
val lazyPackageDescriptor = ClearableLazyValue.create<PackageFragmentDescriptor> {
|
||||
PredefinedPackageFragmentDescriptor(fqName, module, storageManager, packagesToLookupInCompletion) { descriptor ->
|
||||
val widgetReceivers = lazyContext().getWidgetReceivers(forView = false, isExperimental = isExperimental) +
|
||||
lazyContext().getWidgetReceivers(forView = true, isExperimental = isExperimental)
|
||||
|
||||
widgetReceivers
|
||||
widgetReceivers
|
||||
.filter { it.mayHaveCache }
|
||||
.map { genClearCacheFunction(descriptor, it.type) }
|
||||
}
|
||||
}
|
||||
packagesToLookupInCompletion += packageDescriptor
|
||||
allPackageDescriptors += packageDescriptor
|
||||
|
||||
packages[fqName] = lazyPackageDescriptor
|
||||
packagesToLookupInCompletion += LazyAndroidExtensionsPackageFragmentDescriptor(lazyPackageDescriptor, false)
|
||||
}
|
||||
|
||||
return AndroidSyntheticPackageFragmentProvider(allPackageDescriptors)
|
||||
return AndroidSyntheticPackageFragmentProvider(packages)
|
||||
}
|
||||
}
|
||||
|
||||
class AndroidSyntheticPackageFragmentProvider(val packageFragments: Collection<PackageFragmentDescriptor>) : PackageFragmentProvider {
|
||||
override fun getPackageFragments(fqName: FqName) = packageFragments.filter { it.fqName == fqName }
|
||||
class AndroidSyntheticPackageFragmentProvider(
|
||||
val packages: Map<FqName, ClearableLazyValue<PackageFragmentDescriptor>>
|
||||
) : PackageFragmentProvider {
|
||||
override fun getPackageFragments(fqName: FqName) = listOfNotNull(packages[fqName]?.value)
|
||||
|
||||
override fun getSubPackagesOf(fqName: FqName, nameFilter: (Name) -> Boolean): List<FqName> {
|
||||
return packageFragments.asSequence()
|
||||
.map { it.fqName }
|
||||
.filter { !it.isRoot && it.parent() == fqName }
|
||||
.toList()
|
||||
return packages.asSequence()
|
||||
.filter { (k, _) -> !k.isRoot && k.parent() == fqName }
|
||||
.mapTo(mutableListOf()) { it.key }
|
||||
}
|
||||
}
|
||||
}
|
||||
-1
@@ -17,7 +17,6 @@
|
||||
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
|
||||
|
||||
|
||||
+7
-4
@@ -47,12 +47,15 @@ abstract class AbstractAndroidSyntheticPropertyDescriptorTest : KtUsefulTestCase
|
||||
) as AndroidSyntheticPackageFragmentProvider
|
||||
|
||||
val renderer = DescriptorRenderer.COMPACT_WITH_MODIFIERS
|
||||
val expected = fragmentProvider.packageFragments.sortedBy { it.fqName.asString() }.map {
|
||||
val descriptors = it.getMemberScope().getContributedDescriptors()
|
||||
val expected = fragmentProvider.packages.values
|
||||
.map { it() }
|
||||
.sortedBy { it.fqName.asString() }
|
||||
.joinToString(separator = "\n\n\n") {
|
||||
val descriptors = it.getMemberScope().getContributedDescriptors()
|
||||
.sortedWith(MemberComparator.INSTANCE)
|
||||
.map { " " + renderer.render(it) }.joinToString("\n")
|
||||
it.fqName.asString() + (if (descriptors.isNotEmpty()) "\n\n" + descriptors else "")
|
||||
}.joinToString("\n\n\n")
|
||||
it.fqName.asString() + (if (descriptors.isNotEmpty()) "\n\n" + descriptors else "")
|
||||
}
|
||||
|
||||
KotlinTestUtils.assertEqualsToFile(File(path, "result.txt"), expected)
|
||||
}
|
||||
|
||||
+3
-5
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.kotlin.android.synthetic.idea
|
||||
|
||||
import org.jetbrains.kotlin.android.synthetic.AndroidConst
|
||||
import org.jetbrains.kotlin.android.synthetic.descriptors.AndroidSyntheticPackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.android.synthetic.descriptors.PredefinedPackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
@@ -29,7 +28,6 @@ import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||
|
||||
class AndroidIndicesHelperExtension : KotlinIndicesHelperExtension {
|
||||
|
||||
override fun appendExtensionCallables(
|
||||
consumer: MutableList<in CallableDescriptor>,
|
||||
moduleDescriptor: ModuleDescriptor,
|
||||
@@ -50,9 +48,9 @@ class AndroidIndicesHelperExtension : KotlinIndicesHelperExtension {
|
||||
}
|
||||
|
||||
handleScope(packageFragment.getMemberScope())
|
||||
for (fragment in packageFragment.subpackages) {
|
||||
if (fragment is AndroidSyntheticPackageFragmentDescriptor && fragment.packageData.isDeprecated) continue
|
||||
handleScope(fragment.getMemberScope())
|
||||
for (fragment in packageFragment.lazySubpackages) {
|
||||
if (fragment.isDeprecated) continue
|
||||
handleScope(fragment.descriptor().getMemberScope())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user