Skip to content

Commit 59dec61

Browse files
authored
Improve REPL display - Fixes scala/bug#10024 (scala#8319)
Improve REPL display - Fixes scala/bug#10024
2 parents 22f060b + 11a932b commit 59dec61

File tree

105 files changed

+673
-634
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

105 files changed

+673
-634
lines changed

src/repl/scala/tools/nsc/interpreter/IMain.scala

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import scala.tools.nsc.util.{stackTraceString, stringFromWriter}
3737
import scala.tools.nsc.interpreter.Results.{Error, Incomplete, Result, Success}
3838
import scala.tools.nsc.util.Exceptional.rootCause
3939
import scala.util.control.NonFatal
40+
import scala.annotation.tailrec
4041

4142

4243
/** An interpreter for Scala code.
@@ -710,6 +711,30 @@ class IMain(val settings: Settings, parentClassLoaderOverride: Option[ClassLoade
710711
}
711712
}
712713

714+
@inline private final def tyParens[T](ts: Iterable[T]): String = ts.mkString("[", ", ", "]")
715+
@inline private final def implicitParens[T](ts: Iterable[T]): String = ts.mkString("(implicit ", ", ", ")")
716+
@inline private final def parens[T](ts: Iterable[T]): String = ts.mkString("(", ", ", ")")
717+
718+
private def methodTypeAsDef(tp: Type): String = {
719+
720+
def withoutImplicit(sym: Symbol): Symbol = sym.cloneSymbol(sym.owner, sym.flags & ~Flag.IMPLICIT)
721+
722+
def formatParams(params: List[Symbol]): String = {
723+
if (params.headOption.exists(_.isImplicit)) implicitParens(params.map(withoutImplicit(_).defString))
724+
else parens(params.map(_.defString))
725+
}
726+
727+
@tailrec
728+
def loop(tpe: Type, acc: StringBuilder): StringBuilder = tpe match {
729+
case NullaryMethodType(resultType) => acc ++= s": $resultType"
730+
case PolyType(tyParams, resultType) => loop(resultType, acc ++= tyParens(tyParams.map(_.defString)))
731+
case MethodType(params, resultType) => loop(resultType, acc ++= formatParams(params))
732+
case other => acc ++= s": $other"
733+
}
734+
735+
loop(tp, new StringBuilder).toString
736+
}
737+
713738
/** One line of code submitted by the user for interpretation */
714739
class Request(val line: String, origTrees: List[Tree], firstXmlPos: Position = NoPosition, generousImports: Boolean = false, synthetic: Boolean = false) extends ReplRequest {
715740
def defines = defHandlers flatMap (_.definedSymbols)
@@ -933,6 +958,10 @@ class IMain(val settings: Settings, parentClassLoaderOverride: Option[ClassLoade
933958
lazy val compilerTypeOf = typeMap[Type](x => x) withDefaultValue NoType
934959
/** String representations of same. */
935960
lazy val typeOf = typeMap[String](tp => exitingTyper(tp.toString))
961+
/** String representations as if a method type. */
962+
private[this] lazy val defTypeOfMap = typeMap[String](tp => exitingTyper(methodTypeAsDef(tp)))
963+
964+
def defTypeOf(name: Name)(implicit show: Name => String): String = show(name) + defTypeOfMap(name)
936965

937966
lazy val definedSymbols = (
938967
termNames.map(x => x -> applyToResultMember(x, x => x)) ++

src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ trait MemberHandlers {
2626
import global._
2727
import naming._
2828

29-
import ReplStrings.{string2codeQuoted, string2code, any2stringOf}
29+
import ReplStrings.{string2codeQuoted, string2code, any2stringOf, quotedString}
3030

3131
private def codegenln(leadingPlus: Boolean, xs: String*): String = codegen(leadingPlus, (xs ++ Array("\n")): _*)
3232
private def codegenln(xs: String*): String = codegenln(true, xs: _*)
@@ -133,23 +133,32 @@ trait MemberHandlers {
133133
else {
134134
// if this is a lazy val we avoid evaluating it here
135135
val resultString =
136-
if (mods.isLazy) codegenln(false, "<lazy>")
137-
else any2stringOf(path, maxStringElements)
136+
if (mods.isLazy) quotedString(" // unevaluated")
137+
else quotedString(" = ") + " + " + any2stringOf(path, maxStringElements)
138+
139+
val varOrValOrLzy =
140+
if (mods.isMutable) "var"
141+
else if (mods.isLazy) "lazy val"
142+
else "val"
143+
144+
val nameString = {
145+
string2code(prettyName) + (
146+
if (showObjIds) s"""" + f"@$${System.identityHashCode($path)}%8x" + """"
147+
else ""
148+
)
149+
}
150+
151+
val typeString = string2code(req.typeOf(name))
138152

139-
val nameString = string2code(prettyName) + (if (showObjIds) s"""" + f"@$${System.identityHashCode($path)}%8x" + """" else "")
140-
val typeString = string2code(req typeOf name)
141-
s""" + "$nameString: $typeString = " + $resultString"""
153+
s""" + "$varOrValOrLzy $nameString: $typeString" + $resultString"""
142154
}
143155
}
144156
}
145157

146158
class DefHandler(member: DefDef) extends MemberDefHandler(member) {
147159
override def definesValue = flattensToEmpty(member.vparamss) // true if 0-arity
148-
override def resultExtractionCode(req: Request) = {
149-
val nameString = string2code(name)
150-
val typeString = string2code(req typeOf name)
151-
if (mods.isPublic) s""" + "$nameString: $typeString\\n"""" else ""
152-
}
160+
override def resultExtractionCode(req: Request) =
161+
if (mods.isPublic) codegenln(s"def ${req.defTypeOf(name)}") else ""
153162
}
154163

155164
abstract class MacroHandler(member: DefDef) extends MemberDefHandler(member) {
@@ -162,36 +171,34 @@ trait MemberHandlers {
162171
}
163172

164173
class TermMacroHandler(member: DefDef) extends MacroHandler(member) {
165-
def notification(req: Request) = s"defined term macro $name: ${req.typeOf(name)}"
174+
def notification(req: Request) = s"def ${req.defTypeOf(name)}"
166175
}
167176

168177
class AssignHandler(member: Assign) extends MemberHandler(member) {
169178
override def resultExtractionCode(req: Request) =
170-
codegenln(s"mutated ${member.lhs}")
179+
codegenln(s"// mutated ${member.lhs}")
171180
}
172181

173182
class ModuleHandler(module: ModuleDef) extends MemberDefHandler(module) {
174183
override def definesTerm = Some(name.toTermName)
175184
override def definesValue = true
176185

177-
override def resultExtractionCode(req: Request) = codegenln("defined object ", name)
186+
override def resultExtractionCode(req: Request) = codegenln(s"object $name")
178187
}
179188

180189
class ClassHandler(member: ClassDef) extends MemberDefHandler(member) {
181190
override def definedSymbols = List(symbol, symbol.companionSymbol) filterNot (_ == NoSymbol)
182191
override def definesType = Some(name.toTypeName)
183192
override def definesTerm = Some(name.toTermName) filter (_ => mods.isCase)
184193

185-
override def resultExtractionCode(req: Request) =
186-
codegenln("defined %s %s".format(keyword, name))
194+
override def resultExtractionCode(req: Request) = codegenln(s"$keyword $name")
187195
}
188196

189197
class TypeAliasHandler(member: TypeDef) extends MemberDefHandler(member) {
190198
private def isAlias = mods.isPublic && treeInfo.isAliasTypeDef(member)
191199
override def definesType = Some(name.toTypeName) filter (_ => isAlias)
192200

193-
override def resultExtractionCode(req: Request) =
194-
codegenln("defined type alias ", name) + "\n"
201+
override def resultExtractionCode(req: Request) = codegenln(s"type $name")
195202
}
196203

197204
class ImportHandler(imp: Import) extends MemberHandler(imp) {

src/repl/scala/tools/nsc/interpreter/ReplStrings.scala

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,14 @@ object ReplStrings {
3737
res.toString
3838
}
3939

40+
@inline final def quotedString(str: String) =
41+
"\"" + str + "\""
42+
4043
def string2codeQuoted(str: String) =
41-
"\"" + string2code(str) + "\""
44+
quotedString(string2code(str))
4245

4346
def any2stringOf(x: Any, maxlen: Int) =
44-
"_root_.scala.runtime.ScalaRunTime.replStringOf(%s, %s)".format(x, maxlen)
47+
s"_root_.scala.runtime.ScalaRunTime.replStringOf($x, $maxlen)"
4548

4649
// no escaped or nested quotes
4750
private[this] val inquotes = """(['"])(.*?)\1""".r

0 commit comments

Comments
 (0)