Support ProvideDefaultValueFix for NOT_CONSTRUCTABLE_TYPE

This commit is contained in:
Him188 2020-11-10 11:38:24 +08:00
parent c077719c1b
commit e37ac17b82
9 changed files with 100 additions and 23 deletions

View File

@ -16,13 +16,14 @@ import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.diagnostics.Severity.ERROR import org.jetbrains.kotlin.diagnostics.Severity.ERROR
import org.jetbrains.kotlin.psi.KtCallExpression import org.jetbrains.kotlin.psi.KtCallExpression
import org.jetbrains.kotlin.psi.KtNamedDeclaration import org.jetbrains.kotlin.psi.KtNamedDeclaration
import org.jetbrains.kotlin.psi.KtTypeProjection
object MiraiConsoleErrors { object MiraiConsoleErrors {
@JvmField @JvmField
val ILLEGAL_PLUGIN_DESCRIPTION = create<PsiElement, String>(ERROR) val ILLEGAL_PLUGIN_DESCRIPTION = create<PsiElement, String>(ERROR)
@JvmField @JvmField
val NOT_CONSTRUCTABLE_TYPE = create<PsiElement, KtCallExpression, String>(ERROR) val NOT_CONSTRUCTABLE_TYPE = create<KtTypeProjection, KtCallExpression, String>(ERROR)
@JvmField @JvmField
val UNSERIALIZABLE_TYPE = create<PsiElement, ClassDescriptor>(ERROR) val UNSERIALIZABLE_TYPE = create<PsiElement, ClassDescriptor>(ERROR)

View File

@ -32,7 +32,8 @@ object MiraiConsoleErrorsRendering : DefaultErrorMessages.Extension {
put( put(
NOT_CONSTRUCTABLE_TYPE, NOT_CONSTRUCTABLE_TYPE,
"类型 ''{0}'' 无法通过反射直接构造, 需要提供默认值.", "类型 ''{1}'' 无法通过反射直接构造, 需要提供默认值.",
Renderers.EMPTY,
Renderers.STRING, Renderers.STRING,
) )

View File

@ -10,6 +10,6 @@
package net.mamoe.mirai.console.gradle package net.mamoe.mirai.console.gradle
internal object VersionConstants { internal object VersionConstants {
const val CONSOLE_VERSION = "1.0-RC2-dev-1" // value is written here automatically during build const val CONSOLE_VERSION = "1.0-RC2-dev-3" // value is written here automatically during build
const val CORE_VERSION = "1.3.3" // value is written here automatically during build const val CORE_VERSION = "1.3.3" // value is written here automatically during build
} }

View File

@ -31,17 +31,4 @@ object MyPluginMain : KotlinPlugin(
} }
object DataTest : AutoSavePluginConfig("data") {
val pp by value<NoDefaultValue>()
}
@Serializable
data class HasDefaultValue(
val x: Int = 0,
)
data class NoDefaultValue(
val y: Int,
)
val y = "傻逼 yellow" val y = "傻逼 yellow"

View File

@ -15,3 +15,17 @@ object MySimpleCommand000 : SimpleCommand(
} }
} }
object DataTest : AutoSavePluginConfig("data") {
val pp by value<NoDefaultValue>(NoDefaultValue(1))
}
@Serializable
data class HasDefaultValue(
val x: Int = 0,
)
@Serializable
data class NoDefaultValue(
val y: Int,
)

View File

@ -12,6 +12,7 @@ package net.mamoe.mirai.console.intellij
import com.intellij.codeInsight.intention.IntentionAction import com.intellij.codeInsight.intention.IntentionAction
import net.mamoe.mirai.console.compiler.common.diagnostics.MiraiConsoleErrors import net.mamoe.mirai.console.compiler.common.diagnostics.MiraiConsoleErrors
import net.mamoe.mirai.console.intellij.diagnostics.fix.AddSerializerFix import net.mamoe.mirai.console.intellij.diagnostics.fix.AddSerializerFix
import net.mamoe.mirai.console.intellij.diagnostics.fix.ProvideDefaultValueFix
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
import org.jetbrains.kotlin.idea.quickfix.KotlinIntentionActionsFactory import org.jetbrains.kotlin.idea.quickfix.KotlinIntentionActionsFactory
import org.jetbrains.kotlin.idea.quickfix.QuickFixContributor import org.jetbrains.kotlin.idea.quickfix.QuickFixContributor
@ -29,5 +30,6 @@ class QuickFixRegistrar : QuickFixContributor {
} }
MiraiConsoleErrors.UNSERIALIZABLE_TYPE.registerFactory(AddSerializerFix) MiraiConsoleErrors.UNSERIALIZABLE_TYPE.registerFactory(AddSerializerFix)
MiraiConsoleErrors.NOT_CONSTRUCTABLE_TYPE.registerFactory(ProvideDefaultValueFix)
} }
} }

