Added folding support for functions and macro definitions.
This commit is contained in:
parent
f87bc7fea9
commit
cd0bcd22ff
@ -66,6 +66,7 @@ patchPluginXml {
|
|||||||
<li>New: Added semantic highlighting. Currently available for data and address registers and local labels.
|
<li>New: Added semantic highlighting. Currently available for data and address registers and local labels.
|
||||||
<li>Bugfix: addq/subq for address register stated it would affect the condition codes, which it in fact doesn't.
|
<li>Bugfix: addq/subq for address register stated it would affect the condition codes, which it in fact doesn't.
|
||||||
<li>New: Added simple custom navigation bar.
|
<li>New: Added simple custom navigation bar.
|
||||||
|
<li>New: Added folding support for functions and macro definitions.
|
||||||
</ul>
|
</ul>
|
||||||
<p>Full changelog available at <a href="https://github.com/chrisly42/mc68000-asm-plugin#changelog">Github project site</a>.</p>
|
<p>Full changelog available at <a href="https://github.com/chrisly42/mc68000-asm-plugin#changelog">Github project site</a>.</p>
|
||||||
""")
|
""")
|
||||||
|
@ -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.PsiComment
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.PsiWhiteSpace
|
||||||
import com.intellij.psi.util.PsiTreeUtil
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
import com.intellij.util.SmartList
|
import com.intellij.util.SmartList
|
||||||
import com.intellij.util.containers.addIfNotNull
|
import com.intellij.util.containers.addIfNotNull
|
||||||
@ -31,6 +32,31 @@ object M68kPsiWalkUtil {
|
|||||||
return comments.reversed()
|
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? {
|
fun findStatementForElement(psiElement: PsiElement): M68kStatement? {
|
||||||
if (psiElement is M68kStatement) return psiElement
|
if (psiElement is M68kStatement) return psiElement
|
||||||
if (psiElement.parent is M68kFile) {
|
if (psiElement.parent is M68kFile) {
|
||||||
|
@ -21,6 +21,9 @@
|
|||||||
implementationClass="de.platon42.intellij.plugins.m68k.parser.M68kParserDefinition"/>
|
implementationClass="de.platon42.intellij.plugins.m68k.parser.M68kParserDefinition"/>
|
||||||
<lang.syntaxHighlighterFactory language="MC68000"
|
<lang.syntaxHighlighterFactory language="MC68000"
|
||||||
implementationClass="de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighterFactory"/>
|
implementationClass="de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighterFactory"/>
|
||||||
|
<lang.foldingBuilder
|
||||||
|
language="MC68000"
|
||||||
|
implementationClass="de.platon42.intellij.plugins.m68k.folding.M68kFoldingBuilder"/>
|
||||||
<navbar implementation="de.platon42.intellij.plugins.m68k.navigation.M68kStructureAwareNavbar"/>
|
<navbar implementation="de.platon42.intellij.plugins.m68k.navigation.M68kStructureAwareNavbar"/>
|
||||||
<highlightVisitor implementation="de.platon42.intellij.plugins.m68k.syntax.M68kRainbowVisitor"/>
|
<highlightVisitor implementation="de.platon42.intellij.plugins.m68k.syntax.M68kRainbowVisitor"/>
|
||||||
<colorSettingsPage implementation="de.platon42.intellij.plugins.m68k.syntax.M68kColorSettingsPage"/>
|
<colorSettingsPage implementation="de.platon42.intellij.plugins.m68k.syntax.M68kColorSettingsPage"/>
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
package de.platon42.intellij.plugins.m68k.folding
|
||||||
|
|
||||||
|
import com.intellij.testFramework.fixtures.CodeInsightTestFixture
|
||||||
|
import de.platon42.intellij.jupiter.LightCodeInsightExtension
|
||||||
|
import de.platon42.intellij.jupiter.MyFixture
|
||||||
|
import de.platon42.intellij.jupiter.TestDataPath
|
||||||
|
import org.junit.jupiter.api.Assertions.*
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith
|
||||||
|
|
||||||
|
@TestDataPath("src/test/resources/folding")
|
||||||
|
@ExtendWith(LightCodeInsightExtension::class)
|
||||||
|
internal class M68kFoldingBuilderTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
internal fun check_documentation_for_a_symbol_definition(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||||
|
myFixture.testFolding(myFixture.testDataPath + "/folding.asm")
|
||||||
|
}
|
||||||
|
}
|
46
src/test/resources/folding/folding.asm
Normal file
46
src/test/resources/folding/folding.asm
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
; this is a test
|
||||||
|
|
||||||
|
FOO = 1
|
||||||
|
<fold text='[[[ demo_main ]]]'>; this is the main demo routine
|
||||||
|
demo_main:
|
||||||
|
moveq.l #0,d0
|
||||||
|
rts
|
||||||
|
|
||||||
|
; data area starts here
|
||||||
|
.data dc.w 10,0
|
||||||
|
even</fold>
|
||||||
|
|
||||||
|
; this is an unrelated comment
|
||||||
|
|
||||||
|
<fold text='[[[ intro_part1 ]]]'>; this is another folding area
|
||||||
|
; could be anything.
|
||||||
|
|
||||||
|
intro_part1
|
||||||
|
dc.w $47fe
|
||||||
|
illegal
|
||||||
|
rts</fold>
|
||||||
|
|
||||||
|
; this comment is two lines away
|
||||||
|
|
||||||
|
|
||||||
|
<fold text='[[[ intro_part2 ]]]'>intro_part2:
|
||||||
|
moveq.l #0,d1
|
||||||
|
rts</fold>
|
||||||
|
|
||||||
|
; standard macros
|
||||||
|
<fold text='[[[ MACRO BLTWAIT ]]]'>BLTWAIT MACRO
|
||||||
|
.bw\@
|
||||||
|
btst #DMAB_BLTDONE-8,dmaconr(a5)
|
||||||
|
bne.s .bw\@
|
||||||
|
ENDM</fold>
|
||||||
|
|
||||||
|
********************** foobar
|
||||||
|
|
||||||
|
|
||||||
|
<fold text='[[[ some_more_data ]]]'>some_more_data:
|
||||||
|
dc.w $123
|
||||||
|
dc.w $345
|
||||||
|
dc.w $333
|
||||||
|
dc.w $222</fold>
|
||||||
|
|
||||||
|
CUBE_SIZE = 100
|
Loading…
Reference in New Issue
Block a user