diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index 129a77e7e43f..246c7f1600c0 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -62,7 +62,6 @@ trait AllScalaSettings extends CommonScalaSettings, PluginSettings, VerboseSetti /* Decompiler settings */ val printTasty: Setting[Boolean] = BooleanSetting(RootSetting, "print-tasty", "Prints the raw tasty.", aliases = List("--print-tasty")) - val printLines: Setting[Boolean] = BooleanSetting(RootSetting, "print-lines", "Show source code line numbers.", aliases = List("--print-lines")) /* Scala.js-related settings */ val scalajsGenStaticForwardersForNonTopLevelObjects: Setting[Boolean] = BooleanSetting(RootSetting, "scalajs-genStaticForwardersForNonTopLevelObjects", "Generate static forwarders even for non-top-level objects (Scala.js only).") diff --git a/compiler/src/dotty/tools/dotc/core/Decorators.scala b/compiler/src/dotty/tools/dotc/core/Decorators.scala index f8096dddeedd..b78ef947cd8b 100644 --- a/compiler/src/dotty/tools/dotc/core/Decorators.scala +++ b/compiler/src/dotty/tools/dotc/core/Decorators.scala @@ -245,7 +245,7 @@ object Decorators { end extension extension (text: Text) - def show(using Context): String = text.mkString(ctx.settings.pageWidth.value, ctx.settings.printLines.value) + def show(using Context): String = text.mkString(ctx.settings.pageWidth.value) /** Test whether a list of strings representing phases contains * a given phase. See [[config.CompilerCommand#explainAdvanced]] for the diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index 8a6fbd431ce9..139b7f4611a8 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -3579,7 +3579,7 @@ object TypeComparer { } object MatchReducer: - import printing.*, Texts.* + import printing.*, Texts.{*, given} enum MatchResult extends Showable: case Reduced(tp: Type) case Disjoint diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index 630e618fa09d..3de6c969ace7 100644 --- a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -16,7 +16,7 @@ import util.Spans.* import dotty.tools.dotc.ast.{tpd, untpd}, ast.tpd.* import ast.untpd.Modifiers import backend.sjs.JSDefinitions -import printing.Texts.* +import printing.Texts.{*, given} import printing.Printer import io.AbstractFile import util.common.* diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index 22397333196f..d9059bab77af 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -49,9 +49,9 @@ class PlainPrinter(_ctx: Context) extends Printer { protected def controlled(op: => Text): Text = limiter.controlled(op) - def Str(str: String, lineRange: LineRange = EmptyLineRange): Str = + def Str(str: String): Str = limiter.register(str) - Texts.Str(str, lineRange) + Texts.Str(str) given stringToText: Conversion[String, Text] = Str(_) diff --git a/compiler/src/dotty/tools/dotc/printing/Printer.scala b/compiler/src/dotty/tools/dotc/printing/Printer.scala index 2d6e5d858736..191bf82fb0b6 100644 --- a/compiler/src/dotty/tools/dotc/printing/Printer.scala +++ b/compiler/src/dotty/tools/dotc/printing/Printer.scala @@ -3,7 +3,7 @@ package dotc package printing import core.* -import Texts.*, ast.Trees.* +import Texts.{*, given}, ast.Trees.* import Types.{Type, SingletonType, LambdaParam, LambdaType, NamedType, RefinedType}, Symbols.Symbol, Scopes.Scope, Constants.Constant, Names.Name, Denotations._, Annotations.Annotation, Contexts.Context diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala index 5a6124650de8..68d15f256f44 100644 --- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -41,7 +41,6 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { private var enclosingDef: untpd.Tree = untpd.EmptyTree private var myCtx: Context = super.printerContext private var printPos = ctx.settings.YprintPos.value - private val printLines = ctx.settings.printLines.value override def printerContext: Context = myCtx @@ -481,7 +480,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { case id @ Ident(name) => val txt = tree.typeOpt match { case tp: NamedType if name != nme.WILDCARD => - toTextPrefixOf(tp) ~ withPos(selectionString(tp), tree.sourcePos) + toTextPrefixOf(tp) ~ selectionString(tp) case _ => toText(name) } @@ -517,8 +516,8 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { typeApplyText(tree) case Literal(c) => tree.typeOpt match { - case ConstantType(tc) => withPos(toText(tc), tree.sourcePos) - case _ => withPos(toText(c), tree.sourcePos) + case ConstantType(tc) => toText(tc) + case _ => toText(c) } case New(tpt) => keywordStr("new ") ~ { @@ -729,8 +728,8 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { case SymbolLit(str) => "'" + str case InterpolatedString(id, segments) => - def strText(str: Literal) = withPos(escapedString(str.const.stringValue), tree.sourcePos) - def segmentText(segment: Tree) = segment match { + def strText(str: Literal) = escapedString(str.const.stringValue) + def segmentText(segment: Tree): Text = segment match { case Thicket(List(str: Literal, expr)) => strText(str) ~ "{" ~ toTextGlobal(expr) ~ "}" case str: Literal => strText(str) } @@ -968,14 +967,8 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { tree.hasType && tree.symbol.exists && ctx.settings.YprintSyms.value protected def nameIdText[T <: Untyped](tree: NameTree[T]): Text = - if (tree.hasType && tree.symbol.exists && tree.symbol.isType == tree.name.isTypeName) { - val str = nameString(tree.symbol) - tree match { - case tree: RefTree => withPos(str, tree.sourcePos) - case tree: MemberDef => withPos(str, tree.sourcePos.withSpan(tree.nameSpan)) - case _ => str - } - } + if tree.hasType && tree.symbol.exists && tree.symbol.isType == tree.name.isTypeName + then nameString(tree.symbol) else toText(tree.name) ~ idText(tree) private def toTextOwner(tree: Tree[?]) = @@ -1280,11 +1273,4 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { } override def plain: PlainPrinter = 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 - } } diff --git a/compiler/src/dotty/tools/dotc/printing/Texts.scala b/compiler/src/dotty/tools/dotc/printing/Texts.scala index 77670b074833..aa04393a7a60 100644 --- a/compiler/src/dotty/tools/dotc/printing/Texts.scala +++ b/compiler/src/dotty/tools/dotc/printing/Texts.scala @@ -7,17 +7,17 @@ object Texts { @sharable private val ansi = java.util.regex.Pattern.compile("\u001b\\[\\d+m") - sealed abstract class Text { + private val indentMargin: Int = 2 - protected def indentMargin: Int = 2 + sealed abstract class Text { + /** The sub-elements of this text in reverse order */ def relems: List[Text] - def isEmpty: Boolean = this match { - case Str(s, _) => s.isEmpty + def isEmpty: Boolean = this match + case Str(s) => s.isEmpty case Fluid(relems) => relems forall (_.isEmpty) case Vertical(relems) => relems.isEmpty - } // Str Ver Clo Flu // isVertical F T F F @@ -29,10 +29,11 @@ object Texts { def isFluid: Boolean = isInstanceOf[Fluid] def isSplittable: Boolean = isFluid && !isClosed - def close: Text = if isSplittable then Closed(relems) else this + def close: Text = + if isSplittable then Closed(relems) else this - def remaining(width: Int): Int = this match { - case Str(s, _) => + def remaining(width: Int): Int = this match + case Str(s) => width - lengthWithoutAnsi(s) case Fluid(Nil) => width @@ -41,113 +42,86 @@ object Texts { if (r < 0) r else Fluid(prevs).remaining(r) case Vertical(_) => -1 - } - def lastLine: String = this match { - case Str(s, _) => s + def lastLine: String = this match + case Str(s) => s case _ => relems.head.lastLine - } - def appendToLastLine(that: Text): Text = that match { - case Str(s2, lines1) => - this match { - case Str(s1, lines2) => Str(s1 + s2, lines1 `union` lines2) - case Fluid(Str(s1, lines2) :: prev) => Fluid(Str(s1 + s2, lines1 `union` lines2) :: prev) + def appendToLastLine(that: Text): Text = that match + case Str(s2) => + this match + case Str(s1) => Str(s1 + s2) + case Fluid(Str(s1) :: prev) => Fluid(Str(s1 + s2) :: prev) case Fluid(relems) => Fluid(that :: relems) case Vertical(_) => throw new IllegalArgumentException("Unexpected Vertical.appendToLastLine") - } case Fluid(relems) => relems.reverse.foldLeft(this)(_.appendToLastLine(_)) case Vertical(_) => throw new IllegalArgumentException("Unexpected Text.appendToLastLine(Vertical(...))") - } private def appendIndented(that: Text)(width: Int): Text = Fluid(that.layout(width - indentMargin).indented :: this.relems) private def append(width: Int)(that: Text): Text = - if (this.isEmpty) that.layout(width) - else if (that.isEmpty) this - else if (that.isVertical) appendIndented(that)(width) - else if (this.isVertical) Fluid(that.layout(width) :: this.relems) - else if (that.remaining(width - lengthWithoutAnsi(lastLine)) >= 0) appendToLastLine(that) - else if (that.isSplittable) that.relems.reverse.foldLeft(this)(_.append(width)(_)) + if this.isEmpty then that.layout(width) + else if that.isEmpty then this + else if that.isVertical then appendIndented(that)(width) + else if this.isVertical then Fluid(that.layout(width) :: this.relems) + else if that.remaining(width - lengthWithoutAnsi(lastLine)) >= 0 then appendToLastLine(that) + else if that.isSplittable then that.relems.reverse.foldLeft(this)(_.append(width)(_)) else appendIndented(that)(width) private def lengthWithoutAnsi(str: String): Int = ansi.matcher(str).replaceAll("").length - def layout(width: Int): Text = this match { - case Str(s, _) => + def layout(width: Int): Text = this match + case Str(s) => this case Fluid(relems) => relems.reverse.foldLeft(Str(""): Text)(_.append(width)(_)) case Vertical(relems) => Vertical(relems.map(_.layout(width))) - } - def map(f: String => String): Text = this match { - case Str(s, lines) => Str(f(s), lines) + def map(f: String => String): Text = this match + case Str(s) => Str(f(s)) 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, _) => - if (s.startsWith(pre)) s.drop(pre.length) else s + def stripPrefix(pre: String): Text = this match + case Str(s) => + if s.startsWith(pre) then s.drop(pre.length) else s case Fluid(relems) => val elems = relems.reverse val head = elems.head.stripPrefix(pre) - if (head eq elems.head) this else Fluid((head :: elems.tail).reverse) + if head eq elems.head then this else Fluid((head :: elems.tail).reverse) case Vertical(relems) => val elems = relems.reverse val head = elems.head.stripPrefix(pre) if (head eq elems.head) this else Vertical((head :: elems.tail).reverse) - } - private def indented: Text = this match { - case Str(s, lines) => Str((" " * indentMargin) + s, lines) + private def indented: Text = this match + case Str(s) => Str((" " * indentMargin) + s) case Fluid(relems) => Fluid(relems map (_.indented)) case Vertical(relems) => Vertical(relems map (_.indented)) - } - - def print(sb: StringBuilder, numberWidth: Int): Unit = this match { - case Str(s, lines) => - if (numberWidth != 0) { - val ln = lines.show - if (ln.nonEmpty) { - val pad = (numberWidth - ln.length - 1) - assert(pad >= 0) - sb.append(" " * pad) - sb.append(ln) - sb.append("|") - } - } + + def print(sb: StringBuilder): Unit = this match + case Str(s) => sb.append(s.replaceAll("[ ]+$", "")) case _ => var follow = false - for (elem <- relems.reverse) { - if (follow) sb.append(System.lineSeparator) - elem.print(sb, numberWidth) + for elem <- relems.reverse do + if follow then sb.append(System.lineSeparator) + elem.print(sb) follow = true - } - } - def maxLine: Int = this match { - case Str(_, lines) => lines.end - case _ => relems.foldLeft(-1)((acc, relem) => acc max relem.maxLine) - } - - def mkString(width: Int = Int.MaxValue, withLineNumbers: Boolean = false): String = { + def mkString(width: Int = Int.MaxValue): String = val sb = new StringBuilder // width display can be upto a range "n-n" where 1 <= n <= maxLine+1 - val numberWidth = if (withLineNumbers) (2 * (maxLine + 1).toString.length) + 2 else 0 - layout(width - numberWidth).print(sb, numberWidth) + layout(width).print(sb) sb.toString - } def ~ (that: Text): Text = - if (this.isEmpty) that - else if (that.isEmpty) this + if this.isEmpty then that + else if that.isEmpty then this else this match case Fluid(relems1) if !isClosed => that match case Fluid(relems2) if !that.isClosed => Fluid(relems2 ++ relems1) @@ -157,12 +131,12 @@ object Texts { case _ => Fluid(that :: this :: Nil) def ~~ (that: Text): Text = - if (this.isEmpty) that - else if (that.isEmpty) this + if this.isEmpty then that + else if that.isEmpty then this else Fluid(that :: Str(" ") :: this :: Nil) def over (that: Text): Vertical = - if (this.isVertical) Vertical(that :: this.relems) + if this.isVertical then Vertical(that :: this.relems) else Vertical(that :: this :: Nil) } @@ -175,27 +149,22 @@ object Texts { * separator strings `sep`. */ def apply(xs: Iterable[Text], sep: String = " "): Text = - if (sep == "\n") lines(xs) - else { + if sep == "\n" then lines(xs) + else val ys = xs.filterNot(_.isEmpty) - if (ys.isEmpty) Str("") + if ys.isEmpty then Str("") else ys.reduceRight((a, b) => (a ~ sep).close ~ b) - } /** The given texts `xs`, each on a separate line */ def lines(xs: Iterable[Text]): Vertical = Vertical(xs.toList.reverse) extension (text: => Text) def provided(cond: Boolean): Text = if (cond) text else Str("") - } - case class Str(s: String, lineRange: LineRange = EmptyLineRange) extends Text { + case class Str(s: String) extends Text: override def relems: List[Text] = List(this) - override def toString = this match - case Str(s, EmptyLineRange) => s"Str($s)" - case Str(s, lineRange) => s"Str($s, $lineRange)" - } + override def toString = s"Str($s)" case class Vertical(relems: List[Text]) extends Text case class Fluid(relems: List[Text]) extends Text @@ -203,16 +172,5 @@ object Texts { class Closed(relems: List[Text]) extends Fluid(relems): override def productPrefix = "Closed" - 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) + given Conversion[String, Text] = Str(_) } diff --git a/compiler/test/dotty/tools/dotc/CompilationTests.scala b/compiler/test/dotty/tools/dotc/CompilationTests.scala index 74ff53b9ebf3..49d13c4404ff 100644 --- a/compiler/test/dotty/tools/dotc/CompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/CompilationTests.scala @@ -274,9 +274,9 @@ class CompilationTests { // Set -sourceroot such that the source code cannot be found by the compiler val libOptions = tastSourceOptions.and("-sourceroot", "tests/init-global/special") - val lib = compileFile("tests/init-global/special/tastySource/A.scala", libOptions)(group).keepOutput.checkCompile() + val lib = compileFile("tests/init-global/special/tastySource/A.scala", libOptions)(using group).keepOutput.checkCompile() - compileFile("tests/init-global/special/tastySource/B.scala", tastSourceOptions.withClasspath(outDirLib))(group).checkWarnings() + compileFile("tests/init-global/special/tastySource/B.scala", tastSourceOptions.withClasspath(outDirLib))(using group).checkWarnings() lib.delete() } diff --git a/compiler/test/dotty/tools/dotc/TupleShowTests.scala b/compiler/test/dotty/tools/dotc/TupleShowTests.scala index 3aa9d0d84b42..343cc29cd4f9 100644 --- a/compiler/test/dotty/tools/dotc/TupleShowTests.scala +++ b/compiler/test/dotty/tools/dotc/TupleShowTests.scala @@ -52,7 +52,7 @@ class TupleShowTests extends DottyTest: )) chkEq(exp, obt) - @Test def tup3_show10 = chkEq("(Int,\n Long,\n Short)".normEOL, tup3.toText(ctx.printer).mkString(10, false)) + @Test def tup3_show10 = chkEq("(Int,\n Long,\n Short)".normEOL, tup3.toText(ctx.printer).mkString(10)) val res21: String = """|(Int, Int, Int, Int, Int, Long, Long, Long, Long, Long, Int, Int, Int, Int, diff --git a/docs/_docs/contributing/debugging/other-debugging.md b/docs/_docs/contributing/debugging/other-debugging.md index d0d0c2431a04..377fb8852b01 100644 --- a/docs/_docs/contributing/debugging/other-debugging.md +++ b/docs/_docs/contributing/debugging/other-debugging.md @@ -121,7 +121,6 @@ So, the error happened in the Namer's `checkNoConflict` method (after which all Printing from the `show` and `-Xprint` is done from the Printers framework (discussed in more details below). The following settings influence the output of the printers: ```scala -val printLines = BooleanSetting("-print-lines" , "Show source code line numbers.") withAbbreviation "--print-lines" val uniqid = BooleanSetting("-uniqid" , "Uniquely tag all identifiers in debugging output.") withAbbreviation "--unique-id" val XprintInline = BooleanSetting("-Xprint-inline" , "Show where inlined code comes from") val XprintTypes = BooleanSetting("-Xprint-types" , "Print tree types (debugging option).") diff --git a/presentation-compiler/src/main/dotty/tools/pc/RawScalaPresentationCompiler.scala b/presentation-compiler/src/main/dotty/tools/pc/RawScalaPresentationCompiler.scala index 7109d4634230..e7da98de3269 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/RawScalaPresentationCompiler.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/RawScalaPresentationCompiler.scala @@ -65,7 +65,7 @@ case class RawScalaPresentationCompiler( override val scalaVersion = BuildInfo.scalaVersion - private val forbiddenOptions = Set("-print-lines", "-print-tasty") + private val forbiddenOptions = Set("-print-tasty") private val forbiddenDoubleOptions = Set.empty[String] val driverSettings = diff --git a/presentation-compiler/src/main/dotty/tools/pc/ScalaPresentationCompiler.scala b/presentation-compiler/src/main/dotty/tools/pc/ScalaPresentationCompiler.scala index 11adfb639c47..724a0ebf3eac 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/ScalaPresentationCompiler.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/ScalaPresentationCompiler.scala @@ -72,7 +72,7 @@ case class ScalaPresentationCompiler( val scalaVersion = BuildInfo.scalaVersion - private val forbiddenOptions = Set("-print-lines", "-print-tasty") + private val forbiddenOptions = Set("-print-tasty") private val forbiddenDoubleOptions = Set.empty[String] diff --git a/presentation-compiler/src/main/dotty/tools/pc/printer/ShortenedTypePrinter.scala b/presentation-compiler/src/main/dotty/tools/pc/printer/ShortenedTypePrinter.scala index 5dee96c6133c..6d05f6ee7d03 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/printer/ShortenedTypePrinter.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/printer/ShortenedTypePrinter.scala @@ -215,7 +215,7 @@ class ShortenedTypePrinter( def tpe(tpe: Type): String = val dealiased = if (tpe.isNamedTupleType) tpe.deepDealiasAndSimplify else tpe - toText(dealiased).mkString(defaultWidth, false) + toText(dealiased).mkString(defaultWidth) def hoverSymbol(sym: Symbol, info: Type)(using Context): String = val typeSymbol = info.typeSymbol diff --git a/repl/src/dotty/tools/repl/Rendering.scala b/repl/src/dotty/tools/repl/Rendering.scala index 3af59e547fbd..2f0eea3168d1 100644 --- a/repl/src/dotty/tools/repl/Rendering.scala +++ b/repl/src/dotty/tools/repl/Rendering.scala @@ -212,7 +212,7 @@ object Rendering: def showUser(using Context): String = { val printer = new ReplPrinter(ctx) val text = printer.dclText(s) - text.mkString(ctx.settings.pageWidth.value, ctx.settings.printLines.value) + text.mkString(ctx.settings.pageWidth.value) } def rootCause(x: Throwable): Throwable = x match diff --git a/tests/neg/i13026.scala b/tests/neg/i13026.scala deleted file mode 100644 index 847f5e7d8897..000000000000 --- a/tests/neg/i13026.scala +++ /dev/null @@ -1,5 +0,0 @@ -//> using options -print-lines - -val x: Int = "not an int" // error -val y: Int = "not an int" // error -def foo(x: Any) = x.foo // error