Load module annotations in IDE

#KT-22759 Fixed
This commit is contained in:
Alexander Udalov
2018-01-25 17:53:57 +01:00
parent 890374a42a
commit 21e2a3c0b4
13 changed files with 193 additions and 10 deletions
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.idea.caches.resolve
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.util.indexing.FileBasedIndex
import org.jetbrains.kotlin.descriptors.PackagePartProvider
import org.jetbrains.kotlin.idea.vfilefinder.KotlinJvmModuleAnnotationsIndex
import org.jetbrains.kotlin.idea.vfilefinder.KotlinModuleMappingIndex
import org.jetbrains.kotlin.load.kotlin.PackageParts
import org.jetbrains.kotlin.name.ClassId
@@ -33,7 +34,7 @@ class IDEPackagePartProvider(val scope: GlobalSearchScope) : PackagePartProvider
private fun getPackageParts(packageFqName: String): MutableList<PackageParts> =
FileBasedIndex.getInstance().getValues(KotlinModuleMappingIndex.KEY, packageFqName, scope)
override fun getAnnotationsOnBinaryModule(moduleName: String): List<ClassId> {
throw UnsupportedOperationException()
}
// Note that in case of several modules with the same name, we return all annotations on all of them, which is probably incorrect
override fun getAnnotationsOnBinaryModule(moduleName: String): List<ClassId> =
FileBasedIndex.getInstance().getValues(KotlinJvmModuleAnnotationsIndex.KEY, moduleName, scope).flatten()
}
@@ -0,0 +1,25 @@
/*
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.compiler
import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.IDEPackagePartProvider
import org.jetbrains.kotlin.js.resolve.getAnnotationsOnContainingJsModule
import org.jetbrains.kotlin.load.kotlin.getJvmModuleNameForDeserializedDescriptor
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.resolve.ModuleAnnotationsResolver
class IdeModuleAnnotationsResolver(private val project: Project) : ModuleAnnotationsResolver {
override fun getAnnotationsOnContainingModule(descriptor: DeclarationDescriptor): List<ClassId> {
getAnnotationsOnContainingJsModule(descriptor)?.let { return it }
val moduleName = getJvmModuleNameForDeserializedDescriptor(descriptor) ?: return emptyList()
// TODO: allScope is incorrect here, need to look only in the root where this element comes from
return IDEPackagePartProvider(GlobalSearchScope.allScope(project)).getAnnotationsOnBinaryModule(moduleName)
}
}
@@ -0,0 +1,54 @@
/*
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.vfilefinder
import com.intellij.util.indexing.*
import com.intellij.util.io.DataExternalizer
import com.intellij.util.io.IOUtil
import org.jetbrains.kotlin.load.kotlin.ModuleMapping
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration
import java.io.DataInput
import java.io.DataOutput
object KotlinJvmModuleAnnotationsIndex : FileBasedIndexExtension<String, List<ClassId>>() {
val KEY: ID<String, List<ClassId>> = ID.create(KotlinJvmModuleAnnotationsIndex::class.java.canonicalName)
private val KEY_DESCRIPTOR = KotlinModuleMappingIndex.STRING_KEY_DESCRIPTOR
private val VALUE_EXTERNALIZER = object : DataExternalizer<List<ClassId>> {
override fun read(input: DataInput): List<ClassId>? =
IOUtil.readStringList(input).map(ClassId::fromString)
override fun save(out: DataOutput, value: List<ClassId>) =
IOUtil.writeStringList(out, value.map(ClassId::asString))
}
override fun getName() = KEY
override fun dependsOnFileContent() = true
override fun getKeyDescriptor() = KEY_DESCRIPTOR
override fun getValueExternalizer() = VALUE_EXTERNALIZER
override fun getInputFilter(): FileBasedIndex.InputFilter =
FileBasedIndex.InputFilter { file -> file.extension == ModuleMapping.MAPPING_FILE_EXT }
override fun getVersion(): Int = 1
override fun getIndexer(): DataIndexer<String, List<ClassId>, FileContent> = DataIndexer { inputData ->
val file = inputData.file
try {
val moduleMapping = ModuleMapping.create(inputData.content, file.toString(), DeserializationConfiguration.Default)
return@DataIndexer mapOf(file.nameWithoutExtension to moduleMapping.moduleData.annotations)
} catch (e: Exception) {
// Exceptions are already reported in KotlinModuleMappingIndex
emptyMap()
}
}
}
@@ -30,7 +30,7 @@ object KotlinModuleMappingIndex : FileBasedIndexExtension<String, PackageParts>(
val KEY: ID<String, PackageParts> = ID.create(KotlinModuleMappingIndex::class.java.canonicalName)
private val KEY_DESCRIPTOR = object : KeyDescriptor<String> {
internal val STRING_KEY_DESCRIPTOR = object : KeyDescriptor<String> {
override fun save(output: DataOutput, value: String) = IOUtil.writeUTF(output, value)
override fun read(input: DataInput) = IOUtil.readUTF(input)
@@ -63,7 +63,7 @@ object KotlinModuleMappingIndex : FileBasedIndexExtension<String, PackageParts>(
override fun dependsOnFileContent() = true
override fun getKeyDescriptor() = KEY_DESCRIPTOR
override fun getKeyDescriptor() = STRING_KEY_DESCRIPTOR
override fun getValueExternalizer() = VALUE_EXTERNALIZER