Added caching for local label references.
This commit is contained in:
parent
66fa728a45
commit
56697ac1df
@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user