User: joe Date: 14 Apr 26 10:57 Revision: a88ba10c4208e9b05853969b19acd56f91d661cd Summary: Add inspection for missing abstract shadows in enum mixin TeamCity URL: http://ci.mcdev.io:80/viewModification.html?tab=vcsModificationFiles&modId=10520&personal=false Index: src/main/kotlin/platform/mixin/action/GenerateShadowAction.kt =================================================================== --- src/main/kotlin/platform/mixin/action/GenerateShadowAction.kt (revision 60acb35fed6a8e1c8384bd0f999eb2b773a3edf6) +++ src/main/kotlin/platform/mixin/action/GenerateShadowAction.kt (revision a88ba10c4208e9b05853969b19acd56f91d661cd) @@ -151,7 +151,7 @@ }.toList() // Make the class abstract (if not already) - if (shouldMakeAbstract && !psiClass.hasModifierProperty(PsiModifier.ABSTRACT)) { + if (shouldMakeAbstract && !psiClass.hasModifierProperty(PsiModifier.ABSTRACT) && !psiClass.isEnum) { val classModifiers = psiClass.modifierList!! if (classModifiers.hasModifierProperty(PsiModifier.FINAL)) { classModifiers.setModifierProperty(PsiModifier.FINAL, false) Index: src/main/kotlin/platform/mixin/inspection/shadow/MissingAbstractShadowsInEnumInspection.kt =================================================================== --- src/main/kotlin/platform/mixin/inspection/shadow/MissingAbstractShadowsInEnumInspection.kt (revision a88ba10c4208e9b05853969b19acd56f91d661cd) +++ src/main/kotlin/platform/mixin/inspection/shadow/MissingAbstractShadowsInEnumInspection.kt (revision a88ba10c4208e9b05853969b19acd56f91d661cd) @@ -0,0 +1,88 @@ +/* + * Minecraft Development for IntelliJ + * + * https://mcdev.io/ + * + * Copyright (C) 2026 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.shadow + +import com.demonwav.mcdev.platform.mixin.action.insertShadows +import com.demonwav.mcdev.platform.mixin.inspection.MixinInspection +import com.demonwav.mcdev.platform.mixin.util.findOrConstructSourceMethod +import com.demonwav.mcdev.platform.mixin.util.hasAccess +import com.demonwav.mcdev.platform.mixin.util.isMixin +import com.demonwav.mcdev.platform.mixin.util.mixinTargets +import com.demonwav.mcdev.util.findMatchingMethod +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.PsiClass +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiFile +import com.intellij.psi.PsiMethod +import org.objectweb.asm.Opcodes + +class MissingAbstractShadowsInEnumInspection : MixinInspection() { + override fun getStaticDescription() = "Reports missing abstract shadows in enum mixins" + + override fun buildVisitor(holder: ProblemsHolder) = object : JavaElementVisitor() { + override fun visitClass(aClass: PsiClass) { + if (!aClass.isEnum || !aClass.isMixin) { + return + } + + val missingShadows = getMissingShadows(holder.project, aClass) + + if (missingShadows.isNotEmpty()) { + holder.registerProblem( + aClass.nameIdentifier ?: aClass, + "Missing abstract shadows: ${missingShadows.joinToString { it.name }}", + AddMissingShadowsFix(aClass) + ) + } + } + } + + private class AddMissingShadowsFix(aClass: PsiClass) : LocalQuickFixOnPsiElement(aClass) { + override fun getFamilyName() = "Add missing shadows" + override fun getText() = "Add missing shadows" + + override fun invoke(project: Project, psiFile: PsiFile, startElement: PsiElement, endElement: PsiElement) { + val aClass = startElement as? PsiClass ?: return + val missingShadows = getMissingShadows(project, aClass) + insertShadows(project, aClass, missingShadows.asSequence()) + } + } + + companion object { + private fun getMissingShadows(project: Project, aClass: PsiClass): List { + val requiredShadows = aClass.mixinTargets.flatMap { mixinTarget -> + if (!mixinTarget.hasAccess(Opcodes.ACC_ABSTRACT)) { + return@flatMap emptyList() + } + mixinTarget.methods + .filter { it.hasAccess(Opcodes.ACC_ABSTRACT) } + .map { it.findOrConstructSourceMethod(mixinTarget, project, canDecompile = false) } + } + + return requiredShadows.filter { + aClass.findMatchingMethod(it, checkBases = false) == null + } + } + } +} Index: src/main/resources/META-INF/plugin.xml =================================================================== --- src/main/resources/META-INF/plugin.xml (revision 60acb35fed6a8e1c8384bd0f999eb2b773a3edf6) +++ src/main/resources/META-INF/plugin.xml (revision a88ba10c4208e9b05853969b19acd56f91d661cd) @@ -1503,6 +1503,14 @@ level="ERROR" hasStaticDescription="true" implementationClass="com.demonwav.mcdev.platform.mixin.inspection.shadow.ShadowFinalInspection"/> +