@@ -106,39 +106,59 @@ object Formatting {
106106
107107 private type Recorded = AnyRef /* Symbol | ParamRef | SkolemType */
108108
109- private class Seen extends mutable.HashMap [String , List [Recorded ]] {
109+ private case class SeenKey (str : String , isType : Boolean )
110+ private class Seen extends mutable.HashMap [SeenKey , List [Recorded ]] {
110111
111- override def default (key : String ) = Nil
112+ override def default (key : SeenKey ) = Nil
112113
113- def record (str : String , entry : Recorded )(implicit ctx : Context ): String = {
114+ def record (str : String , isType : Boolean , entry : Recorded )(implicit ctx : Context ): String = {
115+
116+ /** If `e1` is an alias of another class of the same name, return the other
117+ * class symbol instead. This normalization avoids recording e.g. scala.List
118+ * and scala.collection.immutable.List as two different types
119+ */
114120 def followAlias (e1 : Recorded ): Recorded = e1 match {
115121 case e1 : Symbol if e1.isAliasType =>
116122 val underlying = e1.typeRef.underlyingClassRef(refinementOK = false ).typeSymbol
117123 if (underlying.name == e1.name) underlying else e1
118124 case _ => e1
119125 }
126+ val key = SeenKey (str, isType)
127+ val existing = apply(key)
120128 lazy val dealiased = followAlias(entry)
121- var alts = apply(str).dropWhile(alt => dealiased ne followAlias(alt))
129+
130+ // alts: The alternatives in `existing` that are equal, or follow (an alias of) `entry`
131+ var alts = existing.dropWhile(alt => dealiased ne followAlias(alt))
122132 if (alts.isEmpty) {
123- alts = entry :: apply(str)
124- update(str , alts)
133+ alts = entry :: existing
134+ update(key , alts)
125135 }
126136 str + " '" * (alts.length - 1 )
127137 }
128138 }
129139
130140 private class ExplainingPrinter (seen : Seen )(_ctx : Context ) extends RefinedPrinter (_ctx) {
141+
142+ /** True if printer should a source module instead of its module class */
143+ private def useSourceModule (sym : Symbol ): Boolean =
144+ sym.is(ModuleClass , butNot = Package ) && sym.sourceModule.exists && ! _ctx.settings.YdebugNames .value
145+
131146 override def simpleNameString (sym : Symbol ): String =
132- if ((sym is ModuleClass ) && sym.sourceModule.exists ) simpleNameString(sym.sourceModule)
133- else seen.record(super .simpleNameString(sym), sym)
147+ if (useSourceModule (sym) ) simpleNameString(sym.sourceModule)
148+ else seen.record(super .simpleNameString(sym), sym.isType, sym )
134149
135150 override def ParamRefNameString (param : ParamRef ): String =
136- seen.record(super .ParamRefNameString (param), param)
151+ seen.record(super .ParamRefNameString (param), param. isInstanceOf [ TypeParamRef ], param )
137152
138153 override def toTextRef (tp : SingletonType ): Text = tp match {
139- case tp : SkolemType => seen.record(tp.repr.toString, tp)
154+ case tp : SkolemType => seen.record(tp.repr.toString, isType = true , tp)
140155 case _ => super .toTextRef(tp)
141156 }
157+
158+ override def toText (tp : Type ): Text = tp match {
159+ case tp : TypeRef if useSourceModule(tp.symbol) => Str (" object " ) ~ super .toText(tp)
160+ case _ => super .toText(tp)
161+ }
142162 }
143163
144164 /** Create explanation for single `Recorded` type or symbol */
@@ -197,10 +217,13 @@ object Formatting {
197217 }
198218
199219 val toExplain : List [(String , Recorded )] = seen.toList.flatMap {
200- case (str, entry :: Nil ) =>
201- if (needsExplanation(entry)) (str, entry) :: Nil else Nil
202- case (str, entries) =>
203- entries.map(alt => (seen.record(str, alt), alt))
220+ case (key, entry :: Nil ) =>
221+ if (needsExplanation(entry)) (key.str, entry) :: Nil else Nil
222+ case (key, entries) =>
223+ for (alt <- entries) yield {
224+ val tickedString = seen.record(key.str, key.isType, alt)
225+ (tickedString, alt)
226+ }
204227 }.sortBy(_._1)
205228
206229 def columnar (parts : List [(String , String )]): List [String ] = {
0 commit comments