Added folding support for functions and macro definitions.
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
package de.platon42.intellij.plugins.m68k.folding
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
import com.intellij.lang.folding.FoldingBuilderEx
|
||||
import com.intellij.lang.folding.FoldingDescriptor
|
||||
import com.intellij.openapi.editor.Document
|
||||
import com.intellij.openapi.project.DumbAware
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import com.intellij.refactoring.suggested.endOffset
|
||||
import com.intellij.refactoring.suggested.startOffset
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kFile
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kMacroDefinition
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kStatement
|
||||
import de.platon42.intellij.plugins.m68k.psi.utils.M68kPsiWalkUtil.getBeginningOfRelatedComment
|
||||
import de.platon42.intellij.plugins.m68k.psi.utils.M68kPsiWalkUtil.isSignificantLine
|
||||
|
||||
class M68kFoldingBuilder : FoldingBuilderEx(), DumbAware {
|
||||
|
||||
override fun buildFoldRegions(root: PsiElement, document: Document, quick: Boolean): Array<FoldingDescriptor> {
|
||||
if (root !is M68kFile) return FoldingDescriptor.EMPTY
|
||||
|
||||
val descriptors = ArrayList<FoldingDescriptor>()
|
||||
var lineElement = root.firstChild
|
||||
var foldingOpen = false
|
||||
var foldingStart: PsiElement? = null
|
||||
var foldingName: String? = null
|
||||
var lastStatement = lineElement as? M68kStatement
|
||||
while (lineElement != null) {
|
||||
if (lineElement is M68kMacroDefinition) {
|
||||
val fd = FoldingDescriptor(lineElement, lineElement.startOffset, lineElement.endOffset, null, "[[[ MACRO " + lineElement.name!! + " ]]]")
|
||||
descriptors.add(fd)
|
||||
}
|
||||
if (lineElement is M68kStatement) {
|
||||
val label = lineElement.globalLabel
|
||||
if (label != null) {
|
||||
foldingOpen = true
|
||||
foldingStart = getBeginningOfRelatedComment(lineElement)
|
||||
foldingName = "[[[ ${label.name} ]]]"
|
||||
}
|
||||
lastStatement = lineElement
|
||||
}
|
||||
lineElement = PsiTreeUtil.skipWhitespacesAndCommentsForward(lineElement)
|
||||
if (foldingOpen) {
|
||||
val stopIt = (lineElement == null) || isSignificantLine(lineElement)
|
||||
if (stopIt) {
|
||||
val fd = FoldingDescriptor(
|
||||
foldingStart!!.parent!!,
|
||||
foldingStart.startOffsetInParent, lastStatement!!.textRangeInParent.endOffset,
|
||||
null, foldingName!!
|
||||
)
|
||||
descriptors.add(fd)
|
||||
foldingOpen = false
|
||||
}
|
||||
}
|
||||
}
|
||||
return descriptors.toArray(FoldingDescriptor.EMPTY)
|
||||
}
|
||||
|
||||
override fun getPlaceholderText(node: ASTNode): String? {
|
||||
return "..."
|
||||
}
|
||||
|
||||
override fun isCollapsedByDefault(node: ASTNode): Boolean {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package de.platon42.intellij.plugins.m68k.psi.utils
|
||||
|
||||
import com.intellij.psi.PsiComment
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiWhiteSpace
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import com.intellij.util.SmartList
|
||||
import com.intellij.util.containers.addIfNotNull
|
||||
@@ -31,6 +32,31 @@ object M68kPsiWalkUtil {
|
||||
return comments.reversed()
|
||||
}
|
||||
|
||||
fun getBeginningOfRelatedComment(lineElement: PsiElement): PsiElement {
|
||||
// go back to catch comments that are not more than one empty line away
|
||||
var relStart = lineElement
|
||||
var prevLine = relStart.prevSibling ?: return lineElement
|
||||
var eolCount = 2
|
||||
do {
|
||||
if (prevLine is PsiComment) {
|
||||
relStart = prevLine
|
||||
eolCount = 1
|
||||
} else if (prevLine is PsiWhiteSpace) {
|
||||
if (--eolCount < 0) break
|
||||
} else {
|
||||
break
|
||||
}
|
||||
prevLine = prevLine.prevSibling ?: break
|
||||
} while (true)
|
||||
return relStart
|
||||
}
|
||||
|
||||
fun isSignificantLine(element: PsiElement) = when (element) {
|
||||
is M68kStatement -> (element.assignment != null) || (element.globalLabel != null)
|
||||
is M68kMacroDefinition -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
fun findStatementForElement(psiElement: PsiElement): M68kStatement? {
|
||||
if (psiElement is M68kStatement) return psiElement
|
||||
if (psiElement.parent is M68kFile) {
|
||||
|
||||
Reference in New Issue
Block a user