@@ -314,13 +314,19 @@ object messages {
314314
315315 val msg : String = {
316316 import core .Flags ._
317- val maxDist = 3
318- val decls = site.decls.toList
319- .filter(_.isType == name.isTypeName)
320- .flatMap { sym =>
321- if (sym.flagsUNSAFE.isOneOf(Synthetic | PrivateLocal ) || sym.isConstructor) Nil
322- else List ((sym.name.show, sym))
323- }
317+ val maxDist = 3 // maximal number of differences to be considered for a hint
318+ val missing = name.show
319+
320+ // The names of all non-synthetic, non-private members of `site`
321+ // that are of the same type/term kind as the missing member.
322+ def candidates : Set [String ] =
323+ for
324+ bc <- site.baseClasses.toSet
325+ sym <- bc.info.decls.filter(sym =>
326+ sym.isType == name.isTypeName
327+ && ! sym.isConstructor
328+ && ! sym.flagsUNSAFE.isOneOf(Synthetic | Private ))
329+ yield sym.name.show
324330
325331 // Calculate Levenshtein distance
326332 def distance (n1 : Iterable [? ], n2 : Iterable [? ]) =
@@ -333,37 +339,18 @@ object messages {
333339 }
334340 }.last
335341
336- // Count number of wrong characters
337- def incorrectChars (x : (String , Int , Symbol )): (String , Symbol , Int ) = {
338- val (currName, _, sym) = x
339- val matching = name.show.zip(currName).foldLeft(0 ) {
340- case (acc, (x,y)) => if (x != y) acc + 1 else acc
341- }
342- (currName, sym, matching)
343- }
344-
345- // Get closest match in `site`
346- def closest : List [String ] =
347- decls
348- .map { (n, sym) => (n, distance(n, name.show), sym) }
349- .collect {
350- case (n, dist, sym)
351- if dist <= maxDist && dist < (name.toString.length min n.length) =>
352- (n, dist, sym)
353- }
354- .groupBy(_._2).toList
355- .sortBy(_._1)
356- .headOption.map(_._2).getOrElse(Nil )
357- .map(incorrectChars).toList
358- .sortBy(_._3)
359- .map(_._1)
360- // [Martin] Note: I have no idea what this does. This shows the
361- // pitfalls of not naming things, functional or not.
342+ // A list of possible candidate strings with their Levenstein distances
343+ // to the name of the missing member
344+ def closest : List [(Int , String )] = candidates
345+ .toList
346+ .map(n => (distance(n.show, missing), n))
347+ .filter((d, n) => d <= maxDist && d < missing.length & d < n.length)
348+ .sorted // sort by distance first, alphabetically second
362349
363350 val finalAddendum =
364351 if addendum.nonEmpty then addendum
365352 else closest match {
366- case n :: _ =>
353+ case (d, n) :: _ =>
367354 val siteName = site match
368355 case site : NamedType => site.name.show
369356 case site => i " $site"
0 commit comments