Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/main/kotlin/insight/InsightUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ import org.jetbrains.uast.UClass
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UMethod
import org.jetbrains.uast.UParameter
import org.jetbrains.uast.getParentOfType
import org.jetbrains.uast.toUElementOfType

val UElement.uastEventListener: Pair<UClass, UMethod>?
get() {
// The PsiIdentifier is going to be a method of course!
val method = this.uastParent as? UMethod ?: return null
val method = this.getParentOfType<UMethod>() ?: return null
if (method.javaPsi.hasModifierProperty(PsiModifier.ABSTRACT)) {
// I don't think any implementation allows for abstract method listeners.
return null
Expand Down
8 changes: 7 additions & 1 deletion src/main/kotlin/insight/ListenerLineMarkerProvider.kt
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,13 @@ class ListenerLineMarkerProvider : LineMarkerProviderDescriptor() {
return null
}

val listener = element.toUElementOfType<UIdentifier>()?.uastEventListener ?: return null
val identifier = element.toUElementOfType<UIdentifier>()
if (identifier?.uastParent !is UMethod) {
// We only target the method name
return null
}

val listener = identifier.uastEventListener ?: return null
// By this point, we can guarantee that the action of "go to declaration" will work
// since the PsiClass can be resolved, meaning the event listener is listening to
// a valid event.
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -13,90 +13,43 @@ package com.demonwav.mcdev.platform.sponge.inspection
import com.demonwav.mcdev.platform.sponge.util.SpongeConstants
import com.demonwav.mcdev.platform.sponge.util.isValidSpongeListener
import com.demonwav.mcdev.platform.sponge.util.resolveSpongeGetterTarget
import com.intellij.codeInsight.AutoPopupController
import com.intellij.codeInspection.AbstractBaseUastLocalInspectionTool
import com.intellij.codeInspection.InspectionManager
import com.intellij.codeInspection.ProblemDescriptor
import com.intellij.openapi.project.Project
import com.intellij.psi.JavaPsiFacade
import com.intellij.psi.PsiAnnotation
import com.intellij.psi.PsiMethod
import com.intellij.psi.util.PsiEditorUtil
import com.intellij.structuralsearch.plugin.util.SmartPsiPointer
import com.siyeh.ig.BaseInspection
import com.siyeh.ig.BaseInspectionVisitor
import com.siyeh.ig.InspectionGadgetsFix
import com.intellij.codeInspection.ProblemHighlightType
import org.jetbrains.uast.UMethod

class SpongeInvalidGetterTargetInspection : BaseInspection() {
class SpongeInvalidGetterTargetInspection : AbstractBaseUastLocalInspectionTool() {

override fun getDisplayName() = "@Getter targeted method does not exist"

override fun buildErrorString(vararg infos: Any?) = staticDescription

override fun getStaticDescription() =
"@Getter must target a method accessible from the event class of this listener"

override fun buildVisitor(): BaseInspectionVisitor {
return object : BaseInspectionVisitor() {
override fun visitMethod(method: PsiMethod) {
if (method.parameters.size < 2 || !method.isValidSpongeListener()) {
return
}

for (i in 1 until method.parameters.size) {
val parameter = method.parameters[i]
val getterAnnotation =
parameter.getAnnotation(SpongeConstants.GETTER_ANNOTATION) as? PsiAnnotation ?: continue

val getterTarget = getterAnnotation.resolveSpongeGetterTarget()
if (getterTarget == null) {
val attribute = getterAnnotation.findAttributeValue("value")
if (attribute == null) {
registerError(getterAnnotation, getterAnnotation)
} else {
registerError(attribute)
}
continue
}
}
}
}
}

override fun buildFix(vararg infos: Any?): InspectionGadgetsFix? {
if (infos.isEmpty()) {
return null
}

val annotation = infos[0] as PsiAnnotation
if (!annotation.isWritable) {
override fun checkMethod(
method: UMethod,
manager: InspectionManager,
isOnTheFly: Boolean
): Array<ProblemDescriptor>? {
if (!method.isValidSpongeListener()) {
return null
}

return QuickFix(annotation, "Add target method")
}

class QuickFix(annotation: PsiAnnotation, private val name: String) : InspectionGadgetsFix() {

private val pointer = SmartPsiPointer(annotation)

override fun doFix(project: Project, descriptor: ProblemDescriptor?) {
doFix(project, pointer.element as PsiAnnotation)
}

override fun getFamilyName() = name

override fun getName() = name

companion object {

fun doFix(project: Project, annotation: PsiAnnotation) {
val value = JavaPsiFacade.getElementFactory(project).createExpressionFromText("\"\"", annotation)
val newValue = annotation.setDeclaredAttributeValue(null, value)
val editor = PsiEditorUtil.Service.getInstance().findEditorByPsiElement(annotation) ?: return
editor.caretModel.removeSecondaryCarets()
editor.selectionModel.removeSelection()
editor.caretModel.moveToOffset(newValue.textOffset + 1)
AutoPopupController.getInstance(project).scheduleAutoPopup(editor)
val problems = mutableListOf<ProblemDescriptor>()
for (parameter in method.uastParameters.drop(1)) {
val getter = parameter.findAnnotation(SpongeConstants.GETTER_ANNOTATION) ?: continue
if (getter.resolveSpongeGetterTarget() == null) {
getter.findAttributeValue("value")?.sourcePsi?.let { problemAnchor ->
problems += manager.createProblemDescriptor(
problemAnchor,
this.staticDescription,
isOnTheFly,
null,
ProblemHighlightType.GENERIC_ERROR_OR_WARNING
)
}
}
}
return problems.toTypedArray()
}
}
Loading