Added caching for local label references.

This commit is contained in:
Chris Hodges 2021-07-19 12:44:46 +02:00
parent 66fa728a45
commit 56697ac1df

View File

@ -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<M68kSymbolReference>(element, TextRange(0, element.textLength)) {
override fun multiResolve(incompleteCode: Boolean): Array<ResolveResult> {
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<M68kLocalLabel> {
val statement = PsiTreeUtil.getStubOrPsiParentOfType(element, M68kStatement::class.java)!!
val results: MutableList<M68kLocalLabel> = 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<M68kLocalLabelReference> {
override fun resolve(ref: M68kLocalLabelReference, incompleteCode: Boolean): Array<ResolveResult> {
val refName = ref.element.symbolName
return findLocalLabels(ref.myElement) { it.name == refName }
.map { PsiElementResolveResult(it) }
.toTypedArray()
}
}
override fun multiResolve(incompleteCode: Boolean): Array<ResolveResult> {
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<Any> {
return findLocalLabels { true }
return findLocalLabels(element) { true }.asSequence()
.distinct()
.map { LookupElementBuilder.createWithIcon(it) }
.toList()
.toTypedArray()
}
private fun findLocalLabels(predicate: (M68kLocalLabel) -> Boolean): List<M68kLocalLabel> {
val statement = PsiTreeUtil.getStubOrPsiParentOfType(element, M68kStatement::class.java)!!
val results: MutableList<M68kLocalLabel> = 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
}
}