Skip to content

Commit

Permalink
Merge pull request #230 from pontem-network/item-presentation
Browse files Browse the repository at this point in the history
Refactor presentation and lookups
  • Loading branch information
mkurnikov authored Nov 8, 2024
2 parents 282b595 + 7a93209 commit 136d6f1
Show file tree
Hide file tree
Showing 26 changed files with 213 additions and 302 deletions.
88 changes: 88 additions & 0 deletions src/main/kotlin/org/move/ide/presentation/Utils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package org.move.ide.presentation

import com.intellij.ide.projectView.PresentationData
import com.intellij.navigation.ItemPresentation
import com.intellij.openapi.util.Iconable
import com.intellij.psi.PsiElement
import org.move.lang.MoveFile
import org.move.lang.core.psi.MvConst
import org.move.lang.core.psi.MvElement
import org.move.lang.core.psi.MvEnumVariant
import org.move.lang.core.psi.MvFunctionLike
import org.move.lang.core.psi.MvModule
import org.move.lang.core.psi.MvNamedElement
import org.move.lang.core.psi.MvNamedFieldDecl
import org.move.lang.core.psi.signatureText
import org.move.lang.core.types.address
import org.move.lang.moveProject
import org.move.lang.toNioPathOrNull
import org.move.openapiext.rootPath
import java.nio.file.Path

fun getPresentation(psi: PsiElement): ItemPresentation {
if (psi is MoveFile) {
return psi.presentation!!
}
val location = psi.locationString(tryRelative = true)
val name = presentableName(psi)
return PresentationData(name, location, psi.getIcon(0), null)
}

fun getPresentationForStructure(psi: PsiElement): ItemPresentation {
if (psi is MoveFile) {
return psi.presentation!!
}
val presentation = buildString {
fun appendCommaList(xs: List<String>) {
append('(')
append(xs.joinToString(", "))
append(')')
}
append(presentableName(psi))
when (psi) {
is MvFunctionLike -> {
append(psi.signatureText)
}
is MvConst -> {
psi.type?.let { append(": ${it.text}") }
}
is MvNamedFieldDecl -> {
psi.type?.let { append(": ${it.text}") }
}
is MvEnumVariant -> {
val fields = psi.tupleFields
if (fields != null) {
appendCommaList(fields.tupleFieldDeclList.map { it.type.text })
}
}
}
}
val icon = psi.getIcon(Iconable.ICON_FLAG_VISIBILITY)
return PresentationData(presentation, null, icon, null)
}

fun PsiElement.locationString(tryRelative: Boolean): String? = when (this) {
is MvModule -> {
val moveProj = this.moveProject
this.address(moveProj)?.text() ?: ""
}
else -> containingFilePath(tryRelative)?.toString()
}

private fun PsiElement.containingFilePath(tryRelative: Boolean): Path? {
val containingFilePath = this.containingFile.toNioPathOrNull() ?: return null
if (tryRelative) {
val rootPath = this.project.rootPath
if (rootPath != null) {
return rootPath.relativize(containingFilePath)
}
}
return containingFilePath
}

private fun presentableName(psi: PsiElement): String? {
return when (psi) {
is MvNamedElement -> psi.name
else -> null
}
}
13 changes: 4 additions & 9 deletions src/main/kotlin/org/move/ide/structureView/ItemTypeSorter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ class ItemTypeComparator: Comparator<MvStructureViewTreeElement> {
}

