@@ -489,147 +489,152 @@ trait TypeDiagnostics {
489
489
def inMode (context : Context , mode : Mode , tree : Tree ): Tree = if (mode.typingMonoExprByValue) apply(context, tree) else tree
490
490
}
491
491
492
- class checkUnused ( typer : Typer ) {
492
+ object UnusedPrivates {
493
493
val ignoreNames : Set [TermName ] = Set (
494
494
" readResolve" , " readObject" , " writeObject" , " writeReplace"
495
495
).map(TermName (_))
496
+ }
496
497
497
- class UnusedPrivates extends Traverser {
498
- val defnTrees = ListBuffer [MemberDef ]()
499
- val targets = mutable.Set [Symbol ]()
500
- val setVars = mutable.Set [Symbol ]()
501
- val treeTypes = mutable.Set [Type ]()
502
- val params = mutable.Set [Symbol ]()
503
- val patvars = mutable.Set [Symbol ]()
504
-
505
- def defnSymbols = defnTrees.toList map (_.symbol)
506
- def localVars = defnSymbols filter (t => t.isLocalToBlock && t.isVar)
507
-
508
- def qualifiesTerm (sym : Symbol ) = (
509
- (sym.isModule || sym.isMethod || sym.isPrivateLocal || sym.isLocalToBlock)
510
- && ! nme.isLocalName(sym.name)
511
- && ! sym.isParameter
512
- && ! sym.isParamAccessor // could improve this, but it's a pain
513
- && ! sym.isEarlyInitialized // lots of false positives in the way these are encoded
514
- && ! (sym.isGetter && sym.accessed.isEarlyInitialized)
515
- )
516
- def qualifiesType (sym : Symbol ) = ! sym.isDefinedInPackage
517
- def qualifies (sym : Symbol ) = (
518
- (sym ne null )
519
- && (sym.isTerm && qualifiesTerm(sym) || sym.isType && qualifiesType(sym))
520
- )
521
- def isExisting (sym : Symbol ) = sym != null && sym.exists
522
-
523
- override def traverse (t : Tree ): Unit = {
524
- val sym = t.symbol
525
- t match {
526
- case m : MemberDef if qualifies(sym) && ! t.isErrorTyped =>
527
- t match {
528
- case ValDef (mods@ _, name@ _, tpt@ _, rhs@ _) if wasPatVarDef(t) =>
529
- if (settings.warnUnusedPatVars && ! atBounded(t)) patvars += sym
530
- case DefDef (mods@ _, name@ _, tparams@ _, vparamss, tpt@ _, rhs@ _) if ! sym.isAbstract && ! sym.isDeprecated && ! sym.isMacro =>
531
- if (sym.isPrimaryConstructor)
532
- for (cpa <- sym.owner.constrParamAccessors if cpa.isPrivateLocal) params += cpa
533
- else if (sym.isSynthetic && sym.isImplicit) return
534
- else if (! sym.isConstructor && rhs.symbol != Predef_??? )
535
- for (vs <- vparamss) params ++= vs.map(_.symbol)
536
- defnTrees += m
537
- case _ =>
538
- defnTrees += m
539
- }
540
- case CaseDef (pat, guard@ _, rhs@ _) if settings.warnUnusedPatVars && ! t.isErrorTyped =>
541
- pat.foreach {
542
- case b @ Bind (n, _) if ! atBounded(b) && n != nme.DEFAULT_CASE => patvars += b.symbol
543
- case _ =>
544
- }
545
- case _ : RefTree if isExisting(sym) => targets += sym
546
- case Assign (lhs, _) if isExisting(lhs.symbol) => setVars += lhs.symbol
547
- case Function (ps, _) if settings.warnUnusedParams && ! t.isErrorTyped => params ++=
548
- ps.filterNot(p => atBounded(p) || p.symbol.isSynthetic).map(_.symbol)
549
- case _ =>
550
- }
498
+ class UnusedPrivates extends Traverser {
499
+ import UnusedPrivates .ignoreNames
500
+ def isEffectivelyPrivate (sym : Symbol ): Boolean = false
501
+ val defnTrees = ListBuffer [MemberDef ]()
502
+ val targets = mutable.Set [Symbol ]()
503
+ val setVars = mutable.Set [Symbol ]()
504
+ val treeTypes = mutable.Set [Type ]()
505
+ val params = mutable.Set [Symbol ]()
506
+ val patvars = mutable.Set [Symbol ]()
507
+
508
+ def defnSymbols = defnTrees.toList map (_.symbol)
509
+ def localVars = defnSymbols filter (t => t.isLocalToBlock && t.isVar)
510
+
511
+ def qualifiesTerm (sym : Symbol ) = (
512
+ (sym.isModule || sym.isMethod || sym.isPrivateLocal || sym.isLocalToBlock || isEffectivelyPrivate(sym))
513
+ && ! nme.isLocalName(sym.name)
514
+ && ! sym.isParameter
515
+ && ! sym.isParamAccessor // could improve this, but it's a pain
516
+ && ! sym.isEarlyInitialized // lots of false positives in the way these are encoded
517
+ && ! (sym.isGetter && sym.accessed.isEarlyInitialized)
518
+ )
519
+ def qualifiesType (sym : Symbol ) = ! sym.isDefinedInPackage
520
+ def qualifies (sym : Symbol ) = (
521
+ (sym ne null )
522
+ && (sym.isTerm && qualifiesTerm(sym) || sym.isType && qualifiesType(sym))
523
+ )
524
+ def isExisting (sym : Symbol ) = sym != null && sym.exists
551
525
552
- if (t.tpe ne null ) {
553
- for (tp <- t.tpe) if (! treeTypes(tp)) {
554
- // Include references to private/local aliases (which might otherwise refer to an enclosing class)
555
- val isAlias = {
556
- val td = tp.typeSymbolDirect
557
- td.isAliasType && (td.isLocal || td.isPrivate)
558
- }
559
- // Ignore type references to an enclosing class. A reference to C must be outside C to avoid warning.
560
- if (isAlias || ! currentOwner.hasTransOwner(tp.typeSymbol)) tp match {
561
- case NoType | NoPrefix =>
562
- case NullaryMethodType (_) =>
563
- case MethodType (_, _) =>
564
- case SingleType (_, _) =>
565
- case ConstantType (Constant (k : Type )) =>
566
- log(s " classOf $k referenced from $currentOwner" )
567
- treeTypes += k
568
- case _ =>
569
- log(s " ${if (isAlias) " alias " else " " }$tp referenced from $currentOwner" )
570
- treeTypes += tp
571
- }
526
+ override def traverse (t : Tree ): Unit = {
527
+ val sym = t.symbol
528
+ t match {
529
+ case m : MemberDef if qualifies(sym) && ! t.isErrorTyped =>
530
+ t match {
531
+ case ValDef (mods@ _, name@ _, tpt@ _, rhs@ _) if wasPatVarDef(t) =>
532
+ if (settings.warnUnusedPatVars && ! atBounded(t)) patvars += sym
533
+ case DefDef (mods@ _, name@ _, tparams@ _, vparamss, tpt@ _, rhs@ _) if ! sym.isAbstract && ! sym.isDeprecated && ! sym.isMacro =>
534
+ if (sym.isPrimaryConstructor)
535
+ for (cpa <- sym.owner.constrParamAccessors if cpa.isPrivateLocal) params += cpa
536
+ else if (sym.isSynthetic && sym.isImplicit) return
537
+ else if (! sym.isConstructor && rhs.symbol != Predef_??? )
538
+ for (vs <- vparamss) params ++= vs.map(_.symbol)
539
+ defnTrees += m
540
+ case _ =>
541
+ defnTrees += m
572
542
}
573
- // e.g. val a = new Foo ; new a.Bar ; don't let a be reported as unused.
574
- for (p <- t.tpe.prefix) condOpt(p) {
575
- case SingleType (_, sym) => targets += sym
543
+ case CaseDef (pat, guard@ _, rhs@ _) if settings.warnUnusedPatVars && ! t.isErrorTyped =>
544
+ pat.foreach {
545
+ case b @ Bind (n, _) if ! atBounded(b) && n != nme.DEFAULT_CASE => patvars += b.symbol
546
+ case _ =>
576
547
}
577
- }
578
- super .traverse(t)
548
+ case _ : RefTree if isExisting(sym) => targets += sym
549
+ case Assign (lhs, _) if isExisting(lhs.symbol) => setVars += lhs.symbol
550
+ case Function (ps, _) if settings.warnUnusedParams && ! t.isErrorTyped => params ++=
551
+ ps.filterNot(p => atBounded(p) || p.symbol.isSynthetic).map(_.symbol)
552
+ case _ =>
579
553
}
580
- def isUnusedType (m : Symbol ): Boolean = (
581
- m.isType
582
- && ! m.isTypeParameterOrSkolem // would be nice to improve this
583
- && (m.isPrivate || m.isLocalToBlock)
584
- && ! (treeTypes.exists(_.exists(_.typeSymbolDirect == m)))
585
- )
586
- def isSyntheticWarnable (sym : Symbol ) = (
587
- sym.isDefaultGetter
588
- )
589
- def isUnusedTerm (m : Symbol ): Boolean = (
590
- m.isTerm
591
- && (! m.isSynthetic || isSyntheticWarnable(m))
592
- && ((m.isPrivate && ! (m.isConstructor && m.owner.isAbstract)) || m.isLocalToBlock)
593
- && ! targets(m)
594
- && ! (m.name == nme.WILDCARD ) // e.g. val _ = foo
595
- && (m.isValueParameter || ! ignoreNames(m.name.toTermName)) // serialization methods
596
- && ! isConstantType(m.info.resultType) // subject to constant inlining
597
- && ! treeTypes.exists(_ contains m) // e.g. val a = new Foo ; new a.Bar
598
- )
599
- def isUnusedParam (m : Symbol ): Boolean = (
600
- isUnusedTerm(m)
601
- && ! m.isDeprecated
602
- && ! m.owner.isDefaultGetter
603
- && ! (m.isParamAccessor && (
604
- m.owner.isImplicit ||
605
- targets.exists(s => s.isParameter
606
- && s.name == m.name && s.owner.isConstructor && s.owner.owner == m.owner) // exclude ctor params
607
- ))
608
- )
609
- def sympos (s : Symbol ): Int =
610
- if (s.pos.isDefined) s.pos.point else if (s.isTerm) s.asTerm.referenced.pos.point else - 1
611
- def treepos (t : Tree ): Int =
612
- if (t.pos.isDefined) t.pos.point else sympos(t.symbol)
613
-
614
- def unusedTypes = defnTrees.toList.filter(t => isUnusedType(t.symbol)).sortBy(treepos)
615
- def unusedTerms = {
616
- val all = defnTrees.toList.filter(v => isUnusedTerm(v.symbol))
617
-
618
- // is this a getter-setter pair? and why is this a difficult question for traits?
619
- def sameReference (g : Symbol , s : Symbol ) =
620
- if (g.accessed.exists && s.accessed.exists) g.accessed == s.accessed
621
- else g.owner == s.owner && g.setterName == s.name // sympos(g) == sympos(s)
622
-
623
- // filter out setters if already warning for getter.
624
- val clean = all.filterNot(v => v.symbol.isSetter && all.exists(g => g.symbol.isGetter && sameReference(g.symbol, v.symbol)))
625
- clean.sortBy(treepos)
554
+
555
+ if (t.tpe ne null ) {
556
+ for (tp <- t.tpe) if (! treeTypes(tp)) {
557
+ // Include references to private/local aliases (which might otherwise refer to an enclosing class)
558
+ val isAlias = {
559
+ val td = tp.typeSymbolDirect
560
+ td.isAliasType && (td.isLocal || td.isPrivate)
561
+ }
562
+ // Ignore type references to an enclosing class. A reference to C must be outside C to avoid warning.
563
+ if (isAlias || ! currentOwner.hasTransOwner(tp.typeSymbol)) tp match {
564
+ case NoType | NoPrefix =>
565
+ case NullaryMethodType (_) =>
566
+ case MethodType (_, _) =>
567
+ case SingleType (_, _) =>
568
+ case ConstantType (Constant (k : Type )) =>
569
+ log(s " classOf $k referenced from $currentOwner" )
570
+ treeTypes += k
571
+ case _ =>
572
+ log(s " ${if (isAlias) " alias " else " " }$tp referenced from $currentOwner" )
573
+ treeTypes += tp
574
+ }
575
+ }
576
+ // e.g. val a = new Foo ; new a.Bar ; don't let a be reported as unused.
577
+ for (p <- t.tpe.prefix) condOpt(p) {
578
+ case SingleType (_, sym) => targets += sym
579
+ }
626
580
}
627
- // local vars which are never set, except those already returned in unused
628
- def unsetVars = localVars.filter(v => ! setVars(v) && ! isUnusedTerm(v)).sortBy(sympos)
629
- def unusedParams = params.toList.filter(isUnusedParam).sortBy(sympos)
630
- def inDefinedAt (p : Symbol ) = p.owner.isMethod && p.owner.name == nme.isDefinedAt && p.owner.owner.isAnonymousFunction
631
- def unusedPatVars = patvars.toList.filter(p => isUnusedTerm(p) && ! inDefinedAt(p)).sortBy(sympos)
581
+ super .traverse(t)
632
582
}
583
+ def isUnusedType (m : Symbol ): Boolean = (
584
+ m.isType
585
+ && ! m.isTypeParameterOrSkolem // would be nice to improve this
586
+ && (m.isPrivate || m.isLocalToBlock || isEffectivelyPrivate(m))
587
+ && ! (treeTypes.exists(_.exists(_.typeSymbolDirect == m)))
588
+ )
589
+ def isSyntheticWarnable (sym : Symbol ) = (
590
+ sym.isDefaultGetter
591
+ )
592
+ def isUnusedTerm (m : Symbol ): Boolean = (
593
+ m.isTerm
594
+ && (! m.isSynthetic || isSyntheticWarnable(m))
595
+ && ((m.isPrivate && ! (m.isConstructor && m.owner.isAbstract)) || m.isLocalToBlock || isEffectivelyPrivate(m))
596
+ && ! targets(m)
597
+ && ! (m.name == nme.WILDCARD ) // e.g. val _ = foo
598
+ && (m.isValueParameter || ! ignoreNames(m.name.toTermName)) // serialization/repl methods
599
+ && ! isConstantType(m.info.resultType) // subject to constant inlining
600
+ && ! treeTypes.exists(_ contains m) // e.g. val a = new Foo ; new a.Bar
601
+ )
602
+ def isUnusedParam (m : Symbol ): Boolean = (
603
+ isUnusedTerm(m)
604
+ && ! m.isDeprecated
605
+ && ! m.owner.isDefaultGetter
606
+ && ! (m.isParamAccessor && (
607
+ m.owner.isImplicit ||
608
+ targets.exists(s => s.isParameter
609
+ && s.name == m.name && s.owner.isConstructor && s.owner.owner == m.owner) // exclude ctor params
610
+ ))
611
+ )
612
+ def sympos (s : Symbol ): Int =
613
+ if (s.pos.isDefined) s.pos.point else if (s.isTerm) s.asTerm.referenced.pos.point else - 1
614
+ def treepos (t : Tree ): Int =
615
+ if (t.pos.isDefined) t.pos.point else sympos(t.symbol)
616
+
617
+ def unusedTypes = defnTrees.toList.filter(t => isUnusedType(t.symbol)).sortBy(treepos)
618
+ def unusedTerms = {
619
+ val all = defnTrees.toList.filter(v => isUnusedTerm(v.symbol))
620
+
621
+ // is this a getter-setter pair? and why is this a difficult question for traits?
622
+ def sameReference (g : Symbol , s : Symbol ) =
623
+ if (g.accessed.exists && s.accessed.exists) g.accessed == s.accessed
624
+ else g.owner == s.owner && g.setterName == s.name // sympos(g) == sympos(s)
625
+
626
+ // filter out setters if already warning for getter.
627
+ val clean = all.filterNot(v => v.symbol.isSetter && all.exists(g => g.symbol.isGetter && sameReference(g.symbol, v.symbol)))
628
+ clean.sortBy(treepos)
629
+ }
630
+ // local vars which are never set, except those already returned in unused
631
+ def unsetVars = localVars.filter(v => ! setVars(v) && ! isUnusedTerm(v)).sortBy(sympos)
632
+ def unusedParams = params.toList.filter(isUnusedParam).sortBy(sympos)
633
+ def inDefinedAt (p : Symbol ) = p.owner.isMethod && p.owner.name == nme.isDefinedAt && p.owner.owner.isAnonymousFunction
634
+ def unusedPatVars = patvars.toList.filter(p => isUnusedTerm(p) && ! inDefinedAt(p)).sortBy(sympos)
635
+ }
636
+
637
+ class checkUnused (typer : Typer ) {
633
638
634
639
object skipMacroCall extends UnusedPrivates {
635
640
override def qualifiesTerm (sym : Symbol ): Boolean =
0 commit comments