All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.org.intellij.markdown.parser.InlineBuilder.kt Maven / Gradle / Ivy

There is a newer version: 0.7.3
Show newest version
package org.intellij.markdown.parser

import org.intellij.markdown.ast.ASTNode
import org.intellij.markdown.ast.ASTNodeBuilder
import org.intellij.markdown.lexer.Compat.assert
import org.intellij.markdown.parser.sequentialparsers.TokensCache

class InlineBuilder(nodeBuilder: ASTNodeBuilder, private val tokensCache: TokensCache) : TreeBuilder(nodeBuilder) {
    private var currentTokenPosition = -1

    override fun flushEverythingBeforeEvent(event: MyEvent, currentNodeChildren: MutableList?) {
        if (currentTokenPosition == -1) {
            currentTokenPosition = event.position
        }

        while (currentTokenPosition < event.position) {
            flushOneTokenToTree(tokensCache, currentNodeChildren, currentTokenPosition)
            currentTokenPosition++
        }
    }

    private fun flushOneTokenToTree(tokensCache: TokensCache, currentNodeChildren: MutableList?, currentTokenPosition: Int) {
        val iterator = tokensCache.Iterator(currentTokenPosition)
        assert(iterator.type != null)
        val nodes = nodeBuilder.createLeafNodes(iterator.type!!, iterator.start, iterator.end)
        for (node in nodes) {
            currentNodeChildren?.add(MyASTNodeWrapper(node, iterator.index, iterator.index + 1))
        }
    }

    override fun createASTNodeOnClosingEvent(event: MyEvent, currentNodeChildren: List, isTopmostNode: Boolean): MyASTNodeWrapper {
        val newNode: ASTNode

        val type = event.info.type
        val startTokenId = event.info.range.first
        val endTokenId = event.info.range.last

        val childrenWithWhitespaces = ArrayList(currentNodeChildren.size)

        if (isTopmostNode) {
            // Set exitOffset to an unreachable offset pointing to the left.
            // This way we ensure that all raw tokens before are included into the current node.
            addRawTokens(tokensCache, childrenWithWhitespaces, startTokenId, -1, -1)
        }
        for (index in 1 until currentNodeChildren.size) {
            val prev = currentNodeChildren[index - 1]
            val next = currentNodeChildren[index]

            childrenWithWhitespaces.add(prev.astNode)

            addRawTokens(tokensCache, childrenWithWhitespaces, prev.endTokenIndex - 1, +1, tokensCache.Iterator(next.startTokenIndex).start)
        }
        if (currentNodeChildren.isNotEmpty()) {
            childrenWithWhitespaces.add(currentNodeChildren.last().astNode)
        }
        if (isTopmostNode) {
            addRawTokens(tokensCache, childrenWithWhitespaces, endTokenId - 1, +1, tokensCache.Iterator(endTokenId).start)
        }

        newNode = nodeBuilder.createCompositeNode(type, childrenWithWhitespaces)
        return MyASTNodeWrapper(newNode, startTokenId, endTokenId)
    }

    private fun addRawTokens(tokensCache: TokensCache, childrenWithWhitespaces: MutableList, from: Int, dx: Int, exitOffset: Int) {
        val iterator = tokensCache.Iterator(from)
        var rawIdx = 0
        while (iterator.rawLookup(rawIdx + dx) != null && iterator.rawStart(rawIdx + dx) != exitOffset) {
            rawIdx += dx
        }
        while (rawIdx != 0) {
            val rawType = iterator.rawLookup(rawIdx)!!
            childrenWithWhitespaces.addAll(nodeBuilder.createLeafNodes(rawType, iterator.rawStart(rawIdx), iterator.rawStart(rawIdx + 1)))
            rawIdx -= dx
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy