summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/Typers.scala
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2009-10-16 16:44:45 +0000
committerPaul Phillips <paulp@improving.org>2009-10-16 16:44:45 +0000
commit3a5e4c9e8bd50864a47152ccea2549c5c35ba9df (patch)
tree401812942d0f4ef711d7df5c09e1823c0bc778cf /src/compiler/scala/tools/nsc/typechecker/Typers.scala
parent136c1cce62ab8a35d7f0a515d7456fe4764611c3 (diff)
downloadscala-3a5e4c9e8bd50864a47152ccea2549c5c35ba9df.tar.gz
scala-3a5e4c9e8bd50864a47152ccea2549c5c35ba9df.tar.bz2
scala-3a5e4c9e8bd50864a47152ccea2549c5c35ba9df.zip
Created -Xstrict-warnings and got the ball roll...
Created -Xstrict-warnings and got the ball rolling with an attempt at spotting variable shadowing. Has to get less noisy but plenty useful as-is.
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Typers.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala73
1 files changed, 48 insertions, 25 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index d9cdb79ea4..56e85c9eff 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1570,17 +1570,64 @@ trait Typers { self: Analyzer =>
error(vparam.tpt.pos,"Parameter type in structural refinement may not refer to abstract type defined outside that same refinement")
}
+ /** does given name name an identifier visible at this point?
+ *
+ * @param name the given name
+ * @return <code>true</code> if an identifier with the given name is visible.
+ */
+ def namesSomeIdent(name: Name): Boolean = namesWhatIdent(name).isDefined
+
+ /** If this name returns a visible identifier, return its symbol.
+ *
+ * @param name the given name
+ * @return <code>Some(sym)</code> if an ident is visible, None otherwise.
+ */
+ def namesWhatIdent(name: Name): Option[Symbol] = {
+ var cx = context
+ while (cx != NoContext) {
+ val pre = cx.enclClass.prefix
+ val defEntry = cx.scope.lookupEntryWithContext(name)(context.owner)
+ if ((defEntry ne null) && defEntry.sym.exists)
+ return Some(defEntry.sym)
+
+ cx = cx.enclClass
+ (pre member name filter (sym => sym.exists && context.isAccessible(sym, pre, false))) match {
+ case NoSymbol => cx = cx.outer
+ case other => return Some(other)
+ }
+ }
+ context.imports map (_ importedSymbol name) find (_ != NoSymbol)
+ }
+
/**
* @param ddef ...
* @return ...
*/
def typedDefDef(ddef: DefDef): DefDef = {
val meth = ddef.symbol
+
+ // If warnings are enabled, attempt to alert about variable shadowing. This only
+ // catches method parameters shadowing identifiers declared in the same file, so more
+ // work is needed. Most of the code here is to filter out false positives.
+ def isAuxConstructor(sym: Symbol) = sym.isConstructor && !sym.isPrimaryConstructor
+ if (settings.Xwarnings.value && unit != null && !isAuxConstructor(ddef.symbol)) {
+ for (v <- ddef.vparamss.flatten ; if (v.symbol == null) || !(v.symbol hasFlag SYNTHETIC))
+ for (other <- namesWhatIdent(v.name) ; if (v ne other) && !other.isDeferred) {
+ val where = other.pos match {
+ case NoPosition => ""
+ case x: Position => "at line %s\n%s".format(x.line, x.lineContent) + """ /* is shadowed by */"""
+ }
+ if (v.pos == NoPosition || other.pos == NoPosition || v.pos.line != other.pos.line)
+ unit.warning(v.pos, "%s (%s) shadows earlier usage %s".format(v.name, v.tpt, where))
+ }
+ }
+
reenterTypeParams(ddef.tparams)
reenterValueParams(ddef.vparamss)
val tparams1 = ddef.tparams mapConserve typedTypeDef
val vparamss1 = ddef.vparamss mapConserve (_ mapConserve typedValDef)
- for (vparams1 <- vparamss1; if !vparams1.isEmpty; vparam1 <- vparams1.init) {
+
+ for (vparams1 <- vparamss1; vparam1 <- vparams1 dropRight 1) {
if (isRepeatedParamType(vparam1.symbol.tpe))
error(vparam1.pos, "*-parameter must come last")
}
@@ -3268,30 +3315,6 @@ trait Typers { self: Analyzer =>
}
}
- /** does given name name an identifier visible at this point?
- *
- * @param name the given name
- * @return <code>true</code> if an identifier with the given name is visible.
- */
- def namesSomeIdent(name: Name): Boolean = {
- var cx = context
- while (cx != NoContext) {
- val pre = cx.enclClass.prefix
- val defEntry = cx.scope.lookupEntryWithContext(name)(context.owner)
- if ((defEntry ne null) && defEntry.sym.exists) return true
- cx = cx.enclClass
- if ((pre.member(name) filter (
- sym => sym.exists && context.isAccessible(sym, pre, false))) != NoSymbol) return true
- cx = cx.outer
- }
- var imports = context.imports // impSym != NoSymbol => it is imported from imports.head
- while (!imports.isEmpty) {
- if (imports.head.importedSymbol(name) != NoSymbol) return true
- imports = imports.tail
- }
- false
- }
-
/** Attribute an identifier consisting of a simple name or an outer reference.
*
* @param tree The tree representing the identifier.