Support reading annotations on java 9 module on sources and binaries

This commit is contained in:
Victor Petukhov
2021-04-07 17:09:29 +03:00
parent 24685ee9d6
commit bc5e92033b
18 changed files with 140 additions and 43 deletions
@@ -46,6 +46,7 @@ import org.jetbrains.kotlin.resolve.calls.tower.ImplicitsExtensionsResolutionFil
import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver
import org.jetbrains.kotlin.resolve.jvm.JvmDiagnosticComponents
import org.jetbrains.kotlin.resolve.jvm.extensions.SyntheticJavaResolveExtension
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver
import org.jetbrains.kotlin.resolve.jvm.multiplatform.OptionalAnnotationPackageFragmentProvider
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
@@ -147,6 +148,7 @@ fun StorageComponentContainer.configureJavaSpecificComponents(
typeEnhancementImprovementsInStrictMode = languageVersionSettings.supportsFeature(LanguageFeature.TypeEnhancementImprovementsInStrictMode)
)
)
useInstance(JavaModuleResolver.getInstance(moduleContext.project))
useImpl<FilesByFacadeFqNameIndexer>()
useImpl<JvmDiagnosticComponents>()
@@ -29,6 +29,8 @@ import org.jetbrains.kotlin.utils.sure
abstract class VirtualFileFinder : KotlinClassFinder {
abstract fun findVirtualFileWithHeader(classId: ClassId): VirtualFile?
abstract fun findSourceOrBinaryVirtualFile(classId: ClassId): VirtualFile?
override fun findKotlinClassOrContent(classId: ClassId): KotlinClassFinder.Result? {
val file = findVirtualFileWithHeader(classId) ?: return null
return KotlinBinaryClassCache.getKotlinBinaryClassOrClassFileContent(file)
@@ -19,19 +19,24 @@ package org.jetbrains.kotlin.resolve.jvm.modules
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiJavaModule
import com.intellij.psi.PsiModifier
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
import org.jetbrains.kotlin.load.java.structure.impl.JavaAnnotationImpl
import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryClassSignatureParser
import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaAnnotation
import org.jetbrains.kotlin.load.java.structure.impl.classFiles.ClassifierResolutionContext
import org.jetbrains.kotlin.load.java.structure.impl.convert
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.jvm.KotlinCliJavaFileManager
import org.jetbrains.org.objectweb.asm.*
import org.jetbrains.kotlin.utils.compact
import org.jetbrains.org.objectweb.asm.ClassReader
import org.jetbrains.org.objectweb.asm.ClassVisitor
import org.jetbrains.org.objectweb.asm.ModuleVisitor
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Opcodes.ACC_TRANSITIVE
import java.io.IOException
class JavaModuleInfo(
val moduleName: String,
val requires: List<Requires>,
val exports: List<Exports>
val exports: List<Exports>,
val annotations: List<JavaAnnotation>
) {
data class Requires(val moduleName: String, val isTransitive: Boolean)
@@ -51,15 +56,20 @@ class JavaModuleInfo(
statement.packageName?.let { packageName ->
Exports(FqName(packageName), statement.moduleNames)
}
}
},
psiJavaModule.annotations.convert(::JavaAnnotationImpl)
)
fun read(file: VirtualFile): JavaModuleInfo? {
val contents = try { file.contentsToByteArray() } catch (e: IOException) { return null }
fun read(file: VirtualFile, javaFileManager: KotlinCliJavaFileManager): JavaModuleInfo? {
val contents = try {
file.contentsToByteArray()
} catch (e: IOException) {
return null
}
var moduleName: String? = null
val requires = arrayListOf<Requires>()
val exports = arrayListOf<Exports>()
val annotations = arrayListOf<JavaAnnotation>()
try {
ClassReader(contents).accept(object : ClassVisitor(Opcodes.API_VERSION) {
@@ -77,6 +87,21 @@ class JavaModuleInfo(
}
}
}
override fun visitAnnotation(descriptor: String?, visible: Boolean): AnnotationVisitor? {
if (descriptor == null) return null
val (annotation, visitor) = BinaryJavaAnnotation.createAnnotationAndVisitor(
descriptor,
ClassifierResolutionContext(javaFileManager::findClass),
BinaryClassSignatureParser(),
isFreshlySupportedTypeUseAnnotation = true
)
annotations.add(annotation)
return visitor
}
}, ClassReader.SKIP_DEBUG or ClassReader.SKIP_CODE or ClassReader.SKIP_FRAMES)
} catch (e: Exception) {
throw IllegalStateException(
@@ -86,9 +111,7 @@ class JavaModuleInfo(
)
}
return if (moduleName != null)
JavaModuleInfo(moduleName!!, requires.compact(), exports.compact())
else null
return moduleName?.let { JavaModuleInfo(it, requires.compact(), exports.compact(), annotations) }
}
}
}
@@ -19,9 +19,10 @@ package org.jetbrains.kotlin.resolve.jvm.modules
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.load.java.lazy.JavaModuleAnnotationsProvider
import org.jetbrains.kotlin.name.FqName
interface JavaModuleResolver {
interface JavaModuleResolver : JavaModuleAnnotationsProvider {
fun checkAccessibility(fileFromOurModule: VirtualFile?, referencedFile: VirtualFile, referencedPackage: FqName?): AccessError?
sealed class AccessError {
@@ -31,7 +32,6 @@ interface JavaModuleResolver {
}
companion object SERVICE {
fun getInstance(project: Project): JavaModuleResolver =
ServiceManager.getService(project, JavaModuleResolver::class.java)
fun getInstance(project: Project): JavaModuleResolver = ServiceManager.getService(project, JavaModuleResolver::class.java)
}
}