From c0e2da6c387fe4dd012305c8b89ab24388933682 Mon Sep 17 00:00:00 2001 From: chrisly42 Date: Tue, 20 Jul 2021 12:31:38 +0200 Subject: [PATCH] Added structure view. --- .../plugins/m68k/psi/M68kLookupUtil.kt | 67 ++++++++++++------- .../structureview/M68kStructureViewElement.kt | 40 +++++++++++ .../structureview/M68kStructureViewFactory.kt | 15 +++++ .../structureview/M68kStructureViewModel.kt | 25 +++++++ src/main/resources/META-INF/plugin.xml | 1 + 5 files changed, 124 insertions(+), 24 deletions(-) create mode 100644 src/main/java/de/platon42/intellij/plugins/m68k/structureview/M68kStructureViewElement.kt create mode 100644 src/main/java/de/platon42/intellij/plugins/m68k/structureview/M68kStructureViewFactory.kt create mode 100644 src/main/java/de/platon42/intellij/plugins/m68k/structureview/M68kStructureViewModel.kt diff --git a/src/main/java/de/platon42/intellij/plugins/m68k/psi/M68kLookupUtil.kt b/src/main/java/de/platon42/intellij/plugins/m68k/psi/M68kLookupUtil.kt index a6b5de8..0d9a827 100644 --- a/src/main/java/de/platon42/intellij/plugins/m68k/psi/M68kLookupUtil.kt +++ b/src/main/java/de/platon42/intellij/plugins/m68k/psi/M68kLookupUtil.kt @@ -10,34 +10,53 @@ import de.platon42.intellij.plugins.m68k.M68kFileType object M68kLookupUtil { fun findAllGlobalLabels(project: Project): List { - return FileTypeIndex.getFiles(M68kFileType.INSTANCE, GlobalSearchScope.allScope(project)).asSequence() - .map { PsiManager.getInstance(project).findFile(it) as M68kFile } - .flatMap { - val results: MutableList = 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 - } + return getFiles(project) + .flatMap(::findAllGlobalLabels) .toList() } + fun findAllGlobalLabels(file: M68kFile): List { + val results: MutableList = ArrayList() + var currentStatement = file.firstChild + while (currentStatement != null) { + val child = currentStatement.firstChild + if (child is M68kGlobalLabel) results.add(child) + currentStatement = PsiTreeUtil.getNextSiblingOfType(currentStatement, M68kStatement::class.java) + } + return results + } + + fun findAllLocalLabels(globalLabel: M68kGlobalLabel): List { + val statement = PsiTreeUtil.getStubOrPsiParentOfType(globalLabel, M68kStatement::class.java)!! + val results: MutableList = ArrayList() + var currentStatement = PsiTreeUtil.getNextSiblingOfType(statement, M68kStatement::class.java) + while (currentStatement != null) { + val child = currentStatement.firstChild + if (child is M68kGlobalLabel) break + if (child is M68kLocalLabel) results.add(child) + currentStatement = PsiTreeUtil.getNextSiblingOfType(currentStatement, M68kStatement::class.java) + } + return results + } + fun findAllSymbolDefinitions(project: Project): List { - return FileTypeIndex.getFiles(M68kFileType.INSTANCE, GlobalSearchScope.allScope(project)).asSequence() - .map { PsiManager.getInstance(project).findFile(it) as M68kFile } - .flatMap { - val results: MutableList = 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 - } + return getFiles(project) + .flatMap(::findAllSymbolDefinitions) .toList() } + + fun findAllSymbolDefinitions(file: M68kFile): List { + val results: MutableList = ArrayList() + var currentStatement = file.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) + } + return results + } + + private fun getFiles(project: Project) = + FileTypeIndex.getFiles(M68kFileType.INSTANCE, GlobalSearchScope.allScope(project)).asSequence() + .map { PsiManager.getInstance(project).findFile(it) as M68kFile } } \ No newline at end of file diff --git a/src/main/java/de/platon42/intellij/plugins/m68k/structureview/M68kStructureViewElement.kt b/src/main/java/de/platon42/intellij/plugins/m68k/structureview/M68kStructureViewElement.kt new file mode 100644 index 0000000..a93ca86 --- /dev/null +++ b/src/main/java/de/platon42/intellij/plugins/m68k/structureview/M68kStructureViewElement.kt @@ -0,0 +1,40 @@ +package de.platon42.intellij.plugins.m68k.structureview + +import com.intellij.ide.structureView.StructureViewTreeElement +import com.intellij.ide.util.treeView.smartTree.TreeElement +import com.intellij.navigation.ItemPresentation +import com.intellij.psi.NavigatablePsiElement +import de.platon42.intellij.plugins.m68k.psi.M68kFile +import de.platon42.intellij.plugins.m68k.psi.M68kGlobalLabel +import de.platon42.intellij.plugins.m68k.psi.M68kLookupUtil +import de.platon42.intellij.plugins.m68k.psi.M68kLookupUtil.findAllLocalLabels + +class M68kStructureViewElement(private val myElement: NavigatablePsiElement) : StructureViewTreeElement { + override fun getValue(): Any = myElement + + override fun getPresentation(): ItemPresentation = myElement.presentation!! + + override fun getChildren(): Array { + return when (myElement) { + is M68kFile -> { + listOf( + M68kLookupUtil.findAllSymbolDefinitions(myElement), + M68kLookupUtil.findAllGlobalLabels(myElement) + ) + .flatten() + .map(::M68kStructureViewElement) + .toTypedArray() + } + is M68kGlobalLabel -> { + findAllLocalLabels(myElement).map(::M68kStructureViewElement).toTypedArray() + } + else -> emptyArray() + } + } + + override fun navigate(requestFocus: Boolean) = myElement.navigate(requestFocus) + + override fun canNavigate() = myElement.canNavigate() + + override fun canNavigateToSource() = myElement.canNavigateToSource() +} \ No newline at end of file diff --git a/src/main/java/de/platon42/intellij/plugins/m68k/structureview/M68kStructureViewFactory.kt b/src/main/java/de/platon42/intellij/plugins/m68k/structureview/M68kStructureViewFactory.kt new file mode 100644 index 0000000..4a63569 --- /dev/null +++ b/src/main/java/de/platon42/intellij/plugins/m68k/structureview/M68kStructureViewFactory.kt @@ -0,0 +1,15 @@ +package de.platon42.intellij.plugins.m68k.structureview + +import com.intellij.ide.structureView.StructureViewBuilder +import com.intellij.ide.structureView.StructureViewModel +import com.intellij.ide.structureView.TreeBasedStructureViewBuilder +import com.intellij.lang.PsiStructureViewFactory +import com.intellij.openapi.editor.Editor +import com.intellij.psi.PsiFile + +class M68kStructureViewFactory : PsiStructureViewFactory { + override fun getStructureViewBuilder(psiFile: PsiFile): StructureViewBuilder = + object : TreeBasedStructureViewBuilder() { + override fun createStructureViewModel(editor: Editor?): StructureViewModel = M68kStructureViewModel(psiFile, editor) + } +} \ No newline at end of file diff --git a/src/main/java/de/platon42/intellij/plugins/m68k/structureview/M68kStructureViewModel.kt b/src/main/java/de/platon42/intellij/plugins/m68k/structureview/M68kStructureViewModel.kt new file mode 100644 index 0000000..eb8b183 --- /dev/null +++ b/src/main/java/de/platon42/intellij/plugins/m68k/structureview/M68kStructureViewModel.kt @@ -0,0 +1,25 @@ +package de.platon42.intellij.plugins.m68k.structureview + +import com.intellij.ide.structureView.StructureViewModel.ElementInfoProvider +import com.intellij.ide.structureView.StructureViewModelBase +import com.intellij.ide.structureView.StructureViewTreeElement +import com.intellij.ide.util.treeView.smartTree.Sorter +import com.intellij.openapi.editor.Editor +import com.intellij.psi.PsiFile +import de.platon42.intellij.plugins.m68k.psi.M68kLocalLabel + +class M68kStructureViewModel(psiFile: PsiFile, editor: Editor?) : + StructureViewModelBase(psiFile, editor, M68kStructureViewElement(psiFile)), ElementInfoProvider { + + override fun isAlwaysShowsPlus(element: StructureViewTreeElement): Boolean { + return false + } + + override fun isAlwaysLeaf(element: StructureViewTreeElement): Boolean { + return element.value is M68kLocalLabel + } + + override fun getSorters(): Array { + return arrayOf(Sorter.ALPHA_SORTER) + } +} \ No newline at end of file diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 0ce46f6..255b9d9 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -25,6 +25,7 @@ +