@@ -139,6 +139,7 @@ class ReplDriver(settings: Array[String],
139
139
// TODO: i5069
140
140
final def bind (name : String , value : Any )(implicit state : State ): State = state
141
141
142
+ // redirecting the output allows us to test `println` in scripted tests
142
143
private def withRedirectedOutput (op : => State ): State = {
143
144
val savedOut = System .out
144
145
val savedErr = System .err
@@ -238,19 +239,29 @@ class ReplDriver(settings: Array[String],
238
239
allImports += (newState.objectIndex -> newImports)
239
240
val newStateWithImports = newState.copy(imports = allImports)
240
241
241
- val warnings = newState.context.reporter.removeBufferedMessages(newState.context)
242
- displayErrors(warnings)(newState) // display warnings
243
- implicit val ctx = newState.context
244
- if (! ctx.settings.XreplDisableDisplay .value)
245
- displayDefinitions(unit.tpdTree, newestWrapper)(newStateWithImports)
246
- else
247
- newStateWithImports
242
+ val warnings = newState.context.reporter
243
+ .removeBufferedMessages(newState.context)
244
+ .map(rendering.formatError)
245
+
246
+ implicit val ctx : Context = newState.context
247
+ val (updatedState, definitions) =
248
+ if (! ctx.settings.XreplDisableDisplay .value)
249
+ renderDefinitions(unit.tpdTree, newestWrapper)(newStateWithImports)
250
+ else
251
+ (newStateWithImports, Seq .empty)
252
+
253
+
254
+ (definitions ++ warnings)
255
+ .sortBy(_.pos.point) // ensure multi-line output is printed in the order it was typed in
256
+ .map(_.msg)
257
+ .foreach(out.println)
258
+
259
+ updatedState
248
260
}
249
261
)
250
262
}
251
263
252
- /** Display definitions from `tree` */
253
- private def displayDefinitions (tree : tpd.Tree , newestWrapper : Name )(implicit state : State ): State = {
264
+ private def renderDefinitions (tree : tpd.Tree , newestWrapper : Name )(implicit state : State ): (State , Seq [Diagnostic ]) = {
254
265
implicit val ctx = state.context
255
266
256
267
def resAndUnit (denot : Denotation ) = {
@@ -264,7 +275,7 @@ class ReplDriver(settings: Array[String],
264
275
name.startsWith(str.REPL_RES_PREFIX ) && hasValidNumber && sym.info == defn.UnitType
265
276
}
266
277
267
- def displayMembers (symbol : Symbol ) = if (tree.symbol.info.exists) {
278
+ def displayMembers (symbol : Symbol ): ( State , Seq [ Diagnostic ]) = if (tree.symbol.info.exists) {
268
279
val info = symbol.info
269
280
val defs =
270
281
info.bounds.hi.finalResultType
@@ -274,51 +285,47 @@ class ReplDriver(settings: Array[String],
274
285
denot.symbol.owner == defn.ObjectClass ||
275
286
denot.symbol.isConstructor
276
287
}
277
- .sortBy(_.name)
278
288
279
289
val vals =
280
290
info.fields
281
291
.filterNot(_.symbol.isOneOf(ParamAccessor | Private | Synthetic | Artifact | Module ))
282
292
.filter(_.symbol.name.is(SimpleNameKind ))
283
- .sortBy(_.name)
284
293
285
294
val typeAliases =
286
- info.bounds.hi.typeMembers.filter(_.symbol.info.isTypeAlias).sortBy(_.name)
295
+ info.bounds.hi.typeMembers.filter(_.symbol.info.isTypeAlias)
287
296
288
- (
289
- typeAliases.map(" // defined alias " + _.symbol.showUser ) ++
297
+ val formattedMembers =
298
+ typeAliases.map(rendering.renderTypeAlias ) ++
290
299
defs.map(rendering.renderMethod) ++
291
- vals.map(rendering.renderVal).flatten
292
- ).foreach(str => out.println(SyntaxHighlighting .highlight(str)))
300
+ vals.flatMap(rendering.renderVal)
293
301
294
- state.copy(valIndex = state.valIndex - vals.count(resAndUnit))
302
+ ( state.copy(valIndex = state.valIndex - vals.count(resAndUnit)), formattedMembers )
295
303
}
296
- else state
304
+ else ( state, Seq .empty)
297
305
298
306
def isSyntheticCompanion (sym : Symbol ) =
299
307
sym.is(Module ) && sym.is(Synthetic )
300
308
301
- def displayTypeDefs (sym : Symbol ) = sym.info.memberClasses
309
+ def typeDefs (sym : Symbol ): Seq [ Diagnostic ] = sym.info.memberClasses
302
310
.collect {
303
311
case x if ! isSyntheticCompanion(x.symbol) && ! x.symbol.name.isReplWrapperName =>
304
- x.symbol
305
- }
306
- .foreach { sym =>
307
- out.println(SyntaxHighlighting .highlight(" // defined " + sym.showUser))
312
+ rendering.renderTypeDef(x)
308
313
}
309
314
310
-
311
315
ctx.atPhase(ctx.typerPhase.next) {
312
316
// Display members of wrapped module:
313
317
tree.symbol.info.memberClasses
314
318
.find(_.symbol.name == newestWrapper.moduleClassName)
315
319
.map { wrapperModule =>
316
- displayTypeDefs(wrapperModule.symbol)
317
- displayMembers(wrapperModule.symbol)
320
+ val formattedTypeDefs = typeDefs(wrapperModule.symbol)
321
+ val (newState, formattedMembers) = displayMembers(wrapperModule.symbol)
322
+ val highlighted = (formattedTypeDefs ++ formattedMembers)
323
+ .map(d => new Diagnostic (d.msg.mapMsg(SyntaxHighlighting .highlight), d.pos, d.level))
324
+ (newState, highlighted)
318
325
}
319
326
.getOrElse {
320
327
// user defined a trait/class/object, so no module needed
321
- state
328
+ ( state, Seq .empty)
322
329
}
323
330
}
324
331
}
@@ -378,18 +385,9 @@ class ReplDriver(settings: Array[String],
378
385
state
379
386
}
380
387
381
- /** A `MessageRenderer` without file positions */
382
- private val messageRenderer = new MessageRendering {
383
- override def posStr (pos : SourcePosition , diagnosticLevel : String , message : Message )(implicit ctx : Context ): String = " "
384
- }
385
-
386
- /** Render messages using the `MessageRendering` trait */
387
- private def renderMessage (dia : Diagnostic ): Context => String =
388
- messageRenderer.messageAndPos(dia.msg, dia.pos, messageRenderer.diagnosticLevel(dia))(_)
389
-
390
- /** Output errors to `out` */
388
+ /** shows all errors nicely formatted */
391
389
private def displayErrors (errs : Seq [Diagnostic ])(implicit state : State ): State = {
392
- errs.map(renderMessage(_)(state.context) ).foreach(out.println)
390
+ errs.map(rendering.formatError ).foreach(out.println)
393
391
state
394
392
}
395
393
}
0 commit comments