diff options
author | Dmitry Petrashko <dark@d-d.me> | 2016-07-17 15:09:09 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-07-17 15:09:09 +0200 |
commit | 9da40cb84d613bcea3a0e0890b2e53129fe60bc6 (patch) | |
tree | 52ca08ba47ed605ffbfcc770d70d749880b84ca2 /src | |
parent | dfa32801f5b2c774a8c792353c1bf1d1781a4a0e (diff) | |
parent | f359953e0437c0b9b2205bf30c53c6206c6c0249 (diff) | |
download | dotty-9da40cb84d613bcea3a0e0890b2e53129fe60bc6.tar.gz dotty-9da40cb84d613bcea3a0e0890b2e53129fe60bc6.tar.bz2 dotty-9da40cb84d613bcea3a0e0890b2e53129fe60bc6.zip |
Merge pull request #1345 from dotty-staging/improve-Xprint
Improve Xprint
Diffstat (limited to 'src')
-rw-r--r-- | src/dotty/tools/dotc/Run.scala | 46 | ||||
-rw-r--r-- | src/dotty/tools/dotc/config/ScalaSettings.scala | 1 | ||||
-rw-r--r-- | src/dotty/tools/dotc/util/DiffUtil.scala | 66 |
3 files changed, 104 insertions, 9 deletions
diff --git a/src/dotty/tools/dotc/Run.scala b/src/dotty/tools/dotc/Run.scala index 928a59214..1c500c913 100644 --- a/src/dotty/tools/dotc/Run.scala +++ b/src/dotty/tools/dotc/Run.scala @@ -2,14 +2,20 @@ package dotty.tools package dotc import core._ -import Contexts._, Periods._, Symbols._, Phases._, Decorators._ +import Contexts._ +import Periods._ +import Symbols._ +import Phases._ +import Decorators._ import dotty.tools.dotc.transform.TreeTransforms.TreeTransformer import io.PlainFile -import util.{SourceFile, NoSource, Stats, SimpleMap} +import util._ import reporting.Reporter import transform.TreeChecker import rewrite.Rewrites import java.io.{BufferedWriter, OutputStreamWriter} + +import scala.annotation.tailrec import scala.reflect.io.VirtualFile import scala.util.control.NonFatal @@ -56,26 +62,48 @@ class Run(comp: Compiler)(implicit ctx: Context) { val phases = ctx.squashPhases(ctx.phasePlan, ctx.settings.Yskip.value, ctx.settings.YstopBefore.value, ctx.settings.YstopAfter.value, ctx.settings.Ycheck.value) ctx.usePhases(phases) + var lastPrintedTree: PrintedTree = NoPrintedTree for (phase <- ctx.allPhases) if (!ctx.reporter.hasErrors) { val start = System.currentTimeMillis units = phase.runOn(units) - def foreachUnit(op: Context => Unit)(implicit ctx: Context): Unit = - for (unit <- units) op(ctx.fresh.setPhase(phase.next).setCompilationUnit(unit)) - if (ctx.settings.Xprint.value.containsPhase(phase)) - foreachUnit(printTree) + if (ctx.settings.Xprint.value.containsPhase(phase)) { + for (unit <- units) { + lastPrintedTree = + printTree(lastPrintedTree)(ctx.fresh.setPhase(phase.next).setCompilationUnit(unit)) + } + } ctx.informTime(s"$phase ", start) } if (!ctx.reporter.hasErrors) Rewrites.writeBack() } - private def printTree(ctx: Context) = { + private sealed trait PrintedTree + private final case class SomePrintedTree(phase: String, tree: String) extends PrintedTree + private object NoPrintedTree extends PrintedTree + + private def printTree(last: PrintedTree)(implicit ctx: Context): PrintedTree = { val unit = ctx.compilationUnit val prevPhase = ctx.phase.prev // can be a mini-phase val squashedPhase = ctx.squashed(prevPhase) + val treeString = unit.tpdTree.show + + ctx.echo(s"result of $unit after $squashedPhase:") - ctx.echo(s"result of $unit after ${squashedPhase}:") - ctx.echo(unit.tpdTree.show(ctx)) + last match { + case SomePrintedTree(phase, lastTreeSting) if lastTreeSting != treeString => + val diff = DiffUtil.mkColoredCodeDiff(treeString, lastTreeSting, ctx.settings.XprintDiffDel.value) + ctx.echo(diff) + SomePrintedTree(squashedPhase.toString, treeString) + + case SomePrintedTree(phase, lastTreeSting) => + ctx.echo(" Unchanged since " + phase) + last + + case NoPrintedTree => + ctx.echo(treeString) + SomePrintedTree(squashedPhase.toString, treeString) + } } def compile(sourceCode: String): Unit = { diff --git a/src/dotty/tools/dotc/config/ScalaSettings.scala b/src/dotty/tools/dotc/config/ScalaSettings.scala index 6a5791b8e..30e4be1d5 100644 --- a/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -85,6 +85,7 @@ class ScalaSettings extends Settings.SettingGroup { val writeICode = PhasesSetting("-Xprint-icode", "Log internal icode to *.icode files after", "icode") val Xprintpos = BooleanSetting("-Xprint-pos", "Print tree positions, as offsets.") val printtypes = BooleanSetting("-Xprint-types", "Print tree types (debugging option).") + val XprintDiffDel = BooleanSetting("-Xprint-diff-del", "Print deleted parts of the tree since last print.") val prompt = BooleanSetting("-Xprompt", "Display a prompt after each error (debugging option).") val script = StringSetting("-Xscript", "object", "Treat the source file as a script and wrap it in a main method.", "") val mainClass = StringSetting("-Xmain-class", "path", "Class for manifest's Main-Class entry (only useful with -d <jar>)", "") diff --git a/src/dotty/tools/dotc/util/DiffUtil.scala b/src/dotty/tools/dotc/util/DiffUtil.scala new file mode 100644 index 000000000..6718ccbf8 --- /dev/null +++ b/src/dotty/tools/dotc/util/DiffUtil.scala @@ -0,0 +1,66 @@ +package dotty.tools.dotc.util + +import scala.annotation.tailrec +import difflib._ + +object DiffUtil { + + private final val ANSI_DEFAULT = "\u001B[0m" + private final val ANSI_RED = "\u001B[31m" + private final val ANSI_GREEN = "\u001B[32m" + private final val ANSI_YELLOW = "\u001B[33m" + private final val ANSI_MAGENTA = "\u001B[35m" + + def mkColoredCodeDiff(code: String, lastCode: String, printDiffDel: Boolean): String = { + import scala.collection.JavaConversions._ + + @tailrec def split(str: String, acc: List[String]): List[String] = { + if (str == "") { + acc.reverse + } else { + val head = str.charAt(0) + val (token, rest) = if (Character.isAlphabetic(head) || Character.isDigit(head)) { + str.span(c => Character.isAlphabetic(c) || Character.isDigit(c)) + } else if (Character.isMirrored(head) || Character.isWhitespace(head)) { + str.splitAt(1) + } else { + str.span { c => + !Character.isAlphabetic(c) && !Character.isDigit(c) && + !Character.isMirrored(c) && !Character.isWhitespace(c) + } + } + split(rest, token :: acc) + } + } + + val lines = split(code, Nil).toArray + val diff = DiffUtils.diff(split(lastCode, Nil), lines.toList) + + for (delta <- diff.getDeltas) { + val pos = delta.getRevised.getPosition + val endPos = pos + delta.getRevised.getLines.size - 1 + + delta.getType.toString match { // Issue #1355 forces us to use the toString + case "INSERT" => + lines(pos) = ANSI_GREEN + lines(pos) + lines(endPos) = lines(endPos) + ANSI_DEFAULT + + case "CHANGE" => + val old = if (!printDiffDel) "" else + ANSI_MAGENTA + delta.getOriginal.getLines.mkString + ANSI_DEFAULT + lines(pos) = old + ANSI_YELLOW + lines(pos) + lines(endPos) = lines(endPos) + ANSI_DEFAULT + + case "DELETE" if printDiffDel => + val deleted = delta.getOriginal.getLines.mkString + if (!deleted.forall(Character.isWhitespace)) { + lines(pos) = ANSI_RED + deleted + ANSI_DEFAULT + lines(pos) + } + + case _ => + } + } + + lines.mkString + } +} |