diff --git a/compiler/src/dotty/tools/dotc/Driver.scala b/compiler/src/dotty/tools/dotc/Driver.scala index 7349c4615938..a1e986394fa6 100644 --- a/compiler/src/dotty/tools/dotc/Driver.scala +++ b/compiler/src/dotty/tools/dotc/Driver.scala @@ -2,7 +2,9 @@ package dotty.tools.dotc import dotty.tools.FatalError import config.CompilerCommand +import core.Comments.{ContextDoc, ContextDocstrings} import core.Contexts.{Context, ContextBase} +import core.Mode import util.DotClass import reporting._ import scala.util.control.NonFatal @@ -44,6 +46,11 @@ class Driver extends DotClass { val ctx = rootCtx.fresh val summary = CompilerCommand.distill(args)(ctx) ctx.setSettings(summary.sstate) + + if (!ctx.settings.YdropComments.value(ctx) || ctx.mode.is(Mode.ReadComments)) { + ctx.setProperty(ContextDoc, new ContextDocstrings) + } + val fileNames = CompilerCommand.checkUsage(summary, sourcesRequired)(ctx) (fileNames, ctx) } diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index c420d9e8e23a..d8ba91ed7c24 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -116,7 +116,7 @@ class ScalaSettings extends Settings.SettingGroup { val YshowPrintErrors = BooleanSetting("-Yshow-print-errors", "don't suppress exceptions thrown during tree printing.") val YtestPickler = BooleanSetting("-Ytest-pickler", "self-test for pickling functionality; should be used with -Ystop-after:pickler") val YcheckReentrant = BooleanSetting("-Ycheck-reentrant", "check that compiled program does not contain vars that can be accessed from a global root.") - val YkeepComments = BooleanSetting("-Ykeep-comments", "Keep comments when scanning source files.") + val YdropComments = BooleanSetting("-Ydrop-comments", "Drop comments when scanning source files.") val YcookComments = BooleanSetting("-Ycook-comments", "Cook the comments (type check `@usecase`, etc.)") val YforceSbtPhases = BooleanSetting("-Yforce-sbt-phases", "Run the phases used by sbt for incremental compilation (ExtractDependencies and ExtractAPI) even if the compiler is ran outside of sbt, for debugging.") val YdumpSbtInc = BooleanSetting("-Ydump-sbt-inc", "For every compiled foo.scala, output the API representation and dependencies used for sbt incremental compilation in foo.inc, implies -Yforce-sbt-phases.") diff --git a/compiler/src/dotty/tools/dotc/core/Comments.scala b/compiler/src/dotty/tools/dotc/core/Comments.scala index c95e56bf525c..0d38791efacc 100644 --- a/compiler/src/dotty/tools/dotc/core/Comments.scala +++ b/compiler/src/dotty/tools/dotc/core/Comments.scala @@ -99,7 +99,7 @@ object Comments { } object Comment { - def apply(pos: Position, raw: String, expanded: Boolean = false, usc: List[UseCase] = Nil)(implicit ctx: Context): Comment = + def apply(pos: Position, raw: String, expanded: Boolean = false, usc: List[UseCase] = Nil): Comment = new Comment(pos, raw) { val isExpanded = expanded val usecases = usc diff --git a/compiler/src/dotty/tools/dotc/core/Mode.scala b/compiler/src/dotty/tools/dotc/core/Mode.scala index c97e20a88d49..020b884b22b3 100644 --- a/compiler/src/dotty/tools/dotc/core/Mode.scala +++ b/compiler/src/dotty/tools/dotc/core/Mode.scala @@ -93,4 +93,8 @@ object Mode { /** We are in the IDE */ val Interactive = newMode(20, "Interactive") + + /** Read comments from definitions when unpickling from TASTY */ + val ReadComments = newMode(21, "ReadComments") + } diff --git a/compiler/src/dotty/tools/dotc/core/quoted/TastyUnpickler.scala b/compiler/src/dotty/tools/dotc/core/quoted/TastyUnpickler.scala index d47294ad7d76..ca58798c4630 100644 --- a/compiler/src/dotty/tools/dotc/core/quoted/TastyUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/quoted/TastyUnpickler.scala @@ -5,13 +5,13 @@ import dotty.tools.dotc.core.tasty.TastyUnpickler.NameTable object TastyUnpickler { class QuotedTreeSectionUnpickler(posUnpickler: Option[PositionUnpickler], splices: Seq[Any]) - extends DottyUnpickler.TreeSectionUnpickler(posUnpickler) { + extends DottyUnpickler.TreeSectionUnpickler(posUnpickler, None) { override def unpickle(reader: TastyReader, nameAtRef: NameTable) = - new TreeUnpickler(reader, nameAtRef, posUnpickler, splices) + new TreeUnpickler(reader, nameAtRef, posUnpickler, None, splices) } } -/** A class for unpickling quoted Tasty trees and symbols. +/** A class for unpickling quoted Tasty trees and symbols. Comments are never unpickled. * @param bytes the bytearray containing the Tasty file from which we unpickle * @param splices splices that will fill the holes in the quote */ @@ -19,6 +19,6 @@ class TastyUnpickler(bytes: Array[Byte], splices: Seq[Any]) extends DottyUnpickl import DottyUnpickler._ import TastyUnpickler._ - protected override def treeSectionUnpickler(posUnpicklerOpt: Option[PositionUnpickler]): TreeSectionUnpickler = + protected override def treeSectionUnpickler(posUnpicklerOpt: Option[PositionUnpickler], commentUnpicklerOpt: Option[CommentUnpickler]): TreeSectionUnpickler = new QuotedTreeSectionUnpickler(posUnpicklerOpt, splices) } diff --git a/compiler/src/dotty/tools/dotc/core/tasty/CommentPickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/CommentPickler.scala new file mode 100644 index 000000000000..b32efeb7b4f2 --- /dev/null +++ b/compiler/src/dotty/tools/dotc/core/tasty/CommentPickler.scala @@ -0,0 +1,43 @@ +package dotty.tools.dotc.core.tasty + +import dotty.tools.dotc.ast.tpd +import dotty.tools.dotc.core.Comments.{Comment, CommentsContext, ContextDocstrings} +import dotty.tools.dotc.core.Contexts.Context +import dotty.tools.dotc.core.tasty.TastyBuffer.Addr + +import java.nio.charset.Charset + +class CommentPickler(pickler: TastyPickler, addrOfTree: tpd.Tree => Option[Addr])(implicit ctx: Context) { + private[this] val buf = new TastyBuffer(5000) + pickler.newSection("Comments", buf) + + def pickleComment(root: tpd.Tree): Unit = { + assert(ctx.docCtx.isDefined, "Trying to pickle comments, but there's no `docCtx`.") + new Traverser(ctx.docCtx.get).traverse(root) + } + + def pickleComment(addrOfTree: Option[Addr], comment: Option[Comment]): Unit = (addrOfTree, comment) match { + case (Some(addr), Some(cmt)) => + val bytes = cmt.raw.getBytes(Charset.forName("UTF-8")) + val length = bytes.length + buf.writeAddr(addr) + buf.writeNat(length) + buf.writeBytes(bytes, length) + buf.writeByte(if (cmt.isExpanded) 1 else 0) + case other => + () + } + + private class Traverser(docCtx: ContextDocstrings) extends tpd.TreeTraverser { + override def traverse(tree: tpd.Tree)(implicit ctx: Context): Unit = + tree match { + case md: tpd.MemberDef => + val comment = docCtx.docstring(md.symbol) + pickleComment(addrOfTree(md), comment) + traverseChildren(md) + case _ => + traverseChildren(tree) + } + } + +} diff --git a/compiler/src/dotty/tools/dotc/core/tasty/CommentUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/CommentUnpickler.scala new file mode 100644 index 000000000000..158794dff72c --- /dev/null +++ b/compiler/src/dotty/tools/dotc/core/tasty/CommentUnpickler.scala @@ -0,0 +1,33 @@ +package dotty.tools.dotc.core.tasty + +import dotty.tools.dotc.core.Comments.Comment +import dotty.tools.dotc.core.Symbols.Symbol +import dotty.tools.dotc.core.tasty.TastyBuffer.Addr +import dotty.tools.dotc.util.Positions + +import scala.collection.mutable.HashMap + +import java.nio.charset.Charset + +class CommentUnpickler(reader: TastyReader) { + import reader._ + + private[tasty] lazy val comments = { + val comments = new HashMap[Addr, Comment] + while (!isAtEnd) { + val addr = readAddr() + val length = readNat() + if (length > 0) { + val bytes = readBytes(length) + val expanded = readByte() == 1 + val rawComment = new String(bytes, Charset.forName("UTF-8")) + comments(addr) = Comment(Positions.NoPosition, rawComment, expanded = expanded) + } + } + comments.toMap + } + + def commentAt(addr: Addr): Option[Comment] = + comments.get(addr) + +} diff --git a/compiler/src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala index 91832b997877..8f2aa8710a7e 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala @@ -17,16 +17,21 @@ object DottyUnpickler { /** Exception thrown if classfile is corrupted */ class BadSignature(msg: String) extends RuntimeException(msg) - class TreeSectionUnpickler(posUnpickler: Option[PositionUnpickler]) + class TreeSectionUnpickler(posUnpickler: Option[PositionUnpickler], commentUnpickler: Option[CommentUnpickler]) extends SectionUnpickler[TreeUnpickler]("ASTs") { def unpickle(reader: TastyReader, nameAtRef: NameTable) = - new TreeUnpickler(reader, nameAtRef, posUnpickler, Seq.empty) + new TreeUnpickler(reader, nameAtRef, posUnpickler, commentUnpickler, Seq.empty) } class PositionsSectionUnpickler extends SectionUnpickler[PositionUnpickler]("Positions") { def unpickle(reader: TastyReader, nameAtRef: NameTable) = new PositionUnpickler(reader) } + + class CommentsSectionUnpickler extends SectionUnpickler[CommentUnpickler]("Comments") { + def unpickle(reader: TastyReader, nameAtRef: NameTable): CommentUnpickler = + new CommentUnpickler(reader) + } } /** A class for unpickling Tasty trees and symbols. @@ -38,7 +43,8 @@ class DottyUnpickler(bytes: Array[Byte]) extends ClassfileParser.Embedded with t val unpickler = new TastyUnpickler(bytes) private val posUnpicklerOpt = unpickler.unpickle(new PositionsSectionUnpickler) - private val treeUnpickler = unpickler.unpickle(treeSectionUnpickler(posUnpicklerOpt)).get + private val commentUnpicklerOpt = unpickler.unpickle(new CommentsSectionUnpickler) + private val treeUnpickler = unpickler.unpickle(treeSectionUnpickler(posUnpicklerOpt, commentUnpicklerOpt)).get /** Enter all toplevel classes and objects into their scopes * @param roots a set of SymDenotations that should be overwritten by unpickling @@ -52,8 +58,8 @@ class DottyUnpickler(bytes: Array[Byte]) extends ClassfileParser.Embedded with t def unpickleTypeTree()(implicit ctx: Context): Tree = treeUnpickler.unpickleTypeTree() - protected def treeSectionUnpickler(posUnpicklerOpt: Option[PositionUnpickler]): TreeSectionUnpickler = { - new TreeSectionUnpickler(posUnpicklerOpt) + protected def treeSectionUnpickler(posUnpicklerOpt: Option[PositionUnpickler], commentUnpicklerOpt: Option[CommentUnpickler]): TreeSectionUnpickler = { + new TreeSectionUnpickler(posUnpicklerOpt, commentUnpicklerOpt) } protected def computeTrees(implicit ctx: Context) = treeUnpickler.unpickle() diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala index 1d659828abfe..f1237189459c 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala @@ -222,6 +222,12 @@ Standard Section: "Positions" Assoc* // same offset in the previously recorded node (or 0 for the first recorded node) Delta = Int // Difference between consecutive offsets, +Standard Section: "Comments" Comment* + + Comment = Length Bytes Byte // Raw comment's bytes encoded as UTF-8, plus a byte indicating + // whether the comment is expanded (1) or not expanded (0) + + **************************************************************************************/ object TastyFormat { diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala index c4ee8cffcf05..3a0442d7cbc6 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala @@ -34,6 +34,7 @@ class TastyPrinter(bytes: Array[Byte])(implicit ctx: Context) { println("Trees:") unpickle(new TreeSectionUnpickler) unpickle(new PositionSectionUnpickler) + unpickle(new CommentSectionUnpickler) } class TreeSectionUnpickler extends SectionUnpickler[Unit]("ASTs") { @@ -120,6 +121,19 @@ class TastyPrinter(bytes: Array[Byte])(implicit ctx: Context) { } } + class CommentSectionUnpickler extends SectionUnpickler[Unit]("Comments") { + def unpickle(reader: TastyReader, tastyName: NameTable): Unit = { + print(s" ${reader.endAddr.index - reader.currentAddr.index}") + val comments = new CommentUnpickler(reader).comments + println(s" comment bytes:") + val sorted = comments.toSeq.sortBy(_._1.index) + for ((addr, cmt) <- sorted) { + print(treeColor("%10d".format(addr.index))) + println(s": ${cmt.raw} (expanded = ${cmt.isExpanded})") + } + } + } + private def nameColor(str: String): String = Magenta(str).show private def treeColor(str: String): String = Yellow(str).show private def lengthColor(str: String): String = Cyan(str).show diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index ce955cee96c3..a032f1dfdb84 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -3,6 +3,7 @@ package dotc package core package tasty +import Comments.CommentsContext import Contexts._, Symbols._, Types._, Scopes._, SymDenotations._, Names._, NameOps._ import StdNames._, Denotations._, Flags._, Constants._, Annotations._ import NameKinds._ @@ -25,13 +26,15 @@ import scala.quoted.Types.TreeType import scala.quoted.Exprs.TastyTreeExpr /** Unpickler for typed trees - * @param reader the reader from which to unpickle - * @param tastyName the nametable - * @param posUNpicklerOpt the unpickler for positions, if it exists + * @param reader the reader from which to unpickle + * @param posUnpicklerOpt the unpickler for positions, if it exists + * @param commentUnpicklerOpt the unpickler for comments, if it exists + * @param splices */ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpicklerOpt: Option[PositionUnpickler], + commentUnpicklerOpt: Option[CommentUnpickler], splices: Seq[Any]) { import TastyFormat._ import TreeUnpickler._ @@ -820,6 +823,16 @@ class TreeUnpickler(reader: TastyReader, // Child annotations for local classes and enum values are not pickled, so // need to be re-established here. sym.registerIfChild(late = true) + + if (ctx.mode.is(Mode.ReadComments)) { + assert(ctx.docCtx.isDefined, "Mode is `ReadComments`, but no `docCtx` is set.") + commentUnpicklerOpt.foreach { commentUnpickler => + val comment = commentUnpickler.commentAt(start) + ctx.docCtx.get.addDocstring(tree.symbol, comment) + tree.setComment(comment) + } + } + tree } diff --git a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala index 877410ddf2ef..68443e5b2125 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala @@ -172,7 +172,7 @@ object Scanners { } class Scanner(source: SourceFile, override val startFrom: Offset = 0)(implicit ctx: Context) extends ScannerCommon(source)(ctx) { - val keepComments = ctx.settings.YkeepComments.value + val keepComments = !ctx.settings.YdropComments.value /** All doc comments kept by their end position in a `Map` */ private[this] var docstringMap: SortedMap[Int, Comment] = SortedMap.empty diff --git a/compiler/src/dotty/tools/dotc/transform/Pickler.scala b/compiler/src/dotty/tools/dotc/transform/Pickler.scala index b36386b9cf1a..a1772c9ca7f8 100644 --- a/compiler/src/dotty/tools/dotc/transform/Pickler.scala +++ b/compiler/src/dotty/tools/dotc/transform/Pickler.scala @@ -60,6 +60,9 @@ class Pickler extends Phase { if (tree.pos.exists) new PositionPickler(pickler, treePkl.buf.addrOfTree).picklePositions(tree :: Nil) + if (!ctx.settings.YdropComments.value) + new CommentPickler(pickler, treePkl.buf.addrOfTree).pickleComment(tree) + // other pickle sections go here. val pickled = pickler.assembleParts() unit.pickled += (cls -> pickled) @@ -84,6 +87,7 @@ class Pickler extends Phase { .setPeriod(Period(ctx.runId + 1, FirstPhaseId)) .setReporter(new ThrowingReporter(ctx.reporter)) .addMode(Mode.ReadPositions) + .addMode(Mode.ReadComments) .addMode(Mode.PrintShowExceptions)) result } diff --git a/compiler/test/dotty/tools/DottyTest.scala b/compiler/test/dotty/tools/DottyTest.scala index 6d2076d0e85c..5b356e169567 100644 --- a/compiler/test/dotty/tools/DottyTest.scala +++ b/compiler/test/dotty/tools/DottyTest.scala @@ -2,6 +2,7 @@ package dotty package tools import dotc.core._ +import dotc.core.Comments.{ContextDoc, ContextDocstrings} import dotc.core.Contexts._ import dotc.core.Symbols._ import dotc.core.Flags._ @@ -39,6 +40,7 @@ trait DottyTest extends ContextEscapeDetection { protected def initializeCtx(fc: FreshContext): Unit = { fc.setSetting(fc.settings.encoding, "UTF8") fc.setSetting(fc.settings.classpath, Jars.dottyLib) + fc.setProperty(ContextDoc, new ContextDocstrings) } private def compilerWithChecker(phase: String)(assertion: (tpd.Tree, Context) => Unit) = new Compiler { diff --git a/compiler/test/dotty/tools/dotc/core/tasty/CommentPicklingTest.scala b/compiler/test/dotty/tools/dotc/core/tasty/CommentPicklingTest.scala new file mode 100644 index 000000000000..8b2a7be3daed --- /dev/null +++ b/compiler/test/dotty/tools/dotc/core/tasty/CommentPicklingTest.scala @@ -0,0 +1,145 @@ +package dotty.tools.dotc.core.tasty + +import dotty.tools.dotc.ast.tpd +import dotty.tools.dotc.ast.tpd.TreeOps +import dotty.tools.dotc.{Driver, Main} +import dotty.tools.dotc.core.Comments.CommentsContext +import dotty.tools.dotc.core.Contexts.Context +import dotty.tools.dotc.core.Decorators.PreNamedString +import dotty.tools.dotc.core.Mode +import dotty.tools.dotc.core.Names.Name +import dotty.tools.dotc.interfaces.Diagnostic.ERROR +import dotty.tools.dotc.reporting.TestReporter + +import dotty.tools.vulpix.{TestConfiguration, ParallelTesting} + +import java.io.IOException +import java.nio.file.{FileSystems, FileVisitOption, FileVisitResult, FileVisitor, Files, Path} +import java.nio.file.attribute.BasicFileAttributes +import java.util.EnumSet + +import scala.collection.JavaConverters.asScalaIteratorConverter +import scala.concurrent.duration.{Duration, DurationInt} + +import org.junit.Test +import org.junit.Assert.{assertEquals, assertFalse, fail} + +class CommentPicklingTest { + + val compileOptions = TestConfiguration.defaultOptions and "-Ykeep-comments" and "-Yemit-tasty" + val unpickleOptions = TestConfiguration.defaultOptions + + @Test def commentOnDef: Unit = { + val sources = "object A { /** foo */ def bar = 2 }" :: Nil + compileAndCheckComment(sources, "bar".toTermName, Some("/** foo */")) + } + + @Test def commentOnVal: Unit = { + val sources = "object A { /** foo */ val bar = 2 }" :: Nil + compileAndCheckComment(sources, "bar".toTermName, Some("/** foo */")) + } + + @Test def commentLocalVal: Unit = { + val sources = "object A { def buzz = { /** foo */ val bar = 3 } }" :: Nil + compileAndCheckComment(sources, "bar".toTermName, Some("/** foo */")) + } + + @Test def commentLocalDef: Unit = { + val sources = "object A { def buzz = { /** foo */ def bar = 5 } }" :: Nil + compileAndCheckComment(sources, "bar".toTermName, Some("/** foo */")) + } + + @Test def commentOnClass: Unit = { + val sources = "/** foo */ class A" :: Nil + compileAndCheckComment(sources, "A".toTypeName, Some("/** foo */")) + } + + @Test def commentOnObject: Unit = { + val sources = "/** foo */ object A" :: Nil + compileAndCheckComment(sources, "A".toTermName, Some("/** foo */")) + } + + @Test def commentOnlazyVal: Unit = { + val sources = "class A { /** foo */ lazy val buzz = 2 }" :: Nil + compileAndCheckComment(sources, "buzz".toTermName, Some("/** foo */")) + } + + private def compileAndCheckComment(sources: List[String], treeName: Name, expectedComment: Option[String]): Unit = { + compileAndUnpickle(sources) { (trees, ctx) => + findTreeNamed(treeName)(trees, ctx) match { + case Some(md: tpd.MemberDef) => + val symbol = md.symbol(ctx) + val comment = for { docCtx <- ctx.docCtx + comment <- docCtx.docstring(symbol) } yield comment.raw + assertEquals(expectedComment, comment) + case other => + fail(s"Unexpected: $other") + } + } + } + + private def findTreeNamed(name: Name)(trees: List[tpd.Tree], ctx: Context): Option[tpd.MemberDef] = { + implicit val _ctx: Context = ctx + trees.flatMap { _.find { case md: tpd.MemberDef => md.name == name; case _ => false } + .map(_.asInstanceOf[tpd.MemberDef]).toList + }.headOption + } + + private def compileAndUnpickle[T](sources: List[String])(fn: (List[tpd.Tree], Context) => T) = { + inTempDirectory { tmp => + val sourceFiles = sources.zipWithIndex.map { + case (src, id) => + val path = tmp.resolve(s"Src$id.scala").toAbsolutePath + Files.write(path, src.getBytes("UTF-8")) + path.toString + } + + val out = tmp.resolve("out") + Files.createDirectories(out) + + val options = compileOptions.and("-d", out.toAbsolutePath.toString).and(sourceFiles: _*) + val reporter = TestReporter.reporter(System.out, logLevel = ERROR) + Main.process(options.all, reporter) + assertFalse("Compilation failed.", reporter.hasErrors) + + val tastyFiles = getAll(tmp, "glob:**.tasty") + val unpicklingOptions = unpickleOptions + .withClasspath(out.toAbsolutePath.toString) + .and("dummy") // Need to pass a dummy source file name + val unpicklingDriver = new UnpicklingDriver + unpicklingDriver.unpickle(unpicklingOptions.all, tastyFiles)(fn) + } + } + + private class UnpicklingDriver extends Driver { + override def initCtx = super.initCtx.addMode(Mode.ReadComments) + def unpickle[T](args: Array[String], paths: List[Path])(fn: (List[tpd.Tree], Context) => T): T = { + implicit val (_, ctx: Context) = setup(args, initCtx) + ctx.initialize() + val trees = paths.flatMap { p => + val bytes = Files.readAllBytes(p) + val unpickler = new DottyUnpickler(bytes) + unpickler.enter(roots = Set.empty) + unpickler.trees(ctx) + } + fn(trees, ctx) + } + } + + private def inTempDirectory[T](fn: Path => T): T = { + val temp = Files.createTempDirectory("temp") + try fn(temp) + finally { + val allFiles = getAll(temp, "glob:**").sortBy(_.toAbsolutePath.toString).reverse + allFiles.foreach(Files.delete(_)) + } + } + + private def getAll(base: Path, pattern: String): List[Path] = { + val paths = Files.walk(base) + val matcher = FileSystems.getDefault.getPathMatcher(pattern) + try paths.filter(matcher.matches).iterator().asScala.toList + finally paths.close() + } + +} diff --git a/compiler/test/dotty/tools/dotc/parsing/DocstringTest.scala b/compiler/test/dotty/tools/dotc/parsing/DocstringTest.scala index 53fddec0bf02..79d7bc055617 100644 --- a/compiler/test/dotty/tools/dotc/parsing/DocstringTest.scala +++ b/compiler/test/dotty/tools/dotc/parsing/DocstringTest.scala @@ -6,7 +6,6 @@ import ast.Trees._ import core.Contexts.Context trait DocstringTest extends DottyTest { - ctx = ctx.fresh.setSetting(ctx.settings.YkeepComments, true) def checkDocString(actual: Option[String], expected: String): Unit = actual match { case Some(str) => diff --git a/doc-tool/src/dotty/tools/dottydoc/DocDriver.scala b/doc-tool/src/dotty/tools/dottydoc/DocDriver.scala index 42eaea8a259b..aacbdcdc3e80 100644 --- a/doc-tool/src/dotty/tools/dottydoc/DocDriver.scala +++ b/doc-tool/src/dotty/tools/dottydoc/DocDriver.scala @@ -22,7 +22,6 @@ class DocDriver extends Driver { val summary = CompilerCommand.distill(args)(ctx) ctx.setSettings(summary.sstate) - ctx.setSetting(ctx.settings.YkeepComments, true) ctx.setSetting(ctx.settings.YcookComments, true) ctx.setSetting(ctx.settings.YnoInline, true) ctx.setProperty(ContextDoc, new ContextDottydoc) diff --git a/doc-tool/test/DottyDocTest.scala b/doc-tool/test/DottyDocTest.scala index df85aeab0f9f..30c7ec2cbf79 100644 --- a/doc-tool/test/DottyDocTest.scala +++ b/doc-tool/test/DottyDocTest.scala @@ -23,7 +23,6 @@ trait DottyDocTest extends MessageRendering { import base.settings._ val ctx = base.initialCtx.fresh ctx.setSetting(ctx.settings.language, List("Scala2")) - ctx.setSetting(ctx.settings.YkeepComments, true) ctx.setSetting(ctx.settings.YcookComments, true) ctx.setSetting(ctx.settings.Ycheck, "all" :: Nil) ctx.setSetting(ctx.settings.YnoInline, true) diff --git a/doc-tool/test/MarkdownTests.scala b/doc-tool/test/MarkdownTests.scala index b9314d015a0b..5d392ada1379 100644 --- a/doc-tool/test/MarkdownTests.scala +++ b/doc-tool/test/MarkdownTests.scala @@ -15,7 +15,6 @@ class MarkdownTests extends DottyDocTest { import base.settings._ val ctx = base.initialCtx.fresh ctx.setSetting(ctx.settings.language, List("Scala2")) - ctx.setSetting(ctx.settings.YkeepComments, true) ctx.setSetting(ctx.settings.YnoInline, true) ctx.setSetting(ctx.settings.Ycheck, "all" :: Nil) // No wiki syntax!