Skip to content

Commit a88ba10

Browse files
committed
Add inspection for missing abstract shadows in enum mixin
1 parent 60acb35 commit a88ba10

3 files changed

Lines changed: 97 additions & 1 deletion

File tree

src/main/kotlin/platform/mixin/action/GenerateShadowAction.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ fun createShadowMembers(
151151
}.toList()
152152

153153
// Make the class abstract (if not already)
154-
if (shouldMakeAbstract && !psiClass.hasModifierProperty(PsiModifier.ABSTRACT)) {
154+
if (shouldMakeAbstract && !psiClass.hasModifierProperty(PsiModifier.ABSTRACT) && !psiClass.isEnum) {
155155
val classModifiers = psiClass.modifierList!!
156156
if (classModifiers.hasModifierProperty(PsiModifier.FINAL)) {
157157
classModifiers.setModifierProperty(PsiModifier.FINAL, false)
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
* Minecraft Development for IntelliJ
3+
*
4+
* https://mcdev.io/
5+
*
6+
* Copyright (C) 2026 minecraft-dev
7+
*
8+
* This program is free software: you can redistribute it and/or modify
9+
* it under the terms of the GNU Lesser General Public License as published
10+
* by the Free Software Foundation, version 3.0 only.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Lesser General Public License
18+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
package com.demonwav.mcdev.platform.mixin.inspection.shadow
22+
23+
import com.demonwav.mcdev.platform.mixin.action.insertShadows
24+
import com.demonwav.mcdev.platform.mixin.inspection.MixinInspection
25+
import com.demonwav.mcdev.platform.mixin.util.findOrConstructSourceMethod
26+
import com.demonwav.mcdev.platform.mixin.util.hasAccess
27+
import com.demonwav.mcdev.platform.mixin.util.isMixin
28+
import com.demonwav.mcdev.platform.mixin.util.mixinTargets
29+
import com.demonwav.mcdev.util.findMatchingMethod
30+
import com.intellij.codeInspection.LocalQuickFixOnPsiElement
31+
import com.intellij.codeInspection.ProblemsHolder
32+
import com.intellij.openapi.project.Project
33+
import com.intellij.psi.JavaElementVisitor
34+
import com.intellij.psi.PsiClass
35+
import com.intellij.psi.PsiElement
36+
import com.intellij.psi.PsiFile
37+
import com.intellij.psi.PsiMethod
38+
import org.objectweb.asm.Opcodes
39+
40+
class MissingAbstractShadowsInEnumInspection : MixinInspection() {
41+
override fun getStaticDescription() = "Reports missing abstract shadows in enum mixins"
42+
43+
override fun buildVisitor(holder: ProblemsHolder) = object : JavaElementVisitor() {
44+
override fun visitClass(aClass: PsiClass) {
45+
if (!aClass.isEnum || !aClass.isMixin) {
46+
return
47+
}
48+
49+
val missingShadows = getMissingShadows(holder.project, aClass)
50+
51+
if (missingShadows.isNotEmpty()) {
52+
holder.registerProblem(
53+
aClass.nameIdentifier ?: aClass,
54+
"Missing abstract shadows: ${missingShadows.joinToString { it.name }}",
55+
AddMissingShadowsFix(aClass)
56+
)
57+
}
58+
}
59+
}
60+
61+
private class AddMissingShadowsFix(aClass: PsiClass) : LocalQuickFixOnPsiElement(aClass) {
62+
override fun getFamilyName() = "Add missing shadows"
63+
override fun getText() = "Add missing shadows"
64+
65+
override fun invoke(project: Project, psiFile: PsiFile, startElement: PsiElement, endElement: PsiElement) {
66+
val aClass = startElement as? PsiClass ?: return
67+
val missingShadows = getMissingShadows(project, aClass)
68+
insertShadows(project, aClass, missingShadows.asSequence())
69+
}
70+
}
71+
72+
companion object {
73+
private fun getMissingShadows(project: Project, aClass: PsiClass): List<PsiMethod> {
74+
val requiredShadows = aClass.mixinTargets.flatMap { mixinTarget ->
75+
if (!mixinTarget.hasAccess(Opcodes.ACC_ABSTRACT)) {
76+
return@flatMap emptyList()
77+
}
78+
mixinTarget.methods
79+
.filter { it.hasAccess(Opcodes.ACC_ABSTRACT) }
80+
.map { it.findOrConstructSourceMethod(mixinTarget, project, canDecompile = false) }
81+
}
82+
83+
return requiredShadows.filter {
84+
aClass.findMatchingMethod(it, checkBases = false) == null
85+
}
86+
}
87+
}
88+
}

src/main/resources/META-INF/plugin.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1503,6 +1503,14 @@
15031503
level="ERROR"
15041504
hasStaticDescription="true"
15051505
implementationClass="com.demonwav.mcdev.platform.mixin.inspection.shadow.ShadowFinalInspection"/>
1506+
<localInspection displayName="Missing abstract shadows in enum mixin"
1507+
shortName="MissingAbstractShadowsInEnumMixin"
1508+
groupName="Mixin"
1509+
language="JAVA"
1510+
enabledByDefault="true"
1511+
level="ERROR"
1512+
hasStaticDescription="true"
1513+
implementationClass="com.demonwav.mcdev.platform.mixin.inspection.shadow.MissingAbstractShadowsInEnumInspection"/>
15061514
<!--endregion-->
15071515

15081516
<!--region Mixin Extras -->

0 commit comments

Comments
 (0)