Skip to content

Commit 11a932b

Browse files
committed
Make repl output source compatible
ValDef repl output is source compatible Side effecting repl output is source compatible Method definition repl output is source compatible Lazy val repl output is source compatible REPL print remove comments from definitions, print macro as def also removed `= <method>` from def and `= <lazy>` from lazy val refactored implementation of withoutImplicit REPL print restore string2code use for types of valdefs REPL print, refactor quoted strings revert partest run/t7455 check for JDK 8 REPL print, add unevaluated comment to lazy val
1 parent 64a5a5d commit 11a932b

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)