diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala | 41 | ||||
-rw-r--r-- | src/repl/scala/tools/nsc/interpreter/ILoop.scala | 8 | ||||
-rw-r--r-- | src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala | 23 | ||||
-rw-r--r-- | src/repl/scala/tools/nsc/interpreter/ReplProps.scala | 3 | ||||
-rw-r--r-- | src/repl/scala/tools/nsc/interpreter/ReplReporter.scala | 18 | ||||
-rw-r--r-- | test/files/neg/t8890.check | 4 | ||||
-rw-r--r-- | test/files/neg/t8890.scala | 11 |
8 files changed, 89 insertions, 21 deletions
diff --git a/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala b/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala index 0b218b711c..5bf611a7b0 100644 --- a/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala +++ b/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala @@ -29,7 +29,7 @@ class ConsoleReporter(val settings: Settings, reader: BufferedReader, writer: Pr case INFO => null } - private def clabel(severity: Severity): String = { + protected def clabel(severity: Severity): String = { val label0 = label(severity) if (label0 eq null) "" else label0 + ": " } diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala index 20e462bbce..866ca37303 100644 --- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala @@ -885,22 +885,31 @@ trait ContextErrors { val WrongNumber, NoParams, ArgsDoNotConform = Value } - private def issueAmbiguousTypeErrorUnlessErroneous(pos: Position, pre: Type, sym1: Symbol, sym2: Symbol, rest: String): Unit = - if (!(pre.isErroneous || sym1.isErroneous || sym2.isErroneous)) { - if (sym1.hasDefault && sym2.hasDefault && sym1.enclClass == sym2.enclClass) { - val methodName = nme.defaultGetterToMethod(sym1.name) - context.issueAmbiguousError(AmbiguousTypeError(sym1.enclClass.pos, - "in "+ sym1.enclClass +", multiple overloaded alternatives of " + methodName + - " define default arguments")) - } else { - context.issueAmbiguousError(AmbiguousTypeError(pos, - ("ambiguous reference to overloaded definition,\n" + - "both " + sym1 + sym1.locationString + " of type " + pre.memberType(sym1) + - "\nand " + sym2 + sym2.locationString + " of type " + pre.memberType(sym2) + - "\nmatch " + rest) - )) - } - } + private def issueAmbiguousTypeErrorUnlessErroneous(pos: Position, pre: Type, sym1: Symbol, sym2: Symbol, rest: String): Unit = { + // To avoid stack overflows (SI-8890), we MUST (at least) report when either `validTargets` OR `ambiguousSuppressed` + // More details: + // If `!context.ambiguousErrors`, `reporter.issueAmbiguousError` (which `context.issueAmbiguousError` forwards to) + // buffers ambiguous errors. In this case, to avoid looping, we must issue even if `!validTargets`. (TODO: why?) + // When not buffering (and thus reporting to the user), we shouldn't issue unless `validTargets`, + // otherwise we report two different errors that trace back to the same root cause, + // and unless `validTargets`, we don't know for sure the ambiguity is real anyway. + val validTargets = !(pre.isErroneous || sym1.isErroneous || sym2.isErroneous) + val ambiguousBuffered = !context.ambiguousErrors + if (validTargets || ambiguousBuffered) + context.issueAmbiguousError( + if (sym1.hasDefault && sym2.hasDefault && sym1.enclClass == sym2.enclClass) { + val methodName = nme.defaultGetterToMethod(sym1.name) + AmbiguousTypeError(sym1.enclClass.pos, + s"in ${sym1.enclClass}, multiple overloaded alternatives of $methodName define default arguments") + + } else { + AmbiguousTypeError(pos, + "ambiguous reference to overloaded definition,\n" + + s"both ${sym1.fullLocationString} of type ${pre.memberType(sym1)}\n" + + s"and ${sym2.fullLocationString} of type ${pre.memberType(sym2)}\n" + + s"match $rest") + }) + } def AccessError(tree: Tree, sym: Symbol, ctx: Context, explanation: String): AbsTypeError = AccessError(tree, sym, ctx.enclClass.owner.thisType, ctx.enclClass.owner, explanation) diff --git a/src/repl/scala/tools/nsc/interpreter/ILoop.scala b/src/repl/scala/tools/nsc/interpreter/ILoop.scala index 72c907305a..6e18682494 100644 --- a/src/repl/scala/tools/nsc/interpreter/ILoop.scala +++ b/src/repl/scala/tools/nsc/interpreter/ILoop.scala @@ -412,8 +412,14 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) } private def readOneLine() = { + import scala.io.AnsiColor.{ MAGENTA, RESET } out.flush() - in readLine prompt + in readLine ( + if (replProps.colorOk) + MAGENTA + prompt + RESET + else + prompt + ) } /** The main read-eval-print loop for the repl. It calls diff --git a/src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala b/src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala index a37cdc2ec8..bcba7b6dfd 100644 --- a/src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala +++ b/src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala @@ -102,6 +102,18 @@ trait MemberHandlers { class GenericHandler(member: Tree) extends MemberHandler(member) + import scala.io.AnsiColor.{ BOLD, BLUE, GREEN, RESET } + + def color(c: String, s: String) = + if (replProps.colorOk) string2code(BOLD) + string2code(c) + s + string2code(RESET) + else s + + def colorName(s: String) = + color(BLUE, string2code(s)) + + def colorType(s: String) = + color(GREEN, string2code(s)) + class ValHandler(member: ValDef) extends MemberDefHandler(member) { val maxStringElements = 1000 // no need to mkString billions of elements override def definesValue = true @@ -119,15 +131,20 @@ trait MemberHandlers { if (replProps.vids) s"""" + f"@$${System.identityHashCode($path)}%8x" + """" else "" - """ + "%s%s: %s = " + %s""".format(string2code(prettyName), vidString, string2code(req typeOf name), resultString) + val nameString = colorName(prettyName) + vidString + val typeString = colorType(req typeOf name) + s""" + "$nameString: $typeString = " + $resultString""" } } } class DefHandler(member: DefDef) extends MemberDefHandler(member) { override def definesValue = flattensToEmpty(member.vparamss) // true if 0-arity - override def resultExtractionCode(req: Request) = - if (mods.isPublic) codegenln(name, ": ", req.typeOf(name)) else "" + override def resultExtractionCode(req: Request) = { + val nameString = colorName(name) + val typeString = colorType(req typeOf name) + if (mods.isPublic) s""" + "$nameString: $typeString\\n"""" else "" + } } abstract class MacroHandler(member: DefDef) extends MemberDefHandler(member) { diff --git a/src/repl/scala/tools/nsc/interpreter/ReplProps.scala b/src/repl/scala/tools/nsc/interpreter/ReplProps.scala index 36e6dbbccc..8c4faf7278 100644 --- a/src/repl/scala/tools/nsc/interpreter/ReplProps.scala +++ b/src/repl/scala/tools/nsc/interpreter/ReplProps.scala @@ -13,6 +13,9 @@ class ReplProps { private def bool(name: String) = BooleanProp.keyExists(name) private def int(name: String) = IntProp(name) + // This property is used in TypeDebugging. Let's recycle it. + val colorOk = bool("scala.color") + val info = bool("scala.repl.info") val debug = bool("scala.repl.debug") val trace = bool("scala.repl.trace") diff --git a/src/repl/scala/tools/nsc/interpreter/ReplReporter.scala b/src/repl/scala/tools/nsc/interpreter/ReplReporter.scala index 88372334d6..e6f5a4089e 100644 --- a/src/repl/scala/tools/nsc/interpreter/ReplReporter.scala +++ b/src/repl/scala/tools/nsc/interpreter/ReplReporter.scala @@ -32,6 +32,24 @@ class ReplReporter(intp: IMain) extends ConsoleReporter(intp.settings, Console.i override def warning(pos: Position, msg: String): Unit = withoutTruncating(super.warning(pos, msg)) override def error(pos: Position, msg: String): Unit = withoutTruncating(super.error(pos, msg)) + import scala.io.AnsiColor.{ RED, YELLOW, RESET } + + def severityColor(severity: Severity): String = severity match { + case ERROR => RED + case WARNING => YELLOW + case INFO => RESET + } + + override def print(pos: Position, msg: String, severity: Severity) { + val prefix = ( + if (replProps.colorOk) + severityColor(severity) + clabel(severity) + RESET + else + clabel(severity) + ) + printMessage(pos, prefix + msg) + } + override def printMessage(msg: String) { // Avoiding deadlock if the compiler starts logging before // the lazy val is complete. diff --git a/test/files/neg/t8890.check b/test/files/neg/t8890.check new file mode 100644 index 0000000000..1b69d6cf30 --- /dev/null +++ b/test/files/neg/t8890.check @@ -0,0 +1,4 @@ +t8890.scala:6: error: not found: type Str + def bar(x: Str): Unit = ??? + ^ +one error found diff --git a/test/files/neg/t8890.scala b/test/files/neg/t8890.scala new file mode 100644 index 0000000000..cbdeb11d43 --- /dev/null +++ b/test/files/neg/t8890.scala @@ -0,0 +1,11 @@ +package foo + +class A { + /** The other */ + def bar(x: Int): Unit = ??? + def bar(x: Str): Unit = ??? +} + +class B { + (new A).bar(0) +}
\ No newline at end of file |