summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2012-10-30 14:29:14 -0700
committerAdriaan Moors <adriaan.moors@epfl.ch>2012-11-01 18:50:43 -0700
commitd0c4be6861109683d80513eda74e5c6ca88f1441 (patch)
treef0604d9f71cd0807e6a5a6351535a78ac18ddefc /src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
parenta70c8219220b637072b52fc834439d90f0cf5b38 (diff)
downloadscala-d0c4be6861109683d80513eda74e5c6ca88f1441.tar.gz
scala-d0c4be6861109683d80513eda74e5c6ca88f1441.tar.bz2
scala-d0c4be6861109683d80513eda74e5c6ca88f1441.zip
Warn about unused private members.
Warnings enabled via -Xlint. It's one of the most requested features. And it is hard to argue we don't need it: see the 99 methods removed in the next commit. This should close SI-440.
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala57
1 files changed, 57 insertions, 0 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
index e5c0f5767c..283d0fa440 100644
--- a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
@@ -426,6 +426,63 @@ trait TypeDiagnostics {
def permanentlyHiddenWarning(pos: Position, hidden: Name, defn: Symbol) =
contextWarning(pos, "imported `%s' is permanently hidden by definition of %s".format(hidden, defn.fullLocationString))
+ object checkUnused {
+ val ignoreNames = Set[TermName]("readResolve", "readObject", "writeObject", "writeReplace")
+
+ class UnusedPrivates extends Traverser {
+ val defnTrees = ListBuffer[MemberDef]()
+ val targets = mutable.Set[Symbol]()
+ def qualifies(sym: Symbol) = (
+ (sym ne null)
+ && (sym.isMethod || sym.isPrivateLocal && !nme.isLocalName(sym.name))
+ && !sym.isParameter
+ && !sym.isParamAccessor // could improve this, but it's a pain
+ )
+
+ override def traverse(t: Tree): Unit = {
+ t match {
+ case t: ValOrDefDef if qualifies(t.symbol) => defnTrees += t
+ case t: RefTree if t.symbol ne null => targets += t.symbol
+ case _ =>
+ }
+ super.traverse(t)
+ }
+ def isUnused(m: Symbol): Boolean = (
+ m.isPrivate
+ && !targets(m)
+ && !ignoreNames(m.name) // serialization methods
+ && !isConstantType(m.info.resultType) // subject to constant inlining
+ )
+ def unused = defnTrees.toList filter (t => isUnused(t.symbol))
+ }
+
+ def apply(unit: CompilationUnit) = {
+ val p = new UnusedPrivates
+ p traverse unit.body
+ p.unused foreach { defn: DefTree =>
+ val sym = defn.symbol
+ val isDefaultGetter = sym.name containsName nme.DEFAULT_GETTER_STRING
+ val pos = (
+ if (defn.pos.isDefined) defn.pos
+ else if (sym.pos.isDefined) sym.pos
+ else sym match {
+ case sym: TermSymbol => sym.referenced.pos
+ case _ => NoPosition
+ }
+ )
+ val what = (
+ if (isDefaultGetter) "default argument"
+ else if (sym.isConstructor) "constructor"
+ else if (sym.isSetter) "setter"
+ else if (sym.isGetter) "getter"
+ else if (sym.isMethod) "method"
+ else "member"
+ )
+ unit.warning(pos, s"private $what in ${sym.owner} is never used")
+ }
+ }
+ }
+
object checkDead {
private var expr: Symbol = NoSymbol