User: joe Date: 06 Nov 25 14:11 Revision: b41aa256651aa9c5d210f7f507e77781786ea232 Summary: Add inspection for when @Local may use a name TeamCity URL: http://ci.mcdev.io:80/viewModification.html?tab=vcsModificationFiles&modId=10233&personal=false Index: src/main/kotlin/platform/mixin/inspection/mixinextras/LocalArgsOnlyInspection.kt =================================================================== --- src/main/kotlin/platform/mixin/inspection/mixinextras/LocalArgsOnlyInspection.kt (revision ed8b7ae8b661c3bb1966e92ae801b17044d00b57) +++ src/main/kotlin/platform/mixin/inspection/mixinextras/LocalArgsOnlyInspection.kt (revision b41aa256651aa9c5d210f7f507e77781786ea232) @@ -44,7 +44,7 @@ override fun buildVisitor(holder: ProblemsHolder): PsiElementVisitor = object : JavaElementVisitor() { override fun visitAnnotation(localAnnotation: PsiAnnotation) { - if (localAnnotation.qualifiedName != MixinConstants.MixinExtras.LOCAL) { + if (!localAnnotation.hasQualifiedName(MixinConstants.MixinExtras.LOCAL)) { return } if (localAnnotation.findDeclaredAttributeValue("argsOnly")?.constantValue == true) { Index: src/main/kotlin/platform/mixin/inspection/mixinextras/LocalMayUseNameInspection.kt =================================================================== --- src/main/kotlin/platform/mixin/inspection/mixinextras/LocalMayUseNameInspection.kt (revision b41aa256651aa9c5d210f7f507e77781786ea232) +++ src/main/kotlin/platform/mixin/inspection/mixinextras/LocalMayUseNameInspection.kt (revision b41aa256651aa9c5d210f7f507e77781786ea232) @@ -0,0 +1,103 @@ +/* + * 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.mixinextras + +import com.demonwav.mcdev.platform.mixin.handlers.InjectorAnnotationHandler +import com.demonwav.mcdev.platform.mixin.handlers.MixinAnnotationHandler +import com.demonwav.mcdev.platform.mixin.inspection.MixinInspection +import com.demonwav.mcdev.platform.mixin.inspection.injector.ModifyVariableMayUseNameInspection.Companion.getVariableNameToIntroduce +import com.demonwav.mcdev.platform.mixin.inspection.injector.ModifyVariableMayUseNameInspection.ReplaceWithNameFix +import com.demonwav.mcdev.platform.mixin.util.LocalInfo +import com.demonwav.mcdev.platform.mixin.util.MixinConstants +import com.demonwav.mcdev.platform.mixin.util.unwrapLocalRef +import com.demonwav.mcdev.util.mapFirstNotNull +import com.intellij.codeInsight.intention.LowPriorityAction +import com.intellij.codeInspection.LocalQuickFix +import com.intellij.codeInspection.ProblemDescriptor +import com.intellij.codeInspection.ProblemsHolder +import com.intellij.codeInspection.options.OptPane +import com.intellij.modcommand.ModCommand +import com.intellij.modcommand.ModCommandQuickFix +import com.intellij.openapi.project.Project +import com.intellij.psi.JavaElementVisitor +import com.intellij.psi.PsiAnnotation +import com.intellij.psi.PsiMethod +import com.intellij.psi.PsiParameter +import com.intellij.psi.util.parentOfType + +class LocalMayUseNameInspection : MixinInspection() { + @JvmField + var ignoreForImplicitLocals = false + + override fun getStaticDescription() = "Reports @Local relying on index or ordinal that may use a name instead" + + override fun getOptionsPane() = OptPane.pane( + OptPane.checkbox("ignoreForImplicitLocals", "Ignore for implicit locals") + ) + + override fun buildVisitor(holder: ProblemsHolder) = object : JavaElementVisitor() { + override fun visitAnnotation(localAnnotation: PsiAnnotation) { + if (!localAnnotation.hasQualifiedName(MixinConstants.MixinExtras.LOCAL)) { + return + } + + val problemElement = localAnnotation.nameReferenceElement ?: return + + val parameter = localAnnotation.parentOfType() ?: return + val method = parameter.declarationScope as? PsiMethod ?: return + + val localType = parameter.type.unwrapLocalRef() + val localInfo = LocalInfo.fromAnnotation(localType, localAnnotation) + + if (ignoreForImplicitLocals && localInfo.isImplicit) { + return + } + + val (injector, injectorAnnotation) = method.annotations.mapFirstNotNull { annotation -> + (MixinAnnotationHandler.forMixinAnnotation(annotation, holder.project) as? InjectorAnnotationHandler)?.let { it to annotation } + } ?: return + + val variableName = getVariableNameToIntroduce(localInfo, injector, injectorAnnotation) ?: return + + val fixes = mutableListOf(ReplaceWithNameFix(localAnnotation, variableName)) + + if (localInfo.isImplicit) { + fixes += IgnoreForImplicitLocalsFix() + } + + holder.registerProblem( + problemElement, + "@Local can use variable name", + *fixes.toTypedArray(), + ) + } + } + + private inner class IgnoreForImplicitLocalsFix : ModCommandQuickFix(), LowPriorityAction { + override fun getFamilyName() = "Ignore for implicit locals" + + override fun perform(project: Project, descriptor: ProblemDescriptor): ModCommand { + return ModCommand.updateInspectionOption(descriptor.psiElement, this@LocalMayUseNameInspection) { + it.ignoreForImplicitLocals = true + } + } + } +} Index: src/main/resources/META-INF/plugin.xml =================================================================== --- src/main/resources/META-INF/plugin.xml (revision ed8b7ae8b661c3bb1966e92ae801b17044d00b57) +++ src/main/resources/META-INF/plugin.xml (revision b41aa256651aa9c5d210f7f507e77781786ea232) @@ -1466,6 +1466,14 @@ level="WARNING" hasStaticDescription="true" implementationClass="com.demonwav.mcdev.platform.mixin.inspection.mixinextras.LocalArgsOnlyInspection"/> +