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
This commit is contained in:
+6
-7
@@ -49,7 +49,7 @@ abstract class KotlinMetadataDecompiler<out V : BinaryVersion>(
|
|||||||
private val invalidBinaryVersion: V,
|
private val invalidBinaryVersion: V,
|
||||||
stubVersion: Int
|
stubVersion: Int
|
||||||
) : ClassFileDecompilers.Full() {
|
) : 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() }
|
private val renderer = DescriptorRenderer.withOptions { defaultDecompilerRendererOptions() }
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ abstract class KotlinMetadataDecompiler<out V : BinaryVersion>(
|
|||||||
|
|
||||||
override fun createFileViewProvider(file: VirtualFile, manager: PsiManager, physical: Boolean): FileViewProvider {
|
override fun createFileViewProvider(file: VirtualFile, manager: PsiManager, physical: Boolean): FileViewProvider {
|
||||||
return KotlinDecompiledFileViewProvider(manager, file, physical) { provider ->
|
return KotlinDecompiledFileViewProvider(manager, file, physical) { provider ->
|
||||||
if (readFile(provider.virtualFile) == null) {
|
if (readFileSafely(provider.virtualFile) == null) {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -70,13 +70,12 @@ abstract class KotlinMetadataDecompiler<out V : BinaryVersion>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun readFile(file: VirtualFile): FileWithMetadata? {
|
private fun readFileSafely(file: VirtualFile, content: ByteArray? = null): FileWithMetadata? {
|
||||||
if (!file.isValid) return null
|
if (!file.isValid) return null
|
||||||
|
|
||||||
return try {
|
return try {
|
||||||
readFile(file.contentsToByteArray(false), file)
|
readFile(content ?: file.contentsToByteArray(false), file)
|
||||||
}
|
} catch (e: IOException) {
|
||||||
catch (e: IOException) {
|
|
||||||
// This is needed because sometimes we're given VirtualFile instances that point to non-existent .jar entries.
|
// 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.
|
// 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,
|
// Note that although calling "refresh()" instead of catching an exception would seem more correct here,
|
||||||
@@ -90,7 +89,7 @@ abstract class KotlinMetadataDecompiler<out V : BinaryVersion>(
|
|||||||
error("Unexpected file type ${virtualFile.fileType}")
|
error("Unexpected file type ${virtualFile.fileType}")
|
||||||
}
|
}
|
||||||
|
|
||||||
val file = readFile(virtualFile)
|
val file = readFileSafely(virtualFile)
|
||||||
|
|
||||||
return when (file) {
|
return when (file) {
|
||||||
null -> {
|
null -> {
|
||||||
|
|||||||
+2
-2
@@ -33,14 +33,14 @@ open class KotlinMetadataStubBuilder(
|
|||||||
private val version: Int,
|
private val version: Int,
|
||||||
private val fileType: FileType,
|
private val fileType: FileType,
|
||||||
private val serializerProtocol: SerializerExtensionProtocol,
|
private val serializerProtocol: SerializerExtensionProtocol,
|
||||||
private val readFile: (ByteArray, VirtualFile) -> FileWithMetadata?
|
private val readFile: (VirtualFile, ByteArray) -> FileWithMetadata?
|
||||||
) : ClsStubBuilder() {
|
) : ClsStubBuilder() {
|
||||||
override fun getStubVersion() = ClassFileStubBuilder.STUB_VERSION + version
|
override fun getStubVersion() = ClassFileStubBuilder.STUB_VERSION + version
|
||||||
|
|
||||||
override fun buildFileStub(content: FileContent): PsiFileStub<*>? {
|
override fun buildFileStub(content: FileContent): PsiFileStub<*>? {
|
||||||
val virtualFile = content.file
|
val virtualFile = content.file
|
||||||
assert(virtualFile.fileType == fileType) { "Unexpected file type ${virtualFile.fileType}" }
|
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) {
|
when (file) {
|
||||||
is FileWithMetadata.Incompatible -> {
|
is FileWithMetadata.Incompatible -> {
|
||||||
|
|||||||
Reference in New Issue
Block a user