summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
diff options
context:
space:
mode:
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