User: joe Date: 23 Jul 24 20:26 Revision: 3f58cd903d19a29b4a7100f9fd294f5f00fdd6b8 Summary: Add inspection to report usages of LocalCapture.CAPTURE_FAILEXCEPTION TeamCity URL: http://ci.mcdev.io:80/viewModification.html?tab=vcsModificationFiles&modId=9502&personal=false Index: src/main/kotlin/platform/mixin/inspection/injector/CaptureFailExceptionInspection.kt =================================================================== --- src/main/kotlin/platform/mixin/inspection/injector/CaptureFailExceptionInspection.kt (revision 3f58cd903d19a29b4a7100f9fd294f5f00fdd6b8) +++ src/main/kotlin/platform/mixin/inspection/injector/CaptureFailExceptionInspection.kt (revision 3f58cd903d19a29b4a7100f9fd294f5f00fdd6b8) @@ -0,0 +1,75 @@ +/* + * Minecraft Development for IntelliJ + * + * https://mcdev.io/ + * + * Copyright (C) 2024 minecraft-dev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, version 3.0 only. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.demonwav.mcdev.platform.mixin.inspection.injector + +import com.demonwav.mcdev.platform.mixin.inspection.MixinInspection +import com.demonwav.mcdev.platform.mixin.util.MixinConstants +import com.intellij.codeInspection.LocalQuickFixOnPsiElement +import com.intellij.codeInspection.ProblemsHolder +import com.intellij.openapi.project.Project +import com.intellij.psi.JavaElementVisitor +import com.intellij.psi.JavaPsiFacade +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiEnumConstant +import com.intellij.psi.PsiFile +import com.intellij.psi.PsiReferenceExpression + +class CaptureFailExceptionInspection : MixinInspection() { + override fun getStaticDescription() = """ + Usage of LocalCapture.CAPTURE_FAILEXCEPTION is usually a mistake and should be replaced with + LocalCapture.CAPTURE_FAILHARD. CAPTURE_FAILEXCEPTION generates code which throws an + exception when the callback is reached, if the locals do not match. If this is really what you want, you can + suppress this warning. + """.trimIndent() + + override fun buildVisitor(holder: ProblemsHolder) = object : JavaElementVisitor() { + override fun visitReferenceExpression(expression: PsiReferenceExpression) { + if (expression.referenceName != "CAPTURE_FAILEXCEPTION") { + return + } + val resolved = expression.resolve() as? PsiEnumConstant ?: return + if (resolved.containingClass?.qualifiedName != MixinConstants.Classes.LOCAL_CAPTURE) { + return + } + + holder.registerProblem( + expression, + "Suspicious usage of CAPTURE_FAILEXCEPTION", + ReplaceWithCaptureFailHardFix(expression) + ) + } + } + + private class ReplaceWithCaptureFailHardFix( + expression: PsiReferenceExpression + ) : LocalQuickFixOnPsiElement(expression) { + override fun getFamilyName() = "Replace with CAPTURE_FAILHARD" + + override fun getText() = "Replace with CAPTURE_FAILHARD" + + override fun invoke(project: Project, file: PsiFile, startElement: PsiElement, endElement: PsiElement) { + val captureFailHardText = "${MixinConstants.Classes.LOCAL_CAPTURE}.CAPTURE_FAILHARD" + val captureFailHardExpr = + JavaPsiFacade.getElementFactory(project).createExpressionFromText(captureFailHardText, startElement) + startElement.replace(captureFailHardExpr) + } + } +} Index: src/main/kotlin/platform/mixin/util/MixinConstants.kt =================================================================== --- src/main/kotlin/platform/mixin/util/MixinConstants.kt (revision 3d0a2ca85b757ee723535bc8a12e0b3d5694f221) +++ src/main/kotlin/platform/mixin/util/MixinConstants.kt (revision 3f58cd903d19a29b4a7100f9fd294f5f00fdd6b8) @@ -45,6 +45,7 @@ const val TARGET_SELECTOR_DYNAMIC = "org.spongepowered.asm.mixin.injection.selectors.ITargetSelectorDynamic" const val SELECTOR_ID = "org.spongepowered.asm.mixin.injection.selectors.ITargetSelectorDynamic.SelectorId" const val SHIFT = "org.spongepowered.asm.mixin.injection.At.Shift" + const val LOCAL_CAPTURE = "org.spongepowered.asm.mixin.injection.callback.LocalCapture" const val SERIALIZED_NAME = "com.google.gson.annotations.SerializedName" const val MIXIN_SERIALIZED_NAME = "org.spongepowered.include.$SERIALIZED_NAME" Index: src/main/resources/META-INF/plugin.xml =================================================================== --- src/main/resources/META-INF/plugin.xml (revision 3d0a2ca85b757ee723535bc8a12e0b3d5694f221) +++ src/main/resources/META-INF/plugin.xml (revision 3f58cd903d19a29b4a7100f9fd294f5f00fdd6b8) @@ -1034,6 +1034,14 @@ level="WARNING" hasStaticDescription="true" implementationClass="com.demonwav.mcdev.platform.mixin.inspection.injector.DiscouragedShiftInspection"/> +