diff --git a/ion/com/amazon/ion/annotations.xml b/ion/com/amazon/ion/annotations.xml new file mode 100644 index 000000000000..3c96a91f1696 --- /dev/null +++ b/ion/com/amazon/ion/annotations.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/model/DataNodeTest.kt b/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/model/DataNodeTest.kt index cffb1d4e6dfe..9ca83c9d5deb 100644 --- a/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/model/DataNodeTest.kt +++ b/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/model/DataNodeTest.kt @@ -1,11 +1,8 @@ // Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.externalSystem.model -import com.intellij.openapi.externalSystem.model.internal.InternalExternalProjectInfo -import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsDataStorage import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream import com.intellij.serialization.ObjectSerializer -import com.intellij.serialization.VersionedFile import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThatExceptionOfType import org.junit.Before @@ -15,7 +12,6 @@ import java.lang.reflect.InvocationHandler import java.lang.reflect.Method import java.lang.reflect.Proxy import java.net.URLClassLoader -import java.nio.file.Paths class DataNodeTest { lateinit var classLoader: ClassLoader @@ -26,25 +22,6 @@ class DataNodeTest { classLoader = URLClassLoader(arrayOf(libUrl), javaClass.classLoader) } - // open https://github.com/apereo/cas project in IDEA and then copy project.dat from system cache to somewhere - //@Test - fun testLoad() { - var versionedFile = VersionedFile(Paths.get("/Volumes/data/big-ion.ion"), ExternalProjectsDataStorage.STORAGE_VERSION) - var start = System.currentTimeMillis() - val data = versionedFile.readList(InternalExternalProjectInfo::class.java, externalSystemBeanConstructed)!! - println("Read in ${System.currentTimeMillis() - start}") - - versionedFile = VersionedFile(Paths.get("/Volumes/data/big-ion2.ion"), ExternalProjectsDataStorage.STORAGE_VERSION, isCompressed = true) - - start = System.currentTimeMillis() - versionedFile.writeList(data, InternalExternalProjectInfo::class.java) - println("Write in ${System.currentTimeMillis() - start}") - - start = System.currentTimeMillis() - versionedFile.writeList(data, InternalExternalProjectInfo::class.java) - println("Second write in ${System.currentTimeMillis() - start}") - } - @Test fun `instance of class from a classloader can be deserialized`() { val barObject = classLoader.loadClass("foo.Bar").newInstance() diff --git a/platform/object-serializer/src/BeanBinding.kt b/platform/object-serializer/src/BeanBinding.kt index 7d69dc246fba..ed7e0e04899b 100644 --- a/platform/object-serializer/src/BeanBinding.kt +++ b/platform/object-serializer/src/BeanBinding.kt @@ -130,12 +130,18 @@ internal class BeanBinding(beanClass: Class<*>) : BaseBeanBinding(beanClass), Bi initArgs[argIndex] = binding.deserialize(subReadContext) } catch (e: Exception) { - context.errors.parameters.add(ReadError("Cannot deserialize parameter value (fieldName=$fieldName, binding=$binding, valueType=${reader.type}, beanClass=${beanClass.name})", e)) + throw SerializationException("Cannot deserialize parameter value (fieldName=$fieldName, binding=$binding, valueType=${reader.type}, beanClass=${beanClass.name})", e) } } } - val instance = constructorInfo.constructor.newInstance(*initArgs) + val instance = try { + constructorInfo.constructor.newInstance(*initArgs) + } + catch (e: Exception) { + throw SerializationException("Cannot create instance (beanClass=${beanClass.name}, initArgs=${initArgs.joinToString()})", e) + } + if (id != -1) { context.objectIdReader.registerObject(instance, id) } @@ -210,6 +216,9 @@ internal class BeanBinding(beanClass: Class<*>) : BaseBeanBinding(beanClass), Bi try { binding.deserialize(instance, accessors[bindingIndex], context) } + catch (e: SerializationException) { + throw e + } catch (e: Exception) { context.errors.fields.add(ReadError("Cannot deserialize field value (field=$fieldName, binding=$binding, valueType=${reader.type}, beanClass=${beanClass.name})", e)) } @@ -221,7 +230,11 @@ private inline fun readStruct(reader: IonReader, read: (fieldName: String, type: reader.stepIn() while (true) { val type = reader.next() ?: break - read(reader.fieldName, type) + val fieldName = reader.fieldName + if (fieldName == null) { + throw IllegalStateException("No valid current value or the current value is not a field of a struct.") + } + read(fieldName, type) } reader.stepOut() } diff --git a/platform/object-serializer/src/CollectionBinding.kt b/platform/object-serializer/src/CollectionBinding.kt index 4ccc6848039a..c599b043a4a3 100644 --- a/platform/object-serializer/src/CollectionBinding.kt +++ b/platform/object-serializer/src/CollectionBinding.kt @@ -47,7 +47,7 @@ internal class CollectionBinding(type: ParameterizedType, context: BindingInitia override fun deserialize(context: ReadContext): Collection { if (context.reader.type == IonType.INT) { LOG.assertTrue(context.reader.intValue() == 0) - return emptyList() + return if (Set::class.java.isAssignableFrom(collectionClass)) emptySet() else emptyList() } val result = createCollection() diff --git a/platform/object-serializer/src/IonObjectSerializer.kt b/platform/object-serializer/src/IonObjectSerializer.kt index d8dfdea71827..2adb5c6df221 100644 --- a/platform/object-serializer/src/IonObjectSerializer.kt +++ b/platform/object-serializer/src/IonObjectSerializer.kt @@ -8,7 +8,6 @@ import com.amazon.ion.system.IonBinaryWriterBuilder import com.amazon.ion.system.IonReaderBuilder import com.amazon.ion.system.IonTextWriterBuilder import com.amazon.ion.system.IonWriterBuilder -import com.intellij.openapi.diagnostic.debug import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream import com.intellij.util.ParameterizedTypeImpl import java.io.IOException @@ -53,7 +52,7 @@ internal class IonObjectSerializer { var isVersionChecked = 0 fun logVersionMismatch(prefix: String, currentVersion: Int) { - LOG.debug { "$prefix version mismatch (file=$inputName, currentVersion: $currentVersion, expectedVersion=$expectedVersion, objectClass=$objectClass)" } + LOG.info("$prefix version mismatch (file=$inputName, currentVersion: $currentVersion, expectedVersion=$expectedVersion, objectClass=$objectClass)") } try { @@ -125,7 +124,12 @@ internal class IonObjectSerializer { reader.use { reader.next() val context = createReadContext(reader, configuration) - return doRead(objectClass, originalType, context) + try { + return doRead(objectClass, originalType, context) + } + finally { + context.errors.report(LOG) + } } } diff --git a/platform/object-serializer/src/context.kt b/platform/object-serializer/src/context.kt index 9d2da9277c65..40243b46fd4a 100644 --- a/platform/object-serializer/src/context.kt +++ b/platform/object-serializer/src/context.kt @@ -39,7 +39,6 @@ internal interface ReadContext { data class ReadErrors( val unknownFields: MutableList = SmartList(), - val parameters: MutableList = SmartList(), val fields: MutableList = SmartList() ) { fun report(logger: Logger) { @@ -49,10 +48,6 @@ data class ReadErrors( if (fields.isNotEmpty()) { logger.warn(unknownFields.joinToString("\n")) } - - if (parameters.isNotEmpty()) { - logger.error(parameters.joinToString("\n")) - } } } diff --git a/platform/object-serializer/testInternalSrc/TestApp.kt b/platform/object-serializer/testInternalSrc/TestApp.kt index 647563f1f556..b4b867aa6fe5 100644 --- a/platform/object-serializer/testInternalSrc/TestApp.kt +++ b/platform/object-serializer/testInternalSrc/TestApp.kt @@ -5,6 +5,8 @@ import com.amazon.ion.system.IonReaderBuilder import com.amazon.ion.system.IonTextWriterBuilder import com.intellij.openapi.util.io.FileUtilRt import com.intellij.util.io.outputStream +import java.io.InputStream +import java.nio.file.Path import java.nio.file.Paths class TestApp { @@ -13,12 +15,17 @@ class TestApp { fun main(args: Array) { val inputFile = Paths.get(args[0]) val outFile = inputFile.parent.resolve(FileUtilRt.getNameWithoutExtension(inputFile.fileName.toString()) + "-text.ion") + readPossiblyCompressedIonFile(inputFile) { input -> - IonReaderBuilder.standard().build(input).use { reader -> - IonTextWriterBuilder.pretty().build(outFile.outputStream().buffered()).use { writer -> - reader.next() - writer.writeValue(reader) - } + decode(input, outFile) + } + } + + private fun decode(input: InputStream, outFile: Path) { + IonReaderBuilder.standard().build(input).use { reader -> + IonTextWriterBuilder.pretty().build(outFile.outputStream().buffered()).use { writer -> + reader.next() + writer.writeValue(reader) } } } diff --git a/platform/object-serializer/testSrc/NonDefaultConstructorTest.kt b/platform/object-serializer/testSrc/NonDefaultConstructorTest.kt index 919d0ea04837..46320ae96f3e 100644 --- a/platform/object-serializer/testSrc/NonDefaultConstructorTest.kt +++ b/platform/object-serializer/testSrc/NonDefaultConstructorTest.kt @@ -8,7 +8,6 @@ import com.intellij.util.io.write import org.junit.Rule import org.junit.Test import org.junit.rules.TestName -import java.lang.reflect.InvocationTargetException class NonDefaultConstructorTest { @Rule @@ -61,11 +60,49 @@ class NonDefaultConstructorTest { file.read(NoDefaultConstructorBean::class.java) } .isInstanceOf(AssertionError::class.java) - .hasCauseInstanceOf(InvocationTargetException::class.java) + .hasCauseInstanceOf(SerializationException::class.java) assertThat(file.file).doesNotExist() } + + @Test + fun `nested list`() { + val ionText = """ + { + '@id':0, + gradleHomeDir:'/Volumes/data/.gradle/wrapper/dists/gradle-5.4.1-bin/e75iq110yv9r9wt1a6619x2xm/gradle-5.4.1', + classpathEntries:[ + { + '@id':1, + classesFile:[ + "/Volumes/data/.gradle/caches/modules-2/files-2.1/com.gradle/build-scan-plugin/2.1/bade2a9009f96169d2b25d3f2023afb2cdf8119f/build-scan-plugin-2.1.jar" + ], + sourcesFile:0, + javadocFile:0 + } + ], + owner:{ + '@id':93, + id:GRADLE, + readableName:Gradle + } + } + """.trimIndent() + + objectSerializer.read(BuildScriptClasspathData::class.java, ionText) + } } +@Suppress("unused") +private class ProjectSystemId @PropertyMapping("id", "readableName") constructor(@JvmField val id: String, @JvmField val readableName: String) + +@Suppress("unused") +private class ClasspathEntry @PropertyMapping("classesFile", "sourcesFile", "javadocFile") constructor(@JvmField val classesFile: MutableSet, + @JvmField val sourcesFile: MutableSet, + @JvmField val javadocFile: MutableSet) + +@Suppress("unused") +private class BuildScriptClasspathData @PropertyMapping("owner", "classpathEntries") constructor(@JvmField val owner: ProjectSystemId, @JvmField val classpathEntries: MutableList) + private class ContainingBean { @JvmField var b: Bean2? = null diff --git a/plugins/gradle/java/intellij.gradle.java.tests.iml b/plugins/gradle/java/intellij.gradle.java.tests.iml index 6a93e4f3e29b..82ac7e8878a5 100644 --- a/plugins/gradle/java/intellij.gradle.java.tests.iml +++ b/plugins/gradle/java/intellij.gradle.java.tests.iml @@ -23,5 +23,6 @@ + \ No newline at end of file diff --git a/plugins/gradle/java/testSources/CacheFileLoadTest.kt b/plugins/gradle/java/testSources/CacheFileLoadTest.kt new file mode 100644 index 000000000000..4f3826ab848b --- /dev/null +++ b/plugins/gradle/java/testSources/CacheFileLoadTest.kt @@ -0,0 +1,47 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.plugins.gradle + +import com.intellij.openapi.externalSystem.model.externalSystemBeanConstructed +import com.intellij.openapi.externalSystem.model.internal.InternalExternalProjectInfo +import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsDataStorage +import com.intellij.serialization.VersionedFile +import com.intellij.testFramework.ProjectRule +import java.nio.file.Paths + +class CacheFileLoadTest { + @JvmField + val projectRule = ProjectRule() + + // open https://github.com/apereo/cas project in IDEA and then copy project.dat from system cache to somewhere + fun testLoad() { + projectRule.project + + var versionedFile = VersionedFile(Paths.get("/Volumes/data/big-ion.ion"), ExternalProjectsDataStorage.STORAGE_VERSION) + var start = System.currentTimeMillis() + val data = versionedFile.readList(InternalExternalProjectInfo::class.java, externalSystemBeanConstructed)!! + println("Read in ${System.currentTimeMillis() - start}") + + for (info in data) { + info.externalProjectStructure?.visit { + try { + it.data + } + catch (e: IllegalStateException) { + if (e.cause !is ClassNotFoundException) { + throw e + } + } + } + } + + versionedFile = VersionedFile(Paths.get("/Volumes/data/big-ion2.ion"), ExternalProjectsDataStorage.STORAGE_VERSION, isCompressed = true) + + start = System.currentTimeMillis() + versionedFile.writeList(data, InternalExternalProjectInfo::class.java) + println("Write in ${System.currentTimeMillis() - start}") + + start = System.currentTimeMillis() + versionedFile.writeList(data, InternalExternalProjectInfo::class.java) + println("Second write in ${System.currentTimeMillis() - start}") + } +} \ No newline at end of file