11package dotty .tools .dotc
22package printing
3- import core .Contexts .Context
43import language .implicitConversions
54
65object Texts {
@@ -12,7 +11,7 @@ object Texts {
1211 def relems : List [Text ]
1312
1413 def isEmpty : Boolean = this match {
15- case Str (s) => s.isEmpty
14+ case Str (s, _ ) => s.isEmpty
1615 case Fluid (relems) => relems forall (_.isEmpty)
1716 case Vertical (relems) => relems.isEmpty
1817 }
@@ -25,7 +24,7 @@ object Texts {
2524 def close = new Closed (relems)
2625
2726 def remaining (width : Int ): Int = this match {
28- case Str (s) =>
27+ case Str (s, _ ) =>
2928 width - s.length
3029 case Fluid (Nil ) =>
3130 width
@@ -37,15 +36,15 @@ object Texts {
3736 }
3837
3938 def lastLine : String = this match {
40- case Str (s) => s
39+ case Str (s, _ ) => s
4140 case _ => relems.head.lastLine
4241 }
4342
4443 def appendToLastLine (that : Text ): Text = that match {
45- case Str (s2) =>
44+ case Str (s2, lines1 ) =>
4645 this match {
47- case Str (s1) => Str (s1 + s2)
48- case Fluid (Str (s1) :: prev) => Fluid (Str (s1 + s2) :: prev)
46+ case Str (s1, lines2 ) => Str (s1 + s2, lines1 union lines2 )
47+ case Fluid (Str (s1, lines2 ) :: prev) => Fluid (Str (s1 + s2, lines1 union lines2 ) :: prev)
4948 case Fluid (relems) => Fluid (that :: relems)
5049 }
5150 case Fluid (relems) =>
@@ -66,7 +65,7 @@ object Texts {
6665 }
6766
6867 def layout (width : Int ): Text = this match {
69- case Str (_) =>
68+ case Str (s, _) =>
7069 this
7170 case Fluid (relems) =>
7271 ((Str (" " ): Text ) /: relems.reverse)(_.append(width)(_))
@@ -75,13 +74,13 @@ object Texts {
7574 }
7675
7776 def map (f : String => String ): Text = this match {
78- case Str (s) => Str (f(s))
77+ case Str (s, lines ) => Str (f(s), lines )
7978 case Fluid (relems) => Fluid (relems map (_ map f))
8079 case Vertical (relems) => Vertical (relems map (_ map f))
8180 }
8281
8382 def stripPrefix (pre : String ): Text = this match {
84- case Str (s) =>
83+ case Str (s, _ ) =>
8584 if (s.startsWith(pre)) s drop pre.length else s
8685 case Fluid (relems) =>
8786 val elems = relems.reverse
@@ -94,26 +93,40 @@ object Texts {
9493 }
9594
9695 private def indented : Text = this match {
97- case Str (s) => Str ((" " * indentMargin) + s)
96+ case Str (s, lines ) => Str ((" " * indentMargin) + s, lines )
9897 case Fluid (relems) => Fluid (relems map (_.indented))
9998 case Vertical (relems) => Vertical (relems map (_.indented))
10099 }
101100
102- def print (sb : StringBuilder ): Unit = this match {
103- case Str (s) =>
101+ def print (sb : StringBuilder , numberWidth : Int ): Unit = this match {
102+ case Str (s, lines) =>
103+ if (numberWidth != 0 ) {
104+ val ln = lines.show
105+ val pad = (numberWidth - ln.length - 1 )
106+ assert(pad >= 0 )
107+ sb.append(" " * pad)
108+ sb.append(ln)
109+ sb.append(" |" )
110+ }
104111 sb.append(s)
105112 case _ =>
106113 var follow = false
107114 for (elem <- relems.reverse) {
108115 if (follow) sb.append(" \n " )
109- elem.print(sb)
116+ elem.print(sb, numberWidth )
110117 follow = true
111118 }
112119 }
113120
114- def mkString (width : Int ): String = {
121+ def maxLine : Int = this match {
122+ case Str (_, lines) => lines.end
123+ case _ => (- 1 /: relems)((acc, relem) => acc max relem.maxLine)
124+ }
125+
126+ def mkString (width : Int , withLineNumbers : Boolean ): String = {
115127 val sb = new StringBuilder
116- layout(width).print(sb)
128+ val numberWidth = if (withLineNumbers) (2 * maxLine.toString.length) + 2 else 0
129+ layout(width - numberWidth).print(sb, numberWidth)
117130 sb.toString
118131 }
119132
@@ -155,7 +168,7 @@ object Texts {
155168 def lines (xs : Traversable [Text ]) = Vertical (xs.toList.reverse)
156169 }
157170
158- case class Str (s : String ) extends Text {
171+ case class Str (s : String , lineRange : LineRange = EmptyLineRange ) extends Text {
159172 override def relems : List [Text ] = List (this )
160173 }
161174
@@ -165,4 +178,15 @@ object Texts {
165178 class Closed (relems : List [Text ]) extends Fluid (relems)
166179
167180 implicit def stringToText (s : String ): Text = Str (s)
181+
182+ /** Inclusive line range */
183+ case class LineRange (start : Int , end : Int ) {
184+ def union (that : LineRange ): LineRange = LineRange (start min that.start, end max that.end)
185+ def show : String =
186+ if (start == end) (start + 1 ).toString
187+ else if (start < end) s " ${start + 1 }- ${end + 1 }"
188+ else " " // empty range
189+ }
190+
191+ object EmptyLineRange extends LineRange (Int .MaxValue , Int .MinValue )
168192}
0 commit comments