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 +