From 7f1a468b2e5cf0d25431324338690cf84eea8277 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Thu, 22 Mar 2018 12:55:46 +0100 Subject: [PATCH] Read virtual files safely in KotlinMetadataStubBuilder Do not fail on an invalid file, or on a file pointing to a non-existent .jar entry, exactly as this is done in KotlinMetadataDecompiler --- .../decompiler/common/KotlinMetadataDecompiler.kt | 13 ++++++------- .../decompiler/common/KotlinMetadataStubBuilder.kt | 4 ++-- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/common/KotlinMetadataDecompiler.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/common/KotlinMetadataDecompiler.kt index f5a9c679f4f..6bc6d1e82da 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/common/KotlinMetadataDecompiler.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/common/KotlinMetadataDecompiler.kt @@ -49,7 +49,7 @@ abstract class KotlinMetadataDecompiler( private val invalidBinaryVersion: V, stubVersion: Int ) : ClassFileDecompilers.Full() { - private val stubBuilder = KotlinMetadataStubBuilder(stubVersion, fileType, serializerProtocol, this::readFile) + private val stubBuilder = KotlinMetadataStubBuilder(stubVersion, fileType, serializerProtocol, ::readFileSafely) private val renderer = DescriptorRenderer.withOptions { defaultDecompilerRendererOptions() } @@ -61,7 +61,7 @@ abstract class KotlinMetadataDecompiler( override fun createFileViewProvider(file: VirtualFile, manager: PsiManager, physical: Boolean): FileViewProvider { return KotlinDecompiledFileViewProvider(manager, file, physical) { provider -> - if (readFile(provider.virtualFile) == null) { + if (readFileSafely(provider.virtualFile) == null) { null } else { @@ -70,13 +70,12 @@ abstract class KotlinMetadataDecompiler( } } - private fun readFile(file: VirtualFile): FileWithMetadata? { + private fun readFileSafely(file: VirtualFile, content: ByteArray? = null): FileWithMetadata? { if (!file.isValid) return null return try { - readFile(file.contentsToByteArray(false), file) - } - catch (e: IOException) { + readFile(content ?: file.contentsToByteArray(false), file) + } catch (e: IOException) { // This is needed because sometimes we're given VirtualFile instances that point to non-existent .jar entries. // Such files are valid (isValid() returns true), but an attempt to read their contents results in a FileNotFoundException. // Note that although calling "refresh()" instead of catching an exception would seem more correct here, @@ -90,7 +89,7 @@ abstract class KotlinMetadataDecompiler( error("Unexpected file type ${virtualFile.fileType}") } - val file = readFile(virtualFile) + val file = readFileSafely(virtualFile) return when (file) { null -> { diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/common/KotlinMetadataStubBuilder.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/common/KotlinMetadataStubBuilder.kt index 7320559b8c0..ec3a2e5fd37 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/common/KotlinMetadataStubBuilder.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/common/KotlinMetadataStubBuilder.kt @@ -33,14 +33,14 @@ open class KotlinMetadataStubBuilder( private val version: Int, private val fileType: FileType, private val serializerProtocol: SerializerExtensionProtocol, - private val readFile: (ByteArray, VirtualFile) -> FileWithMetadata? + private val readFile: (VirtualFile, ByteArray) -> FileWithMetadata? ) : ClsStubBuilder() { override fun getStubVersion() = ClassFileStubBuilder.STUB_VERSION + version override fun buildFileStub(content: FileContent): PsiFileStub<*>? { val virtualFile = content.file assert(virtualFile.fileType == fileType) { "Unexpected file type ${virtualFile.fileType}" } - val file = readFile(content.content, virtualFile) ?: return null + val file = readFile(virtualFile, content.content) ?: return null when (file) { is FileWithMetadata.Incompatible -> {