Avoid another case of reading file content when building stubs

Do not read file content in isKotlinInternalCompiledFile() if possible
This commit is contained in:
Dmitry Jemerov
2017-04-18 18:02:10 +02:00
parent 83169ad781
commit f801c5f3f8
4 changed files with 21 additions and 12 deletions
@@ -32,7 +32,7 @@ object IDEKotlinBinaryClassCache {
/** /**
* Checks if this file is a compiled Kotlin class file (not necessarily ABI-compatible with the current plugin) * Checks if this file is a compiled Kotlin class file (not necessarily ABI-compatible with the current plugin)
*/ */
fun isKotlinJvmCompiledFile(file: VirtualFile): Boolean { fun isKotlinJvmCompiledFile(file: VirtualFile, fileContent: ByteArray? = null): Boolean {
if (file.extension != JavaClassFileType.INSTANCE!!.defaultExtension) { if (file.extension != JavaClassFileType.INSTANCE!!.defaultExtension) {
return false return false
} }
@@ -41,7 +41,7 @@ object IDEKotlinBinaryClassCache {
if (cached != null) { if (cached != null) {
return cached.isKotlinBinary return cached.isKotlinBinary
} }
return getKotlinBinaryClass(file) != null return getKotlinBinaryClass(file, fileContent) != null
} }
fun getKotlinBinaryClass(file: VirtualFile, fileContent: ByteArray? = null): KotlinJvmBinaryClass? { fun getKotlinBinaryClass(file: VirtualFile, fileContent: ByteArray? = null): KotlinJvmBinaryClass? {
@@ -49,16 +49,17 @@ fun isKotlinWithCompatibleAbiVersion(file: VirtualFile): Boolean {
* Checks if this file is a compiled "internal" Kotlin class, i.e. a Kotlin class (not necessarily ABI-compatible with the current plugin) * Checks if this file is a compiled "internal" Kotlin class, i.e. a Kotlin class (not necessarily ABI-compatible with the current plugin)
* which should NOT be decompiled (and, as a result, shown under the library in the Project view, be searchable via Find class, etc.) * which should NOT be decompiled (and, as a result, shown under the library in the Project view, be searchable via Find class, etc.)
*/ */
fun isKotlinInternalCompiledFile(file: VirtualFile): Boolean { fun isKotlinInternalCompiledFile(file: VirtualFile, fileContent: ByteArray): Boolean {
if (!IDEKotlinBinaryClassCache.isKotlinJvmCompiledFile(file)) { if (!IDEKotlinBinaryClassCache.isKotlinJvmCompiledFile(file, fileContent)) {
return false return false
} }
if (ClassFileViewProvider.isInnerClass(file)) { val innerClass = ClassFileViewProvider.isInnerClass(file, fileContent)
if (innerClass) {
return true return true
} }
val (header, classId) = IDEKotlinBinaryClassCache.getKotlinBinaryClassHeaderData(file) ?: return false val (header, classId) = IDEKotlinBinaryClassCache.getKotlinBinaryClassHeaderData(file, fileContent) ?: return false
if (classId.isLocal) return true if (classId.isLocal) return true
return header.kind == KotlinClassHeader.Kind.SYNTHETIC_CLASS || return header.kind == KotlinClassHeader.Kind.SYNTHETIC_CLASS ||
@@ -37,6 +37,7 @@ import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.types.asFlexibleType import org.jetbrains.kotlin.types.asFlexibleType
import org.jetbrains.kotlin.types.isFlexible import org.jetbrains.kotlin.types.isFlexible
import java.io.IOException
class KotlinClassFileDecompiler : ClassFileDecompilers.Full() { class KotlinClassFileDecompiler : ClassFileDecompilers.Full() {
private val stubBuilder = KotlinClsStubBuilder() private val stubBuilder = KotlinClsStubBuilder()
@@ -47,14 +48,21 @@ class KotlinClassFileDecompiler : ClassFileDecompilers.Full() {
override fun createFileViewProvider(file: VirtualFile, manager: PsiManager, physical: Boolean): KotlinDecompiledFileViewProvider { override fun createFileViewProvider(file: VirtualFile, manager: PsiManager, physical: Boolean): KotlinDecompiledFileViewProvider {
val project = manager.project val project = manager.project
return KotlinDecompiledFileViewProvider(manager, file, physical) { provider -> return KotlinDecompiledFileViewProvider(manager, file, physical) factory@{ provider ->
val virtualFile = provider.virtualFile val virtualFile = provider.virtualFile
val fileIndex = ServiceManager.getService(project, FileIndexFacade::class.java) val fileIndex = ServiceManager.getService(project, FileIndexFacade::class.java)
when { if (!fileIndex.isInLibraryClasses(virtualFile) && fileIndex.isInSource(virtualFile)) return@factory null
!fileIndex.isInLibraryClasses(virtualFile) && fileIndex.isInSource(virtualFile) -> null val content = try {
isKotlinInternalCompiledFile(virtualFile) -> null virtualFile.contentsToByteArray(false)
else -> KtClsFile(provider)
} }
catch (e: IOException) {
return@factory null
}
if (isKotlinInternalCompiledFile(virtualFile, content))
null
else
KtClsFile(provider)
} }
} }
} }
@@ -44,7 +44,7 @@ open class KotlinClsStubBuilder : ClsStubBuilder() {
override fun buildFileStub(content: FileContent): PsiFileStub<*>? { override fun buildFileStub(content: FileContent): PsiFileStub<*>? {
val file = content.file val file = content.file
if (isKotlinInternalCompiledFile(file)) { if (isKotlinInternalCompiledFile(file, content.content)) {
return null return null
} }