Skip to content

Add -print-lines #3523

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Nov 23, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions compiler/src/dotty/tools/dotc/config/ScalaSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@ class ScalaSettings extends Settings.SettingGroup {
val rewrite = OptionSetting[Rewrites]("-rewrite", "When used in conjunction with -language:Scala2 rewrites sources to migrate to new syntax")
val silentWarnings = BooleanSetting("-nowarn", "Silence all warnings.")
val fromTasty = BooleanSetting("-from-tasty", "Compile classes from tasty in classpath. The arguments are used as class names.")

/** Decompiler settings */
val printTasty = BooleanSetting("-print-tasty", "Prints the raw tasty when decompiling.")
val printLines = BooleanSetting("-print-lines", "Show source code line numbers.")

/** -X "Advanced" settings
*/
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/Decorators.scala
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ object Decorators {
}

implicit class TextToString(val text: Text) extends AnyVal {
def show(implicit ctx: Context) = text.mkString(ctx.settings.pageWidth.value)
def show(implicit ctx: Context) = text.mkString(ctx.settings.pageWidth.value, ctx.settings.printLines.value)
}

/** Test whether a list of strings representing phases contains
Expand Down
31 changes: 25 additions & 6 deletions compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,16 @@ import config.Config
import transform.SymUtils._
import scala.annotation.switch
import language.implicitConversions
import dotty.tools.dotc.util.SourcePosition


class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {

/** A stack of enclosing DefDef, TypeDef, or ClassDef, or ModuleDefs nodes */
private[this] var enclosingDef: untpd.Tree = untpd.EmptyTree
private[this] var myCtx: Context = _ctx
private[this] var printPos = ctx.settings.Yprintpos.value
private[this] val printLines = ctx.settings.printLines.value
override protected[this] implicit def ctx: Context = myCtx

def withEnclosingDef(enclDef: Tree[_ >: Untyped])(op: => Text): Text = {
Expand Down Expand Up @@ -287,9 +290,17 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
if (ctx.settings.uniqid.value && tree.hasType && tree.symbol.exists) s"#${tree.symbol.id}" else ""
}

def nameIdText(tree: untpd.NameTree): Text =
if (tree.hasType && tree.symbol.exists) nameString(tree.symbol)
def nameIdText(tree: untpd.NameTree): Text = {
if (tree.hasType && tree.symbol.exists) {
val str: Text = nameString(tree.symbol)
tree match {
case tree: RefTree => withPos(str, tree.pos)
case tree: MemberDef => withPos(str, tree.namePos)
case _ => str
}
}
else toText(tree.name) ~ idText(tree)
}

def toTextTemplate(impl: Template, ofNew: Boolean = false): Text = {
val Template(constr @ DefDef(_, tparams, vparamss, _, _), parents, self, _) = impl
Expand Down Expand Up @@ -343,7 +354,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
tree.typeOpt match {
case tp: NamedType if name != nme.WILDCARD =>
val pre = if (tp.symbol is JavaStatic) tp.prefix.widen else tp.prefix
toTextPrefix(pre) ~ selectionString(tp)
toTextPrefix(pre) ~ withPos(selectionString(tp), tree.pos)
case _ =>
toText(name)
}
Expand All @@ -365,8 +376,8 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
toTextLocal(fun) ~ "[" ~ toTextGlobal(args, ", ") ~ "]"
case Literal(c) =>
tree.typeOpt match {
case ConstantType(tc) => toText(tc)
case _ => toText(c)
case ConstantType(tc) => withPos(toText(tc), tree.pos)
case _ => withPos(toText(c), tree.pos)
}
case New(tpt) =>
"new " ~ {
Expand Down Expand Up @@ -517,7 +528,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
case SymbolLit(str) =>
"'" + str
case InterpolatedString(id, segments) =>
def strText(str: Literal) = Str(escapedString(str.const.stringValue))
def strText(str: Literal) = withPos(escapedString(str.const.stringValue), tree.pos)
def segmentText(segment: Tree) = segment match {
case Thicket(List(str: Literal, expr)) => strText(str) ~ "{" ~ toTextGlobal(expr) ~ "}"
case str: Literal => strText(str)
Expand Down Expand Up @@ -694,4 +705,12 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
}

override def plain = new PlainPrinter(_ctx)

private def withPos(txt: Text, pos: SourcePosition): Text = {
if (!printLines || !pos.exists) txt
else txt match {
case Str(s, _) => Str(s, LineRange(pos.line, pos.endLine))
case _ => txt
}
}
}
58 changes: 41 additions & 17 deletions compiler/src/dotty/tools/dotc/printing/Texts.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package dotty.tools.dotc
package printing
import core.Contexts.Context
import language.implicitConversions

object Texts {
Expand All @@ -12,7 +11,7 @@ object Texts {
def relems: List[Text]

def isEmpty: Boolean = this match {
case Str(s) => s.isEmpty
case Str(s, _) => s.isEmpty
case Fluid(relems) => relems forall (_.isEmpty)
case Vertical(relems) => relems.isEmpty
}
Expand All @@ -25,7 +24,7 @@ object Texts {
def close = new Closed(relems)

def remaining(width: Int): Int = this match {
case Str(s) =>
case Str(s, _) =>
width - s.length
case Fluid(Nil) =>
width
Expand All @@ -37,15 +36,15 @@ object Texts {
}

def lastLine: String = this match {
case Str(s) => s
case Str(s, _) => s
case _ => relems.head.lastLine
}

def appendToLastLine(that: Text): Text = that match {
case Str(s2) =>
case Str(s2, lines1) =>
this match {
case Str(s1) => Str(s1 + s2)
case Fluid(Str(s1) :: prev) => Fluid(Str(s1 + s2) :: prev)
case Str(s1, lines2) => Str(s1 + s2, lines1 union lines2)
case Fluid(Str(s1, lines2) :: prev) => Fluid(Str(s1 + s2, lines1 union lines2) :: prev)
case Fluid(relems) => Fluid(that :: relems)
}
case Fluid(relems) =>
Expand All @@ -66,7 +65,7 @@ object Texts {
}

def layout(width: Int): Text = this match {
case Str(_) =>
case Str(s, _) =>
this
case Fluid(relems) =>
((Str(""): Text) /: relems.reverse)(_.append(width)(_))
Expand All @@ -75,13 +74,13 @@ object Texts {
}

def map(f: String => String): Text = this match {
case Str(s) => Str(f(s))
case Str(s, lines) => Str(f(s), lines)
case Fluid(relems) => Fluid(relems map (_ map f))
case Vertical(relems) => Vertical(relems map (_ map f))
}

def stripPrefix(pre: String): Text = this match {
case Str(s) =>
case Str(s, _) =>
if (s.startsWith(pre)) s drop pre.length else s
case Fluid(relems) =>
val elems = relems.reverse
Expand All @@ -94,26 +93,40 @@ object Texts {
}

private def indented: Text = this match {
case Str(s) => Str((" " * indentMargin) + s)
case Str(s, lines) => Str((" " * indentMargin) + s, lines)
case Fluid(relems) => Fluid(relems map (_.indented))
case Vertical(relems) => Vertical(relems map (_.indented))
}

def print(sb: StringBuilder): Unit = this match {
case Str(s) =>
def print(sb: StringBuilder, numberWidth: Int): Unit = this match {
case Str(s, lines) =>
if (numberWidth != 0) {
val ln = lines.show
val pad = (numberWidth - ln.length - 1)
assert(pad >= 0)
sb.append(" " * pad)
sb.append(ln)
sb.append("|")
}
sb.append(s)
case _ =>
var follow = false
for (elem <- relems.reverse) {
if (follow) sb.append("\n")
elem.print(sb)
elem.print(sb, numberWidth)
follow = true
}
}

def mkString(width: Int): String = {
def maxLine: Int = this match {
case Str(_, lines) => lines.end
case _ => (-1 /: relems)((acc, relem) => acc max relem.maxLine)
}

def mkString(width: Int, withLineNumbers: Boolean): String = {
val sb = new StringBuilder
layout(width).print(sb)
val numberWidth = if (withLineNumbers) (2 * maxLine.toString.length) + 2 else 0
layout(width - numberWidth).print(sb, numberWidth)
sb.toString
}

Expand Down Expand Up @@ -155,7 +168,7 @@ object Texts {
def lines(xs: Traversable[Text]) = Vertical(xs.toList.reverse)
}

case class Str(s: String) extends Text {
case class Str(s: String, lineRange: LineRange = EmptyLineRange) extends Text {
override def relems: List[Text] = List(this)
}

Expand All @@ -165,4 +178,15 @@ object Texts {
class Closed(relems: List[Text]) extends Fluid(relems)

implicit def stringToText(s: String): Text = Str(s)

/** Inclusive line range */
case class LineRange(start: Int, end: Int) {
def union(that: LineRange): LineRange = LineRange(start min that.start, end max that.end)
def show: String =
if (start == end) (start + 1).toString
else if (start < end) s"${start + 1}-${end + 1}"
else "" // empty range
}

object EmptyLineRange extends LineRange(Int.MaxValue, Int.MinValue)
}
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/repl/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ package object repl {
def showUser(implicit ctx: Context): String = {
val printer = new UserFacingPrinter(ctx)
val text = printer.dclText(s)
text.mkString(ctx.settings.pageWidth.value)
text.mkString(ctx.settings.pageWidth.value, ctx.settings.printLines.value)
}
}

Expand Down