From 39145634e6184b05d188219e11651d7436f42e34 Mon Sep 17 00:00:00 2001 From: Him188 Date: Fri, 18 Sep 2020 20:00:47 +0800 Subject: [PATCH] Support UNSERIALIZABLE_TYPE for detecting `@Serializable` annotations --- .../diagnostics/MiraiConsoleErrors.java | 1 + .../MiraiConsoleErrorsRendering.kt | 9 +++-- .../console/compiler/common/utilCommon.kt | 2 ++ .../org/example/myplugin/MyPluginMain.kt | 2 ++ .../diagnostics/PluginDataValuesChecker.kt | 35 +++++++++---------- 5 files changed, 29 insertions(+), 20 deletions(-) diff --git a/tools/compiler-common/src/main/java/net/mamoe/mirai/console/compiler/common/diagnostics/MiraiConsoleErrors.java b/tools/compiler-common/src/main/java/net/mamoe/mirai/console/compiler/common/diagnostics/MiraiConsoleErrors.java index 001c7d4d5..fcf17ee32 100644 --- a/tools/compiler-common/src/main/java/net/mamoe/mirai/console/compiler/common/diagnostics/MiraiConsoleErrors.java +++ b/tools/compiler-common/src/main/java/net/mamoe/mirai/console/compiler/common/diagnostics/MiraiConsoleErrors.java @@ -18,6 +18,7 @@ import static org.jetbrains.kotlin.diagnostics.Severity.ERROR; public interface MiraiConsoleErrors { DiagnosticFactory1 ILLEGAL_PLUGIN_DESCRIPTION = DiagnosticFactory1.create(ERROR); DiagnosticFactory1 NOT_CONSTRUCTABLE_TYPE = DiagnosticFactory1.create(ERROR); + DiagnosticFactory1 UNSERIALIZABLE_TYPE = DiagnosticFactory1.create(ERROR); @Deprecated Object _init = new Object() { diff --git a/tools/compiler-common/src/main/kotlin/net/mamoe/mirai/console/compiler/common/diagnostics/MiraiConsoleErrorsRendering.kt b/tools/compiler-common/src/main/kotlin/net/mamoe/mirai/console/compiler/common/diagnostics/MiraiConsoleErrorsRendering.kt index 6353a08cb..ddab8060e 100644 --- a/tools/compiler-common/src/main/kotlin/net/mamoe/mirai/console/compiler/common/diagnostics/MiraiConsoleErrorsRendering.kt +++ b/tools/compiler-common/src/main/kotlin/net/mamoe/mirai/console/compiler/common/diagnostics/MiraiConsoleErrorsRendering.kt @@ -9,8 +9,7 @@ package net.mamoe.mirai.console.compiler.common.diagnostics -import net.mamoe.mirai.console.compiler.common.diagnostics.MiraiConsoleErrors.ILLEGAL_PLUGIN_DESCRIPTION -import net.mamoe.mirai.console.compiler.common.diagnostics.MiraiConsoleErrors.NOT_CONSTRUCTABLE_TYPE +import net.mamoe.mirai.console.compiler.common.diagnostics.MiraiConsoleErrors.* import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticFactoryToRendererMap import org.jetbrains.kotlin.diagnostics.rendering.Renderers @@ -28,6 +27,12 @@ object MiraiConsoleErrorsRendering : DefaultErrorMessages.Extension { "类型 {0} 无法通过反射直接构造, 需要提供默认值.", Renderers.STRING ) + + put( + UNSERIALIZABLE_TYPE, + "类型 {0} 无法被自动序列化, 需要添加序列化器", + Renderers.STRING + ) } override fun getMap() = MAP diff --git a/tools/compiler-common/src/main/kotlin/net/mamoe/mirai/console/compiler/common/utilCommon.kt b/tools/compiler-common/src/main/kotlin/net/mamoe/mirai/console/compiler/common/utilCommon.kt index 8bdabfe92..4726abb9f 100644 --- a/tools/compiler-common/src/main/kotlin/net/mamoe/mirai/console/compiler/common/utilCommon.kt +++ b/tools/compiler-common/src/main/kotlin/net/mamoe/mirai/console/compiler/common/utilCommon.kt @@ -9,8 +9,10 @@ package net.mamoe.mirai.console.compiler.common +import org.jetbrains.kotlin.name.FqName import kotlin.contracts.contract +val SERIALIZABLE_FQ_NAME = FqName("kotlinx.serialization.Serializable") fun Map.firstValue(): V = this.entries.first().value fun Map.firstKey(): K = this.entries.first().key diff --git a/tools/intellij-plugin/run/projects/test-project/src/main/kotlin/org/example/myplugin/MyPluginMain.kt b/tools/intellij-plugin/run/projects/test-project/src/main/kotlin/org/example/myplugin/MyPluginMain.kt index 5ab9b553e..7dd80641a 100644 --- a/tools/intellij-plugin/run/projects/test-project/src/main/kotlin/org/example/myplugin/MyPluginMain.kt +++ b/tools/intellij-plugin/run/projects/test-project/src/main/kotlin/org/example/myplugin/MyPluginMain.kt @@ -1,5 +1,6 @@ package org.example.myplugin +import kotlinx.serialization.Serializable import net.mamoe.mirai.console.data.AutoSavePluginConfig import net.mamoe.mirai.console.data.value import net.mamoe.mirai.console.plugin.jvm.JvmPluginDescription @@ -26,6 +27,7 @@ object DataTest : AutoSavePluginConfig() { val pp by value() } +@Serializable data class HasDefaultValue( val x: Int = 0, ) diff --git a/tools/intellij-plugin/src/main/kotlin/net/mamoe/mirai/console/intellij/diagnostics/PluginDataValuesChecker.kt b/tools/intellij-plugin/src/main/kotlin/net/mamoe/mirai/console/intellij/diagnostics/PluginDataValuesChecker.kt index 9b0552829..16e6e2cf8 100644 --- a/tools/intellij-plugin/src/main/kotlin/net/mamoe/mirai/console/intellij/diagnostics/PluginDataValuesChecker.kt +++ b/tools/intellij-plugin/src/main/kotlin/net/mamoe/mirai/console/intellij/diagnostics/PluginDataValuesChecker.kt @@ -10,12 +10,10 @@ package net.mamoe.mirai.console.intellij.diagnostics import com.intellij.psi.PsiElement +import net.mamoe.mirai.console.compiler.common.SERIALIZABLE_FQ_NAME import net.mamoe.mirai.console.compiler.common.castOrNull import net.mamoe.mirai.console.compiler.common.diagnostics.MiraiConsoleErrors -import net.mamoe.mirai.console.compiler.common.resolve.PLUGIN_DATA_VALUE_FUNCTIONS_FQ_FQ_NAME -import net.mamoe.mirai.console.compiler.common.resolve.ResolveContextKind -import net.mamoe.mirai.console.compiler.common.resolve.hasNoArgConstructor -import net.mamoe.mirai.console.compiler.common.resolve.resolveContextKind +import net.mamoe.mirai.console.compiler.common.resolve.* import net.mamoe.mirai.console.intellij.resolve.resolveAllCallsWithElement import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor @@ -41,24 +39,25 @@ class PluginDataValuesChecker : DeclarationChecker { (p.isReified || p.resolveContextKind == ResolveContextKind.RESTRICTED_NO_ARG_CONSTRUCTOR) && t is SimpleType }.forEach { (e, callExpr) -> - val (_, t) = e - val classDescriptor = t.constructor.declarationDescriptor?.castOrNull() + val (_, type) = e + val classDescriptor = type.constructor.declarationDescriptor?.castOrNull() - fun getInspectionTarget(): PsiElement { - return callExpr.typeArguments.find { it.references.firstOrNull()?.canonicalText == t.fqName?.toString() } ?: callExpr + val inspectionTarget: PsiElement by lazy { + callExpr.typeArguments.find { it.references.firstOrNull()?.canonicalText == type.fqName?.toString() } ?: callExpr } - fun reportInspection() { - context.report(MiraiConsoleErrors.NOT_CONSTRUCTABLE_TYPE.on( - getInspectionTarget(), - t.fqName?.asString().toString()) + if (classDescriptor == null + || !classDescriptor.hasNoArgConstructor() + ) return@forEach context.report(MiraiConsoleErrors.NOT_CONSTRUCTABLE_TYPE.on( + inspectionTarget, + type.fqName?.asString().toString()) + ) + + if (!classDescriptor.hasAnnotation(SERIALIZABLE_FQ_NAME)) // TODO: 2020/9/18 external serializers + return@forEach context.report(MiraiConsoleErrors.UNSERIALIZABLE_TYPE.on( + inspectionTarget, + type.fqName?.asString().toString()) ) - } - - when { - classDescriptor == null -> reportInspection() - !classDescriptor.hasNoArgConstructor() -> reportInspection() - } } } } \ No newline at end of file