diff options
10 files changed, 79 insertions, 51 deletions
diff --git a/src/compiler/scala/tools/nsc/Interpreter.scala b/src/compiler/scala/tools/nsc/Interpreter.scala index 48cc5bc61b..9e2966e976 100644 --- a/src/compiler/scala/tools/nsc/Interpreter.scala +++ b/src/compiler/scala/tools/nsc/Interpreter.scala @@ -614,13 +614,13 @@ class Interpreter(val settings: Settings, out: PrintWriter) private class ImportHandler(imp: Import) extends MemberHandler(imp) { /** Whether this import includes a wildcard import */ - override val importsWildcard = imp.selectors.map(_._1) contains USCOREkw + override val importsWildcard = imp.selectors.map(_.name) contains USCOREkw /** The individual names imported by this statement */ override val importedNames: Seq[Name] = for { - (_, sel) <- imp.selectors - if (sel != null && sel != USCOREkw) - name <- List(sel.toTypeName, sel.toTermName) + sel <- imp.selectors + if (sel.rename != null && sel.rename != USCOREkw) + name <- List(sel.rename.toTypeName, sel.rename.toTermName) } yield name diff --git a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala index f208cc54fb..275b422d5f 100644 --- a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala +++ b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala @@ -195,9 +195,9 @@ abstract class TreePrinters { case Import(expr, selectors) => // Is this selector remapping a name (i.e, {name1 => name2}) - def isNotRemap(s: (Name, Name)) : Boolean = (s._1 == nme.WILDCARD || s._1 == s._2) - def selectorToString(s: (Name, Name)): String = - if (isNotRemap(s)) s._1.toString else s._1.toString + "=>" + s._2.toString + def isNotRemap(s: ImportSelector) : Boolean = (s.name == nme.WILDCARD || s.name == s.rename) + def selectorToString(s: ImportSelector): String = + if (isNotRemap(s)) s.name.toString else s.name.toString + "=>" + s.rename.toString print("import "); print(expr) print(".") diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index 19e904700f..f91ff83e37 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -535,12 +535,23 @@ trait Trees { LabelDef(sym.name, params map Ident, rhs) setSymbol sym } + /** Import selector + * + * Representation of an imported name its optional rename and their optional positions + * + * @param name the imported name + * @param namePos its position or -1 if undefined + * @param rename the name the import is renamed to (== name if no renaming) + * @param renamePos the position of the rename or -1 if undefined + */ + case class ImportSelector(name: Name, namePos: Int, rename: Name, renamePos: Int) + /** Import clause * * @param expr * @param selectors */ - case class Import(expr: Tree, selectors: List[(Name, Name)]) + case class Import(expr: Tree, selectors: List[ImportSelector]) extends SymTree // The symbol of an Import is an import symbol @see Symbol.newImport // It's used primarily as a marker to check that the import has been typechecked. @@ -1042,7 +1053,7 @@ trait Trees { def DefDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree): DefDef def TypeDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], rhs: Tree): TypeDef def LabelDef(tree: Tree, name: Name, params: List[Ident], rhs: Tree): LabelDef - def Import(tree: Tree, expr: Tree, selectors: List[(Name, Name)]): Import + def Import(tree: Tree, expr: Tree, selectors: List[ImportSelector]): Import def DocDef(tree: Tree, comment: String, definition: Tree): DocDef def Template(tree: Tree, parents: List[Tree], self: ValDef, body: List[Tree]): Template def Block(tree: Tree, stats: List[Tree], expr: Tree): Block @@ -1097,7 +1108,7 @@ trait Trees { new TypeDef(mods, name, tparams, rhs).copyAttrs(tree) def LabelDef(tree: Tree, name: Name, params: List[Ident], rhs: Tree) = new LabelDef(name, params, rhs).copyAttrs(tree) - def Import(tree: Tree, expr: Tree, selectors: List[(Name, Name)]) = + def Import(tree: Tree, expr: Tree, selectors: List[ImportSelector]) = new Import(expr, selectors).copyAttrs(tree) def DocDef(tree: Tree, comment: String, definition: Tree) = new DocDef(comment, definition).copyAttrs(tree) @@ -1213,7 +1224,7 @@ trait Trees { if (name0 == name) && (params0 == params) && (rhs0 == rhs) => t case _ => treeCopy.LabelDef(tree, name, params, rhs) } - def Import(tree: Tree, expr: Tree, selectors: List[(Name, Name)]) = tree match { + def Import(tree: Tree, expr: Tree, selectors: List[ImportSelector]) = tree match { case t @ Import(expr0, selectors0) if (expr0 == expr) && (selectors0 == selectors) => t case _ => treeCopy.Import(tree, expr, selectors) diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 9540351a65..7730b2c48e 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -1892,8 +1892,9 @@ self => } def loop(): Tree = if (in.token == USCORE) { + val uscoreOffset = in.offset in.nextToken() - Import(t, List((nme.WILDCARD, null))) + Import(t, List(ImportSelector(nme.WILDCARD, uscoreOffset, null, -1))) } else if (in.token == LBRACE) { Import(t, importSelectors()) } else { @@ -1906,7 +1907,7 @@ self => in.nextToken() loop() } else { - Import(t, List((name, name))) + Import(t, List(ImportSelector(name, nameOffset, name, nameOffset))) } } atPos(start) { loop() } @@ -1914,8 +1915,8 @@ self => /** ImportSelectors ::= `{' {ImportSelector `,'} (ImportSelector | `_') `}' */ - def importSelectors(): List[(Name, Name)] = { - val names = new ListBuffer[(Name, Name)] + def importSelectors(): List[ImportSelector] = { + val names = new ListBuffer[ImportSelector] accept(LBRACE) var isLast = importSelector(names) while (!isLast && in.token == COMMA) { @@ -1928,19 +1929,31 @@ self => /** ImportSelector ::= Id [`=>' Id | `=>' `_'] */ - def importSelector(names: ListBuffer[(Name, Name)]): Boolean = + def importSelector(names: ListBuffer[ImportSelector]): Boolean = if (in.token == USCORE) { - in.nextToken(); names += ((nme.WILDCARD, null)); true + val uscoreOffset = in.offset + in.nextToken(); names += ImportSelector(nme.WILDCARD, uscoreOffset, null, -1); true } else { + val nameOffset = in.offset val name = ident() - names += (( - name, + + val (name1, name1Offset) = if (in.token == ARROW) { in.nextToken() - if (in.token == USCORE) { in.nextToken(); nme.WILDCARD } else ident() + if (in.token == USCORE) { + val uscoreOffset = in.offset + in.nextToken(); + (nme.WILDCARD, uscoreOffset) + } else { + val renameOffset = in.offset + val rename = ident() + (rename, renameOffset) + } } else { - name - })) + (name, nameOffset) + } + + names += ImportSelector(name, nameOffset, name1, name1Offset) false } diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala index 1406416f5f..5f5db8015a 100644 --- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala @@ -630,7 +630,7 @@ trait JavaParsers extends JavaScanners { def importCompanionObject(cdef: ClassDef): Tree = atPos(cdef.pos) { - Import(Ident(cdef.name.toTermName), List((nme.WILDCARD, null))) + Import(Ident(cdef.name.toTermName), List(ImportSelector(nme.WILDCARD, -1, null, -1))) } // Importing the companion object members cannot be done uncritically: see @@ -661,21 +661,24 @@ trait JavaParsers extends JavaScanners { accept(IMPORT) val pos = in.currentPos val buf = new ListBuffer[Name] - def collectIdents() { + def collectIdents() : Int = { if (in.token == ASTERISK) { + val starOffset = in.pos in.nextToken buf += nme.WILDCARD + starOffset } else { + val nameOffset = in.pos buf += ident() if (in.token == DOT) { in.nextToken collectIdents() - } + } else nameOffset } } if (in.token == STATIC) in.nextToken else buf += nme.ROOTPKG - collectIdents() + val lastnameOffset = collectIdents() accept(SEMI) val names = buf.toList if (names.length < 2) { @@ -686,8 +689,8 @@ trait JavaParsers extends JavaScanners { val lastname = names.last List { atPos(pos) { - if (lastname == nme.WILDCARD) Import(qual, List((lastname, null))) - else Import(qual, List((lastname, lastname))) + if (lastname == nme.WILDCARD) Import(qual, List(ImportSelector(lastname, lastnameOffset, null, -1))) + else Import(qual, List(ImportSelector(lastname, lastnameOffset, lastname, lastnameOffset))) } } } diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala index 3ef8f38a9f..a5521c7eb9 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala @@ -265,7 +265,7 @@ abstract class Pickler extends SubComponent { case Import(expr, selectors) => putTree(expr) - for ((from,to) <- selectors) { + for (ImportSelector(from, _, to, _) <- selectors) { putEntry(from) putEntry(to) } @@ -714,7 +714,7 @@ abstract class Pickler extends SubComponent { writeRef(tree.tpe) writeRef(tree.symbol) writeRef(expr) - for ((from, to) <- selectors) { + for (ImportSelector(from, _, to, _) <- selectors) { writeRef(from) writeRef(to) } diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala index 9dba9f9925..2b4d7d33de 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala @@ -545,7 +545,7 @@ abstract class UnPickler { val selectors = until(end, () => { val from = readNameRef() val to = readNameRef() - (from, to) + ImportSelector(from, -1, to, -1) }) (Import(expr, selectors). setSymbol(symbol). diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index fcb4833df7..058a731670 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -63,7 +63,7 @@ trait Contexts { self: Analyzer => assert(pkg ne null) val qual = gen.mkAttributedStableRef(pkg) sc = sc.makeNewImport( - Import(qual, List((nme.WILDCARD, null))) + Import(qual, List(ImportSelector(nme.WILDCARD, -1, null, -1))) .setSymbol(NoSymbol.newImport(NoPosition).setFlag(SYNTHETIC).setInfo(ImportType(qual))) .setType(NoType)) sc.depth += 1 @@ -465,10 +465,10 @@ trait Contexts { self: Analyzer => private def collectImplicitImports(imp: ImportInfo): List[ImplicitInfo] = { val pre = imp.qual.tpe - def collect(sels: List[(Name, Name)]): List[ImplicitInfo] = sels match { + def collect(sels: List[ImportSelector]): List[ImplicitInfo] = sels match { case List() => List() - case List((nme.WILDCARD, _)) => collectImplicits(pre.implicitMembers, pre) - case (from, to) :: sels1 => + case List(ImportSelector(nme.WILDCARD, _, _, _)) => collectImplicits(pre.implicitMembers, pre) + case ImportSelector(from, _, to, _) :: sels1 => var impls = collect(sels1) filter (info => info.name != from) if (to != nme.WILDCARD) { val sym = imp.importedSymbol(to) @@ -550,7 +550,7 @@ trait Contexts { self: Analyzer => /** Is name imported explicitly, not via wildcard? */ def isExplicitImport(name: Name): Boolean = - tree.selectors exists (_._2 == name.toTermName) + tree.selectors exists (_.rename == name.toTermName) /** The symbol with name <code>name</code> imported from import clause * <code>tree</code>. @@ -560,15 +560,15 @@ trait Contexts { self: Analyzer => var renamed = false var selectors = tree.selectors while (selectors != Nil && result == NoSymbol) { - if (selectors.head._1 != nme.WILDCARD) - notifyImport(name, qual.tpe, selectors.head._1, selectors.head._2) + if (selectors.head.name != nme.WILDCARD) + notifyImport(name, qual.tpe, selectors.head.name, selectors.head.rename) - if (selectors.head._2 == name.toTermName) + if (selectors.head.rename == name.toTermName) result = qual.tpe.member( - if (name.isTypeName) selectors.head._1.toTypeName else selectors.head._1) - else if (selectors.head._1 == name.toTermName) + if (name.isTypeName) selectors.head.name.toTypeName else selectors.head.name) + else if (selectors.head.name == name.toTermName) renamed = true - else if (selectors.head._1 == nme.WILDCARD && !renamed) + else if (selectors.head.name == nme.WILDCARD && !renamed) result = qual.tpe.member(name) selectors = selectors.tail } @@ -578,10 +578,10 @@ trait Contexts { self: Analyzer => def allImportedSymbols: List[Symbol] = qual.tpe.members flatMap (transformImport(tree.selectors, _)) - private def transformImport(selectors: List[(Name, Name)], sym: Symbol): List[Symbol] = selectors match { + private def transformImport(selectors: List[ImportSelector], sym: Symbol): List[Symbol] = selectors match { case List() => List() - case List((nme.WILDCARD, _)) => List(sym) - case (from, to) :: _ if (from == sym.name) => + case List(ImportSelector(nme.WILDCARD, _, _, _)) => List(sym) + case ImportSelector(from, _, to, _) :: _ if (from == sym.name) => if (to == nme.WILDCARD) List() else { val sym1 = sym.cloneSymbol; sym1.name = to; List(sym1) } case _ :: rest => transformImport(rest, sym) diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 9128b4ed29..f31394407e 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -1182,17 +1182,17 @@ trait Namers { self: Analyzer => } true } - def checkSelectors(selectors: List[(Name, Name)]): Unit = selectors match { - case (from, to) :: rest => + def checkSelectors(selectors: List[ImportSelector]): Unit = selectors match { + case ImportSelector(from, _, to, _) :: rest => if (from != nme.WILDCARD && base != ErrorType) { if (base.member(from) == NoSymbol && base.member(from.toTypeName) == NoSymbol) context.error(tree.pos, from.decode + " is not a member of " + expr); if (checkNotRedundant(tree.pos, from, to)) checkNotRedundant(tree.pos, from.toTypeName, to.toTypeName) } - if (from != nme.WILDCARD && (rest.exists (sel => sel._1 == from))) + if (from != nme.WILDCARD && (rest.exists (sel => sel.name == from))) context.error(tree.pos, from.decode + " is renamed twice"); - if ((to ne null) && to != nme.WILDCARD && (rest exists (sel => sel._2 == to))) + if ((to ne null) && to != nme.WILDCARD && (rest exists (sel => sel.rename == to))) context.error(tree.pos, to.decode + " appears twice as a target of a renaming"); checkSelectors(rest) case Nil => diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index df17dcc416..68f6009127 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1830,8 +1830,9 @@ trait Typers { self: Analyzer => if (imp0 ne null) { context = context.makeNewImport(imp0) imp0.symbol.initialize - } - EmptyTree + imp0 + } else + EmptyTree case _ => if (localTarget && !includesTargetPos(stat)) { stat |