Skip to content

Commit 0146642

Browse files
committed
mixin: Use TargetReference to properly resolve targets in folding builder
Fixes #278
1 parent 3ed58c8 commit 0146642

File tree

4 files changed

+41
-21
lines changed

4 files changed

+41
-21
lines changed

src/main/kotlin/com/demonwav/mcdev/platform/mixin/folding/MixinFoldingBuilder.kt

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@
1111
package com.demonwav.mcdev.platform.mixin.folding
1212

1313
import com.demonwav.mcdev.platform.mixin.MixinModuleType
14+
import com.demonwav.mcdev.platform.mixin.reference.target.TargetReference
1415
import com.demonwav.mcdev.platform.mixin.util.MixinConstants.Annotations.AT
15-
import com.demonwav.mcdev.platform.mixin.util.MixinMemberReference
16-
import com.demonwav.mcdev.util.constantStringValue
1716
import com.intellij.lang.ASTNode
1817
import com.intellij.lang.folding.CustomFoldingBuilder
1918
import com.intellij.lang.folding.FoldingDescriptor
19+
import com.intellij.navigation.NavigationItem
2020
import com.intellij.openapi.editor.Document
2121
import com.intellij.openapi.util.TextRange
2222
import com.intellij.psi.CommonClassNames
@@ -50,27 +50,25 @@ class MixinFoldingBuilder : CustomFoldingBuilder() {
5050
}
5151
}
5252

