diff --git a/src/main/java/de/platon42/intellij/plugins/m68k/refs/M68kLocalLabelReference.kt b/src/main/java/de/platon42/intellij/plugins/m68k/refs/M68kLocalLabelReference.kt index 473dc24..e7a492e 100644 --- a/src/main/java/de/platon42/intellij/plugins/m68k/refs/M68kLocalLabelReference.kt +++ b/src/main/java/de/platon42/intellij/plugins/m68k/refs/M68kLocalLabelReference.kt @@ -6,6 +6,7 @@ import com.intellij.psi.PsiElement import com.intellij.psi.PsiElementResolveResult import com.intellij.psi.PsiPolyVariantReferenceBase import com.intellij.psi.ResolveResult +import com.intellij.psi.impl.source.resolve.ResolveCache import com.intellij.psi.util.PsiTreeUtil import com.intellij.util.SmartList import de.platon42.intellij.plugins.m68k.psi.M68kGlobalLabel @@ -15,12 +16,45 @@ import de.platon42.intellij.plugins.m68k.psi.M68kSymbolReference class M68kLocalLabelReference(element: M68kSymbolReference) : PsiPolyVariantReferenceBase(element, TextRange(0, element.textLength)) { - override fun multiResolve(incompleteCode: Boolean): Array { - val refName = myElement.symbolName + companion object { + val INSTANCE = Resolver() - return findLocalLabels { it.name == refName } - .map { PsiElementResolveResult(it) } - .toTypedArray() + fun findLocalLabels(element: M68kSymbolReference, predicate: (M68kLocalLabel) -> Boolean): List { + val statement = PsiTreeUtil.getStubOrPsiParentOfType(element, M68kStatement::class.java)!! + val results: MutableList = SmartList() + // go backward + var currentStatement = PsiTreeUtil.getPrevSiblingOfType(statement, M68kStatement::class.java) + while (currentStatement != null) { + val child = currentStatement.firstChild + if (child is M68kGlobalLabel) break + if (child is M68kLocalLabel && predicate.invoke(child)) results.add(child) + currentStatement = PsiTreeUtil.getPrevSiblingOfType(currentStatement, M68kStatement::class.java) + } + // go forward + currentStatement = statement + while (currentStatement != null) { + val child = currentStatement.firstChild + if (child is M68kGlobalLabel) break + if (child is M68kLocalLabel && predicate.invoke(child)) results.add(child) + currentStatement = PsiTreeUtil.getNextSiblingOfType(currentStatement, M68kStatement::class.java) + } + return results + } + } + + class Resolver : ResolveCache.PolyVariantResolver { + override fun resolve(ref: M68kLocalLabelReference, incompleteCode: Boolean): Array { + val refName = ref.element.symbolName + + return findLocalLabels(ref.myElement) { it.name == refName } + .map { PsiElementResolveResult(it) } + .toTypedArray() + } + } + + override fun multiResolve(incompleteCode: Boolean): Array { + return ResolveCache.getInstance(element.project) + .resolveWithCaching(this, INSTANCE, false, incompleteCode) } override fun resolve(): PsiElement? { @@ -29,30 +63,10 @@ class M68kLocalLabelReference(element: M68kSymbolReference) : PsiPolyVariantRefe } override fun getVariants(): Array { - return findLocalLabels { true } + return findLocalLabels(element) { true }.asSequence() + .distinct() .map { LookupElementBuilder.createWithIcon(it) } + .toList() .toTypedArray() } - - private fun findLocalLabels(predicate: (M68kLocalLabel) -> Boolean): List { - val statement = PsiTreeUtil.getStubOrPsiParentOfType(element, M68kStatement::class.java)!! - val results: MutableList = SmartList() - // go backward - var currentStatement = PsiTreeUtil.getPrevSiblingOfType(statement, M68kStatement::class.java) - while (currentStatement != null) { - val child = currentStatement.firstChild - if (child is M68kGlobalLabel) break - if (child is M68kLocalLabel && predicate.invoke(child)) results.add(child) - currentStatement = PsiTreeUtil.getPrevSiblingOfType(currentStatement, M68kStatement::class.java) - } - // go forward - currentStatement = statement - while (currentStatement != null) { - val child = currentStatement.firstChild - if (child is M68kGlobalLabel) break - if (child is M68kLocalLabel && predicate.invoke(child)) results.add(child) - currentStatement = PsiTreeUtil.getNextSiblingOfType(currentStatement, M68kStatement::class.java) - } - return results - } } \ No newline at end of file