diff --git a/generators/build.gradle.kts b/generators/build.gradle.kts index 496b8152213..1c7578b493b 100644 --- a/generators/build.gradle.kts +++ b/generators/build.gradle.kts @@ -70,6 +70,7 @@ dependencies { testCompile(projectTests(":kotlin-noarg-compiler-plugin")) testCompile(projectTests(":kotlin-sam-with-receiver-compiler-plugin")) testCompile(projectTests(":kotlinx-serialization-compiler-plugin")) + testCompile(projectTests(":kotlinx-serialization-ide-plugin")) testCompile(projectTests(":plugins:fir:fir-plugin-prototype")) testCompile(projectTests(":idea:jvm-debugger:jvm-debugger-test")) testCompile(projectTests(":generators:test-generator")) diff --git a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt index 422cd867c35..5282e0d17bd 100644 --- a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt +++ b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt @@ -196,6 +196,8 @@ import org.jetbrains.kotlin.tools.projectWizard.wizard.AbstractYamlNewWizardProj import org.jetbrains.kotlinx.serialization.AbstractSerializationIrBytecodeListingTest import org.jetbrains.kotlinx.serialization.AbstractSerializationPluginBytecodeListingTest import org.jetbrains.kotlinx.serialization.AbstractSerializationPluginDiagnosticTest +import org.jetbrains.kotlinx.serialization.idea.AbstractSerializationPluginIdeDiagnosticTest +import org.jetbrains.kotlinx.serialization.idea.AbstractSerializationQuickFixTest fun main(args: Array) { System.setProperty("java.awt.headless", "true") @@ -1795,6 +1797,18 @@ fun main(args: Array) { } } + testGroup( + "plugins/kotlin-serialization/kotlin-serialization-ide/test", + "plugins/kotlin-serialization/kotlin-serialization-ide/testData" + ) { + testClass { + model("diagnostics") + } + testClass { + model("quickfix", pattern = "^([\\w\\-_]+)\\.kt$", filenameStartsLowerCase = true) + } + } + testGroup("plugins/fir/fir-plugin-prototype/tests", "plugins/fir/fir-plugin-prototype/testData") { testClass { model("") diff --git a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as41 b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as41 index 51ef15e2838..25a09538437 100644 --- a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as41 +++ b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as41 @@ -162,6 +162,8 @@ import org.jetbrains.kotlin.test.TargetBackend import org.jetbrains.kotlinx.serialization.AbstractSerializationPluginBytecodeListingTest import org.jetbrains.kotlinx.serialization.AbstractSerializationPluginDiagnosticTest import org.jetbrains.kotlinx.serialization.AbstractSerializationIrBytecodeListingTest +import org.jetbrains.kotlinx.serialization.idea.AbstractSerializationPluginIdeDiagnosticTest +import org.jetbrains.kotlinx.serialization.idea.AbstractSerializationQuickFixTest fun main(args: Array) { System.setProperty("java.awt.headless", "true") @@ -1220,6 +1222,18 @@ fun main(args: Array) { model("codegen") } } + + testGroup( + "plugins/kotlin-serialization/kotlin-serialization-ide/test", + "plugins/kotlin-serialization/kotlin-serialization-ide/testData" + ) { + testClass { + model("diagnostics") + } + testClass { + model("quickfix", pattern = "^([\\w\\-_]+)\\.kt$", filenameStartsLowerCase = true) + } + } /* testGroup("plugins/android-extensions/android-extensions-idea/tests", "plugins/android-extensions/android-extensions-idea/testData") { testClass { diff --git a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as42 b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as42 index 7e525475af3..f1313162a98 100644 --- a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as42 +++ b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as42 @@ -159,6 +159,8 @@ import org.jetbrains.kotlin.test.TargetBackend import org.jetbrains.kotlinx.serialization.AbstractSerializationPluginBytecodeListingTest import org.jetbrains.kotlinx.serialization.AbstractSerializationPluginDiagnosticTest import org.jetbrains.kotlinx.serialization.AbstractSerializationIrBytecodeListingTest +import org.jetbrains.kotlinx.serialization.idea.AbstractSerializationPluginIdeDiagnosticTest +import org.jetbrains.kotlinx.serialization.idea.AbstractSerializationQuickFixTest fun main(args: Array) { System.setProperty("java.awt.headless", "true") @@ -1148,6 +1150,18 @@ fun main(args: Array) { model("codegen") } } + + testGroup( + "plugins/kotlin-serialization/kotlin-serialization-ide/test", + "plugins/kotlin-serialization/kotlin-serialization-ide/testData" + ) { + testClass { + model("diagnostics") + } + testClass { + model("quickfix", pattern = "^([\\w\\-_]+)\\.kt$", filenameStartsLowerCase = true) + } + } /* testGroup("plugins/android-extensions/android-extensions-idea/tests", "plugins/android-extensions/android-extensions-idea/testData") { testClass { diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/build.gradle.kts b/plugins/kotlin-serialization/kotlin-serialization-compiler/build.gradle.kts index 228c4b316dc..a6d69bef9d0 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/build.gradle.kts +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/build.gradle.kts @@ -21,7 +21,7 @@ dependencies { testCompile(projectTests(":compiler:tests-common")) testCompile(commonDep("junit:junit")) - testImplementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime-jvm:1.0-M1-1.4.0-rc") { isTransitive = false } + testImplementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.1.0") testRuntimeOnly(intellijCoreDep()) { includeJars("intellij-core") } testRuntimeOnly(intellijDep()) { includeJars("platform-concurrency") } diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/diagnostic/SerializationErrors.java b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/diagnostic/SerializationErrors.java index abfe1313713..544e220addb 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/diagnostic/SerializationErrors.java +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/diagnostic/SerializationErrors.java @@ -29,6 +29,8 @@ public interface SerializationErrors { DiagnosticFactory0 TRANSIENT_MISSING_INITIALIZER = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 TRANSIENT_IS_REDUNDANT = DiagnosticFactory0.create(WARNING); + DiagnosticFactory0 JSON_FORMAT_REDUNDANT_DEFAULT = DiagnosticFactory0.create(WARNING); + DiagnosticFactory0 JSON_FORMAT_REDUNDANT = DiagnosticFactory0.create(WARNING); DiagnosticFactory0 INCORRECT_TRANSIENT = DiagnosticFactory0.create(WARNING); @@ -42,4 +44,4 @@ public interface SerializationErrors { .initializeFactoryNamesAndDefaultErrorMessages(SerializationErrors.class, SerializationPluginErrorsRendering.INSTANCE); } }; -} \ No newline at end of file +} diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/diagnostic/SerializationPluginErrorsRendering.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/diagnostic/SerializationPluginErrorsRendering.kt index f561aba2015..30e1a185f61 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/diagnostic/SerializationPluginErrorsRendering.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/diagnostic/SerializationPluginErrorsRendering.kt @@ -74,6 +74,14 @@ object SerializationPluginErrorsRendering : DefaultErrorMessages.Extension { SerializationErrors.TRANSIENT_IS_REDUNDANT, "Property does not have backing field which makes it non-serializable and therefore @Transient is redundant" ) + MAP.put( + SerializationErrors.JSON_FORMAT_REDUNDANT_DEFAULT, + "Redundant creation of Json default format. Creating instances for each usage can be slow." + ) + MAP.put( + SerializationErrors.JSON_FORMAT_REDUNDANT, + "Redundant creation of Json format. Creating instances for each usage can be slow." + ) MAP.put( SerializationErrors.INCORRECT_TRANSIENT, "@kotlin.jvm.Transient does not affect @Serializable classes. Please use @kotlinx.serialization.Transient instead." @@ -96,4 +104,4 @@ object SerializationPluginErrorsRendering : DefaultErrorMessages.Extension { Renderers.STRING ) } -} \ No newline at end of file +} diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/AbstractSerializationIrBytecodeListingTest.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/AbstractSerializationIrBytecodeListingTest.kt index c56ba1b6cf2..18e7585f369 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/AbstractSerializationIrBytecodeListingTest.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/AbstractSerializationIrBytecodeListingTest.kt @@ -13,7 +13,7 @@ import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationComp import java.io.File abstract class AbstractSerializationIrBytecodeListingTest : AbstractAsmLikeInstructionListingTest() { - private val runtimeLibraryPath = getSerializationLibraryRuntimeJar() + private val coreLibraryPath = getSerializationCoreLibraryJar() override fun getExpectedTextFileName(wholeFile: File): String { return wholeFile.nameWithoutExtension + ".ir.txt" @@ -23,6 +23,6 @@ abstract class AbstractSerializationIrBytecodeListingTest : AbstractAsmLikeInstr override fun setupEnvironment(environment: KotlinCoreEnvironment) { SerializationComponentRegistrar.registerExtensions(environment.project) - environment.updateClasspath(listOf(JvmClasspathRoot(runtimeLibraryPath!!))) + environment.updateClasspath(listOf(JvmClasspathRoot(coreLibraryPath!!))) } } diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/AbstractSerializationPluginBytecodeListingTest.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/AbstractSerializationPluginBytecodeListingTest.kt index 551448ce745..e41118aacda 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/AbstractSerializationPluginBytecodeListingTest.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/AbstractSerializationPluginBytecodeListingTest.kt @@ -5,17 +5,16 @@ package org.jetbrains.kotlinx.serialization -import junit.framework.TestCase import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot import org.jetbrains.kotlin.codegen.AbstractAsmLikeInstructionListingTest import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationComponentRegistrar abstract class AbstractSerializationPluginBytecodeListingTest : AbstractAsmLikeInstructionListingTest() { - private val runtimeLibraryPath = getSerializationLibraryRuntimeJar() + private val coreLibraryPath = getSerializationCoreLibraryJar() override fun setupEnvironment(environment: KotlinCoreEnvironment) { SerializationComponentRegistrar.registerExtensions(environment.project) - environment.updateClasspath(listOf(JvmClasspathRoot(runtimeLibraryPath!!))) + environment.updateClasspath(listOf(JvmClasspathRoot(coreLibraryPath!!))) } -} \ No newline at end of file +} diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/AbstractSerializationPluginDiagnosticTest.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/AbstractSerializationPluginDiagnosticTest.kt index f4c6607c75e..3961143efb0 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/AbstractSerializationPluginDiagnosticTest.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/AbstractSerializationPluginDiagnosticTest.kt @@ -13,10 +13,10 @@ import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationComp @OptIn(ObsoleteTestInfrastructure::class) abstract class AbstractSerializationPluginDiagnosticTest : AbstractDiagnosticsTest() { - private val runtimeLibraryPath = getSerializationLibraryRuntimeJar() + private val coreLibraryPath = getSerializationCoreLibraryJar() override fun setupEnvironment(environment: KotlinCoreEnvironment) { SerializationComponentRegistrar.registerExtensions(environment.project) - environment.updateClasspath(listOf(JvmClasspathRoot(runtimeLibraryPath!!))) + environment.updateClasspath(listOf(JvmClasspathRoot(coreLibraryPath!!))) } } diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/RuntimeSearch.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/RuntimeSearch.kt index 3f97a5fdb29..18e7cc91ee6 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/RuntimeSearch.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/RuntimeSearch.kt @@ -13,25 +13,25 @@ import java.io.File import kotlin.test.assertTrue class RuntimeLibraryInClasspathTest { - private val runtimeLibraryPath = getSerializationLibraryRuntimeJar() + private val coreLibraryPath = getSerializationCoreLibraryJar() @Test fun testRuntimeLibraryExists() { TestCase.assertNotNull( "kotlinx-serialization runtime library is not found. Make sure it is present in test classpath", - runtimeLibraryPath + coreLibraryPath ) } @Test fun testRuntimeHasSufficientVersion() { - val version = VersionReader.getVersionsFromManifest(runtimeLibraryPath!!) + val version = VersionReader.getVersionsFromManifest(coreLibraryPath!!) assertTrue(version.currentCompilerMatchRequired(), "Runtime version too high") assertTrue(version.implementationVersionMatchSupported(), "Runtime version too low") } } -internal fun getSerializationLibraryRuntimeJar(): File? = try { +internal fun getSerializationCoreLibraryJar(): File? = try { PathUtil.getResourcePathForClass(Class.forName("kotlinx.serialization.KSerializer")) } catch (e: ClassNotFoundException) { null diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/codegen/Basic.ir.txt b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/codegen/Basic.ir.txt index 8d781abb2a7..67e8d9c59a5 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/codegen/Basic.ir.txt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/codegen/Basic.ir.txt @@ -165,10 +165,6 @@ public final class ListOfUsers$$serializer : java/lang/Object, kotlinx/serializa public kotlinx.serialization.descriptors.SerialDescriptor getDescriptor() - public ListOfUsers patch(kotlinx.serialization.encoding.Decoder decoder, ListOfUsers old) - - public java.lang.Object patch(kotlinx.serialization.encoding.Decoder decoder, java.lang.Object old) - public void serialize(kotlinx.serialization.encoding.Encoder encoder, ListOfUsers value) { LABEL (L0) ALOAD (1) @@ -276,18 +272,19 @@ public final class ListOfUsers : java/lang/Object { public void (int seen1, java.util.List list, kotlinx.serialization.internal.SerializationConstructorMarker serializationConstructorMarker) { LABEL (L0) LINENUMBER (12) - ALOAD (0) - INVOKESPECIAL (java/lang/Object, , ()V) + ICONST_1 + ICONST_1 + ILOAD (1) + IAND + IF_ICMPEQ (L1) ILOAD (1) ICONST_1 - IAND - IFNE (L1) - NEW - DUP - LDC (list) - INVOKESPECIAL (kotlinx/serialization/MissingFieldException, , (Ljava/lang/String;)V) - ATHROW + GETSTATIC (INSTANCE, LListOfUsers$$serializer;) + INVOKEVIRTUAL (ListOfUsers$$serializer, getDescriptor, ()Lkotlinx/serialization/descriptors/SerialDescriptor;) + INVOKESTATIC (kotlinx/serialization/internal/PluginExceptionsKt, throwMissingFieldException, (IILkotlinx/serialization/descriptors/SerialDescriptor;)V) LABEL (L1) + ALOAD (0) + INVOKESPECIAL (java/lang/Object, , ()V) ALOAD (0) ALOAD (2) PUTFIELD (list, Ljava/util/List;) @@ -453,10 +450,6 @@ public final class OptionalUser$$serializer : java/lang/Object, kotlinx/serializ public kotlinx.serialization.descriptors.SerialDescriptor getDescriptor() - public OptionalUser patch(kotlinx.serialization.encoding.Decoder decoder, OptionalUser old) - - public java.lang.Object patch(kotlinx.serialization.encoding.Decoder decoder, java.lang.Object old) - public void serialize(kotlinx.serialization.encoding.Encoder encoder, OptionalUser value) { LABEL (L0) ALOAD (1) @@ -608,31 +601,41 @@ public final class OptionalUser : java/lang/Object { public void (int seen1, User user, kotlinx.serialization.internal.SerializationConstructorMarker serializationConstructorMarker) { LABEL (L0) LINENUMBER (9) + ICONST_0 + ILOAD (1) + IAND + IFEQ (L1) + ILOAD (1) + ICONST_0 + GETSTATIC (INSTANCE, LOptionalUser$$serializer;) + INVOKEVIRTUAL (OptionalUser$$serializer, getDescriptor, ()Lkotlinx/serialization/descriptors/SerialDescriptor;) + INVOKESTATIC (kotlinx/serialization/internal/PluginExceptionsKt, throwMissingFieldException, (IILkotlinx/serialization/descriptors/SerialDescriptor;)V) + LABEL (L1) ALOAD (0) INVOKESPECIAL (java/lang/Object, , ()V) ILOAD (1) ICONST_1 IAND - IFNE (L1) + IFNE (L2) ALOAD (0) - LABEL (L2) + LABEL (L3) LINENUMBER (10) NEW DUP LDC () LDC () INVOKESPECIAL (User, , (Ljava/lang/String;Ljava/lang/String;)V) - LABEL (L3) + LABEL (L4) LINENUMBER (9) PUTFIELD (user, LUser;) - GOTO (L4) - LABEL (L1) + GOTO (L5) + LABEL (L2) ALOAD (0) ALOAD (2) PUTFIELD (user, LUser;) - LABEL (L4) - RETURN LABEL (L5) + RETURN + LABEL (L6) } public void () { @@ -829,10 +832,6 @@ public final class User$$serializer : java/lang/Object, kotlinx/serialization/in public kotlinx.serialization.descriptors.SerialDescriptor getDescriptor() - public User patch(kotlinx.serialization.encoding.Decoder decoder, User old) - - public java.lang.Object patch(kotlinx.serialization.encoding.Decoder decoder, java.lang.Object old) - public void serialize(kotlinx.serialization.encoding.Encoder encoder, User value) { LABEL (L0) ALOAD (1) @@ -948,36 +947,27 @@ public final class User : java/lang/Object { public void (int seen1, java.lang.String firstName, java.lang.String lastName, kotlinx.serialization.internal.SerializationConstructorMarker serializationConstructorMarker) { LABEL (L0) LINENUMBER (6) + ICONST_3 + ICONST_3 + ILOAD (1) + IAND + IF_ICMPEQ (L1) + ILOAD (1) + ICONST_3 + GETSTATIC (INSTANCE, LUser$$serializer;) + INVOKEVIRTUAL (User$$serializer, getDescriptor, ()Lkotlinx/serialization/descriptors/SerialDescriptor;) + INVOKESTATIC (kotlinx/serialization/internal/PluginExceptionsKt, throwMissingFieldException, (IILkotlinx/serialization/descriptors/SerialDescriptor;)V) + LABEL (L1) ALOAD (0) INVOKESPECIAL (java/lang/Object, , ()V) - ILOAD (1) - ICONST_1 - IAND - IFNE (L1) - NEW - DUP - LDC (firstName) - INVOKESPECIAL (kotlinx/serialization/MissingFieldException, , (Ljava/lang/String;)V) - ATHROW - LABEL (L1) ALOAD (0) ALOAD (2) PUTFIELD (firstName, Ljava/lang/String;) - ILOAD (1) - ICONST_2 - IAND - IFNE (L2) - NEW - DUP - LDC (lastName) - INVOKESPECIAL (kotlinx/serialization/MissingFieldException, , (Ljava/lang/String;)V) - ATHROW - LABEL (L2) ALOAD (0) ALOAD (3) PUTFIELD (lastName, Ljava/lang/String;) RETURN - LABEL (L3) + LABEL (L2) } public final java.lang.String getFirstName() diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/codegen/Basic.txt b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/codegen/Basic.txt index da0e96240fb..61386440f9a 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/codegen/Basic.txt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/codegen/Basic.txt @@ -144,10 +144,6 @@ public final class ListOfUsers$$serializer : java/lang/Object, kotlinx/serializa public kotlinx.serialization.descriptors.SerialDescriptor getDescriptor() - public ListOfUsers patch(kotlinx.serialization.encoding.Decoder decoder, ListOfUsers old) - - public java.lang.Object patch(kotlinx.serialization.encoding.Decoder p0, java.lang.Object p1) - public void serialize(kotlinx.serialization.encoding.Encoder encoder, ListOfUsers value) { LABEL (L0) ALOAD (1) @@ -241,19 +237,20 @@ public final class ListOfUsers : java/lang/Object { public void (int seen1, java.util.List list, kotlinx.serialization.internal.SerializationConstructorMarker serializationConstructorMarker) { LABEL (L0) - ALOAD (0) - INVOKESPECIAL (java/lang/Object, , ()V) + ICONST_1 + DUP + ILOAD (1) + IAND + IF_ICMPEQ (L1) ILOAD (1) ICONST_1 - IAND - IFNE (L1) - NEW - DUP - LDC (list) - INVOKESPECIAL (kotlinx/serialization/MissingFieldException, , (Ljava/lang/String;)V) + GETSTATIC (INSTANCE, LListOfUsers$$serializer;) CHECKCAST - ATHROW + INVOKEINTERFACE (kotlinx/serialization/KSerializer, getDescriptor, ()Lkotlinx/serialization/descriptors/SerialDescriptor;) + INVOKESTATIC (kotlinx/serialization/internal/PluginExceptionsKt, throwMissingFieldException, (IILkotlinx/serialization/descriptors/SerialDescriptor;)V) LABEL (L1) + ALOAD (0) + INVOKESPECIAL (java/lang/Object, , ()V) ALOAD (0) ALOAD (2) PUTFIELD (list, Ljava/util/List;) @@ -427,10 +424,6 @@ public final class OptionalUser$$serializer : java/lang/Object, kotlinx/serializ public kotlinx.serialization.descriptors.SerialDescriptor getDescriptor() - public OptionalUser patch(kotlinx.serialization.encoding.Decoder decoder, OptionalUser old) - - public java.lang.Object patch(kotlinx.serialization.encoding.Decoder p0, java.lang.Object p1) - public void serialize(kotlinx.serialization.encoding.Encoder encoder, OptionalUser value) { LABEL (L0) ALOAD (1) @@ -553,19 +546,31 @@ public final class OptionalUser : java/lang/Object { public void (int seen1, User user, kotlinx.serialization.internal.SerializationConstructorMarker serializationConstructorMarker) { LABEL (L0) + ICONST_0 + DUP + ILOAD (1) + IAND + IF_ICMPEQ (L1) + ILOAD (1) + ICONST_0 + GETSTATIC (INSTANCE, LOptionalUser$$serializer;) + CHECKCAST + INVOKEINTERFACE (kotlinx/serialization/KSerializer, getDescriptor, ()Lkotlinx/serialization/descriptors/SerialDescriptor;) + INVOKESTATIC (kotlinx/serialization/internal/PluginExceptionsKt, throwMissingFieldException, (IILkotlinx/serialization/descriptors/SerialDescriptor;)V) + LABEL (L1) ALOAD (0) INVOKESPECIAL (java/lang/Object, , ()V) ILOAD (1) ICONST_1 IAND - IFEQ (L1) + IFEQ (L2) ALOAD (0) ALOAD (2) PUTFIELD (user, LUser;) - GOTO (L2) - LABEL (L1) + GOTO (L3) + LABEL (L2) ALOAD (0) - LABEL (L3) + LABEL (L4) LINENUMBER (10) NEW DUP @@ -573,9 +578,9 @@ public final class OptionalUser : java/lang/Object { LDC () INVOKESPECIAL (User, , (Ljava/lang/String;Ljava/lang/String;)V) PUTFIELD (user, LUser;) - LABEL (L2) + LABEL (L3) RETURN - LABEL (L4) + LABEL (L5) } public final User getUser() @@ -781,10 +786,6 @@ public final class User$$serializer : java/lang/Object, kotlinx/serialization/in public kotlinx.serialization.descriptors.SerialDescriptor getDescriptor() - public User patch(kotlinx.serialization.encoding.Decoder decoder, User old) - - public java.lang.Object patch(kotlinx.serialization.encoding.Decoder p0, java.lang.Object p1) - public void serialize(kotlinx.serialization.encoding.Encoder encoder, User value) { LABEL (L0) ALOAD (1) @@ -886,38 +887,28 @@ public final class User : java/lang/Object { public void (int seen1, java.lang.String firstName, java.lang.String lastName, kotlinx.serialization.internal.SerializationConstructorMarker serializationConstructorMarker) { LABEL (L0) + ICONST_3 + DUP + ILOAD (1) + IAND + IF_ICMPEQ (L1) + ILOAD (1) + ICONST_3 + GETSTATIC (INSTANCE, LUser$$serializer;) + CHECKCAST + INVOKEINTERFACE (kotlinx/serialization/KSerializer, getDescriptor, ()Lkotlinx/serialization/descriptors/SerialDescriptor;) + INVOKESTATIC (kotlinx/serialization/internal/PluginExceptionsKt, throwMissingFieldException, (IILkotlinx/serialization/descriptors/SerialDescriptor;)V) + LABEL (L1) ALOAD (0) INVOKESPECIAL (java/lang/Object, , ()V) - ILOAD (1) - ICONST_1 - IAND - IFNE (L1) - NEW - DUP - LDC (firstName) - INVOKESPECIAL (kotlinx/serialization/MissingFieldException, , (Ljava/lang/String;)V) - CHECKCAST - ATHROW - LABEL (L1) ALOAD (0) ALOAD (2) PUTFIELD (firstName, Ljava/lang/String;) - ILOAD (1) - ICONST_2 - IAND - IFNE (L2) - NEW - DUP - LDC (lastName) - INVOKESPECIAL (kotlinx/serialization/MissingFieldException, , (Ljava/lang/String;)V) - CHECKCAST - ATHROW - LABEL (L2) ALOAD (0) ALOAD (3) PUTFIELD (lastName, Ljava/lang/String;) RETURN - LABEL (L3) + LABEL (L2) } public final java.lang.String getFirstName() diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/DuplicateSerialName.txt b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/DuplicateSerialName.txt index e97115b80ae..ae4b5da28e0 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/DuplicateSerialName.txt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/DuplicateSerialName.txt @@ -15,7 +15,6 @@ package public open override /*1*/ /*synthesized*/ fun deserialize(/*0*/ decoder: kotlinx.serialization.encoding.Decoder): Derived public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int - @kotlin.Deprecated(level = DeprecationLevel.ERROR, message = "Patch function is deprecated for removal since this functionality is no longer supported by serializer.Some formats may provide implementation-specific patching in their Decoders.") public open override /*1*/ /*fake_override*/ fun patch(/*0*/ decoder: kotlinx.serialization.encoding.Decoder, /*1*/ old: Derived): Derived public open override /*1*/ /*synthesized*/ fun serialize(/*0*/ encoder: kotlinx.serialization.encoding.Encoder, /*1*/ value: Derived): kotlin.Unit public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun typeParametersSerializers(): kotlin.Array> @@ -45,7 +44,6 @@ package public open override /*1*/ /*synthesized*/ fun deserialize(/*0*/ decoder: kotlinx.serialization.encoding.Decoder): Parent public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int - @kotlin.Deprecated(level = DeprecationLevel.ERROR, message = "Patch function is deprecated for removal since this functionality is no longer supported by serializer.Some formats may provide implementation-specific patching in their Decoders.") public open override /*1*/ /*fake_override*/ fun patch(/*0*/ decoder: kotlinx.serialization.encoding.Decoder, /*1*/ old: Parent): Parent public open override /*1*/ /*synthesized*/ fun serialize(/*0*/ encoder: kotlinx.serialization.encoding.Encoder, /*1*/ value: Parent): kotlin.Unit public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun typeParametersSerializers(): kotlin.Array> diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/LazyRecursionBug.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/LazyRecursionBug.kt index d2455d7f342..36c4e55b8bb 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/LazyRecursionBug.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/LazyRecursionBug.kt @@ -1,4 +1,5 @@ // This test enshures that analysis ends up without compiler exceptions +// !DIAGNOSTICS: -EXPERIMENTAL_API_USAGE import kotlinx.serialization.* diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/LazyRecursionBug.txt b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/LazyRecursionBug.txt index 9785192e6af..ee1732239e6 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/LazyRecursionBug.txt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/LazyRecursionBug.txt @@ -13,7 +13,6 @@ package public open override /*1*/ /*synthesized*/ fun deserialize(/*0*/ decoder: kotlinx.serialization.encoding.Decoder): Digest public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int - @kotlin.Deprecated(level = DeprecationLevel.ERROR, message = "Patch function is deprecated for removal since this functionality is no longer supported by serializer.Some formats may provide implementation-specific patching in their Decoders.") public open override /*1*/ /*fake_override*/ fun patch(/*0*/ decoder: kotlinx.serialization.encoding.Decoder, /*1*/ old: Digest): Digest public open override /*1*/ /*synthesized*/ fun serialize(/*0*/ encoder: kotlinx.serialization.encoding.Encoder, /*1*/ value: Digest): kotlin.Unit public final /*synthesized*/ fun serializer(): kotlinx.serialization.KSerializer public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NoSuitableCtorInParent.txt b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NoSuitableCtorInParent.txt index e12efb7ccfd..1c4700e479b 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NoSuitableCtorInParent.txt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NoSuitableCtorInParent.txt @@ -16,7 +16,6 @@ package public open override /*1*/ /*synthesized*/ fun deserialize(/*0*/ decoder: kotlinx.serialization.encoding.Decoder): Derived public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int - @kotlin.Deprecated(level = DeprecationLevel.ERROR, message = "Patch function is deprecated for removal since this functionality is no longer supported by serializer.Some formats may provide implementation-specific patching in their Decoders.") public open override /*1*/ /*fake_override*/ fun patch(/*0*/ decoder: kotlinx.serialization.encoding.Decoder, /*1*/ old: Derived): Derived public open override /*1*/ /*synthesized*/ fun serialize(/*0*/ encoder: kotlinx.serialization.encoding.Encoder, /*1*/ value: Derived): kotlin.Unit public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun typeParametersSerializers(): kotlin.Array> diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NonSerializable.txt b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NonSerializable.txt index 9dcee6c1988..0dfb58e9182 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NonSerializable.txt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NonSerializable.txt @@ -15,7 +15,6 @@ package public open override /*1*/ /*synthesized*/ fun deserialize(/*0*/ decoder: kotlinx.serialization.encoding.Decoder): Basic public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int - @kotlin.Deprecated(level = DeprecationLevel.ERROR, message = "Patch function is deprecated for removal since this functionality is no longer supported by serializer.Some formats may provide implementation-specific patching in their Decoders.") public open override /*1*/ /*fake_override*/ fun patch(/*0*/ decoder: kotlinx.serialization.encoding.Decoder, /*1*/ old: Basic): Basic public open override /*1*/ /*synthesized*/ fun serialize(/*0*/ encoder: kotlinx.serialization.encoding.Encoder, /*1*/ value: Basic): kotlin.Unit public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun typeParametersSerializers(): kotlin.Array> @@ -45,7 +44,6 @@ package public open override /*1*/ /*synthesized*/ fun deserialize(/*0*/ decoder: kotlinx.serialization.encoding.Decoder): Inside public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int - @kotlin.Deprecated(level = DeprecationLevel.ERROR, message = "Patch function is deprecated for removal since this functionality is no longer supported by serializer.Some formats may provide implementation-specific patching in their Decoders.") public open override /*1*/ /*fake_override*/ fun patch(/*0*/ decoder: kotlinx.serialization.encoding.Decoder, /*1*/ old: Inside): Inside public open override /*1*/ /*synthesized*/ fun serialize(/*0*/ encoder: kotlinx.serialization.encoding.Encoder, /*1*/ value: Inside): kotlin.Unit public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun typeParametersSerializers(): kotlin.Array> @@ -82,7 +80,6 @@ public final class NonSerializable { public open override /*1*/ /*synthesized*/ fun deserialize(/*0*/ decoder: kotlinx.serialization.encoding.Decoder): WithImplicitType public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int - @kotlin.Deprecated(level = DeprecationLevel.ERROR, message = "Patch function is deprecated for removal since this functionality is no longer supported by serializer.Some formats may provide implementation-specific patching in their Decoders.") public open override /*1*/ /*fake_override*/ fun patch(/*0*/ decoder: kotlinx.serialization.encoding.Decoder, /*1*/ old: WithImplicitType): WithImplicitType public open override /*1*/ /*synthesized*/ fun serialize(/*0*/ encoder: kotlinx.serialization.encoding.Encoder, /*1*/ value: WithImplicitType): kotlin.Unit public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun typeParametersSerializers(): kotlin.Array> diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NullabilityIncompatible.txt b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NullabilityIncompatible.txt index 2a5a923ecf3..8dcf020f79e 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NullabilityIncompatible.txt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NullabilityIncompatible.txt @@ -15,7 +15,6 @@ package public open override /*1*/ /*synthesized*/ fun deserialize(/*0*/ decoder: kotlinx.serialization.encoding.Decoder): Foo public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int - @kotlin.Deprecated(level = DeprecationLevel.ERROR, message = "Patch function is deprecated for removal since this functionality is no longer supported by serializer.Some formats may provide implementation-specific patching in their Decoders.") public open override /*1*/ /*fake_override*/ fun patch(/*0*/ decoder: kotlinx.serialization.encoding.Decoder, /*1*/ old: Foo): Foo public open override /*1*/ /*synthesized*/ fun serialize(/*0*/ encoder: kotlinx.serialization.encoding.Encoder, /*1*/ value: Foo): kotlin.Unit public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun typeParametersSerializers(): kotlin.Array> @@ -51,7 +50,6 @@ public final class NopeNullableSerializer : kotlinx.serialization.KSerializer> diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/SerializableEnums.txt b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/SerializableEnums.txt index 80246518bdc..1e4d711f84a 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/SerializableEnums.txt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/SerializableEnums.txt @@ -6,7 +6,6 @@ public object EnumSerializer : kotlinx.serialization.KSerializer> @@ -70,7 +68,6 @@ public object EnumSerializer : kotlinx.serialization.KSerializer> diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/SerializerTypeCompatibleForSpecials.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/SerializerTypeCompatibleForSpecials.kt index ae6e6425f7d..411fb0b81a6 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/SerializerTypeCompatibleForSpecials.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/SerializerTypeCompatibleForSpecials.kt @@ -1,3 +1,4 @@ +// !DIAGNOSTICS: -EXPERIMENTAL_API_USAGE // WITH_RUNTIME // SKIP_TXT @@ -15,4 +16,4 @@ object BazSerializer: KSerializer class Foo1(@Polymorphic val i: Baz) @Serializable -class Foo2(val li: MutableList<@Serializable(with = BazSerializer::class) Baz>) \ No newline at end of file +class Foo2(val li: MutableList<@Serializable(with = BazSerializer::class) Baz>) diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/SerializerTypeIncompatible.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/SerializerTypeIncompatible.kt index 5767ef717ab..d604bcbb3c4 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/SerializerTypeIncompatible.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/SerializerTypeIncompatible.kt @@ -1,3 +1,4 @@ +// !DIAGNOSTICS: -EXPERIMENTAL_API_USAGE // WITH_RUNTIME // SKIP_TXT @@ -32,4 +33,4 @@ class Foo5(@Serializable(with = BazSerializer::class) val i: Bar) @Serializable -class Foo7(@Serializable(with = NullableBazSerializer::class) val i: Bar?) \ No newline at end of file +class Foo7(@Serializable(with = NullableBazSerializer::class) val i: Bar?) diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/Transients.txt b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/Transients.txt index 38dac7a4101..4cd20063cf8 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/Transients.txt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/Transients.txt @@ -19,7 +19,6 @@ package public open override /*1*/ /*synthesized*/ fun deserialize(/*0*/ decoder: kotlinx.serialization.encoding.Decoder): WithTransients public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int - @kotlin.Deprecated(level = DeprecationLevel.ERROR, message = "Patch function is deprecated for removal since this functionality is no longer supported by serializer.Some formats may provide implementation-specific patching in their Decoders.") public open override /*1*/ /*fake_override*/ fun patch(/*0*/ decoder: kotlinx.serialization.encoding.Decoder, /*1*/ old: WithTransients): WithTransients public open override /*1*/ /*synthesized*/ fun serialize(/*0*/ encoder: kotlinx.serialization.encoding.Encoder, /*1*/ value: WithTransients): kotlin.Unit public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun typeParametersSerializers(): kotlin.Array> diff --git a/plugins/kotlin-serialization/kotlin-serialization-ide/build.gradle.kts b/plugins/kotlin-serialization/kotlin-serialization-ide/build.gradle.kts index 4a8e1af0448..1677990b3f4 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-ide/build.gradle.kts +++ b/plugins/kotlin-serialization/kotlin-serialization-ide/build.gradle.kts @@ -19,8 +19,24 @@ dependencies { excludeInAndroidStudio(rootProject) { compileOnly(intellijPluginDep("maven")) } compileOnly(intellijPluginDep("gradle")) - testCompileOnly(intellijDep()) - testRuntimeOnly(intellijDep()) + testCompile(toolsJar()) + testCompile(projectTests(":idea")) + testCompile(projectTests(":compiler:tests-common")) + testCompile(projectTests(":idea:idea-test-framework")) + testCompile(project(":kotlin-test:kotlin-test-junit")) + testCompile(commonDep("junit:junit")) + testCompile(projectTests(":idea:idea-frontend-independent")) + + testImplementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.1.0") + + testRuntimeOnly(intellijCoreDep()) { includeJars("intellij-core") } + + testRuntime(project(":allopen-ide-plugin")) + testRuntime(project(":plugins:parcelize:parcelize-ide")) + testRuntime(project(":sam-with-receiver-ide-plugin")) + testRuntime(project(":noarg-ide-plugin")) + testCompile(intellijDep()) + testCompile(intellijPluginDep("java")) } sourceSets { @@ -29,7 +45,8 @@ sourceSets { } runtimeJar() +testsJar() projectTest(parallel = true) { - -} \ No newline at end of file + workingDir = rootDir +} diff --git a/plugins/kotlin-serialization/kotlin-serialization-ide/resources/messages/KotlinSerializationBundle.properties b/plugins/kotlin-serialization/kotlin-serialization-ide/resources/messages/KotlinSerializationBundle.properties new file mode 100644 index 00000000000..647eed962c7 --- /dev/null +++ b/plugins/kotlin-serialization/kotlin-serialization-ide/resources/messages/KotlinSerializationBundle.properties @@ -0,0 +1,2 @@ +extract.json.to.property=Extract Json format creation to property +replace.with.default.json.format=Replace with default Json format instance diff --git a/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/compiler/diagnostic/JsonFormatRedundantDiagnostic.kt b/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/compiler/diagnostic/JsonFormatRedundantDiagnostic.kt new file mode 100644 index 00000000000..e430ca932f2 --- /dev/null +++ b/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/compiler/diagnostic/JsonFormatRedundantDiagnostic.kt @@ -0,0 +1,96 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlinx.serialization.compiler.diagnostic + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.calls.callUtil.getReceiverExpression +import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall +import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker +import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext +import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument +import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument +import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument +import org.jetbrains.kotlin.idea.imports.importableFqName +import org.jetbrains.kotlin.idea.refactoring.fqName.fqName +import org.jetbrains.kotlin.psi.KtNamedFunction +import org.jetbrains.kotlin.psi.unpackFunctionLiteral +import org.jetbrains.kotlin.resolve.BindingContext + + +class JsonFormatRedundantDiagnostic : CallChecker { + private val jsonFqName = FqName("kotlinx.serialization.json.Json") + private val jsonDefaultFqName = FqName("kotlinx.serialization.json.Json.Default") + private val parameterNameFrom = Name.identifier("from") + private val parameterNameBuilderAction = Name.identifier("builderAction") + + override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { + val functionDescriptor = resolvedCall.resultingDescriptor as? SimpleFunctionDescriptor ?: return + val bindingContext = context.trace.bindingContext + + if (isJsonFormatCreation(functionDescriptor)) { + if (isDefaultFormat(resolvedCall, bindingContext)) { + context.trace.report(SerializationErrors.JSON_FORMAT_REDUNDANT_DEFAULT.on(resolvedCall.call.callElement)) + } + return + } + + val receiverExpression = resolvedCall.getReceiverExpression() ?: return + val receiverResolvedCall = receiverExpression.getResolvedCall(bindingContext) ?: return + val receiverFunctionDescriptor = receiverResolvedCall.resultingDescriptor as? SimpleFunctionDescriptor ?: return + + if (isJsonFormatCreation(receiverFunctionDescriptor) && !isDefaultFormat(receiverResolvedCall, bindingContext)) { + context.trace.report(SerializationErrors.JSON_FORMAT_REDUNDANT.on(receiverExpression.originalElement)) + } + } + + private fun isJsonFormatCreation(descriptor: SimpleFunctionDescriptor): Boolean { + return descriptor.importableFqName == jsonFqName + } + + private fun isDefaultFormat(resolvedCall: ResolvedCall<*>, context: BindingContext): Boolean { + var defaultFrom = false + var emptyBuilder = false + + resolvedCall.valueArguments.forEach { (paramDesc, arg) -> + when (paramDesc.name) { + parameterNameFrom -> defaultFrom = isDefaultFormatArgument(arg, context) + parameterNameBuilderAction -> emptyBuilder = isEmptyFunctionArgument(arg) + } + } + + return defaultFrom && emptyBuilder + } + + private fun isDefaultFormatArgument(arg: ResolvedValueArgument, context: BindingContext): Boolean { + if (arg is DefaultValueArgument) return true + if (arg !is ExpressionValueArgument) return false + val expression = arg.valueArgument?.getArgumentExpression() ?: return false + + val fqName = context[BindingContext.EXPRESSION_TYPE_INFO, expression]?.type?.fqName ?: return false + return fqName == jsonDefaultFqName + } + + private fun isEmptyFunctionArgument(arg: ResolvedValueArgument): Boolean { + if (arg !is ExpressionValueArgument) { + return false + } + val argumentExpression = arg.valueArgument?.getArgumentExpression() ?: return false + + val blockExpression = if (argumentExpression is KtNamedFunction) { + // anonymous functions + argumentExpression.bodyBlockExpression ?: return true + } else { + // function literal + argumentExpression.unpackFunctionLiteral()?.bodyExpression + } + + return blockExpression?.statements?.isEmpty() ?: false + } +} diff --git a/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationIDEContainerContributor.kt b/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationIDEContainerContributor.kt index f5878500e0b..d7ab4564c02 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationIDEContainerContributor.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationIDEContainerContributor.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.container.useInstance import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor import org.jetbrains.kotlin.platform.TargetPlatform +import org.jetbrains.kotlinx.serialization.compiler.diagnostic.JsonFormatRedundantDiagnostic import org.jetbrains.kotlinx.serialization.compiler.diagnostic.SerializationPluginIDEDeclarationChecker class SerializationIDEContainerContributor : StorageComponentContainerContributor { @@ -19,5 +20,6 @@ class SerializationIDEContainerContributor : StorageComponentContainerContributo moduleDescriptor: ModuleDescriptor ) { container.useInstance(SerializationPluginIDEDeclarationChecker()) + container.useInstance(JsonFormatRedundantDiagnostic()) } -} \ No newline at end of file +} diff --git a/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/idea/KotlinSerializationBundle.kt b/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/idea/KotlinSerializationBundle.kt new file mode 100644 index 00000000000..b9f3816385d --- /dev/null +++ b/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/idea/KotlinSerializationBundle.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlinx.serialization.idea + +import org.jetbrains.annotations.NonNls +import org.jetbrains.annotations.PropertyKey +import org.jetbrains.kotlin.util.AbstractKotlinBundle + +@NonNls +private const val BUNDLE = "messages.KotlinSerializationBundle" + +object KotlinSerializationBundle : AbstractKotlinBundle(BUNDLE) { + @JvmStatic + fun message(@NonNls @PropertyKey(resourceBundle = BUNDLE) key: String, vararg params: Any): String = getMessage(key, *params) + + @JvmStatic + fun htmlMessage(@NonNls @PropertyKey(resourceBundle = BUNDLE) key: String, vararg params: Any): String = + getMessage(key, *params).withHtml() +} diff --git a/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/idea/quickfixes/JsonRedundantDefaultQuickFix.kt b/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/idea/quickfixes/JsonRedundantDefaultQuickFix.kt new file mode 100644 index 00000000000..092ac6400dd --- /dev/null +++ b/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/idea/quickfixes/JsonRedundantDefaultQuickFix.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlinx.serialization.idea.quickfixes + +import com.intellij.codeInsight.intention.IntentionAction +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.project.Project +import org.jetbrains.kotlin.diagnostics.Diagnostic +import org.jetbrains.kotlin.idea.quickfix.KotlinQuickFixAction +import org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactory +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlinx.serialization.compiler.diagnostic.SerializationErrors +import org.jetbrains.kotlinx.serialization.idea.KotlinSerializationBundle + +internal class JsonRedundantDefaultQuickFix(expression: KtCallExpression) : KotlinQuickFixAction(expression) { + override fun invoke(project: Project, editor: Editor?, file: KtFile) { + val element = element ?: return + val call = element as? KtCallExpression ?: return + val callee = call.calleeExpression ?: return + call.replace(callee) + } + + override fun getFamilyName(): String = text + + override fun getText(): String = KotlinSerializationBundle.message("replace.with.default.json.format") + + object Factory : KotlinSingleIntentionActionFactory() { + override fun createAction(diagnostic: Diagnostic): IntentionAction? { + if (diagnostic.factory != SerializationErrors.JSON_FORMAT_REDUNDANT_DEFAULT) return null + val castedDiagnostic = SerializationErrors.JSON_FORMAT_REDUNDANT_DEFAULT.cast(diagnostic) + + val element: KtCallExpression = castedDiagnostic.psiElement as? KtCallExpression ?: return null + return JsonRedundantDefaultQuickFix(element) + } + } +} diff --git a/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/idea/quickfixes/JsonRedundantQuickFix.kt b/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/idea/quickfixes/JsonRedundantQuickFix.kt new file mode 100644 index 00000000000..9b4265b5cf5 --- /dev/null +++ b/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/idea/quickfixes/JsonRedundantQuickFix.kt @@ -0,0 +1,79 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlinx.serialization.idea.quickfixes + +import com.intellij.codeInsight.intention.IntentionAction +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.editor.ScrollType +import com.intellij.openapi.project.Project +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.diagnostics.Diagnostic +import org.jetbrains.kotlin.idea.KotlinBundle +import org.jetbrains.kotlin.idea.quickfix.KotlinQuickFixAction +import org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactory +import org.jetbrains.kotlin.idea.refactoring.chooseContainerElementIfNecessary +import org.jetbrains.kotlin.idea.refactoring.getExtractionContainers +import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.* +import org.jetbrains.kotlin.idea.refactoring.introduce.introduceProperty.KotlinIntroducePropertyHandler +import org.jetbrains.kotlin.idea.refactoring.introduce.showErrorHintByKey +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.getOutermostParentContainedIn +import org.jetbrains.kotlinx.serialization.compiler.diagnostic.SerializationErrors +import org.jetbrains.kotlinx.serialization.idea.KotlinSerializationBundle + +internal class JsonRedundantQuickFix(expression: KtCallExpression) : KotlinQuickFixAction(expression) { + override fun invoke(project: Project, editor: Editor?, file: KtFile) { + editor ?: return + val element = element ?: return + + selectContainer(element, project, editor) { + editor.scrollingModel.scrollToCaret(ScrollType.MAKE_VISIBLE) + + val outermostParent = element.getOutermostParentContainedIn(it) + if (outermostParent == null) { + showErrorHintByKey(project, editor, "cannot.refactor.no.container", text) + return@selectContainer + } + KotlinIntroducePropertyHandler().doInvoke(project, editor, file, listOf(element), outermostParent) + } + } + + override fun getFamilyName(): String = text + + override fun getText(): String = KotlinSerializationBundle.message("extract.json.to.property") + + object Factory : KotlinSingleIntentionActionFactory() { + override fun createAction(diagnostic: Diagnostic): IntentionAction? { + if (diagnostic.factory != SerializationErrors.JSON_FORMAT_REDUNDANT) return null + val castedDiagnostic = SerializationErrors.JSON_FORMAT_REDUNDANT.cast(diagnostic) + + val element: KtCallExpression = castedDiagnostic.psiElement as? KtCallExpression ?: return null + return JsonRedundantQuickFix(element) + } + } + + private fun selectContainer(element: PsiElement, project: Project, editor: Editor, onSelect: (PsiElement) -> Unit) { + val parent = element.parent ?: throw AssertionError("Should have at least one parent") + + val containers = parent.getExtractionContainers(strict = true, includeAll = true) + .filter { it is KtClassBody || (it is KtFile && !it.isScript()) } + + if (containers.isEmpty()) { + showErrorHintByKey(project, editor, "cannot.refactor.no.container", text) + return + } + + chooseContainerElementIfNecessary( + containers, + editor, + KotlinBundle.message("title.select.target.code.block"), + true, + { it }, + { onSelect(it) } + ) + } + +} diff --git a/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/idea/quickfixes/SerializationQuickFixContributor.kt b/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/idea/quickfixes/SerializationQuickFixContributor.kt index df870ab45ba..4a1a77bf07d 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/idea/quickfixes/SerializationQuickFixContributor.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/idea/quickfixes/SerializationQuickFixContributor.kt @@ -12,5 +12,7 @@ import org.jetbrains.kotlinx.serialization.compiler.diagnostic.SerializationErro class SerializationQuickFixContributor : QuickFixContributor { override fun registerQuickFixes(quickFixes: QuickFixes) { quickFixes.register(SerializationErrors.INCORRECT_TRANSIENT, AddKotlinxSerializationTransientImportQuickFix.Factory) + quickFixes.register(SerializationErrors.JSON_FORMAT_REDUNDANT_DEFAULT, JsonRedundantDefaultQuickFix.Factory) + quickFixes.register(SerializationErrors.JSON_FORMAT_REDUNDANT, JsonRedundantQuickFix.Factory) } -} \ No newline at end of file +} diff --git a/plugins/kotlin-serialization/kotlin-serialization-ide/test/org/jetbrains/kotlinx/serialization/idea/AbstractSerializationPluginIdeDiagnosticTest.kt b/plugins/kotlin-serialization/kotlin-serialization-ide/test/org/jetbrains/kotlinx/serialization/idea/AbstractSerializationPluginIdeDiagnosticTest.kt new file mode 100644 index 00000000000..768bc1c2e3f --- /dev/null +++ b/plugins/kotlin-serialization/kotlin-serialization-ide/test/org/jetbrains/kotlinx/serialization/idea/AbstractSerializationPluginIdeDiagnosticTest.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlinx.serialization.idea + +import org.jetbrains.kotlin.ObsoleteTestInfrastructure +import org.jetbrains.kotlin.checkers.AbstractDiagnosticsTest +import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment +import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot +import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor +import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationIDEContainerContributor + +@OptIn(ObsoleteTestInfrastructure::class) +abstract class AbstractSerializationPluginIdeDiagnosticTest : AbstractDiagnosticsTest() { + private val coreLibraryPath = getSerializationCoreLibraryJar()!! + private val jsonLibraryPath = getSerializationJsonLibraryJar()!! + + override fun setupEnvironment(environment: KotlinCoreEnvironment) { + if (!StorageComponentContainerContributor.getInstances(project).any { it is SerializationIDEContainerContributor }) { + StorageComponentContainerContributor.registerExtension(project, SerializationIDEContainerContributor()) + } + environment.updateClasspath(listOf(JvmClasspathRoot(coreLibraryPath), JvmClasspathRoot(jsonLibraryPath))) + } +} diff --git a/plugins/kotlin-serialization/kotlin-serialization-ide/test/org/jetbrains/kotlinx/serialization/idea/AbstractSerializationQuickFixTest.kt b/plugins/kotlin-serialization/kotlin-serialization-ide/test/org/jetbrains/kotlinx/serialization/idea/AbstractSerializationQuickFixTest.kt new file mode 100644 index 00000000000..e50e57eae5d --- /dev/null +++ b/plugins/kotlin-serialization/kotlin-serialization-ide/test/org/jetbrains/kotlinx/serialization/idea/AbstractSerializationQuickFixTest.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlinx.serialization.idea + +import org.jetbrains.kotlin.idea.quickfix.AbstractQuickFixTest +import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil + +abstract class AbstractSerializationQuickFixTest : AbstractQuickFixTest() { + override fun setUp() { + super.setUp() + val coreJar = getSerializationCoreLibraryJar()!! + val jsonJar = getSerializationJsonLibraryJar()!! + ConfigLibraryUtil.addLibrary(module, "Serialization core", coreJar.parentFile.absolutePath, arrayOf(coreJar.name)) + ConfigLibraryUtil.addLibrary(module, "Serialization JSON", jsonJar.parentFile.absolutePath, arrayOf(jsonJar.name)) + } + + override fun tearDown() { + ConfigLibraryUtil.removeLibrary(module, "Serialization JSON") + ConfigLibraryUtil.removeLibrary(module, "Serialization core") + + super.tearDown() + } +} diff --git a/plugins/kotlin-serialization/kotlin-serialization-ide/test/org.jetbrains.kotlinx.serialization.idea/AnnotationNamesConsistencyTest.kt b/plugins/kotlin-serialization/kotlin-serialization-ide/test/org/jetbrains/kotlinx/serialization/idea/AnnotationNamesConsistencyTest.kt similarity index 100% rename from plugins/kotlin-serialization/kotlin-serialization-ide/test/org.jetbrains.kotlinx.serialization.idea/AnnotationNamesConsistencyTest.kt rename to plugins/kotlin-serialization/kotlin-serialization-ide/test/org/jetbrains/kotlinx/serialization/idea/AnnotationNamesConsistencyTest.kt diff --git a/plugins/kotlin-serialization/kotlin-serialization-ide/test/org/jetbrains/kotlinx/serialization/idea/RuntimeSearch.kt b/plugins/kotlin-serialization/kotlin-serialization-ide/test/org/jetbrains/kotlinx/serialization/idea/RuntimeSearch.kt new file mode 100644 index 00000000000..88175926f71 --- /dev/null +++ b/plugins/kotlin-serialization/kotlin-serialization-ide/test/org/jetbrains/kotlinx/serialization/idea/RuntimeSearch.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlinx.serialization.idea + +import junit.framework.TestCase +import org.jetbrains.kotlin.utils.PathUtil +import org.jetbrains.kotlinx.serialization.compiler.diagnostic.VersionReader +import org.junit.Test +import java.io.File +import kotlin.test.assertTrue + +class RuntimeLibraryInClasspathTest { + private val runtimeLibraryPath = getSerializationCoreLibraryJar() + + @Test + fun testRuntimeLibraryExists() { + TestCase.assertNotNull( + "kotlinx-serialization runtime library is not found. Make sure it is present in test classpath", + runtimeLibraryPath + ) + } + + @Test + fun testRuntimeHasSufficientVersion() { + val version = VersionReader.getVersionsFromManifest(runtimeLibraryPath!!) + assertTrue(version.currentCompilerMatchRequired(), "Runtime version too high") + assertTrue(version.implementationVersionMatchSupported(), "Runtime version too low") + } +} + +internal fun getSerializationCoreLibraryJar(): File? = try { + PathUtil.getResourcePathForClass(Class.forName("kotlinx.serialization.KSerializer")) +} catch (e: ClassNotFoundException) { + null +} + +internal fun getSerializationJsonLibraryJar(): File? = try { + PathUtil.getResourcePathForClass(Class.forName("kotlinx.serialization.json.Json")) +} catch (e: ClassNotFoundException) { + null +} diff --git a/plugins/kotlin-serialization/kotlin-serialization-ide/test/org/jetbrains/kotlinx/serialization/idea/SerializationPluginIdeDiagnosticTestGenerated.java b/plugins/kotlin-serialization/kotlin-serialization-ide/test/org/jetbrains/kotlinx/serialization/idea/SerializationPluginIdeDiagnosticTestGenerated.java new file mode 100644 index 00000000000..c70643d84f2 --- /dev/null +++ b/plugins/kotlin-serialization/kotlin-serialization-ide/test/org/jetbrains/kotlinx/serialization/idea/SerializationPluginIdeDiagnosticTestGenerated.java @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlinx.serialization.idea; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; +import org.jetbrains.kotlin.test.KotlinTestUtils; +import org.jetbrains.kotlin.test.util.KtTestUtil; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.runner.RunWith; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("plugins/kotlin-serialization/kotlin-serialization-ide/testData/diagnostics") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class SerializationPluginIdeDiagnosticTestGenerated extends AbstractSerializationPluginIdeDiagnosticTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInDiagnostics() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/kotlin-serialization/kotlin-serialization-ide/testData/diagnostics"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @TestMetadata("JsonRedundantFormat.kt") + public void testJsonRedundantFormat() throws Exception { + runTest("plugins/kotlin-serialization/kotlin-serialization-ide/testData/diagnostics/JsonRedundantFormat.kt"); + } +} diff --git a/plugins/kotlin-serialization/kotlin-serialization-ide/test/org/jetbrains/kotlinx/serialization/idea/SerializationQuickFixTestGenerated.java b/plugins/kotlin-serialization/kotlin-serialization-ide/test/org/jetbrains/kotlinx/serialization/idea/SerializationQuickFixTestGenerated.java new file mode 100644 index 00000000000..1d34258d285 --- /dev/null +++ b/plugins/kotlin-serialization/kotlin-serialization-ide/test/org/jetbrains/kotlinx/serialization/idea/SerializationQuickFixTestGenerated.java @@ -0,0 +1,41 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlinx.serialization.idea; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; +import org.jetbrains.kotlin.test.KotlinTestUtils; +import org.jetbrains.kotlin.test.util.KtTestUtil; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.runner.RunWith; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("plugins/kotlin-serialization/kotlin-serialization-ide/testData/quickfix") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class SerializationQuickFixTestGenerated extends AbstractSerializationQuickFixTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInQuickfix() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/kotlin-serialization/kotlin-serialization-ide/testData/quickfix"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), null, true); + } + + @TestMetadata("DefaultFormat.kt") + public void testDefaultFormat() throws Exception { + runTest("plugins/kotlin-serialization/kotlin-serialization-ide/testData/quickfix/DefaultFormat.kt"); + } + + @TestMetadata("DefaultFormatWithAlias.kt") + public void testDefaultFormatWithAlias() throws Exception { + runTest("plugins/kotlin-serialization/kotlin-serialization-ide/testData/quickfix/DefaultFormatWithAlias.kt"); + } +} diff --git a/plugins/kotlin-serialization/kotlin-serialization-ide/testData/diagnostics/JsonRedundantFormat.kt b/plugins/kotlin-serialization/kotlin-serialization-ide/testData/diagnostics/JsonRedundantFormat.kt new file mode 100644 index 00000000000..10bb0fe3f6a --- /dev/null +++ b/plugins/kotlin-serialization/kotlin-serialization-ide/testData/diagnostics/JsonRedundantFormat.kt @@ -0,0 +1,82 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER,-UNUSED_VARIABLE +// SKIP_TXT + +// FILE: test.kt +import kotlinx.serialization.* +import kotlinx.serialization.json.* + +object Instance + +val defaultWarn = Json {} +val receiverWarn = Json {encodeDefaults = true}.encodeToString(Instance) +val noWarnFormat = Json {encodeDefaults = true} +val receiverNoWarn = noWarnFormat.encodeToString(Instance) +val defaultNoWarn = Json.encodeToString(Instance) + +class SomeContainerClass { + val memberDefaultWarn = Json {} + val memberReceiverWarn = Json {encodeDefaults = true}.encodeToString(Instance) + val memberNoWarnFormat = Json {encodeDefaults = true} + val memberReceiverNoWarn = noWarnFormat.encodeToString(Instance) + val memberDefaultNoWarn = Json.encodeToString(Instance) + + fun testDefaultWarnings() { + Json {} + Json() {} + Json {}.encodeToString(Any()) + Json {}.encodeToString(Instance) + Json { /*some comment*/ }.encodeToString(Instance) + val localDefaultFormat = Json {} + Json(Json.Default) {} + Json(Json) {} + Json(Json.Default, {}) + Json(builderAction = {}) + Json(builderAction = fun JsonBuilder.() {}) + Json(builderAction = fun JsonBuilder.() = Unit) + + "{}".let { + Json {}.decodeFromString(it) + } + } + + fun testReceiverWarnings() { + Json {encodeDefaults = true}.encodeToString(Instance) + val encoded = Json {encodeDefaults = true}.encodeToString(Instance) + Json {encodeDefaults = true}.decodeFromString("{}") + Json {encodeDefaults = true}.hashCode() + Json {encodeDefaults = true}.toString() + + Json(noWarnFormat) {encodeDefaults = true}.encodeToString(Instance) + Json(builderAction = {encodeDefaults = true}).encodeToString(Instance) + Json(noWarnFormat, {encodeDefaults = true}).encodeToString(Instance) + Json(builderAction = fun JsonBuilder.() {encodeDefaults = true}).encodeToString(Instance) + + "{}".let { + Json {encodeDefaults = true}.decodeFromString(it) + } + } + + fun testReceiverNoWarnings() { + val localFormat = Json {encodeDefaults = true} + localFormat.encodeToString(Instance) + localFormat.decodeFromString("{}") + localFormat.hashCode() + localFormat.toString() + } + + fun testDefaultNoWarnings() { + val localDefault = Json + Json.encodeToString(Instance) + Json.decodeFromString("{}") + Json.hashCode() + Json.toString() + Json(builderAction = this::builder) + Json(Json.Default, this::builder) + } + + private fun builder(builder: JsonBuilder) { + //now its empty builder + } +} + + diff --git a/plugins/kotlin-serialization/kotlin-serialization-ide/testData/quickfix/DefaultFormat.kt b/plugins/kotlin-serialization/kotlin-serialization-ide/testData/quickfix/DefaultFormat.kt new file mode 100644 index 00000000000..93f3cc25cc0 --- /dev/null +++ b/plugins/kotlin-serialization/kotlin-serialization-ide/testData/quickfix/DefaultFormat.kt @@ -0,0 +1,7 @@ +// "Replace with default Json format instance" "true" +import kotlinx.serialization.* +import kotlinx.serialization.json.* + +fun foo() { + Json {}.encodeToString(Any()) +} diff --git a/plugins/kotlin-serialization/kotlin-serialization-ide/testData/quickfix/DefaultFormat.kt.after b/plugins/kotlin-serialization/kotlin-serialization-ide/testData/quickfix/DefaultFormat.kt.after new file mode 100644 index 00000000000..3ff3fed7a52 --- /dev/null +++ b/plugins/kotlin-serialization/kotlin-serialization-ide/testData/quickfix/DefaultFormat.kt.after @@ -0,0 +1,7 @@ +// "Replace with default Json format instance" "true" +import kotlinx.serialization.* +import kotlinx.serialization.json.* + +fun foo() { + Json.encodeToString(Any()) +} diff --git a/plugins/kotlin-serialization/kotlin-serialization-ide/testData/quickfix/DefaultFormatWithAlias.kt b/plugins/kotlin-serialization/kotlin-serialization-ide/testData/quickfix/DefaultFormatWithAlias.kt new file mode 100644 index 00000000000..377090c85a2 --- /dev/null +++ b/plugins/kotlin-serialization/kotlin-serialization-ide/testData/quickfix/DefaultFormatWithAlias.kt @@ -0,0 +1,8 @@ +// "Replace with default Json format instance" "true" +import kotlinx.serialization.* +import kotlinx.serialization.json.* +import kotlinx.serialization.json.Json as Alias + +fun foo() { + Alias {} +} diff --git a/plugins/kotlin-serialization/kotlin-serialization-ide/testData/quickfix/DefaultFormatWithAlias.kt.after b/plugins/kotlin-serialization/kotlin-serialization-ide/testData/quickfix/DefaultFormatWithAlias.kt.after new file mode 100644 index 00000000000..b6691cbf8cd --- /dev/null +++ b/plugins/kotlin-serialization/kotlin-serialization-ide/testData/quickfix/DefaultFormatWithAlias.kt.after @@ -0,0 +1,8 @@ +// "Replace with default Json format instance" "true" +import kotlinx.serialization.* +import kotlinx.serialization.json.* +import kotlinx.serialization.json.Json as Alias + +fun foo() { + Alias +}