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.PsiElementResolveResult
import com.intellij.psi.PsiPolyVariantReferenceBase import com.intellij.psi.PsiPolyVariantReferenceBase
import com.intellij.psi.ResolveResult import com.intellij.psi.ResolveResult
import com.intellij.psi.impl.source.resolve.ResolveCache
import com.intellij.psi.util.PsiTreeUtil import com.intellij.psi.util.PsiTreeUtil
import com.intellij.util.SmartList import com.intellij.util.SmartList
import de.platon42.intellij.plugins.m68k.psi.M68kGlobalLabel 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)) { class M68kLocalLabelReference(element: M68kSymbolReference) : PsiPolyVariantReferenceBase<M68kSymbolReference>(element, TextRange(0, element.textLength)) {
override fun multiResolve(incompleteCode: Boolean): Array<ResolveResult> { companion object {
val refName = myElement.symbolName val INSTANCE = Resolver()
return findLocalLabels { it.name == refName } fun findLocalLabels(element: M68kSymbolReference, predicate: (M68kLocalLabel) -> Boolean): List<M68kLocalLabel> {
.map { PsiElementResolveResult(it) } val statement = PsiTreeUtil.getStubOrPsiParentOfType(element, M68kStatement::class.java)!!
.toTypedArray() 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? { override fun resolve(): PsiElement? {
@ -29,30 +63,10 @@ class M68kLocalLabelReference(element: M68kSymbolReference) : PsiPolyVariantRefe
} }
override fun getVariants(): Array<Any> { override fun getVariants(): Array<Any> {
return findLocalLabels { true } return findLocalLabels(element) { true }.asSequence()
.distinct()
.map { LookupElementBuilder.createWithIcon(it) } .map { LookupElementBuilder.createWithIcon(it) }
.toList()
.toTypedArray() .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
}
} }