diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/treeexport/TextTreeRenderer.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/treeexport/TextTreeRenderer.java
new file mode 100644
index 0000000000..8d1e822672
--- /dev/null
+++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/treeexport/TextTreeRenderer.java
@@ -0,0 +1,210 @@
+/*
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+
+package net.sourceforge.pmd.util.treeexport;
+
+import java.io.IOException;
+
+import net.sourceforge.pmd.annotation.Experimental;
+import net.sourceforge.pmd.lang.ast.Node;
+import net.sourceforge.pmd.properties.AbstractPropertySource;
+import net.sourceforge.pmd.properties.PropertyDescriptor;
+import net.sourceforge.pmd.properties.PropertyFactory;
+import net.sourceforge.pmd.properties.PropertySource;
+
+/**
+ * A simple recursive printer. Output looks like so:
+ *
+ *
+ *
+ * +- LocalVariableDeclaration
+ * +- Type
+ * | +- PrimitiveType
+ * +- VariableDeclarator
+ * +- VariableDeclaratorId
+ * +- VariableInitializer
+ * +- 1 child not shown
+ *
+ *
+ *
+ * or
+ *
+ *
+ *
+ * └─ LocalVariableDeclaration
+ * ├─ Type
+ * │ └─ PrimitiveType
+ * └─ VariableDeclarator
+ * ├─ VariableDeclaratorId
+ * └─ VariableInitializer
+ * └─ 1 child not shown
+ *
+ *
+ *
+ *
+ * By default just prints the structure, like shown above. You can
+ * configure it to render nodes differently by overriding {@link #appendNodeInfoLn(Appendable, Node)}.
+ */
+@Experimental
+public class TextTreeRenderer implements TreeRenderer {
+
+ static final TreeRendererDescriptor DESCRIPTOR = new TreeRendererDescriptor() {
+
+ private final PropertyDescriptor onlyAscii =
+ PropertyFactory.booleanProperty("onlyAsciiChars")
+ .defaultValue(false)
+ .desc("Use only ASCII characters in the structure")
+ .build();
+
+ private final PropertyDescriptor maxLevel =
+ PropertyFactory.intProperty("maxLevel")
+ .defaultValue(-1)
+ .desc("Max level on which to recurse. Negative means unbounded")
+ .build();
+
+ @Override
+ public PropertySource newPropertyBundle() {
+
+ PropertySource bundle = new AbstractPropertySource() {
+ @Override
+ protected String getPropertySourceType() {
+ return "tree renderer";
+ }
+
+ @Override
+ public String getName() {
+ return "text";
+ }
+ };
+
+ bundle.definePropertyDescriptor(onlyAscii);
+ bundle.definePropertyDescriptor(maxLevel);
+
+ return bundle;
+ }
+
+ @Override
+ public String id() {
+ return "text";
+ }
+
+ @Override
+ public String description() {
+ return "Text renderer";
+ }
+
+ @Override
+ public TreeRenderer produceRenderer(PropertySource properties) {
+ return new TextTreeRenderer(properties.getProperty(onlyAscii), properties.getProperty(maxLevel));
+ }
+ };
+
+ private final Strings str;
+ private final int maxLevel;
+
+ /**
+ * Creates a new text renderer.
+ *
+ * @param onlyAscii Whether to output the skeleton of the tree with
+ * only ascii characters. If false, uses unicode chars
+ * like '├'
+ * @param maxLevel Max level on which to recurse. Negative means
+ * unbounded. If the max level is reached, a placeholder
+ * is dumped, like "1 child is not shown". This is
+ * controlled by {@link #appendBoundaryForNodeLn(Node, Appendable, String)}.
+ */
+ public TextTreeRenderer(boolean onlyAscii, int maxLevel) {
+ this.str = onlyAscii ? Strings.ASCII : Strings.UNICODE;
+ this.maxLevel = maxLevel;
+ }
+
+ @Override
+ public void renderSubtree(Node node, Appendable out) throws IOException {
+ printInnerNode(node, out, 0, "", true);
+ }
+
+ private String childPrefix(String prefix, boolean isTail) {
+ return prefix + (isTail ? str.gap : str.verticalEdge);
+ }
+
+
+ protected final void appendIndent(Appendable out, String prefix, boolean isTail) throws IOException {
+ out.append(prefix).append(isTail ? str.tailFork : str.fork);
+ }
+
+ /**
+ * Append info about the node. The indent has already been appended.
+ * This should end with a newline. The default just appends the name
+ * of the node, and no other information.
+ */
+ protected void appendNodeInfoLn(Appendable out, Node node) throws IOException {
+ out.append(node.getXPathNodeName()).append("\n");
+ }
+
+
+ private void printInnerNode(Node node,
+ Appendable out,
+ int level,
+ String prefix,
+ boolean isTail) throws IOException {
+
+ appendIndent(out, prefix, isTail);
+ appendNodeInfoLn(out, node);
+
+ if (level == maxLevel) {
+ if (node.getNumChildren() > 0) {
+ appendBoundaryForNodeLn(node, out, childPrefix(prefix, isTail));
+ }
+ } else {
+ int n = node.getNumChildren() - 1;
+ String childPrefix = childPrefix(prefix, isTail);
+ for (int i = 0; i < node.getNumChildren(); i++) {
+ Node child = node.getChild(i);
+ printInnerNode(child, out, level + 1, childPrefix, i == n);
+ }
+ }
+ }
+
+ protected void appendBoundaryForNodeLn(Node node, Appendable out, String indentStr) throws IOException {
+ appendIndent(out, indentStr, true);
+
+ if (node.getNumChildren() == 1) {
+ out.append("1 child is not shown");
+ } else {
+ out.append(String.valueOf(node.getNumChildren())).append(" children are not shown");
+ }
+
+ out.append('\n');
+ }
+
+ private static final class Strings {
+
+ private static final Strings ASCII = new Strings(
+ "+- ",
+ "+- ",
+ "| ",
+ " "
+ );
+ private static final Strings UNICODE = new Strings(
+ "└─ ",
+ "├─ ",
+ "│ ",
+ " "
+ );
+
+ private final String tailFork;
+ private final String fork;
+ private final String verticalEdge;
+ private final String gap;
+
+
+ private Strings(String tailFork, String fork, String verticalEdge, String gap) {
+ this.tailFork = tailFork;
+ this.fork = fork;
+ this.verticalEdge = verticalEdge;
+ this.gap = gap;
+ }
+ }
+
+}
diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/treeexport/TreeRenderers.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/treeexport/TreeRenderers.java
index 3fc1e5ea1a..8f47c9c9e8 100644
--- a/pmd-core/src/main/java/net/sourceforge/pmd/util/treeexport/TreeRenderers.java
+++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/treeexport/TreeRenderers.java
@@ -102,7 +102,10 @@ public final class TreeRenderers {
static {
- REGISTRY.put(XML.id(), XML);
+ List builtinDescriptors = Arrays.asList(XML, TextTreeRenderer.DESCRIPTOR);
+ for (TreeRendererDescriptor descriptor : builtinDescriptors) {
+ REGISTRY.put(descriptor.id(), descriptor);
+ }
}
diff --git a/pmd-lang-test/pom.xml b/pmd-lang-test/pom.xml
index 910eda2842..2de8d05bb9 100644
--- a/pmd-lang-test/pom.xml
+++ b/pmd-lang-test/pom.xml
@@ -132,7 +132,7 @@
com.github.oowekyala.treeutils
tree-matchers
- 2.0.1
+ 2.1.0
compile
diff --git a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/AstMatcherDslAdapter.kt b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/AstMatcherDslAdapter.kt
index 99ed28c236..419fafabff 100644
--- a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/AstMatcherDslAdapter.kt
+++ b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/AstMatcherDslAdapter.kt
@@ -4,6 +4,7 @@
package net.sourceforge.pmd.lang.ast.test
+import com.github.oowekyala.treeutils.DoublyLinkedTreeLikeAdapter
import com.github.oowekyala.treeutils.TreeLikeAdapter
import com.github.oowekyala.treeutils.matchers.MatchingConfig
import com.github.oowekyala.treeutils.matchers.TreeNodeWrapper
@@ -12,10 +13,14 @@ import com.github.oowekyala.treeutils.printers.KotlintestBeanTreePrinter
import net.sourceforge.pmd.lang.ast.Node
/** An adapter for [baseShouldMatchSubtree]. */
-object NodeTreeLikeAdapter : TreeLikeAdapter {
+object NodeTreeLikeAdapter : DoublyLinkedTreeLikeAdapter {
override fun getChildren(node: Node): List = node.findChildrenOfType(Node::class.java)
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.safeGetChild(index)
}
/** A subtree matcher written in the DSL documented on [TreeNodeWrapper]. */
diff --git a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseParsingHelper.kt b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseParsingHelper.kt
index 4a486a397c..c209327c9f 100644
--- a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseParsingHelper.kt
+++ b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseParsingHelper.kt
@@ -35,12 +35,18 @@ abstract class BaseParsingHelper, T : RootNode
@JvmStatic
val defaultNoProcess = Params(false, null, null, "")
+
@JvmStatic
val defaultProcess = Params(true, null, null, "")
}
}
+ internal val resourceLoader: Class<*>
+ get() = params.resourceLoader ?: javaClass
+
+ internal val resourcePrefix: String get() = params.resourcePrefix
+
/**
* Returns the language version with the given version string.
* If null, this defaults to the default language version for
@@ -138,10 +144,10 @@ abstract class BaseParsingHelper, T : RootNode
parse(readClassSource(clazz), version)
protected fun readResource(resourceName: String): String {
- val rloader = params.resourceLoader ?: javaClass
- val input = rloader.getResourceAsStream(params.resourcePrefix + resourceName)
- ?: throw IllegalArgumentException("Unable to find resource file ${params.resourcePrefix + resourceName} from $rloader")
+ val input = resourceLoader.getResourceAsStream(params.resourcePrefix + resourceName)
+ ?: throw IllegalArgumentException("Unable to find resource file ${params.resourcePrefix + resourceName} from $resourceLoader")
+
return consume(input)
}
diff --git a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseTreeDumpTest.kt b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseTreeDumpTest.kt
new file mode 100644
index 0000000000..4e52a66651
--- /dev/null
+++ b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseTreeDumpTest.kt
@@ -0,0 +1,74 @@
+/*
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+
+package net.sourceforge.pmd.lang.ast.test
+
+import net.sourceforge.pmd.util.treeexport.TreeRenderer
+import java.nio.file.Path
+import java.nio.file.Paths
+import kotlin.test.assertEquals
+
+
+/**
+ * Compare a dump of a file against a saved baseline.
+ *
+ * @param printer The node printer used to dump the trees
+ * @param extension Extension that the unparsed source file is supposed to have
+ */
+abstract class BaseTreeDumpTest(
+ val printer: TreeRenderer,
+ val extension: String
+) {
+
+ abstract val parser: BaseParsingHelper<*, *>
+
+ /**
+ * Executes the test. The test files are looked up using the [parser].
+ * The reference test file must be named [fileBaseName] + [ExpectedExt].
+ * The source file to parse must be named [fileBaseName] + [extension].
+ */
+ fun doTest(fileBaseName: String) {
+ val expectedFile = findTestFile(parser.resourceLoader, "${parser.resourcePrefix}/$fileBaseName$ExpectedExt").toFile()
+ val sourceFile = findTestFile(parser.resourceLoader, "${parser.resourcePrefix}/$fileBaseName$extension").toFile()
+
+ assert(sourceFile.isFile) {
+ "Source file $sourceFile is missing"
+ }
+
+ val parsed = parser.parse(sourceFile.readText()) // UTF-8
+ val actual = StringBuilder().also { printer.renderSubtree(parsed, it) }.toString()
+
+ if (!expectedFile.exists()) {
+ expectedFile.writeText(actual)
+ throw AssertionError("Reference file doesn't exist, created it at $expectedFile")
+ }
+
+ val expected = expectedFile.readText()
+
+ assertEquals(expected.normalize(), actual.normalize(), "Tree dump comparison failed, see the reference: $expectedFile")
+ }
+
+ // Outputting a path makes for better error messages
+ private val srcTestResources = let {
+ // this is set from maven surefire
+ System.getProperty("mvn.project.src.test.resources")
+ ?.let { Paths.get(it).toAbsolutePath() }
+ // that's for when the tests are run inside the IDE
+ ?: Paths.get(javaClass.protectionDomain.codeSource.location.file)
+ // go up from target/test-classes into the project root
+ .resolve("../../src/test/resources").normalize()
+ }
+
+ private fun findTestFile(contextClass: Class<*>, resourcePath: String): Path {
+ val path = contextClass.`package`.name.replace('.', '/')
+ return srcTestResources.resolve("$path/$resourcePath")
+ }
+
+ companion object {
+ const val ExpectedExt = ".txt"
+
+ fun String.normalize() = replace(Regex("\\R"), "\n")
+ }
+
+}
diff --git a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/NodePrinters.kt b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/NodePrinters.kt
new file mode 100644
index 0000000000..7e476c62c3
--- /dev/null
+++ b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/NodePrinters.kt
@@ -0,0 +1,77 @@
+/*
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+
+package net.sourceforge.pmd.lang.ast.test
+
+import net.sourceforge.pmd.lang.ast.Node
+import net.sourceforge.pmd.lang.ast.xpath.Attribute
+import net.sourceforge.pmd.util.treeexport.TextTreeRenderer
+import org.apache.commons.lang3.StringEscapeUtils
+
+/**
+ * Prints just the structure, like so:
+ *
+ * └── LocalVariableDeclaration
+ * ├── Type
+ * │ └── PrimitiveType
+ * └── VariableDeclarator
+ * ├── VariableDeclaratorId
+ * └── VariableInitializer
+ * └── 1 child not shown
+ *
+ */
+val SimpleNodePrinter = TextTreeRenderer(true, -1)
+
+
+open class RelevantAttributePrinter : BaseNodeAttributePrinter() {
+
+ private val Ignored = setOf("BeginLine", "EndLine", "BeginColumn", "EndColumn", "FindBoundary", "SingleLine")
+
+ override fun ignoreAttribute(node: Node, attribute: Attribute): Boolean =
+ Ignored.contains(attribute.name) || attribute.name == "Image" && attribute.value == null
+
+}
+
+/**
+ * Base attribute printer, subclass to filter attributes.
+ */
+open class BaseNodeAttributePrinter : TextTreeRenderer(true, -1) {
+
+ protected open fun ignoreAttribute(node: Node, attribute: Attribute): Boolean = true
+
+ override fun appendNodeInfoLn(out: Appendable, node: Node) {
+ out.append(node.xPathNodeName)
+
+ node.xPathAttributesIterator
+ .asSequence()
+ // sort to get deterministic results
+ .sortedBy { it.name }
+ .filterNot { ignoreAttribute(node, it) }
+ .joinTo(buffer = out, prefix = "[", postfix = "]") {
+ "@${it.name} = ${valueToString(it.value)}"
+ }
+ }
+
+ protected open fun valueToString(value: Any?): String? {
+ return when (value) {
+ is String -> "\"" + StringEscapeUtils.unescapeJava(value) + "\""
+ is Char -> '\''.toString() + value.toString().replace("'".toRegex(), "\\'") + '\''.toString()
+ is Enum<*> -> value.enumDeclaringClass.simpleName + "." + value.name
+ is Class<*> -> value.canonicalName?.let { "$it.class" }
+ is Number, is Boolean, null -> value.toString()
+ else -> null
+ }
+ }
+
+ private val Enum<*>.enumDeclaringClass: Class<*>
+ get() = this.javaClass.let {
+ when {
+ it.isEnum -> it
+ else -> it.enclosingClass.takeIf { it.isEnum }
+ ?: throw IllegalStateException()
+ }
+ }
+
+}
+
diff --git a/pmd-scala/src/test/kotlin/net/sourceforge/pmd/lang/scala/ast/ScalaParserTests.kt b/pmd-scala/src/test/kotlin/net/sourceforge/pmd/lang/scala/ast/ScalaParserTests.kt
new file mode 100644
index 0000000000..b156424fa7
--- /dev/null
+++ b/pmd-scala/src/test/kotlin/net/sourceforge/pmd/lang/scala/ast/ScalaParserTests.kt
@@ -0,0 +1,23 @@
+/*
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+
+package net.sourceforge.pmd.lang.scala.ast
+
+import net.sourceforge.pmd.lang.ast.test.BaseParsingHelper
+import net.sourceforge.pmd.lang.ast.test.BaseTreeDumpTest
+import net.sourceforge.pmd.lang.ast.test.SimpleNodePrinter
+import org.junit.Test
+
+class ScalaParserTests : BaseTreeDumpTest(SimpleNodePrinter, ".scala") {
+
+ override val parser: BaseParsingHelper<*, *>
+ get() = ScalaParsingHelper.DEFAULT.withResourceContext(javaClass, "testdata")
+
+ @Test
+ fun testSomeScalaFeatures() = doTest("List")
+
+ @Test
+ fun testPackageObject() = doTest("package")
+
+}
diff --git a/pmd-scala/src/test/resources/net/sourceforge/pmd/lang/scala/ast/testdata/List.scala b/pmd-scala/src/test/resources/net/sourceforge/pmd/lang/scala/ast/testdata/List.scala
new file mode 100644
index 0000000000..0c5ca22710
--- /dev/null
+++ b/pmd-scala/src/test/resources/net/sourceforge/pmd/lang/scala/ast/testdata/List.scala
@@ -0,0 +1,324 @@
+/*
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+
+package scala
+package collection
+package immutable
+
+import scala.annotation.unchecked.uncheckedVariance
+import scala.annotation.tailrec
+import mutable.{Builder, ListBuffer}
+import scala.collection.generic.DefaultSerializable
+import scala.runtime.Statics.releaseFence
+
+/** A class for immutable linked lists representing ordered collections
+ * of elements of type `A`.
+ *
+ */
+@SerialVersionUID(3L)
+sealed abstract class List[+A]
+ extends AbstractSeq[A]
+ with LinearSeq[A]
+ with LinearSeqOps[A, List, List[A]]
+ with StrictOptimizedLinearSeqOps[A, List, List[A]]
+ with StrictOptimizedSeqOps[A, List, List[A]]
+ with IterableFactoryDefaults[A, List]
+ with DefaultSerializable {
+
+ override def iterableFactory: SeqFactory[List] = List
+
+ override def take(n: Int): List[A] = if (isEmpty || n <= 0) Nil else {
+ val h = new ::(head, Nil)
+ var t = h
+ var rest = tail
+ var i = 1
+ while ( {
+ if (rest.isEmpty) return this; i < n
+ }) {
+ i += 1
+ val nx = new ::(rest.head, Nil)
+ t.next = nx
+ t = nx
+ rest = rest.tail
+ }
+ releaseFence()
+ h
+ }
+
+ /**
+ * @example {{{
+ * // Given a list
+ * val letters = List('a','b','c','d','e')
+ *
+ * // `slice` returns all elements beginning at index `from` and afterwards,
+ * // up until index `until` (excluding index `until`.)
+ * letters.slice(1,3) // Returns List('b','c')
+ * }}}
+ */
+ override def slice(from: Int, until: Int): List[A] = {
+ val lo = scala.math.max(from, 0)
+ if (until <= lo || isEmpty) Nil
+ else this drop lo take (until - lo)
+ }
+
+ override def takeRight(n: Int): List[A] = {
+ @tailrec
+ def loop(lead: List[A], lag: List[A]): List[A] = lead match {
+ case Nil => lag
+ case _ :: tail => loop(tail, lag.tail)
+ }
+ loop(drop(n), this)
+ }
+
+ // dropRight is inherited from LinearSeq
+
+ override def splitAt(n: Int): (List[A], List[A]) = {
+ val b = new ListBuffer[A]
+ var i = 0
+ var these = this
+ while (!these.isEmpty && i < n) {
+ i += 1
+ b += these.head
+ these = these.tail
+ }
+ (b.toList, these)
+ }
+
+ override def updated[B >: A](index: Int, elem: B): List[B] = {
+ var i = 0
+ var current = this
+ val prefix = ListBuffer.empty[B]
+ while (i < index && current.nonEmpty) {
+ i += 1
+ prefix += current.head
+ current = current.tail
+ }
+ if (i == index && current.nonEmpty) {
+ prefix.prependToList(elem :: current.tail)
+ } else {
+ throw new IndexOutOfBoundsException(s"$index is out of bounds (min 0, max ${leng t h-1})")
+ }
+ }
+
+ final override def map[B](f: A => B): List[B] = {
+ if (this eq Nil) Nil else {
+ val h = new ::[B](f(head), Nil)
+ var t: ::[B] = h
+ var rest = tail
+ while (rest ne Nil) {
+ val nx = new ::(f(rest.head), Nil)
+ t.next = nx
+ t = nx
+ rest = rest.tail
+ }
+ releaseFence()
+ h
+ }
+ }
+
+ final override def collect[B](pf: PartialFunction[A, B]): List[B] = {
+ if (this eq Nil) Nil else {
+ var rest = this
+ var h: ::[B] = null
+ var x: Any = null
+ // Special case for first element
+ while (h eq null) {
+ x = pf.applyOrElse(rest.head, List.partialNotApplied)
+ if (x.asInstanceOf[AnyRef] ne List.partialNotApplied) h = new ::(x.asInstanceOf[B], Nil)
+ rest = rest.tail
+ if (rest eq Nil) return if (h eq null) Nil else h
+ }
+ var t = h
+ // Remaining elements
+ while (rest ne Nil) {
+ x = pf.applyOrElse(rest.head, List.partialNotApplied)
+ if (x.asInstanceOf[AnyRef] ne List.partialNotApplied) {
+ val nx = new ::(x.asInstanceOf[B], Nil)
+ t.next = nx
+ t = nx
+ }
+ rest = rest.tail
+ }
+ releaseFence()
+ h
+ }
+ }
+
+ final override def flatMap[B](f: A => IterableOnce[B]): List[B] = {
+ var rest = this
+ var h: ::[B] = null
+ var t: ::[B] = null
+ while (rest ne Nil) {
+ val it = f(rest.head).iterator
+ while (it.hasNext) {
+ val nx = new ::(it.next(), Nil)
+ if (t eq null) {
+ h = nx
+ } else {
+ t.next = nx
+ }
+ t = nx
+ }
+ rest = rest.tail
+ }
+ if (h eq null) Nil else {releaseFence(); h}
+ }
+
+ @inline final override def takeWhile(p: A => Boolean): List[A] = {
+ val b = new ListBuffer[A]
+ var these = this
+ while (!these.isEmpty && p(these.head)) {
+ b += these.head
+ these = these.tail
+ }
+ b.toList
+ }
+
+ @inline final override def span(p: A => Boolean): (List[A], List[A]) = {
+ val b = new ListBuffer[A]
+ var these = this
+ while (!these.isEmpty && p(these.head)) {
+ b += these.head
+ these = these.tail
+ }
+ (b.toList, these)
+ }
+
+ // Overridden with an implementation identical to the inherited one (at this time)
+ // solely so it can be finalized and thus inlinable.
+ @inline final override def foreach[U](f: A => U): Unit = {
+ var these = this
+ while (!these.isEmpty) {
+ f(these.head)
+ these = these.tail
+ }
+ }
+
+ final override def reverse: List[A] = {
+ var result: List[A] = Nil
+ var these = this
+ while (!these.isEmpty) {
+ result = these.head :: result
+ these = these.tail
+ }
+ result
+ }
+
+ final override def foldRight[B](z: B)(op: (A, B) => B): B = {
+ var acc = z
+ var these: List[A] = reverse
+ while (!these.isEmpty) {
+ acc = op(these.head, acc)
+ these = these.tail
+ }
+ acc
+ }
+
+ // Copy/Paste overrides to avoid interface calls inside loops.
+
+ override final def length: Int = {
+ var these = this
+ var len = 0
+ while (!these.isEmpty) {
+ len += 1
+ these = these.tail
+ }
+ len
+ }
+
+ override final def lengthCompare(len: Int): Int = {
+ @tailrec def loop(i: Int, xs: List[A]): Int = {
+ if (i == len)
+ if (xs.isEmpty) 0 else 1
+ else if (xs.isEmpty)
+ -1
+ else
+ loop(i + 1, xs.tail)
+ }
+ if (len < 0) 1
+ else loop(0, coll)
+ }
+
+ override final def forall(p: A => Boolean): Boolean = {
+ var these: List[A] = this
+ while (!these.isEmpty) {
+ if (!p(these.head)) return false
+ these = these.tail
+ }
+ true
+ }
+
+ override final def exists(p: A => Boolean): Boolean = {
+ var these: List[A] = this
+ while (!these.isEmpty) {
+ if (p(these.head)) return true
+ these = these.tail
+ }
+ false
+ }
+
+ override final def contains[A1 >: A](elem: A1): Boolean = {
+ var these: List[A] = this
+ while (!these.isEmpty) {
+ if (these.head == elem) return true
+ these = these.tail
+ }
+ false
+ }
+
+ override final def find(p: A => Boolean): Option[A] = {
+ var these: List[A] = this
+ while (!these.isEmpty) {
+ if (p(these.head)) return Some(these.head)
+ these = these.tail
+ }
+ None
+ }
+}
+// Internal code that mutates `next` _must_ call `Statics.releaseFence()` if either immediately, or
+// before a newly-allocated, thread-local :: instance is aliased (e.g. in ListBuffer.toList)
+final case class :: [+A](override val head: A, private[scala] var next: List[A @uncheckedVariance]) // sound because `next` is used only locally
+ extends List[A] {
+ releaseFence()
+ override def headOption: Some[A] = Some(head)
+ override def tail: List[A] = next
+}
+
+case object Nil extends List[Nothing] {
+ override def head: Nothing = throw new NoSuchElementException("head of empty list")
+ override def headOption: None.type = None
+ override def tail: Nothing = throw new UnsupportedOperationException("tail of empty list")
+ override def last: Nothing = throw new NoSuchElementException("last of empty list")
+ override def init: Nothing = throw new UnsupportedOperationException("init of empty list")
+ override def knownSize: Int = 0
+ override def iterator: Iterator[Nothing] = Iterator.empty
+ override def unzip[A1, A2](implicit asPair: Nothing => (A1, A2)): (List[A1], List[A2]) = EmptyUnzip
+
+ @transient
+ private[this] val EmptyUnzip = (Nil, Nil)
+}
+
+/**
+ * $factoryInfo
+ * @define coll list
+ * @define Coll `List`
+ */
+@SerialVersionUID(3L)
+object List extends StrictOptimizedSeqFactory[List] {
+ private val TupleOfNil = (Nil, Nil)
+
+ def from[B](coll: collection.IterableOnce[B]): List[B] = coll match {
+ case coll: List[B] => coll
+ case _ if coll.knownSize == 0 => empty[B]
+ case b: ListBuffer[B] => b.toList
+ case _ => ListBuffer.from(coll).toList
+ }
+
+ def newBuilder[A]: Builder[A, List[A]] = new ListBuffer()
+
+ def empty[A]: List[A] = Nil
+
+ @transient
+ private[collection] val partialNotApplied = new Function1[Any, Any] { def apply(x: Any): Any = this }
+}
diff --git a/pmd-scala/src/test/resources/net/sourceforge/pmd/lang/scala/ast/testdata/List.txt b/pmd-scala/src/test/resources/net/sourceforge/pmd/lang/scala/ast/testdata/List.txt
new file mode 100644
index 0000000000..52f77880f0
--- /dev/null
+++ b/pmd-scala/src/test/resources/net/sourceforge/pmd/lang/scala/ast/testdata/List.txt
@@ -0,0 +1,1634 @@
++- Source
+ +- Pkg
+ +- TermName
+ +- Pkg
+ +- TermName
+ +- Pkg
+ +- TermName
+ +- Import
+ | +- Importer
+ | +- TermSelect
+ | | +- TermSelect
+ | | | +- TermName
+ | | | +- TermName
+ | | +- TermName
+ | +- ImporteeName
+ | +- NameIndeterminate
+ +- Import
+ | +- Importer
+ | +- TermSelect
+ | | +- TermName
+ | | +- TermName
+ | +- ImporteeName
+ | +- NameIndeterminate
+ +- Import
+ | +- Importer
+ | +- TermName
+ | +- ImporteeName
+ | | +- NameIndeterminate
+ | +- ImporteeName
+ | +- NameIndeterminate
+ +- Import
+ | +- Importer
+ | +- TermSelect
+ | | +- TermSelect
+ | | | +- TermName
+ | | | +- TermName
+ | | +- TermName
+ | +- ImporteeName
+ | +- NameIndeterminate
+ +- Import
+ | +- Importer
+ | +- TermSelect
+ | | +- TermSelect
+ | | | +- TermName
+ | | | +- TermName
+ | | +- TermName
+ | +- ImporteeName
+ | +- NameIndeterminate
+ +- DefnClass
+ | +- ModAnnot
+ | | +- Init
+ | | +- TypeName
+ | | +- NameAnonymous
+ | | +- LitLong
+ | +- ModSealed
+ | +- ModAbstract
+ | +- TypeName
+ | +- TypeParam
+ | | +- ModCovariant
+ | | +- TypeName
+ | | +- TypeBounds
+ | +- CtorPrimary
+ | | +- NameAnonymous
+ | +- Template
+ | +- Init
+ | | +- TypeApply
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- NameAnonymous
+ | +- Init
+ | | +- TypeApply
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- NameAnonymous
+ | +- Init
+ | | +- TypeApply
+ | | | +- TypeName
+ | | | +- TypeName
+ | | | +- TypeName
+ | | | +- TypeApply
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- NameAnonymous
+ | +- Init
+ | | +- TypeApply
+ | | | +- TypeName
+ | | | +- TypeName
+ | | | +- TypeName
+ | | | +- TypeApply
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- NameAnonymous
+ | +- Init
+ | | +- TypeApply
+ | | | +- TypeName
+ | | | +- TypeName
+ | | | +- TypeName
+ | | | +- TypeApply
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- NameAnonymous
+ | +- Init
+ | | +- TypeApply
+ | | | +- TypeName
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- NameAnonymous
+ | +- Init
+ | | +- TypeName
+ | | +- NameAnonymous
+ | +- Self
+ | | +- NameAnonymous
+ | +- DefnDef
+ | | +- ModOverride
+ | | +- TermName
+ | | +- TypeApply
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- TermName
+ | +- DefnDef
+ | | +- ModOverride
+ | | +- TermName
+ | | +- TermParam
+ | | | +- TermName
+ | | | +- TypeName
+ | | +- TypeApply
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- TermIf
+ | | +- TermApplyInfix
+ | | | +- TermName
+ | | | +- TermName
+ | | | +- TermApplyInfix
+ | | | +- TermName
+ | | | +- TermName
+ | | | +- LitInt
+ | | +- TermName
+ | | +- TermBlock
+ | | +- DefnVal
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- TermNew
+ | | | +- Init
+ | | | +- TypeName
+ | | | +- NameAnonymous
+ | | | +- TermName
+ | | | +- TermName
+ | | +- DefnVar
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- TermName
+ | | +- DefnVar
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- TermName
+ | | +- DefnVar
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- LitInt
+ | | +- TermWhile
+ | | | +- TermBlock
+ | | | | +- TermIf
+ | | | | | +- TermSelect
+ | | | | | | +- TermName
+ | | | | | | +- TermName
+ | | | | | +- TermReturn
+ | | | | | | +- TermThis
+ | | | | | | +- NameAnonymous
+ | | | | | +- LitUnit
+ | | | | +- TermApplyInfix
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermBlock
+ | | | +- TermApplyInfix
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | | +- LitInt
+ | | | +- DefnVal
+ | | | | +- PatVar
+ | | | | | +- TermName
+ | | | | +- TermNew
+ | | | | +- Init
+ | | | | +- TypeName
+ | | | | +- NameAnonymous
+ | | | | +- TermSelect
+ | | | | | +- TermName
+ | | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermAssign
+ | | | | +- TermSelect
+ | | | | | +- TermName
+ | | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermAssign
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermAssign
+ | | | +- TermName
+ | | | +- TermSelect
+ | | | +- TermName
+ | | | +- TermName
+ | | +- TermApply
+ | | | +- TermName
+ | | +- TermName
+ | +- DefnDef
+ | | +- ModOverride
+ | | +- TermName
+ | | +- TermParam
+ | | | +- TermName
+ | | | +- TypeName
+ | | +- TermParam
+ | | | +- TermName
+ | | | +- TypeName
+ | | +- TypeApply
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- TermBlock
+ | | +- DefnVal
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- TermApply
+ | | | +- TermSelect
+ | | | | +- TermSelect
+ | | | | | +- TermName
+ | | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermName
+ | | | +- LitInt
+ | | +- TermIf
+ | | +- TermApplyInfix
+ | | | +- TermApplyInfix
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermName
+ | | | +- TermName
+ | | +- TermName
+ | | +- TermApplyInfix
+ | | +- TermApplyInfix
+ | | | +- TermThis
+ | | | | +- NameAnonymous
+ | | | +- TermName
+ | | | +- TermName
+ | | +- TermName
+ | | +- TermApplyInfix
+ | | +- TermName
+ | | +- TermName
+ | | +- TermName
+ | +- DefnDef
+ | | +- ModOverride
+ | | +- TermName
+ | | +- TermParam
+ | | | +- TermName
+ | | | +- TypeName
+ | | +- TypeApply
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- TermBlock
+ | | +- DefnDef
+ | | | +- ModAnnot
+ | | | | +- Init
+ | | | | +- TypeName
+ | | | | +- NameAnonymous
+ | | | +- TermName
+ | | | +- TermParam
+ | | | | +- TermName
+ | | | | +- TypeApply
+ | | | | +- TypeName
+ | | | | +- TypeName
+ | | | +- TermParam
+ | | | | +- TermName
+ | | | | +- TypeApply
+ | | | | +- TypeName
+ | | | | +- TypeName
+ | | | +- TypeApply
+ | | | | +- TypeName
+ | | | | +- TypeName
+ | | | +- TermMatch
+ | | | +- TermName
+ | | | +- Case
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- Case
+ | | | +- PatExtractInfix
+ | | | | +- PatWildcard
+ | | | | +- TermName
+ | | | | +- PatVar
+ | | | | +- TermName
+ | | | +- TermApply
+ | | | +- TermName
+ | | | +- TermName
+ | | | +- TermSelect
+ | | | +- TermName
+ | | | +- TermName
+ | | +- TermApply
+ | | +- TermName
+ | | +- TermApply
+ | | | +- TermName
+ | | | +- TermName
+ | | +- TermThis
+ | | +- NameAnonymous
+ | +- DefnDef
+ | | +- ModOverride
+ | | +- TermName
+ | | +- TermParam
+ | | | +- TermName
+ | | | +- TypeName
+ | | +- TypeTuple
+ | | | +- TypeApply
+ | | | | +- TypeName
+ | | | | +- TypeName
+ | | | +- TypeApply
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- TermBlock
+ | | +- DefnVal
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- TermNew
+ | | | +- Init
+ | | | +- TypeApply
+ | | | | +- TypeName
+ | | | | +- TypeName
+ | | | +- NameAnonymous
+ | | +- DefnVar
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- LitInt
+ | | +- DefnVar
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- TermThis
+ | | | +- NameAnonymous
+ | | +- TermWhile
+ | | | +- TermApplyInfix
+ | | | | +- TermApplyUnary
+ | | | | | +- TermName
+ | | | | | +- TermSelect
+ | | | | | +- TermName
+ | | | | | +- TermName
+ | | | | +- TermName
+ | | | | +- TermApplyInfix
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermBlock
+ | | | +- TermApplyInfix
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | | +- LitInt
+ | | | +- TermApplyInfix
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | | +- TermSelect
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermAssign
+ | | | +- TermName
+ | | | +- TermSelect
+ | | | +- TermName
+ | | | +- TermName
+ | | +- TermTuple
+ | | +- TermSelect
+ | | | +- TermName
+ | | | +- TermName
+ | | +- TermName
+ | +- DefnDef
+ | | +- ModOverride
+ | | +- TermName
+ | | +- TypeParam
+ | | | +- TypeName
+ | | | +- TypeBounds
+ | | | +- TypeName
+ | | +- TermParam
+ | | | +- TermName
+ | | | +- TypeName
+ | | +- TermParam
+ | | | +- TermName
+ | | | +- TypeName
+ | | +- TypeApply
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- TermBlock
+ | | +- DefnVar
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- LitInt
+ | | +- DefnVar
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- TermThis
+ | | | +- NameAnonymous
+ | | +- DefnVal
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- TermApplyType
+ | | | +- TermSelect
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TypeName
+ | | +- TermWhile
+ | | | +- TermApplyInfix
+ | | | | +- TermApplyInfix
+ | | | | | +- TermName
+ | | | | | +- TermName
+ | | | | | +- TermName
+ | | | | +- TermName
+ | | | | +- TermSelect
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermBlock
+ | | | +- TermApplyInfix
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | | +- LitInt
+ | | | +- TermApplyInfix
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | | +- TermSelect
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermAssign
+ | | | +- TermName
+ | | | +- TermSelect
+ | | | +- TermName
+ | | | +- TermName
+ | | +- TermIf
+ | | +- TermApplyInfix
+ | | | +- TermApplyInfix
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermName
+ | | | +- TermSelect
+ | | | +- TermName
+ | | | +- TermName
+ | | +- TermBlock
+ | | | +- TermApply
+ | | | +- TermSelect
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermApplyInfix
+ | | | +- TermName
+ | | | +- TermName
+ | | | +- TermSelect
+ | | | +- TermName
+ | | | +- TermName
+ | | +- TermBlock
+ | | +- TermThrow
+ | | +- TermNew
+ | | +- Init
+ | | +- TypeName
+ | | +- NameAnonymous
+ | | +- TermInterpolate
+ | | +- TermName
+ | | +- LitString
+ | | +- LitString
+ | | +- LitString
+ | | +- TermName
+ | | +- TermApplyInfix
+ | | +- TermName
+ | | +- TermName
+ | | +- TermApplyInfix
+ | | +- TermName
+ | | +- TermName
+ | | +- LitInt
+ | +- DefnDef
+ | | +- ModFinal
+ | | +- ModOverride
+ | | +- TermName
+ | | +- TypeParam
+ | | | +- TypeName
+ | | | +- TypeBounds
+ | | +- TermParam
+ | | | +- TermName
+ | | | +- TypeFunction
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- TypeApply
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- TermBlock
+ | | +- TermIf
+ | | +- TermApplyInfix
+ | | | +- TermThis
+ | | | | +- NameAnonymous
+ | | | +- TermName
+ | | | +- TermName
+ | | +- TermName
+ | | +- TermBlock
+ | | +- DefnVal
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- TermNew
+ | | | +- Init
+ | | | +- TypeApply
+ | | | | +- TypeName
+ | | | | +- TypeName
+ | | | +- NameAnonymous
+ | | | +- TermApply
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermName
+ | | +- DefnVar
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- TypeApply
+ | | | | +- TypeName
+ | | | | +- TypeName
+ | | | +- TermName
+ | | +- DefnVar
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- TermName
+ | | +- TermWhile
+ | | | +- TermApplyInfix
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermBlock
+ | | | +- DefnVal
+ | | | | +- PatVar
+ | | | | | +- TermName
+ | | | | +- TermNew
+ | | | | +- Init
+ | | | | +- TypeName
+ | | | | +- NameAnonymous
+ | | | | +- TermApply
+ | | | | | +- TermName
+ | | | | | +- TermSelect
+ | | | | | +- TermName
+ | | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermAssign
+ | | | | +- TermSelect
+ | | | | | +- TermName
+ | | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermAssign
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermAssign
+ | | | +- TermName
+ | | | +- TermSelect
+ | | | +- TermName
+ | | | +- TermName
+ | | +- TermApply
+ | | | +- TermName
+ | | +- TermName
+ | +- DefnDef
+ | | +- ModFinal
+ | | +- ModOverride
+ | | +- TermName
+ | | +- TypeParam
+ | | | +- TypeName
+ | | | +- TypeBounds
+ | | +- TermParam
+ | | | +- TermName
+ | | | +- TypeApply
+ | | | +- TypeName
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- TypeApply
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- TermBlock
+ | | +- TermIf
+ | | +- TermApplyInfix
+ | | | +- TermThis
+ | | | | +- NameAnonymous
+ | | | +- TermName
+ | | | +- TermName
+ | | +- TermName
+ | | +- TermBlock
+ | | +- DefnVar
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- TermThis
+ | | | +- NameAnonymous
+ | | +- DefnVar
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- TypeApply
+ | | | | +- TypeName
+ | | | | +- TypeName
+ | | | +- LitNull
+ | | +- DefnVar
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- TypeName
+ | | | +- LitNull
+ | | +- TermWhile
+ | | | +- TermApplyInfix
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | | +- LitNull
+ | | | +- TermBlock
+ | | | +- TermAssign
+ | | | | +- TermName
+ | | | | +- TermApply
+ | | | | +- TermSelect
+ | | | | | +- TermName
+ | | | | | +- TermName
+ | | | | +- TermSelect
+ | | | | | +- TermName
+ | | | | | +- TermName
+ | | | | +- TermSelect
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermIf
+ | | | | +- TermApplyInfix
+ | | | | | +- TermApplyType
+ | | | | | | +- TermSelect
+ | | | | | | | +- TermName
+ | | | | | | | +- TermName
+ | | | | | | +- TypeName
+ | | | | | +- TermName
+ | | | | | +- TermSelect
+ | | | | | +- TermName
+ | | | | | +- TermName
+ | | | | +- TermAssign
+ | | | | | +- TermName
+ | | | | | +- TermNew
+ | | | | | +- Init
+ | | | | | +- TypeName
+ | | | | | +- NameAnonymous
+ | | | | | +- TermApplyType
+ | | | | | | +- TermSelect
+ | | | | | | | +- TermName
+ | | | | | | | +- TermName
+ | | | | | | +- TypeName
+ | | | | | +- TermName
+ | | | | +- LitUnit
+ | | | +- TermAssign
+ | | | | +- TermName
+ | | | | +- TermSelect
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermIf
+ | | | +- TermApplyInfix
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermReturn
+ | | | | +- TermIf
+ | | | | +- TermApplyInfix
+ | | | | | +- TermName
+ | | | | | +- TermName
+ | | | | | +- LitNull
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- LitUnit
+ | | +- DefnVar
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- TermName
+ | | +- TermWhile
+ | | | +- TermApplyInfix
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermBlock
+ | | | +- TermAssign
+ | | | | +- TermName
+ | | | | +- TermApply
+ | | | | +- TermSelect
+ | | | | | +- TermName
+ | | | | | +- TermName
+ | | | | +- TermSelect
+ | | | | | +- TermName
+ | | | | | +- TermName
+ | | | | +- TermSelect
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermIf
+ | | | | +- TermApplyInfix
+ | | | | | +- TermApplyType
+ | | | | | | +- TermSelect
+ | | | | | | | +- TermName
+ | | | | | | | +- TermName
+ | | | | | | +- TypeName
+ | | | | | +- TermName
+ | | | | | +- TermSelect
+ | | | | | +- TermName
+ | | | | | +- TermName
+ | | | | +- TermBlock
+ | | | | | +- DefnVal
+ | | | | | | +- PatVar
+ | | | | | | | +- TermName
+ | | | | | | +- TermNew
+ | | | | | | +- Init
+ | | | | | | +- TypeName
+ | | | | | | +- NameAnonymous
+ | | | | | | +- TermApplyType
+ | | | | | | | +- TermSelect
+ | | | | | | | | +- TermName
+ | | | | | | | | +- TermName
+ | | | | | | | +- TypeName
+ | | | | | | +- TermName
+ | | | | | +- TermAssign
+ | | | | | | +- TermSelect
+ | | | | | | | +- TermName
+ | | | | | | | +- TermName
+ | | | | | | +- TermName
+ | | | | | +- TermAssign
+ | | | | | +- TermName
+ | | | | | +- TermName
+ | | | | +- LitUnit
+ | | | +- TermAssign
+ | | | +- TermName
+ | | | +- TermSelect
+ | | | +- TermName
+ | | | +- TermName
+ | | +- TermApply
+ | | | +- TermName
+ | | +- TermName
+ | +- DefnDef
+ | | +- ModFinal
+ | | +- ModOverride
+ | | +- TermName
+ | | +- TypeParam
+ | | | +- TypeName
+ | | | +- TypeBounds
+ | | +- TermParam
+ | | | +- TermName
+ | | | +- TypeFunction
+ | | | +- TypeName
+ | | | +- TypeApply
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- TypeApply
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- TermBlock
+ | | +- DefnVar
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- TermThis
+ | | | +- NameAnonymous
+ | | +- DefnVar
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- TypeApply
+ | | | | +- TypeName
+ | | | | +- TypeName
+ | | | +- LitNull
+ | | +- DefnVar
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- TypeApply
+ | | | | +- TypeName
+ | | | | +- TypeName
+ | | | +- LitNull
+ | | +- TermWhile
+ | | | +- TermApplyInfix
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermBlock
+ | | | +- DefnVal
+ | | | | +- PatVar
+ | | | | | +- TermName
+ | | | | +- TermSelect
+ | | | | +- TermApply
+ | | | | | +- TermName
+ | | | | | +- TermSelect
+ | | | | | +- TermName
+ | | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermWhile
+ | | | | +- TermSelect
+ | | | | | +- TermName
+ | | | | | +- TermName
+ | | | | +- TermBlock
+ | | | | +- DefnVal
+ | | | | | +- PatVar
+ | | | | | | +- TermName
+ | | | | | +- TermNew
+ | | | | | +- Init
+ | | | | | +- TypeName
+ | | | | | +- NameAnonymous
+ | | | | | +- TermApply
+ | | | | | | +- TermSelect
+ | | | | | | +- TermName
+ | | | | | | +- TermName
+ | | | | | +- TermName
+ | | | | +- TermIf
+ | | | | | +- TermApplyInfix
+ | | | | | | +- TermName
+ | | | | | | +- TermName
+ | | | | | | +- LitNull
+ | | | | | +- TermBlock
+ | | | | | | +- TermAssign
+ | | | | | | +- TermName
+ | | | | | | +- TermName
+ | | | | | +- TermBlock
+ | | | | | +- TermAssign
+ | | | | | +- TermSelect
+ | | | | | | +- TermName
+ | | | | | | +- TermName
+ | | | | | +- TermName
+ | | | | +- TermAssign
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermAssign
+ | | | +- TermName
+ | | | +- TermSelect
+ | | | +- TermName
+ | | | +- TermName
+ | | +- TermIf
+ | | +- TermApplyInfix
+ | | | +- TermName
+ | | | +- TermName
+ | | | +- LitNull
+ | | +- TermName
+ | | +- TermBlock
+ | | +- TermApply
+ | | | +- TermName
+ | | +- TermName
+ | +- DefnDef
+ | | +- ModAnnot
+ | | | +- Init
+ | | | +- TypeName
+ | | | +- NameAnonymous
+ | | +- ModFinal
+ | | +- ModOverride
+ | | +- TermName
+ | | +- TermParam
+ | | | +- TermName
+ | | | +- TypeFunction
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- TypeApply
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- TermBlock
+ | | +- DefnVal
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- TermNew
+ | | | +- Init
+ | | | +- TypeApply
+ | | | | +- TypeName
+ | | | | +- TypeName
+ | | | +- NameAnonymous
+ | | +- DefnVar
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- TermThis
+ | | | +- NameAnonymous
+ | | +- TermWhile
+ | | | +- TermApplyInfix
+ | | | | +- TermApplyUnary
+ | | | | | +- TermName
+ | | | | | +- TermSelect
+ | | | | | +- TermName
+ | | | | | +- TermName
+ | | | | +- TermName
+ | | | | +- TermApply
+ | | | | +- TermName
+ | | | | +- TermSelect
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermBlock
+ | | | +- TermApplyInfix
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | | +- TermSelect
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermAssign
+ | | | +- TermName
+ | | | +- TermSelect
+ | | | +- TermName
+ | | | +- TermName
+ | | +- TermSelect
+ | | +- TermName
+ | | +- TermName
+ | +- DefnDef
+ | | +- ModAnnot
+ | | | +- Init
+ | | | +- TypeName
+ | | | +- NameAnonymous
+ | | +- ModFinal
+ | | +- ModOverride
+ | | +- TermName
+ | | +- TermParam
+ | | | +- TermName
+ | | | +- TypeFunction
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- TypeTuple
+ | | | +- TypeApply
+ | | | | +- TypeName
+ | | | | +- TypeName
+ | | | +- TypeApply
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- TermBlock
+ | | +- DefnVal
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- TermNew
+ | | | +- Init
+ | | | +- TypeApply
+ | | | | +- TypeName
+ | | | | +- TypeName
+ | | | +- NameAnonymous
+ | | +- DefnVar
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- TermThis
+ | | | +- NameAnonymous
+ | | +- TermWhile
+ | | | +- TermApplyInfix
+ | | | | +- TermApplyUnary
+ | | | | | +- TermName
+ | | | | | +- TermSelect
+ | | | | | +- TermName
+ | | | | | +- TermName
+ | | | | +- TermName
+ | | | | +- TermApply
+ | | | | +- TermName
+ | | | | +- TermSelect
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermBlock
+ | | | +- TermApplyInfix
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | | +- TermSelect
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermAssign
+ | | | +- TermName
+ | | | +- TermSelect
+ | | | +- TermName
+ | | | +- TermName
+ | | +- TermTuple
+ | | +- TermSelect
+ | | | +- TermName
+ | | | +- TermName
+ | | +- TermName
+ | +- DefnDef
+ | | +- ModAnnot
+ | | | +- Init
+ | | | +- TypeName
+ | | | +- NameAnonymous
+ | | +- ModFinal
+ | | +- ModOverride
+ | | +- TermName
+ | | +- TypeParam
+ | | | +- TypeName
+ | | | +- TypeBounds
+ | | +- TermParam
+ | | | +- TermName
+ | | | +- TypeFunction
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- TypeName
+ | | +- TermBlock
+ | | +- DefnVar
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- TermThis
+ | | | +- NameAnonymous
+ | | +- TermWhile
+ | | +- TermApplyUnary
+ | | | +- TermName
+ | | | +- TermSelect
+ | | | +- TermName
+ | | | +- TermName
+ | | +- TermBlock
+ | | +- TermApply
+ | | | +- TermName
+ | | | +- TermSelect
+ | | | +- TermName
+ | | | +- TermName
+ | | +- TermAssign
+ | | +- TermName
+ | | +- TermSelect
+ | | +- TermName
+ | | +- TermName
+ | +- DefnDef
+ | | +- ModFinal
+ | | +- ModOverride
+ | | +- TermName
+ | | +- TypeApply
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- TermBlock
+ | | +- DefnVar
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- TypeApply
+ | | | | +- TypeName
+ | | | | +- TypeName
+ | | | +- TermName
+ | | +- DefnVar
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- TermThis
+ | | | +- NameAnonymous
+ | | +- TermWhile
+ | | | +- TermApplyUnary
+ | | | | +- TermName
+ | | | | +- TermSelect
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermBlock
+ | | | +- TermAssign
+ | | | | +- TermName
+ | | | | +- TermApplyInfix
+ | | | | +- TermSelect
+ | | | | | +- TermName
+ | | | | | +- TermName
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermAssign
+ | | | +- TermName
+ | | | +- TermSelect
+ | | | +- TermName
+ | | | +- TermName
+ | | +- TermName
+ | +- DefnDef
+ | | +- ModFinal
+ | | +- ModOverride
+ | | +- TermName
+ | | +- TypeParam
+ | | | +- TypeName
+ | | | +- TypeBounds
+ | | +- TermParam
+ | | | +- TermName
+ | | | +- TypeName
+ | | +- TermParam
+ | | | +- TermName
+ | | | +- TypeFunction
+ | | | +- TypeName
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- TypeName
+ | | +- TermBlock
+ | | +- DefnVar
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- TermName
+ | | +- DefnVar
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- TypeApply
+ | | | | +- TypeName
+ | | | | +- TypeName
+ | | | +- TermName
+ | | +- TermWhile
+ | | | +- TermApplyUnary
+ | | | | +- TermName
+ | | | | +- TermSelect
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermBlock
+ | | | +- TermAssign
+ | | | | +- TermName
+ | | | | +- TermApply
+ | | | | +- TermName
+ | | | | +- TermSelect
+ | | | | | +- TermName
+ | | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermAssign
+ | | | +- TermName
+ | | | +- TermSelect
+ | | | +- TermName
+ | | | +- TermName
+ | | +- TermName
+ | +- DefnDef
+ | | +- ModOverride
+ | | +- ModFinal
+ | | +- TermName
+ | | +- TypeName
+ | | +- TermBlock
+ | | +- DefnVar
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- TermThis
+ | | | +- NameAnonymous
+ | | +- DefnVar
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- LitInt
+ | | +- TermWhile
+ | | | +- TermApplyUnary
+ | | | | +- TermName
+ | | | | +- TermSelect
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermBlock
+ | | | +- TermApplyInfix
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | | +- LitInt
+ | | | +- TermAssign
+ | | | +- TermName
+ | | | +- TermSelect
+ | | | +- TermName
+ | | | +- TermName
+ | | +- TermName
+ | +- DefnDef
+ | | +- ModOverride
+ | | +- ModFinal
+ | | +- TermName
+ | | +- TermParam
+ | | | +- TermName
+ | | | +- TypeName
+ | | +- TypeName
+ | | +- TermBlock
+ | | +- DefnDef
+ | | | +- ModAnnot
+ | | | | +- Init
+ | | | | +- TypeName
+ | | | | +- NameAnonymous
+ | | | +- TermName
+ | | | +- TermParam
+ | | | | +- TermName
+ | | | | +- TypeName
+ | | | +- TermParam
+ | | | | +- TermName
+ | | | | +- TypeApply
+ | | | | +- TypeName
+ | | | | +- TypeName
+ | | | +- TypeName
+ | | | +- TermBlock
+ | | | +- TermIf
+ | | | +- TermApplyInfix
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermIf
+ | | | | +- TermSelect
+ | | | | | +- TermName
+ | | | | | +- TermName
+ | | | | +- LitInt
+ | | | | +- LitInt
+ | | | +- TermIf
+ | | | +- TermSelect
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- LitInt
+ | | | +- TermApply
+ | | | +- TermName
+ | | | +- TermApplyInfix
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | | +- LitInt
+ | | | +- TermSelect
+ | | | +- TermName
+ | | | +- TermName
+ | | +- TermIf
+ | | +- TermApplyInfix
+ | | | +- TermName
+ | | | +- TermName
+ | | | +- LitInt
+ | | +- LitInt
+ | | +- TermApply
+ | | +- TermName
+ | | +- LitInt
+ | | +- TermName
+ | +- DefnDef
+ | | +- ModOverride
+ | | +- ModFinal
+ | | +- TermName
+ | | +- TermParam
+ | | | +- TermName
+ | | | +- TypeFunction
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- TypeName
+ | | +- TermBlock
+ | | +- DefnVar
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- TypeApply
+ | | | | +- TypeName
+ | | | | +- TypeName
+ | | | +- TermThis
+ | | | +- NameAnonymous
+ | | +- TermWhile
+ | | | +- TermApplyUnary
+ | | | | +- TermName
+ | | | | +- TermSelect
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermBlock
+ | | | +- TermIf
+ | | | | +- TermApplyUnary
+ | | | | | +- TermName
+ | | | | | +- TermApply
+ | | | | | +- TermName
+ | | | | | +- TermSelect
+ | | | | | +- TermName
+ | | | | | +- TermName
+ | | | | +- TermReturn
+ | | | | | +- LitBoolean
+ | | | | +- LitUnit
+ | | | +- TermAssign
+ | | | +- TermName
+ | | | +- TermSelect
+ | | | +- TermName
+ | | | +- TermName
+ | | +- LitBoolean
+ | +- DefnDef
+ | | +- ModOverride
+ | | +- ModFinal
+ | | +- TermName
+ | | +- TermParam
+ | | | +- TermName
+ | | | +- TypeFunction
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- TypeName
+ | | +- TermBlock
+ | | +- DefnVar
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- TypeApply
+ | | | | +- TypeName
+ | | | | +- TypeName
+ | | | +- TermThis
+ | | | +- NameAnonymous
+ | | +- TermWhile
+ | | | +- TermApplyUnary
+ | | | | +- TermName
+ | | | | +- TermSelect
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermBlock
+ | | | +- TermIf
+ | | | | +- TermApply
+ | | | | | +- TermName
+ | | | | | +- TermSelect
+ | | | | | +- TermName
+ | | | | | +- TermName
+ | | | | +- TermReturn
+ | | | | | +- LitBoolean
+ | | | | +- LitUnit
+ | | | +- TermAssign
+ | | | +- TermName
+ | | | +- TermSelect
+ | | | +- TermName
+ | | | +- TermName
+ | | +- LitBoolean
+ | +- DefnDef
+ | | +- ModOverride
+ | | +- ModFinal
+ | | +- TermName
+ | | +- TypeParam
+ | | | +- TypeName
+ | | | +- TypeBounds
+ | | | +- TypeName
+ | | +- TermParam
+ | | | +- TermName
+ | | | +- TypeName
+ | | +- TypeName
+ | | +- TermBlock
+ | | +- DefnVar
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- TypeApply
+ | | | | +- TypeName
+ | | | | +- TypeName
+ | | | +- TermThis
+ | | | +- NameAnonymous
+ | | +- TermWhile
+ | | | +- TermApplyUnary
+ | | | | +- TermName
+ | | | | +- TermSelect
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermBlock
+ | | | +- TermIf
+ | | | | +- TermApplyInfix
+ | | | | | +- TermSelect
+ | | | | | | +- TermName
+ | | | | | | +- TermName
+ | | | | | +- TermName
+ | | | | | +- TermName
+ | | | | +- TermReturn
+ | | | | | +- LitBoolean
+ | | | | +- LitUnit
+ | | | +- TermAssign
+ | | | +- TermName
+ | | | +- TermSelect
+ | | | +- TermName
+ | | | +- TermName
+ | | +- LitBoolean
+ | +- DefnDef
+ | +- ModOverride
+ | +- ModFinal
+ | +- TermName
+ | +- TermParam
+ | | +- TermName
+ | | +- TypeFunction
+ | | +- TypeName
+ | | +- TypeName
+ | +- TypeApply
+ | | +- TypeName
+ | | +- TypeName
+ | +- TermBlock
+ | +- DefnVar
+ | | +- PatVar
+ | | | +- TermName
+ | | +- TypeApply
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- TermThis
+ | | +- NameAnonymous
+ | +- TermWhile
+ | | +- TermApplyUnary
+ | | | +- TermName
+ | | | +- TermSelect
+ | | | +- TermName
+ | | | +- TermName
+ | | +- TermBlock
+ | | +- TermIf
+ | | | +- TermApply
+ | | | | +- TermName
+ | | | | +- TermSelect
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermReturn
+ | | | | +- TermApply
+ | | | | +- TermName
+ | | | | +- TermSelect
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- LitUnit
+ | | +- TermAssign
+ | | +- TermName
+ | | +- TermSelect
+ | | +- TermName
+ | | +- TermName
+ | +- TermName
+ +- DefnClass
+ | +- ModFinal
+ | +- ModCase
+ | +- TypeName
+ | +- TypeParam
+ | | +- ModCovariant
+ | | +- TypeName
+ | | +- TypeBounds
+ | +- CtorPrimary
+ | | +- NameAnonymous
+ | | +- TermParam
+ | | | +- ModOverride
+ | | | +- ModValParam
+ | | | +- TermName
+ | | | +- TypeName
+ | | +- TermParam
+ | | +- ModPrivate
+ | | | +- NameIndeterminate
+ | | +- ModVarParam
+ | | +- TermName
+ | | +- TypeApply
+ | | +- TypeName
+ | | +- TypeAnnotate
+ | | +- TypeName
+ | | +- ModAnnot
+ | | +- Init
+ | | +- TypeName
+ | | +- NameAnonymous
+ | +- Template
+ | +- Init
+ | | +- TypeApply
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- NameAnonymous
+ | +- Self
+ | | +- NameAnonymous
+ | +- TermApply
+ | | +- TermName
+ | +- DefnDef
+ | | +- ModOverride
+ | | +- TermName
+ | | +- TypeApply
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- TermApply
+ | | +- TermName
+ | | +- TermName
+ | +- DefnDef
+ | +- ModOverride
+ | +- TermName
+ | +- TypeApply
+ | | +- TypeName
+ | | +- TypeName
+ | +- TermName
+ +- DefnObject
+ | +- ModCase
+ | +- TermName
+ | +- Template
+ | +- Init
+ | | +- TypeApply
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- NameAnonymous
+ | +- Self
+ | | +- NameAnonymous
+ | +- DefnDef
+ | | +- ModOverride
+ | | +- TermName
+ | | +- TypeName
+ | | +- TermThrow
+ | | +- TermNew
+ | | +- Init
+ | | +- TypeName
+ | | +- NameAnonymous
+ | | +- LitString
+ | +- DefnDef
+ | | +- ModOverride
+ | | +- TermName
+ | | +- TypeSingleton
+ | | | +- TermName
+ | | +- TermName
+ | +- DefnDef
+ | | +- ModOverride
+ | | +- TermName
+ | | +- TypeName
+ | | +- TermThrow
+ | | +- TermNew
+ | | +- Init
+ | | +- TypeName
+ | | +- NameAnonymous
+ | | +- LitString
+ | +- DefnDef
+ | | +- ModOverride
+ | | +- TermName
+ | | +- TypeName
+ | | +- TermThrow
+ | | +- TermNew
+ | | +- Init
+ | | +- TypeName
+ | | +- NameAnonymous
+ | | +- LitString
+ | +- DefnDef
+ | | +- ModOverride
+ | | +- TermName
+ | | +- TypeName
+ | | +- TermThrow
+ | | +- TermNew
+ | | +- Init
+ | | +- TypeName
+ | | +- NameAnonymous
+ | | +- LitString
+ | +- DefnDef
+ | | +- ModOverride
+ | | +- TermName
+ | | +- TypeName
+ | | +- LitInt
+ | +- DefnDef
+ | | +- ModOverride
+ | | +- TermName
+ | | +- TypeApply
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- TermSelect
+ | | +- TermName
+ | | +- TermName
+ | +- DefnDef
+ | | +- ModOverride
+ | | +- TermName
+ | | +- TypeParam
+ | | | +- TypeName
+ | | | +- TypeBounds
+ | | +- TypeParam
+ | | | +- TypeName
+ | | | +- TypeBounds
+ | | +- TermParam
+ | | | +- ModImplicit
+ | | | +- TermName
+ | | | +- TypeFunction
+ | | | +- TypeName
+ | | | +- TypeTuple
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- TypeTuple
+ | | | +- TypeApply
+ | | | | +- TypeName
+ | | | | +- TypeName
+ | | | +- TypeApply
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- TermName
+ | +- DefnVal
+ | +- ModAnnot
+ | | +- Init
+ | | +- TypeName
+ | | +- NameAnonymous
+ | +- ModPrivate
+ | | +- TermThis
+ | | +- NameAnonymous
+ | +- PatVar
+ | | +- TermName
+ | +- TermTuple
+ | +- TermName
+ | +- TermName
+ +- DefnObject
+ +- ModAnnot
+ | +- Init
+ | +- TypeName
+ | +- NameAnonymous
+ | +- LitLong
+ +- TermName
+ +- Template
+ +- Init
+ | +- TypeApply
+ | | +- TypeName
+ | | +- TypeName
+ | +- NameAnonymous
+ +- Self
+ | +- NameAnonymous
+ +- DefnVal
+ | +- ModPrivate
+ | | +- NameAnonymous
+ | +- PatVar
+ | | +- TermName
+ | +- TermTuple
+ | +- TermName
+ | +- TermName
+ +- DefnDef
+ | +- TermName
+ | +- TypeParam
+ | | +- TypeName
+ | | +- TypeBounds
+ | +- TermParam
+ | | +- TermName
+ | | +- TypeApply
+ | | +- TypeSelect
+ | | | +- TermName
+ | | | +- TypeName
+ | | +- TypeName
+ | +- TypeApply
+ | | +- TypeName
+ | | +- TypeName
+ | +- TermMatch
+ | +- TermName
+ | +- Case
+ | | +- PatTyped
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- TypeApply
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- TermName
+ | +- Case
+ | | +- PatWildcard
+ | | +- TermApplyInfix
+ | | | +- TermSelect
+ | | | | +- TermName
+ | | | | +- TermName
+ | | | +- TermName
+ | | | +- LitInt
+ | | +- TermApplyType
+ | | +- TermName
+ | | +- TypeName
+ | +- Case
+ | | +- PatTyped
+ | | | +- PatVar
+ | | | | +- TermName
+ | | | +- TypeApply
+ | | | +- TypeName
+ | | | +- TypeName
+ | | +- TermSelect
+ | | +- TermName
+ | | +- TermName
+ | +- Case
+ | +- PatWildcard
+ | +- TermSelect
+ | +- TermApply
+ | | +- TermSelect
+ | | | +- TermName
+ | | | +- TermName
+ | | +- TermName
+ | +- TermName
+ +- DefnDef
+ | +- TermName
+ | +- TypeParam
+ | | +- TypeName
+ | | +- TypeBounds
+ | +- TypeApply
+ | | +- TypeName
+ | | +- TypeName
+ | | +- TypeApply
+ | | +- TypeName
+ | | +- TypeName
+ | +- TermNew
+ | +- Init
+ | +- TypeName
+ | +- NameAnonymous
+ +- DefnDef
+ | +- TermName
+ | +- TypeParam
+ | | +- TypeName
+ | | +- TypeBounds
+ | +- TypeApply
+ | | +- TypeName
+ | | +- TypeName
+ | +- TermName
+ +- DefnVal
+ +- ModAnnot
+ | +- Init
+ | +- TypeName
+ | +- NameAnonymous
+ +- ModPrivate
+ | +- NameIndeterminate
+ +- PatVar
+ | +- TermName
+ +- TermNewAnonymous
+ +- Template
+ +- Init
+ | +- TypeApply
+ | | +- TypeName
+ | | +- TypeName
+ | | +- TypeName
+ | +- NameAnonymous
+ +- Self
+ | +- NameAnonymous
+ +- DefnDef
+ +- TermName
+ +- TermParam
+ | +- TermName
+ | +- TypeName
+ +- TypeName
+ +- TermThis
+ +- NameAnonymous
diff --git a/pmd-scala/src/test/resources/net/sourceforge/pmd/lang/scala/ast/testdata/package.scala b/pmd-scala/src/test/resources/net/sourceforge/pmd/lang/scala/ast/testdata/package.scala
new file mode 100644
index 0000000000..4acf9bf2b7
--- /dev/null
+++ b/pmd-scala/src/test/resources/net/sourceforge/pmd/lang/scala/ast/testdata/package.scala
@@ -0,0 +1,22 @@
+
+/*
+ * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
+ */
+
+package scala.collection
+
+
+package object immutable {
+ type StringOps = scala.collection.StringOps
+ val StringOps = scala.collection.StringOps
+ type StringView = scala.collection.StringView
+ val StringView = scala.collection.StringView
+
+ @deprecated("Use Iterable instead of Traversable", "2.13.0")
+ type Traversable[+X] = Iterable[X]
+ @deprecated("Use Iterable instead of Traversable", "2.13.0")
+ val Traversable = Iterable
+
+ @deprecated("Use Map instead of DefaultMap", "2.13.0")
+ type DefaultMap[K, +V] = scala.collection.immutable.Map[K, V]
+}
\ No newline at end of file
diff --git a/pmd-scala/src/test/resources/net/sourceforge/pmd/lang/scala/ast/testdata/package.txt b/pmd-scala/src/test/resources/net/sourceforge/pmd/lang/scala/ast/testdata/package.txt
new file mode 100644
index 0000000000..0a5eedd4b5
--- /dev/null
+++ b/pmd-scala/src/test/resources/net/sourceforge/pmd/lang/scala/ast/testdata/package.txt
@@ -0,0 +1,90 @@
++- Source
+ +- Pkg
+ +- TermSelect
+ | +- TermName
+ | +- TermName
+ +- PkgObject
+ +- TermName
+ +- Template
+ +- Self
+ | +- NameAnonymous
+ +- DefnType
+ | +- TypeName
+ | +- TypeSelect
+ | +- TermSelect
+ | | +- TermName
+ | | +- TermName
+ | +- TypeName
+ +- DefnVal
+ | +- PatVar
+ | | +- TermName
+ | +- TermSelect
+ | +- TermSelect
+ | | +- TermName
+ | | +- TermName
+ | +- TermName
+ +- DefnType
+ | +- TypeName
+ | +- TypeSelect
+ | +- TermSelect
+ | | +- TermName
+ | | +- TermName
+ | +- TypeName
+ +- DefnVal
+ | +- PatVar
+ | | +- TermName
+ | +- TermSelect
+ | +- TermSelect
+ | | +- TermName
+ | | +- TermName
+ | +- TermName
+ +- DefnType
+ | +- ModAnnot
+ | | +- Init
+ | | +- TypeName
+ | | +- NameAnonymous
+ | | +- LitString
+ | | +- LitString
+ | +- TypeName
+ | +- TypeParam
+ | | +- ModCovariant
+ | | +- TypeName
+ | | +- TypeBounds
+ | +- TypeApply
+ | +- TypeName
+ | +- TypeName
+ +- DefnVal
+ | +- ModAnnot
+ | | +- Init
+ | | +- TypeName
+ | | +- NameAnonymous
+ | | +- LitString
+ | | +- LitString
+ | +- PatVar
+ | | +- TermName
+ | +- TermName
+ +- DefnType
+ +- ModAnnot
+ | +- Init
+ | +- TypeName
+ | +- NameAnonymous
+ | +- LitString
+ | +- LitString
+ +- TypeName
+ +- TypeParam
+ | +- TypeName
+ | +- TypeBounds
+ +- TypeParam
+ | +- ModCovariant
+ | +- TypeName
+ | +- TypeBounds
+ +- TypeApply
+ +- TypeSelect
+ | +- TermSelect
+ | | +- TermSelect
+ | | | +- TermName
+ | | | +- TermName
+ | | +- TermName
+ | +- TypeName
+ +- TypeName
+ +- TypeName
diff --git a/pom.xml b/pom.xml
index 1dfe7db0e1..3252464717 100644
--- a/pom.xml
+++ b/pom.xml
@@ -256,6 +256,9 @@
once
alphabetical
+
+ ${project.basedir}/src/test/resources
+