53+
private fun formatElement(element: PsiElement): String? {
54+
return when (element) {
55+
is PsiMethod -> PsiFormatUtil.formatMethod(element, PsiSubstitutor.EMPTY,
56+
PsiFormatUtilBase.SHOW_NAME or PsiFormatUtilBase.SHOW_PARAMETERS or SHOW_CONTAINING_CLASS,
57+
PsiFormatUtilBase.SHOW_TYPE)
58+
is PsiVariable -> PsiFormatUtil.formatVariable(element,
59+
PsiFormatUtilBase.SHOW_NAME or SHOW_CONTAINING_CLASS, PsiSubstitutor.EMPTY)
60+
is NavigationItem -> element.presentation?.presentableText
61+
else -> null
62+
}
63+
}
64+
5365
override fun getLanguagePlaceholderText(node: ASTNode, range: TextRange): String {
5466
val element = node.psi
55-
when (element) {
56-
is PsiTypeCastExpression -> {
57-
val castText = element.castType?.text ?: return node.text
58-
return "($castText)"
59-
}
60-
is PsiAnnotationMemberValue -> {
61-
val value = element.constantStringValue ?: return node.text
62-
val member = MixinMemberReference.parse(value)?.resolveMember(element.project, element.resolveScope) ?: return node.text
63-
return when (member) {
64-
is PsiMethod -> PsiFormatUtil.formatMethod(member, PsiSubstitutor.EMPTY,
65-
PsiFormatUtilBase.SHOW_NAME or PsiFormatUtilBase.SHOW_PARAMETERS or SHOW_CONTAINING_CLASS,
66-
PsiFormatUtilBase.SHOW_TYPE)
67-
is PsiVariable -> PsiFormatUtil.formatVariable(member, PsiFormatUtilBase.SHOW_NAME or SHOW_CONTAINING_CLASS, PsiSubstitutor.EMPTY)
68-
else -> member.presentation?.presentableText ?: node.text
69-
}
70-
}
67+
return when (element) {
68+
is PsiTypeCastExpression -> "(${element.castType?.text ?: return node.text})"
69+
is PsiAnnotationMemberValue -> TargetReference.resolveTarget(element)?.let { formatElement(it) } ?: node.text
70+
else -> node.text
7171
}
72-
73-
return node.text
7472
}
7573

7674
override fun buildLanguageFoldRegions(descriptors: MutableList<FoldingDescriptor>, root: PsiElement, document: Document, quick: Boolean) {

src/main/kotlin/com/demonwav/mcdev/platform/mixin/reference/target/ConstructorTargetReference.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
package com.demonwav.mcdev.platform.mixin.reference.target
1212

1313
import com.demonwav.mcdev.util.constantStringValue
14+
import com.demonwav.mcdev.util.findQualifiedClass
1415
import com.demonwav.mcdev.util.internalName
1516
import com.demonwav.mcdev.util.shortName
1617
import com.intellij.codeInsight.completion.JavaLookupElementBuilder
@@ -21,6 +22,11 @@ import com.intellij.psi.PsiNewExpression
2122

2223
object ConstructorTargetReference : TargetReference.Handler<PsiClass>() {
2324

25+
override fun resolveTarget(context: PsiElement): PsiElement? {
26+
val name = context.constantStringValue?.replace('/', '.') ?: return null
27+
return findQualifiedClass(name, context)
28+
}
29+
2430
override fun createFindUsagesVisitor(context: PsiElement, targetClass: PsiClass, checkOnly: Boolean): CollectVisitor<out PsiElement>? {
2531
val name = context.constantStringValue?.replace('/', '.') ?: return null
2632
return FindUsagesVisitor(name, checkOnly)

src/main/kotlin/com/demonwav/mcdev/platform/mixin/reference/target/TargetReference.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@ object TargetReference : PolyReferenceResolver(), MixinReference {
6767
return handler.usesMemberReference()
6868
}
6969

70+
fun resolveTarget(context: PsiElement): PsiElement? {
71+
val handler = getHandler(context.annotationFromValue ?: return null) ?: return null
72+
return handler.resolveTarget(context)
73+
}
74+
7075
private fun getTargetMethod(at: PsiAnnotation): PsiMethod? {
7176
// TODO: Right now this will only work for Mixins with a single target class
7277
val methodValue = at.annotationFromArrayValue?.findDeclaredAttributeValue("method") ?: return null
@@ -116,6 +121,8 @@ object TargetReference : PolyReferenceResolver(), MixinReference {
116121

117122
open fun usesMemberReference() = false
118123

124+
abstract fun resolveTarget(context: PsiElement): PsiElement?
125+
119126
abstract fun createFindUsagesVisitor(context: PsiElement, targetClass: PsiClass,
120127
checkOnly: Boolean): CollectVisitor<out PsiElement>?
121128
abstract fun createCollectUsagesVisitor(): CollectVisitor<T>
@@ -129,6 +136,11 @@ object TargetReference : PolyReferenceResolver(), MixinReference {
129136

130137
protected abstract fun createLookup(targetClass: PsiClass, m: T, owner: PsiClass): LookupElementBuilder
131138

139+
override open fun resolveTarget(context: PsiElement): PsiElement? {
140+
val value = context.constantStringValue ?: return null
141+
return MixinMemberReference.parse(value)?.resolveMember(context.project, context.resolveScope)
142+
}
143+
132144
protected open fun getInternalName(m: QualifiedMember<T>): String {
133145
return m.member.name!!
134146
}

src/main/kotlin/com/demonwav/mcdev/util/MemberReference.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,11 @@ data class MemberReference(val name: String, val descriptor: String? = null,
6262

6363
@Contract(pure = true)
6464
private inline fun <R> resolve(project: Project, scope: GlobalSearchScope, ret: (PsiClass, PsiMember) -> R): R? {
65-
val psiClass = findQualifiedClass(project, this.owner!!, scope) ?: return null
65+
if (this.owner == null) {
66+
throw IllegalStateException("Cannot resolve unqualified member reference (owner == null)")
67+
}
68+
69+
val psiClass = findQualifiedClass(project, this.owner, scope) ?: return null
6670

6771
val member: PsiMember? = if (descriptor != null && descriptor.startsWith('(')) {
6872
// Method, we assume there is only one (since this member descriptor is full qualified)

0 commit comments

Comments
 (0)