@@ -9,6 +9,9 @@ import Decorators._
9
9
import scala .annotation .switch
10
10
import scala .util .control .NonFatal
11
11
import reporting .diagnostic .MessageContainer
12
+ import util .DiffUtil
13
+ import Highlighting .{ highlightToString => _ , _ }
14
+ import SyntaxHighlighting ._
12
15
13
16
object Formatting {
14
17
@@ -113,65 +116,103 @@ object Formatting {
113
116
seen.record(super .polyParamNameString(param), param)
114
117
}
115
118
116
- def explained2 (op : Context => String )(implicit ctx : Context ): String = {
117
- val seen = new Seen
118
- val explainCtx = ctx.printer match {
119
- case dp : ExplainingPrinter => ctx // re-use outer printer and defer explanation to it
120
- case _ => ctx.fresh.setPrinterFn(ctx => new ExplainingPrinter (seen)(ctx))
121
- }
119
+ def explanation (entry : Recorded )(implicit ctx : Context ): String = {
120
+ def boundStr (bound : Type , default : ClassSymbol , cmp : String ) =
121
+ if (bound.isRef(default)) " " else i " $cmp $bound"
122
122
123
- def explanation (entry : Recorded ): String = {
124
- def boundStr (bound : Type , default : ClassSymbol , cmp : String ) =
125
- if (bound.isRef(default)) " " else i " $cmp $bound"
123
+ def boundsStr (bounds : TypeBounds ): String = {
124
+ val lo = boundStr(bounds.lo, defn.NothingClass , " >:" )
125
+ val hi = boundStr(bounds.hi, defn.AnyClass , " <:" )
126
+ if (lo.isEmpty) hi
127
+ else if (hi.isEmpty) lo
128
+ else s " $lo and $hi"
129
+ }
126
130
127
- def boundsStr ( bounds : TypeBounds ): String = {
128
- val lo = boundStr( bounds.lo, defn. NothingClass , " >: " )
129
- val hi = boundStr(bounds.hi, defn. AnyClass , " <: " )
130
- if (lo.isEmpty) hi
131
- else if (hi.isEmpty) lo
132
- else s " $lo and $hi "
133
- }
131
+ def addendum ( cat : String , info : Type ): String = info match {
132
+ case bounds @ TypeBounds (lo, hi) if bounds ne TypeBounds .empty =>
133
+ if (lo eq hi) i " which is an alias of $lo "
134
+ else i " with $cat ${boundsStr(bounds)} "
135
+ case _ =>
136
+ " "
137
+ }
134
138
135
- def addendum ( cat : String , info : Type )( implicit ctx : Context ) : String = info match {
136
- case bounds @ TypeBounds (lo, hi) if bounds ne TypeBounds .empty =>
137
- if (lo eq hi) i " which is an alias of $lo "
138
- else i " with $cat ${boundsStr(bounds)} "
139
- case _ =>
140
- " "
141
- }
139
+ entry match {
140
+ case param : PolyParam =>
141
+ s " is a type variable ${addendum( " constraint " , ctx.typeComparer.bounds(param))} "
142
+ case sym : Symbol =>
143
+ s " is a ${ctx.printer.kindString(sym)}${sym.showExtendedLocation}${addendum( " bounds " , sym.info)} "
144
+ }
145
+ }
142
146
143
- entry match {
144
- case param : PolyParam =>
145
- s " is a type variable ${addendum(" constraint" , ctx.typeComparer.bounds(param))}"
146
- case sym : Symbol =>
147
- s " is a ${ctx.printer.kindString(sym)}${sym.showExtendedLocation}${addendum(" bounds" , sym.info)}"
148
- }
147
+ private def explanations (seen : Seen )(implicit ctx : Context ): String = {
148
+ def needsExplanation (entry : Recorded ) = entry match {
149
+ case param : PolyParam => ctx.typerState.constraint.contains(param)
150
+ case _ => false
149
151
}
150
152
151
- def explanations (seen : Seen )(implicit ctx : Context ): String = {
152
- def needsExplanation (entry : Recorded ) = entry match {
153
- case param : PolyParam => ctx.typerState.constraint.contains(param)
154
- case _ => false
153
+ val toExplain : List [(String , Recorded )] = seen.toList.flatMap {
154
+ case (str, entry :: Nil ) =>
155
+ if (needsExplanation(entry)) (str, entry) :: Nil else Nil
156
+ case (str, entries) =>
157
+ entries.map(alt => (seen.record(str, alt), alt))
158
+ }.sortBy(_._1)
159
+
160
+ def columnar (parts : List [(String , String )], sep : String ): List [String ] = {
161
+ lazy val maxLen = parts.map(_._1.length).max
162
+ parts.map {
163
+ case (leader, trailer) =>
164
+ s " ` $leader` ${" " * (maxLen - leader.length)}$sep$trailer"
155
165
}
156
- val toExplain : List [(String , Recorded )] = seen.toList.flatMap {
157
- case (str, entry :: Nil ) =>
158
- if (needsExplanation(entry)) (str, entry) :: Nil else Nil
159
- case (str, entries) =>
160
- entries.map(alt => (seen.record(str, alt), alt))
161
- }.sortBy(_._1)
162
- val explainParts = toExplain.map { case (str, entry) => (str, explanation(entry)) }
163
- val explainLines = columnar(explainParts, " " )
164
- if (explainLines.isEmpty) " " else i " \n\n where $explainLines% \n % \n "
165
166
}
166
167
168
+ val explainParts = toExplain.map { case (str, entry) => (str, explanation(entry)) }
169
+ val explainLines = columnar(explainParts, " " )
170
+ if (explainLines.isEmpty) " " else i " where $explainLines% \n % \n "
171
+ }
172
+
173
+ def explained2 (op : Context => String )(implicit ctx : Context ): String = {
174
+ val seen = new Seen
175
+ val explainCtx = ctx.printer match {
176
+ case dp : ExplainingPrinter =>
177
+ ctx // re-use outer printer and defer explanation to it
178
+ case _ => ctx.fresh.setPrinterFn(ctx => new ExplainingPrinter (seen)(ctx))
179
+ }
167
180
op(explainCtx) ++ explanations(seen)
168
181
}
169
182
170
- def columnar (parts : List [(String , String )], sep : String ): List [String ] = {
171
- lazy val maxLen = parts.map(_._1.length).max
172
- parts.map {
173
- case (leader, trailer) =>
174
- s " $leader${" " * (maxLen - leader.length)}$sep$trailer"
183
+ def disambiguateTypes (args : Type * )(implicit ctx : Context ): String = {
184
+ val seen = new Seen
185
+ object polyparams extends TypeTraverser {
186
+ def traverse (tp : Type ): Unit = tp match {
187
+ case tp : NamedType =>
188
+ val sym = tp.symbol
189
+ if (! sym.is(Package )) {
190
+ if (! sym.isClass) traverse(tp.info)
191
+ traverse(tp.prefix)
192
+ }
193
+ case tp : ThisType =>
194
+ traverse(tp.underlying)
195
+ case tp : ConstantType =>
196
+ traverse(tp.underlying)
197
+ case tp : MethodParam =>
198
+ traverse(tp.underlying)
199
+ case tp : PolyParam =>
200
+ seen.record(tp.show, tp)
201
+ traverse(tp.underlying)
202
+ case _ =>
203
+ traverseChildren(tp)
204
+ }
205
+ }
206
+ args.foreach(polyparams.traverse)
207
+ explanations(seen)
208
+ }
209
+
210
+ def typeDiff (found : Type , expected : Type )(implicit ctx : Context ): (String , String ) = {
211
+ (found, expected) match {
212
+ case (rf1 : RefinedType , rf2 : RefinedType ) =>
213
+ DiffUtil .mkColoredTypeDiff(rf1.show, rf2.show)
214
+ case _ =>
215
+ (hl " ${found.show}" , hl " ${expected.show}" )
175
216
}
176
217
}
177
218
}
0 commit comments