diff options
author | Paul Phillips <paulp@improving.org> | 2011-12-03 15:27:52 -0800 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2011-12-03 20:04:10 -0800 |
commit | 3e9e4ecf360e6eda5c26f798abfcb9bb882cf772 (patch) | |
tree | a0e9d34abff1403e30cb562ee0733cbe3d6496d7 /src/compiler/scala/tools/nsc/typechecker/Typers.scala | |
parent | f7d436a0abf350ff573f155392393c357f489a93 (diff) | |
download | scala-3e9e4ecf360e6eda5c26f798abfcb9bb882cf772.tar.gz scala-3e9e4ecf360e6eda5c26f798abfcb9bb882cf772.tar.bz2 scala-3e9e4ecf360e6eda5c26f798abfcb9bb882cf772.zip |
Added -Ysuggest-idents.
Suggest possible alternatives when an identifier is not in scope.
% scala -Ysuggest-idents
scala> import scala.collection.mutable._
import scala.collection.mutable._
scala> new MistBuffer
<console>:11: error: not found: type MistBuffer (similar: ListBuffer, Buffer)
new MistBuffer
^
Too bad, no MistBuffer. We'll settle for ListBuffer.
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Typers.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 36 |
1 files changed, 27 insertions, 9 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 16c0cb40ff..30d10325be 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -19,6 +19,7 @@ import symtab.Flags._ import util.Statistics import util.Statistics._ import scala.tools.util.StringOps.{ countAsString, countElementsAsString } +import scala.tools.util.EditDistance.similarString // Suggestion check whether we can do without priming scopes with symbols of outer scopes, // like the IDE does. @@ -3752,7 +3753,11 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { defSym = EmptyPackageClass.tpe.nonPrivateMember(name) defSym != NoSymbol } - + def startingIdentContext = ( + // ignore current variable scope in patterns to enforce linearity + if ((mode & (PATTERNmode | TYPEPATmode)) == 0) context + else context.outer + ) // A symbol qualifies if it exists and is not stale. Stale symbols // are made to disappear here. In addition, // if we are in a constructor of a pattern, we ignore all definitions @@ -3768,13 +3773,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { if (defSym == NoSymbol) { var defEntry: ScopeEntry = null // the scope entry of defSym, if defined in a local scope - var cx = context - if ((mode & (PATTERNmode | TYPEPATmode)) != 0) { - // println("ignoring scope: "+name+" "+cx.scope+" "+cx.outer.scope) - // ignore current variable scope in patterns to enforce linearity - cx = cx.outer - } - + var cx = startingIdentContext while (defSym == NoSymbol && cx != NoContext) { currentRun.compileSourceFor(context.asInstanceOf[analyzer.Context], name) pre = cx.enclClass.prefix @@ -3872,7 +3871,26 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { if (inaccessibleSym eq NoSymbol) { // Avoiding some spurious error messages: see SI-2388. if (reporter.hasErrors && (name startsWith tpnme.ANON_CLASS_NAME)) () - else error(tree.pos, "not found: "+decodeWithKind(name, context.owner)) + else { + val similar = ( + // name length check to limit unhelpful suggestions for e.g. "x" and "b1" + if (settings.suggestIdents.value && name.length > 2) { + val allowed = ( + startingIdentContext.enclosingContextChain + flatMap (ctx => ctx.scope.toList ++ ctx.imports.flatMap(_.allImportedSymbols)) + filter (sym => sym.isTerm == name.isTermName) + filterNot (sym => sym.isPackage || sym.isSynthetic || sym.hasMeaninglessName) + ) + val allowedStrings = ( + allowed.map("" + _.name).distinct.sorted + filterNot (s => (s contains '$') || (s contains ' ')) + ) + similarString("" + name, allowedStrings) + } + else "" + ) + error(tree.pos, "not found: "+decodeWithKind(name, context.owner) + similar) + } } else new AccessError( tree, inaccessibleSym, context.enclClass.owner.thisType, |