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

net.sourceforge.pmd.lang.test.ast.AstMatcherDslAdapter.kt Maven / Gradle / Ivy

Go to download

Module containing utilities to test language implementations, including parsers and ASTs. This module uses Kotlin.

There is a newer version: 7.5.0
Show newest version
/*
 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
 */

package net.sourceforge.pmd.lang.test.ast

import com.github.oowekyala.treeutils.DoublyLinkedTreeLikeAdapter
import com.github.oowekyala.treeutils.matchers.MatchingConfig
import com.github.oowekyala.treeutils.matchers.TreeNodeWrapper
import com.github.oowekyala.treeutils.matchers.baseShouldMatchSubtree
import com.github.oowekyala.treeutils.printers.KotlintestBeanTreePrinter
import net.sourceforge.pmd.lang.ast.Node
import io.kotest.matchers.should as ktShould

/** An adapter for [baseShouldMatchSubtree]. */
object NodeTreeLikeAdapter : DoublyLinkedTreeLikeAdapter {
    override fun getChildren(node: Node): List = node.children().toList()

    override fun nodeName(type: Class): String = type.simpleName.removePrefix("AST")

    override fun getParent(node: Node): Node? = node.parent

    override fun getChild(node: Node, index: Int): Node? = node.children().get(index)
}

/** A [NodeSpec] that returns a value. */
typealias ValuedNodeSpec = TreeNodeWrapper.() -> O

/** A subtree matcher written in the DSL documented on [TreeNodeWrapper]. */
typealias NodeSpec = ValuedNodeSpec

/** A function feedable to [io.kotest.matchers.should], which fails the test if an [AssertionError] is thrown. */
typealias Assertions = (M) -> Unit

fun  ValuedNodeSpec.ignoreResult(): NodeSpec {
    val me = this
    return { this.me() }
}

val DefaultMatchingConfig = MatchingConfig(
        adapter = NodeTreeLikeAdapter,
        errorPrinter = KotlintestBeanTreePrinter(NodeTreeLikeAdapter),
        implicitAssertions = { it.assertTextRangeIsOk() }
)

/** A shorthand for [baseShouldMatchSubtree] providing the [NodeTreeLikeAdapter]. */
inline fun  Node?.shouldMatchNode(ignoreChildren: Boolean = false, noinline nodeSpec: ValuedNodeSpec) {
    this.baseShouldMatchSubtree(DefaultMatchingConfig, ignoreChildren, nodeSpec.ignoreResult())
}

/**
 * Returns [an assertion function][Assertions] asserting that its parameter conforms to the given [NodeSpec].
 *
 * Use it with [io.kotest.matchers.should], e.g. `node should matchNode {}`.
 *
 * See also the samples on [TreeNodeWrapper].
 *
 * @param N Expected type of the node
 *
 * @param ignoreChildren If true, calls to [TreeNodeWrapper.child] in the [nodeSpec] are forbidden.
 *                       The number of children of the child is not asserted.
 *
 * @param nodeSpec Sequence of assertions to carry out on the node, which can be referred to by [TreeNodeWrapper.it].
 *                 Assertions may consist of [NWrapper.child] calls, which perform the same type of node
 *                 matching on a child of the tested node.
 *
 * @return A matcher for AST nodes, suitable for use by [io.kotest.matchers.should].
 */
inline fun  matchNode(ignoreChildren: Boolean = false, noinline nodeSpec: ValuedNodeSpec)
        : Assertions = { it.shouldMatchNode(ignoreChildren, nodeSpec) }

/**
 * The spec applies to the parent, shifted so that [this] node
 * is the first node to be queried. This allows using sweeter
 * DSL constructs like in the Java module.
 */
fun Node.shouldMatchN(matcher: ValuedNodeSpec) {
    val idx = indexInParent
    parent ktShould matchNode {
        if (idx > 0) {
            unspecifiedChildren(idx)
        }
        matcher()
        val left = it.numChildren - 1 - idx
        if (left > 0) {
            unspecifiedChildren(left)
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy