Added support for referencing / refactoring of global variables and symbols. Added getPresentation() for structural view, but does not seem to be working yet. Also Find Usages still reports "Unclassified" :-/

This commit is contained in:
2021-07-20 10:31:50 +02:00
parent 5edaf47f28
commit c00a403638
13 changed files with 301 additions and 4 deletions
@@ -1,8 +1,19 @@
package de.platon42.intellij.plugins.m68k.psi
import com.intellij.extapi.psi.ASTWrapperPsiElement
import com.intellij.ide.projectView.PresentationData
import com.intellij.lang.ASTNode
import com.intellij.navigation.ItemPresentation
import de.platon42.intellij.plugins.m68k.M68kIcons
import javax.swing.Icon
abstract class M68kGlobalLabelMixin(node: ASTNode) : ASTWrapperPsiElement(node), M68kGlobalLabel {
override fun getPresentation(): ItemPresentation? {
return PresentationData(name, containingFile?.name, getIcon(0), null)
}
override fun getIcon(flags: Int): Icon? {
return M68kIcons.GLOBAL_LABEL
}
}
@@ -1,12 +1,18 @@
package de.platon42.intellij.plugins.m68k.psi
import com.intellij.extapi.psi.ASTWrapperPsiElement
import com.intellij.ide.projectView.PresentationData
import com.intellij.lang.ASTNode
import com.intellij.navigation.ItemPresentation
import de.platon42.intellij.plugins.m68k.M68kIcons
import javax.swing.Icon
abstract class M68kLocalLabelMixin(node: ASTNode) : ASTWrapperPsiElement(node), M68kLocalLabel {
override fun getPresentation(): ItemPresentation? {
return PresentationData(name, containingFile?.name, getIcon(0), null)
}
override fun getIcon(flags: Int): Icon? {
return M68kIcons.LOCAL_LABEL
}
@@ -0,0 +1,43 @@
package de.platon42.intellij.plugins.m68k.psi
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiManager
import com.intellij.psi.search.FileTypeIndex
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.util.PsiTreeUtil
import de.platon42.intellij.plugins.m68k.M68kFileType
object M68kLookupUtil {
fun findAllGlobalLabels(project: Project): List<M68kGlobalLabel> {
return FileTypeIndex.getFiles(M68kFileType.INSTANCE, GlobalSearchScope.allScope(project)).asSequence()
.map { PsiManager.getInstance(project).findFile(it) as M68kFile }
.flatMap {
val results: MutableList<M68kGlobalLabel> = ArrayList()
var currentStatement = it.firstChild
while (currentStatement != null) {
val child = currentStatement.firstChild
if (child is M68kGlobalLabel) results.add(child)
currentStatement = PsiTreeUtil.getNextSiblingOfType(currentStatement, M68kStatement::class.java)
}
results
}
.toList()
}
fun findAllSymbolDefinitions(project: Project): List<M68kSymbolDefinition> {
return FileTypeIndex.getFiles(M68kFileType.INSTANCE, GlobalSearchScope.allScope(project)).asSequence()
.map { PsiManager.getInstance(project).findFile(it) as M68kFile }
.flatMap {
val results: MutableList<M68kSymbolDefinition> = ArrayList()
var currentStatement = it.firstChild
while (currentStatement != null) {
val child = currentStatement.firstChild
if (child is M68kAssignment) results.add(child.firstChild as M68kSymbolDefinition)
currentStatement = PsiTreeUtil.getNextSiblingOfType(currentStatement, M68kStatement::class.java)
}
results
}
.toList()
}
}
@@ -1,8 +1,19 @@
package de.platon42.intellij.plugins.m68k.psi
import com.intellij.extapi.psi.ASTWrapperPsiElement
import com.intellij.ide.projectView.PresentationData
import com.intellij.lang.ASTNode
import com.intellij.navigation.ItemPresentation
import de.platon42.intellij.plugins.m68k.M68kIcons
import javax.swing.Icon
abstract class M68kSymbolDefinitionMixin(node: ASTNode) : ASTWrapperPsiElement(node), M68kSymbolDefinition {
override fun getPresentation(): ItemPresentation? {
return PresentationData(name, containingFile?.name, getIcon(0), null)
}
override fun getIcon(flags: Int): Icon? {
return M68kIcons.SYMBOL_DEF
}
}
@@ -0,0 +1,66 @@
package de.platon42.intellij.plugins.m68k.refs
import com.intellij.codeInsight.lookup.LookupElementBuilder
import com.intellij.openapi.util.TextRange
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.search.GlobalSearchScope
import de.platon42.intellij.plugins.m68k.psi.M68kGlobalLabel
import de.platon42.intellij.plugins.m68k.psi.M68kLookupUtil
import de.platon42.intellij.plugins.m68k.psi.M68kSymbolDefinition
import de.platon42.intellij.plugins.m68k.psi.M68kSymbolReference
class M68kGlobalLabelSymbolReference(element: M68kSymbolReference) :
PsiPolyVariantReferenceBase<M68kSymbolReference>(element, TextRange(0, element.textLength)) {
companion object {
val INSTANCE = Resolver()
fun findGlobalLabels(element: M68kSymbolReference, predicate: (M68kGlobalLabel) -> Boolean): List<M68kGlobalLabel> {
return M68kLookupUtil.findAllGlobalLabels(element.project).filter(predicate)
}
fun findSymbolDefinitions(element: M68kSymbolReference, predicate: (M68kSymbolDefinition) -> Boolean): List<M68kSymbolDefinition> {
return M68kLookupUtil.findAllSymbolDefinitions(element.project).filter(predicate)
}
private fun getCurrentFileSearchScope(element: PsiElement): GlobalSearchScope {
return GlobalSearchScope.fileScope(element.containingFile.originalFile)
}
}
class Resolver : ResolveCache.PolyVariantResolver<M68kGlobalLabelSymbolReference> {
override fun resolve(ref: M68kGlobalLabelSymbolReference, incompleteCode: Boolean): Array<ResolveResult> {
val refName = ref.element.symbolName
val globalLabelMatches: Array<ResolveResult> = findGlobalLabels(ref.myElement) { it.name == refName }
.map { PsiElementResolveResult(it) }
.toTypedArray()
if (globalLabelMatches.isNotEmpty()) return globalLabelMatches
return findSymbolDefinitions(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? {
val resolveResults = multiResolve(false)
return resolveResults.singleOrNull()?.element
}
override fun getVariants(): Array<Any> {
return listOf(findGlobalLabels(element) { true }, findSymbolDefinitions(element) { true }).asSequence()
.flatten()
.map { LookupElementBuilder.createWithIcon(it) }
.toList()
.toTypedArray()
}
}
@@ -9,10 +9,12 @@ class M68kReferenceContributor : PsiReferenceContributor() {
companion object {
val localLabelReferenceProvider = LocalLabelReferenceProvider()
val globalLabelReferenceProvider = GlobalLabelSymbolReferenceProvider()
}
override fun registerReferenceProviders(registrar: PsiReferenceRegistrar) {
registrar.registerReferenceProvider(PlatformPatterns.psiElement(M68kSymbolReference::class.java), localLabelReferenceProvider)
registrar.registerReferenceProvider(PlatformPatterns.psiElement(M68kSymbolReference::class.java), globalLabelReferenceProvider)
}
class LocalLabelReferenceProvider : PsiReferenceProvider() {
@@ -22,4 +24,12 @@ class M68kReferenceContributor : PsiReferenceContributor() {
return arrayOf(M68kLocalLabelReference(symbolReference))
}
}
class GlobalLabelSymbolReferenceProvider : PsiReferenceProvider() {
override fun getReferencesByElement(element: PsiElement, context: ProcessingContext): Array<PsiReference> {
val symbolReference = element as M68kSymbolReference
if (symbolReference.isLocalLabelRef) return emptyArray()
return arrayOf(M68kGlobalLabelSymbolReference(symbolReference))
}
}
}
@@ -0,0 +1,55 @@
package de.platon42.intellij.plugins.m68k.refs
import com.intellij.codeInsight.lookup.LookupElementBuilder
import com.intellij.openapi.util.TextRange
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.search.GlobalSearchScope
import de.platon42.intellij.plugins.m68k.psi.M68kLookupUtil
import de.platon42.intellij.plugins.m68k.psi.M68kSymbolDefinition
import de.platon42.intellij.plugins.m68k.psi.M68kSymbolReference
class M68kSymbolDefinitionReference(element: M68kSymbolReference) :
PsiPolyVariantReferenceBase<M68kSymbolReference>(element, TextRange(0, element.textLength)) {
companion object {
val INSTANCE = Resolver()
fun findSymbolDefinitions(element: M68kSymbolReference, predicate: (M68kSymbolDefinition) -> Boolean): List<M68kSymbolDefinition> {
return M68kLookupUtil.findAllSymbolDefinitions(element.project).filter(predicate)
}
private fun getCurrentFileSearchScope(element: PsiElement): GlobalSearchScope {
return GlobalSearchScope.fileScope(element.containingFile.originalFile)
}
}
class Resolver : ResolveCache.PolyVariantResolver<M68kSymbolDefinitionReference> {
override fun resolve(ref: M68kSymbolDefinitionReference, incompleteCode: Boolean): Array<ResolveResult> {
val refName = ref.element.symbolName
return findSymbolDefinitions(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? {
val resolveResults = multiResolve(false)
return resolveResults.singleOrNull()?.element
}
override fun getVariants(): Array<Any> {
return findSymbolDefinitions(element) { true }
.map { LookupElementBuilder.createWithIcon(it) }
.toTypedArray()
}
}
@@ -8,10 +8,7 @@ import com.intellij.psi.PsiNamedElement
import com.intellij.psi.tree.TokenSet
import de.platon42.intellij.plugins.m68k.lexer.M68kLexer
import de.platon42.intellij.plugins.m68k.lexer.M68kLexerPrefs
import de.platon42.intellij.plugins.m68k.psi.M68kGlobalLabel
import de.platon42.intellij.plugins.m68k.psi.M68kLocalLabel
import de.platon42.intellij.plugins.m68k.psi.M68kSymbolDefinition
import de.platon42.intellij.plugins.m68k.psi.M68kTypes
import de.platon42.intellij.plugins.m68k.psi.*
import org.jetbrains.annotations.Nls
import org.jetbrains.annotations.NonNls
@@ -40,6 +37,7 @@ class M68kFindUsagesProvider : FindUsagesProvider {
is M68kGlobalLabel -> "global label"
is M68kLocalLabel -> "local label"
is M68kSymbolDefinition -> "symbol definition"
is M68kSymbolReference -> "symbol reference"
else -> ""
}
}
@@ -49,6 +47,7 @@ class M68kFindUsagesProvider : FindUsagesProvider {
is M68kGlobalLabel -> element.name!!
is M68kLocalLabel -> element.name!!
is M68kSymbolDefinition -> element.parent.text
is M68kSymbolReference -> element.symbolName
else -> ""
}
}