From 0dc31af73ddb3bad4d7fb2ec0d9e8054c766e807 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Wed, 23 Nov 2016 16:31:39 +0300 Subject: [PATCH] Introduce KotlinMetadataFinder#hasMetadataPackage Before creating a MetadataPackageFragment, check that the corresponding directory (across the classpath) contains at least one .kotlin_metadata file. Otherwise we're creating packages for every simple name queried during the resolution and sometimes prefer a (empty) package to the existing class, for example when the latter class is star-imported --- .../kotlin/cli/jvm/compiler/JvmCliVirtualFileFinder.kt | 9 +++++++++ .../load/kotlin/reflect/ReflectKotlinClassFinder.kt | 3 +++ .../deserialization/KotlinMetadataFinder.kt | 7 +++++++ .../deserialization/MetadataPackageFragmentProvider.kt | 4 +++- .../classFile/DeserializerForClassfileDecompiler.kt | 3 +++ .../org/jetbrains/kotlin/idea/vfilefinder/fileFinders.kt | 3 +++ 6 files changed, 28 insertions(+), 1 deletion(-) diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/JvmCliVirtualFileFinder.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/JvmCliVirtualFileFinder.kt index 7b56d301553..86dbf41e106 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/JvmCliVirtualFileFinder.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/JvmCliVirtualFileFinder.kt @@ -42,6 +42,15 @@ class JvmCliVirtualFileFinder( return findBinaryClass(classId, classId.shortClassName.asString() + MetadataPackageFragment.METADATA_FILE_EXTENSION)?.inputStream } + override fun hasMetadataPackage(fqName: FqName): Boolean { + var found = false + index.traverseDirectoriesInPackage(fqName, continueSearch = { dir, _ -> + found = found or dir.children.any { it.extension == MetadataPackageFragment.METADATA_FILE_EXTENSION.substring(1) } + !found + }) + return found + } + override fun findBuiltInsData(packageFqName: FqName): InputStream? { // "" is just a made-up name // JvmDependenciesIndex requires the ClassId of the class which we're searching for, to cache the last request+result diff --git a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/kotlin/reflect/ReflectKotlinClassFinder.kt b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/kotlin/reflect/ReflectKotlinClassFinder.kt index e0dd60aac27..6ee203e276f 100644 --- a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/kotlin/reflect/ReflectKotlinClassFinder.kt +++ b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/kotlin/reflect/ReflectKotlinClassFinder.kt @@ -39,6 +39,9 @@ class ReflectKotlinClassFinder(private val classLoader: ClassLoader) : KotlinCla // TODO override fun findMetadata(classId: ClassId): InputStream? = null + // TODO + override fun hasMetadataPackage(fqName: FqName): Boolean = false + // TODO: load built-ins from classLoader override fun findBuiltInsData(packageFqName: FqName): InputStream? = null } diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/KotlinMetadataFinder.kt b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/KotlinMetadataFinder.kt index b429cd40a88..1f059523e28 100644 --- a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/KotlinMetadataFinder.kt +++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/KotlinMetadataFinder.kt @@ -27,6 +27,13 @@ interface KotlinMetadataFinder { */ fun findMetadata(classId: ClassId): InputStream? + /** + * @return `true` iff this finder is able to locate the package with the given [fqName], containing .kotlin_metadata files. + * Note that returning `true` makes [MetadataPackageFragmentProvider] construct the package fragment for the package, + * and that fact can alter the qualified name expression resolution in the compiler front-end + */ + fun hasMetadataPackage(fqName: FqName): Boolean + /** * @return an [InputStream] which should be used to load the .kotlin_builtins file for package with the given [packageFqName]. */ diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MetadataPackageFragmentProvider.kt b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MetadataPackageFragmentProvider.kt index 4a74b9506c6..bf25ae0504d 100644 --- a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MetadataPackageFragmentProvider.kt +++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MetadataPackageFragmentProvider.kt @@ -60,7 +60,9 @@ class MetadataPackageFragmentProvider( } override fun findPackage(fqName: FqName): DeserializedPackageFragment? = - MetadataPackageFragment(fqName, storageManager, moduleDescriptor, packagePartProvider, finder) + if (finder.hasMetadataPackage(fqName)) + MetadataPackageFragment(fqName, storageManager, moduleDescriptor, packagePartProvider, finder) + else null } class MetadataPackageFragment( diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/DeserializerForClassfileDecompiler.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/DeserializerForClassfileDecompiler.kt index 35f55a23b59..b10ea274bf7 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/DeserializerForClassfileDecompiler.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/DeserializerForClassfileDecompiler.kt @@ -119,6 +119,9 @@ class DirectoryBasedClassFinder( // TODO override fun findMetadata(classId: ClassId): InputStream? = null + // TODO + override fun hasMetadataPackage(fqName: FqName): Boolean = false + // TODO: load built-ins from packageDirectory? override fun findBuiltInsData(packageFqName: FqName): InputStream? = null } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/vfilefinder/fileFinders.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/vfilefinder/fileFinders.kt index b0a36acd387..bc46b39a46f 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/vfilefinder/fileFinders.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/vfilefinder/fileFinders.kt @@ -59,6 +59,9 @@ class JvmIDEVirtualFileFinder(private val scope: GlobalSearchScope) : VirtualFil // TODO override fun findMetadata(classId: ClassId): InputStream? = null + // TODO + override fun hasMetadataPackage(fqName: FqName): Boolean = false + // TODO: load built-ins metadata from scope override fun findBuiltInsData(packageFqName: FqName): InputStream? = null