private fun getIntKind(treeElement: MvStructureViewTreeElement): Int {
val element = treeElement.element
return when (element) {
val psi = treeElement.psi
return when (psi) {
is MvConst -> 0
is MvStruct -> 1
is MvFunction -> 2
Expand All @@ -29,13 +29,8 @@ class ItemTypeComparator: Comparator<MvStructureViewTreeElement> {
class ItemTypeSorter: Sorter {
override fun getComparator(): Comparator<*> = ItemTypeComparator()

override fun getPresentation(): ActionPresentation {
return ActionPresentationData(
"By Type",
null,
AllIcons.ObjectBrowser.SortByType
)
}
override fun getPresentation(): ActionPresentation =
ActionPresentationData("By Type", null, AllIcons.ObjectBrowser.SortByType)

override fun isVisible(): Boolean = true

Expand Down
23 changes: 7 additions & 16 deletions src/main/kotlin/org/move/ide/structureView/MvStructureViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,12 @@ class MvStructureViewModel(editor: Editor?, moveFile: MoveFile):
class HidePrivateFunctionsFilter: Filter {
override fun isVisible(treeNode: TreeElement): Boolean {
// if action is set, only public items are visible
return (treeNode as? MvStructureViewTreeElement)?.isPublic ?: true
return (treeNode as? MvStructureViewTreeElement)?.isPublicItem != false
}

@Suppress("DialogTitleCapitalization")
override fun getPresentation(): ActionPresentation {
return ActionPresentationData(
"Hide private functions", null, PlatformIcons.PRIVATE_ICON
)
}
override fun getPresentation(): ActionPresentation =
ActionPresentationData("Hide private functions", null, PlatformIcons.PRIVATE_ICON)

override fun getName() = ID

Expand All @@ -65,11 +62,8 @@ class HideTestFunctionsFilter: Filter {
}

@Suppress("DialogTitleCapitalization")
override fun getPresentation(): ActionPresentation {
return ActionPresentationData(
"Hide #[test] functions", null, AllIcons.Nodes.Test
)
}
override fun getPresentation(): ActionPresentation =
ActionPresentationData("Hide #[test] functions", null, AllIcons.Nodes.Test)

override fun getName() = ID

Expand All @@ -87,11 +81,8 @@ class HideTestOnlyItemsFilter: Filter {
}

@Suppress("DialogTitleCapitalization")
override fun getPresentation(): ActionPresentation {
return ActionPresentationData(
"Hide #[test_only] items", null, AllIcons.Nodes.Type
)
}
override fun getPresentation(): ActionPresentation =
ActionPresentationData("Hide #[test_only] items", null, AllIcons.Nodes.Type)

override fun getName() = ID

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,65 +2,76 @@ package org.move.ide.structureView

import com.intellij.ide.projectView.PresentationData
import com.intellij.ide.structureView.StructureViewTreeElement
import com.intellij.ide.util.treeView.TreeAnchorizer
import com.intellij.ide.util.treeView.smartTree.TreeElement
import com.intellij.navigation.ItemPresentation
import com.intellij.openapi.ui.Queryable
import com.intellij.psi.NavigatablePsiElement
import com.intellij.psi.PsiElement
import com.intellij.util.containers.map2Array
import org.move.ide.presentation.getPresentationForStructure
import org.move.lang.MoveFile
import org.move.lang.core.psi.*
import org.move.lang.core.psi.ext.*
import org.move.openapiext.common.isUnitTestMode

class MvStructureViewTreeElement(val element: NavigatablePsiElement): StructureViewTreeElement,
Queryable {
val isPublic: Boolean
get() {
return when (element) {
is MvFunction -> element.isPublic
is MvConst -> false
else -> true
}
}
class MvStructureViewTreeElement(element: NavigatablePsiElement): StructureViewTreeElement,
Queryable {

val isTestFunction: Boolean
val psiAnchor = TreeAnchorizer.getService().createAnchor(element)
val psi: NavigatablePsiElement?
get() =
(element as? MvFunction)?.hasTestAttr ?: false
TreeAnchorizer.getService().retrieveElement(psiAnchor) as? NavigatablePsiElement

val isTestOnlyItem: Boolean
get() =
(element as? MvDocAndAttributeOwner)?.hasTestOnlyAttr ?: false
val isPublicItem: Boolean =
when (val psi = psi) {
is MvFunction -> psi.isPublic
is MvConst -> false
else -> true
}

override fun navigate(requestFocus: Boolean) = element.navigate(requestFocus)
override fun canNavigate(): Boolean = element.canNavigate()
override fun canNavigateToSource(): Boolean = element.canNavigateToSource()
override fun getPresentation(): ItemPresentation = this.element.presentation ?: PresentationData()
val isTestFunction: Boolean get() = (psi as? MvFunction)?.hasTestAttr == true

override fun getChildren(): Array<TreeElement> {
val items = when (element) {
is MoveFile -> {
listOf(
element.modules().toList(),
element.scripts().flatMap { it.functionList }
).flatten()
}
is MvAddressDef -> element.modules()
is MvModule -> {
listOf(
element.consts(),
element.structs(),
element.enumList,
element.allFunctions(),
element.specFunctions(),
).flatten()
}
is MvFieldsOwner -> element.namedFields
is MvEnum -> element.variants
else -> emptyList()
}
return items.map { MvStructureViewTreeElement(it) }.toTypedArray()
val isTestOnlyItem: Boolean get() = (psi as? MvDocAndAttributeOwner)?.hasTestOnlyAttr == true

override fun navigate(requestFocus: Boolean) {
psi?.navigate(requestFocus)
}

override fun getValue(): Any = this.element
override fun canNavigate(): Boolean = psi?.canNavigate() == true
override fun canNavigateToSource(): Boolean = psi?.canNavigateToSource() == true
override fun getValue(): PsiElement? = psi

override fun getPresentation(): ItemPresentation =
psi?.let(::getPresentationForStructure) ?: PresentationData("", null, null, null)

override fun getChildren(): Array<out TreeElement?> =
childElements.map2Array { MvStructureViewTreeElement(it) }

private val childElements: List<NavigatablePsiElement>
get() {
return when (val psi = psi) {
is MoveFile -> {
listOf(
psi.modules().toList(),
psi.scripts().flatMap { it.functionList }
).flatten()
}
is MvAddressDef -> psi.modules()
is MvModule -> {
listOf(
psi.consts(),
psi.structs(),
psi.enumList,
psi.allFunctions(),
psi.specFunctions(),
).flatten()
}
is MvFieldsOwner -> psi.namedFields
is MvEnum -> psi.variants
else -> emptyList()
}
}

// Used in `RsStructureViewTest`
override fun putInfo(info: MutableMap<in String, in String>) {
Expand Down
Loading

0 comments on commit 136d6f1

Please sign in to comment.