From 760df9843a910d6c3618e490c752eb03fb6924bd Mon Sep 17 00:00:00 2001 From: Den Shabalin Date: Fri, 6 Dec 2013 18:01:05 +0100 Subject: SI-8030 force symbols on presentation compiler initialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit forces a number of built-in symbols in presentation compiler to prevent them from being entered during parsing. The property “parsing doesn’t enter new symbols” is tested on a rich source file that contains significant number of variations of Scala syntax. --- .../files/presentation/parse-invariants/Test.scala | 107 +++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 test/files/presentation/parse-invariants/Test.scala (limited to 'test/files/presentation/parse-invariants/Test.scala') diff --git a/test/files/presentation/parse-invariants/Test.scala b/test/files/presentation/parse-invariants/Test.scala new file mode 100644 index 0000000000..128896ccaa --- /dev/null +++ b/test/files/presentation/parse-invariants/Test.scala @@ -0,0 +1,107 @@ +import scala.tools.nsc.interactive.tests.InteractiveTest +import scala.reflect.internal.util.SourceFile +import scala.tools.nsc.interactive.Response + +object Test extends InteractiveTest { + + override def execute(): Unit = { + val sf = sourceFiles.find(_.file.name == "A.scala").head + noNewSymbols(sf) + uniqueParseTree(sf) + unattributedParseTree(sf) + neverModifyParseTree(sf) + shouldAlwaysReturnParseTree(sf) + } + + /** + * Asking for a parseTree should not enter any new symbols. + */ + private def noNewSymbols(sf: SourceFile) { + def nextId() = compiler.NoSymbol.newTermSymbol(compiler.TermName("dummy"), compiler.NoPosition, compiler.NoFlags).id + val id = nextId() + val tree = compiler.parseTree(sf) + val id2 = nextId() + if (id2 == id + 1) { + reporter.println("NoNewSymbolsEntered OK") + } else { + reporter.println("NoNewSymbolsEntered FAILED") + } + } + + /** + * Asking twice for a parseTree on the same source should always return a new tree + */ + private def uniqueParseTree(sf: SourceFile) { + val parseTree1 = compiler.parseTree(sf) + val parseTree2 = compiler.parseTree(sf) + if (parseTree1 != parseTree2) { + reporter.println("Unique OK") + } else { + reporter.println("Unique FAILED") + } + } + + /** + * A parseTree should never contain any symbols or types + */ + private def unattributedParseTree(sf: SourceFile) { + if (noSymbolsOrTypes(compiler.parseTree(sf))) { + reporter.println("Unattributed OK") + } else { + reporter.println("Unattributed FAILED") + } + } + + /** + * Once you have obtained a parseTree it should never change + */ + private def neverModifyParseTree(sf: SourceFile) { + val parsedTree = compiler.parseTree(sf) + loadSourceAndWaitUntilTypechecked(sf) + if (noSymbolsOrTypes(parsedTree)) { + reporter.println("NeverModify OK") + } else { + reporter.println("NeverModify FAILED") + } + } + + /** + * Should always return a parse tree + */ + private def shouldAlwaysReturnParseTree(sf: SourceFile) { + loadSourceAndWaitUntilTypechecked(sf) + if (noSymbolsOrTypes(compiler.parseTree(sf))) { + reporter.println("AlwaysParseTree OK") + } else { + reporter.println("AlwaysParseTree FAILED") + } + } + + /** + * Load a source and block while it is type-checking. + */ + private def loadSourceAndWaitUntilTypechecked(sf: SourceFile): Unit = { + compiler.askToDoFirst(sf) + val res = new Response[Unit] + compiler.askReload(List(sf), res) + res.get + askLoadedTyped(sf).get + } + + /** + * Traverses a tree and makes sure that there are no types or symbols present in the tree with + * the exception of the symbol for the package 'scala'. This is because that symbol will be + * present in some of the nodes that the compiler generates. + */ + private def noSymbolsOrTypes(tree: compiler.Tree): Boolean = { + tree.forAll { t => + (t.symbol == null || + t.symbol == compiler.NoSymbol || + t.symbol == compiler.definitions.ScalaPackage // ignore the symbol for the scala package for now + ) && ( + t.tpe == null || + t.tpe == compiler.NoType) + } + } + +} \ No newline at end of file -- cgit v1.2.3