View File

@ -9,7 +9,6 @@
package net.mamoe.mirai.console.intellij.diagnostics 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.SERIALIZABLE_FQ_NAME
import net.mamoe.mirai.console.compiler.common.castOrNull import net.mamoe.mirai.console.compiler.common.castOrNull
import net.mamoe.mirai.console.compiler.common.diagnostics.MiraiConsoleErrors import net.mamoe.mirai.console.compiler.common.diagnostics.MiraiConsoleErrors
@ -42,10 +41,10 @@ class PluginDataValuesChecker : DeclarationChecker {
val (_, type) = e val (_, type) = e
val classDescriptor = type.constructor.declarationDescriptor?.castOrNull<ClassDescriptor>() val classDescriptor = type.constructor.declarationDescriptor?.castOrNull<ClassDescriptor>()
val inspectionTarget: PsiElement by lazy { val inspectionTarget = kotlin.run {
val fqName = type.fqName ?: return@lazy callExpr val fqName = type.fqName ?: return@run null
callExpr.typeArguments.find { it.typeReference?.isReferencing(fqName) == true } ?: callExpr callExpr.typeArguments.find { it.typeReference?.isReferencing(fqName) == true }
} } ?: return@forEach
if (classDescriptor == null if (classDescriptor == null
|| !classDescriptor.hasNoArgConstructor() || !classDescriptor.hasNoArgConstructor()

View File

@ -38,4 +38,6 @@ fun KtTypeReference.isReferencing(fqName: FqName): Boolean {
return resolveReferencedType()?.getKotlinFqName() == fqName return resolveReferencedType()?.getKotlinFqName() == fqName
} }
fun KtTypeReference.resolveReferencedType() = this.typeElement.castOrNull<KtUserType>()?.referenceExpression?.mainReference?.resolve() val KtTypeReference.referencedUserType: KtUserType? get() = this.typeElement.castOrNull()
fun KtTypeReference.resolveReferencedType() = referencedUserType?.referenceExpression?.mainReference?.resolve()

View File

@ -0,0 +1,71 @@
/*
* Copyright 2019-2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package net.mamoe.mirai.console.intellij.diagnostics.fix
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiFile
import com.intellij.psi.SmartPointerManager
import com.intellij.psi.SmartPsiElementPointer
import net.mamoe.mirai.console.compiler.common.castOrNull
import net.mamoe.mirai.console.compiler.common.diagnostics.MiraiConsoleErrors
import net.mamoe.mirai.console.intellij.resolve.findChild
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.DiagnosticWithParameters2
import org.jetbrains.kotlin.idea.core.moveCaret
import org.jetbrains.kotlin.idea.inspections.KotlinUniversalQuickFix
import org.jetbrains.kotlin.idea.quickfix.KotlinCrossLanguageQuickFixAction
import org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactory
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.endOffset
/**
* @see MiraiConsoleErrors.NOT_CONSTRUCTABLE_TYPE
*/
class ProvideDefaultValueFix(
element: KtCallExpression,
private val typeProjection: SmartPsiElementPointer<KtTypeProjection>,
) : KotlinCrossLanguageQuickFixAction<KtCallExpression>(element), KotlinUniversalQuickFix {
override fun getFamilyName(): String = "Mirai Console"
override fun getText(): String = "添加默认值"
override fun invokeImpl(project: Project, editor: Editor?, file: PsiFile) {
val element = element ?: return
if (file !is KtFile) return
/*
val refereeFqName = element.resolve()?.getKotlinFqName() ?: return
val referee = file.resolveImportReference(refereeFqName).singleOrNull { it is ClassDescriptor } ?: return
ImportInsertHelper.getInstance(project).importDescriptor(file, referee)
*/
val typeName = typeProjection.element?.typeReference?.typeElement?.castOrNull<KtUserType>()?.referencedName ?: return
val argumentList = element.findChild<KtValueArgumentList>() ?: return
val offset = argumentList.leftParenthesis?.endOffset ?: return
project.executeWriteCommand(name) {
argumentList.addArgument(KtPsiFactory(project).createArgument("$typeName()"))
editor?.moveCaret(offset + typeName.length + 1)
}
}
companion object : KotlinSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
val diagnostic1 = diagnostic.castOrNull<DiagnosticWithParameters2<KtTypeProjection, KtCallExpression, *>>() ?: return null
return ProvideDefaultValueFix(diagnostic1.a, SmartPointerManager.createPointer(diagnostic1.psiElement))
}
override fun isApplicableForCodeFragment(): Boolean = false
}
}