Skip to content

Commit

Permalink
Merge pull request #9582 from smarter/wildcard-import
Browse files Browse the repository at this point in the history
Support Scala 3 wildcard and renaming imports under -Xsource:3
  • Loading branch information
lrytz committed Apr 20, 2021
2 parents 87b0c70 + c719da7 commit 1c77d74
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 17 deletions.
45 changes: 28 additions & 17 deletions src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
Expand Up @@ -2570,19 +2570,27 @@ self =>
def loop(expr: Tree): Tree = {
expr setPos expr.pos.makeTransparent
val selectors: List[ImportSelector] = in.token match {
case USCORE => List(wildImportSelector()) // import foo.bar._;
case LBRACE => importSelectors() // import foo.bar.{ x, y, z }
case _ =>
val nameOffset = in.offset
val name = ident()
if (in.token == DOT) {
// import foo.bar.ident.<unknown> and so create a select node and recurse.
val t = atPos(start, if (name == nme.ERROR) in.offset else nameOffset)(Select(expr, name))
in.nextToken()
return loop(t)
case USCORE =>
List(wildImportSelector()) // import foo.bar._
case IDENTIFIER if currentRun.isScala3 && in.name == raw.STAR =>
List(wildImportSelector()) // import foo.bar.*
case LBRACE =>
importSelectors() // import foo.bar.{ x, y, z }
case _ =>
if (settings.isScala3 && lookingAhead { isRawIdent && in.name == nme.as })
List(importSelector()) // import foo.bar as baz
else {
val nameOffset = in.offset
val name = ident()
if (in.token == DOT) {
// import foo.bar.ident.<unknown> and so create a select node and recurse.
val t = atPos(start, if (name == nme.ERROR) in.offset else nameOffset)(Select(expr, name))
in.nextToken()
return loop(t)
}
// import foo.bar.Baz;
else List(makeImportSelector(name, nameOffset))
}
// import foo.bar.Baz;
else List(makeImportSelector(name, nameOffset))
}
// reaching here means we're done walking.
atPos(start)(Import(expr, selectors))
Expand Down Expand Up @@ -2625,17 +2633,20 @@ self =>
val bbq = in.token == BACKQUOTED_IDENT
val name = wildcardOrIdent()
var renameOffset = -1
val rename = in.token match {
case ARROW =>

val rename =
if (in.token == ARROW || (settings.isScala3 && isRawIdent && in.name == nme.as)) {
in.nextToken()
renameOffset = in.offset
if (name == nme.WILDCARD && !bbq) syntaxError(renameOffset, "Wildcard import cannot be renamed")
wildcardOrIdent()
case _ if name == nme.WILDCARD && !bbq => null
case _ =>
}
else if (name == nme.WILDCARD && !bbq) null
else {
renameOffset = start
name
}
}

ImportSelector(name, start, rename, renameOffset)
}

Expand Down
3 changes: 3 additions & 0 deletions src/reflect/scala/reflect/internal/StdNames.scala
Expand Up @@ -658,6 +658,9 @@ trait StdNames {
val long2Long: NameType = nameType("long2Long")
val boolean2Boolean: NameType = nameType("boolean2Boolean")

// Scala 3 import syntax
val as: NameType = nameType("as")

// Compiler utilized names

val AnnotatedType: NameType = nameType("AnnotatedType")
Expand Down
4 changes: 4 additions & 0 deletions test/files/neg/import-future.check
@@ -0,0 +1,4 @@
import-future.scala:15: error: not found: value unrelated
unrelated(1) // error
^
1 error
27 changes: 27 additions & 0 deletions test/files/neg/import-future.scala
@@ -0,0 +1,27 @@
// scalac: -Xsource:3
//

class D {
def *(y: Int): Int = y
def unrelated(y: Int): Int = y
}

object Test {
val d = new D

def one: Int = {
import d.`*`

unrelated(1) // error

*(1)
}

def two: Int = {
import d.*

unrelated(1)

*(1)
}
}
25 changes: 25 additions & 0 deletions test/files/pos/import-future.scala
@@ -0,0 +1,25 @@
// scalac: -Xsource:3
//

import java.io as jio
import scala.{collection as c}

import c.mutable as mut
import mut.ArrayBuffer as Buf

object O {
val x: jio.IOException = ???
val y = Buf(1, 2, 3)

type OString = String
def foo22(x: Int) = x
}

class C {
import O.{ foo22 as foo, OString as OS }
println(foo(22))
val s: OS = ""

import mut.*
val ab = ArrayBuffer(1)
}

0 comments on commit 1c77d74

Please sign in to comment.