summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
diff options
context:
space:
mode:
authorSeth Tisue <seth@tisue.net>2015-07-20 13:32:17 -0400
committerSeth Tisue <seth@tisue.net>2015-07-20 13:32:17 -0400
commitf55bdbff0ba20a4fb3805e27b4b01752f45bc490 (patch)
treedbc1eeae7d3dea1730603d6b3d8255aed8637b48 /src/compiler/scala/tools/nsc/typechecker/Contexts.scala
parent100a234882a86a249ebe586b4e75fede58c098c3 (diff)
parentac0e1d8c7f158a809a135855d821cbeb7f1bec92 (diff)
downloadscala-f55bdbff0ba20a4fb3805e27b4b01752f45bc490.tar.gz
scala-f55bdbff0ba20a4fb3805e27b4b01752f45bc490.tar.bz2
scala-f55bdbff0ba20a4fb3805e27b4b01752f45bc490.zip
Merge pull request #4616 from som-snytt/issue/9383
SI-9383 Improved unused import warning
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Contexts.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala53
1 files changed, 29 insertions, 24 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index 4c840818da..fa266d43ed 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -24,7 +24,8 @@ trait Contexts { self: Analyzer =>
object NoContext
extends Context(EmptyTree, NoSymbol, EmptyScope, NoCompilationUnit,
- null) { // We can't pass the uninitialized `this`. Instead, we treat null specially in `Context#outer`
+ // We can't pass the uninitialized `this`. Instead, we treat null specially in `Context#outer`
+ null) {
enclClass = this
enclMethod = this
@@ -48,12 +49,11 @@ trait Contexts { self: Analyzer =>
def ambiguousDefnAndImport(owner: Symbol, imp: ImportInfo) =
LookupAmbiguous(s"it is both defined in $owner and imported subsequently by \n$imp")
- private lazy val startContext = {
- NoContext.make(
+ private lazy val startContext = NoContext.make(
Template(List(), noSelfType, List()) setSymbol global.NoSymbol setType global.NoType,
rootMirror.RootClass,
- rootMirror.RootClass.info.decls)
- }
+ rootMirror.RootClass.info.decls
+ )
private lazy val allUsedSelectors =
mutable.Map[ImportInfo, Set[ImportSelector]]() withDefaultValue Set()
@@ -802,6 +802,14 @@ trait Contexts { self: Analyzer =>
(e ne null) && (e.owner == scope) && (!settings.isScala212 || e.sym.exists)
})
+ /** Do something with the symbols with name `name` imported via the import in `imp`,
+ * if any such symbol is accessible from this context and is a qualifying implicit.
+ */
+ private def withQualifyingImplicitAlternatives(imp: ImportInfo, name: Name, pre: Type)(f: Symbol => Unit) = for {
+ sym <- importedAccessibleSymbol(imp, name, requireExplicit = false, record = false).alternatives
+ if isQualifyingImplicit(name, sym, pre, imported = true)
+ } f(sym)
+
private def collectImplicits(syms: Scope, pre: Type, imported: Boolean = false): List[ImplicitInfo] =
for (sym <- syms.toList if isQualifyingImplicit(sym.name, sym, pre, imported)) yield
new ImplicitInfo(sym.name, pre, sym)
@@ -819,9 +827,9 @@ trait Contexts { self: Analyzer =>
case ImportSelector(from, _, to, _) :: sels1 =>
var impls = collect(sels1) filter (info => info.name != from)
if (to != nme.WILDCARD) {
- for (sym <- importedAccessibleSymbol(imp, to).alternatives)
- if (isQualifyingImplicit(to, sym, pre, imported = true))
- impls = new ImplicitInfo(to, pre, sym) :: impls
+ withQualifyingImplicitAlternatives(imp, to, pre) { sym =>
+ impls = new ImplicitInfo(to, pre, sym) :: impls
+ }
}
impls
}
@@ -946,11 +954,8 @@ trait Contexts { self: Analyzer =>
/** The symbol with name `name` imported via the import in `imp`,
* if any such symbol is accessible from this context.
*/
- def importedAccessibleSymbol(imp: ImportInfo, name: Name): Symbol =
- importedAccessibleSymbol(imp, name, requireExplicit = false)
-
- private def importedAccessibleSymbol(imp: ImportInfo, name: Name, requireExplicit: Boolean): Symbol =
- imp.importedSymbol(name, requireExplicit) filter (s => isAccessible(s, imp.qual.tpe, superAccess = false))
+ private def importedAccessibleSymbol(imp: ImportInfo, name: Name, requireExplicit: Boolean, record: Boolean): Symbol =
+ imp.importedSymbol(name, requireExplicit, record) filter (s => isAccessible(s, imp.qual.tpe, superAccess = false))
private def requiresQualifier(s: Symbol) = (
s.owner.isClass
@@ -1057,7 +1062,7 @@ trait Contexts { self: Analyzer =>
def imp2Explicit = imp2 isExplicitImport name
def lookupImport(imp: ImportInfo, requireExplicit: Boolean) =
- importedAccessibleSymbol(imp, name, requireExplicit) filter qualifies
+ importedAccessibleSymbol(imp, name, requireExplicit, record = true) filter qualifies
// Java: A single-type-import declaration d in a compilation unit c of package p
// that imports a type named n shadows, throughout c, the declarations of:
@@ -1353,7 +1358,6 @@ trait Contexts { self: Analyzer =>
protected def handleError(pos: Position, msg: String): Unit = onTreeCheckerError(pos, msg)
}
-
class ImportInfo(val tree: Import, val depth: Int) {
def pos = tree.pos
def posOf(sel: ImportSelector) = tree.pos withPoint sel.namePos
@@ -1369,19 +1373,20 @@ trait Contexts { self: Analyzer =>
def isExplicitImport(name: Name): Boolean =
tree.selectors exists (_.rename == name.toTermName)
- /** The symbol with name `name` imported from import clause `tree`.
- */
- def importedSymbol(name: Name): Symbol = importedSymbol(name, requireExplicit = false)
+ /** The symbol with name `name` imported from import clause `tree`. */
+ def importedSymbol(name: Name): Symbol = importedSymbol(name, requireExplicit = false, record = true)
- private def recordUsage(sel: ImportSelector, result: Symbol) {
- def posstr = pos.source.file.name + ":" + posOf(sel).line
- def resstr = if (tree.symbol.hasCompleteInfo) s"(qual=$qual, $result)" else s"(expr=${tree.expr}, ${result.fullLocationString})"
- debuglog(s"In $this at $posstr, selector '${selectorString(sel)}' resolved to $resstr")
+ private def recordUsage(sel: ImportSelector, result: Symbol): Unit = {
+ debuglog(s"In $this at ${ pos.source.file.name }:${ posOf(sel).line }, selector '${ selectorString(sel)
+ }' resolved to ${
+ if (tree.symbol.hasCompleteInfo) s"(qual=$qual, $result)"
+ else s"(expr=${tree.expr}, ${result.fullLocationString})"
+ }")
allUsedSelectors(this) += sel
}
/** If requireExplicit is true, wildcard imports are not considered. */
- def importedSymbol(name: Name, requireExplicit: Boolean): Symbol = {
+ def importedSymbol(name: Name, requireExplicit: Boolean, record: Boolean): Symbol = {
var result: Symbol = NoSymbol
var renamed = false
var selectors = tree.selectors
@@ -1398,7 +1403,7 @@ trait Contexts { self: Analyzer =>
if (result == NoSymbol)
selectors = selectors.tail
}
- if (settings.warnUnusedImport && selectors.nonEmpty && result != NoSymbol && pos != NoPosition)
+ if (record && settings.warnUnusedImport && selectors.nonEmpty && result != NoSymbol && pos != NoPosition)
recordUsage(current, result)
// Harden against the fallout from bugs like SI-6745