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