diff --git a/buildfile/src/main/scala/sbt/internal/parser/SbtParser.scala b/buildfile/src/main/scala/sbt/internal/parser/SbtParser.scala index d77ea69d2..b3e0de9c9 100644 --- a/buildfile/src/main/scala/sbt/internal/parser/SbtParser.scala +++ b/buildfile/src/main/scala/sbt/internal/parser/SbtParser.scala @@ -283,6 +283,8 @@ private[sbt] case class SbtParser(path: VirtualFileRef, lines: Seq[String]) imports.map { tree => val pos = tree.sourcePos val content = String(pos.source.content.slice(pos.start, pos.end)).trim - (content, tree.sourcePos.line) + // Dotty splits `import a, b` into separate Import trees; subsequent ones lack `import` + val importStr = if content.startsWith("import ") then content else s"import $content" + (importStr, tree.sourcePos.line) } end SbtParser diff --git a/buildfile/src/test/scala/sbt/internal/SbtParserTest.scala b/buildfile/src/test/scala/sbt/internal/SbtParserTest.scala index 19b9e6259..fbb677bc1 100644 --- a/buildfile/src/test/scala/sbt/internal/SbtParserTest.scala +++ b/buildfile/src/test/scala/sbt/internal/SbtParserTest.scala @@ -37,6 +37,68 @@ lazy val foo = project .settings(x := y)""" -> LineRange(7, 8))) } + test("comma separated imports") { + val ref = VirtualFileRef.of("vfile") + val code = """import scala.util, util.Random + +def f = Random.nextInt() +""" + val p = SbtParser(ref, code.linesIterator.toList) + assert(p.imports.size == 2) + assert(p.imports(0)._1 == "import scala.util") + assert(p.imports(1)._1 == "import util.Random") + assert(p.settings.size == 1) + } + + test("comma separated imports with three entries") { + val ref = VirtualFileRef.of("vfile") + val code = """import scala.util, util.Random, util.Properties + +val x = 1 +""" + val p = SbtParser(ref, code.linesIterator.toList) + assert(p.imports.size == 3) + assert(p.imports(0)._1 == "import scala.util") + assert(p.imports(1)._1 == "import util.Random") + assert(p.imports(2)._1 == "import util.Properties") + } + + test("comma separated imports with wildcard") { + val ref = VirtualFileRef.of("vfile") + val code = """import scala.util, util.* + +val x = 1 +""" + val p = SbtParser(ref, code.linesIterator.toList) + assert(p.imports.size == 2) + assert(p.imports(0)._1 == "import scala.util") + assert(p.imports(1)._1 == "import util.*") + } + + test("comma separated imports with rename") { + val ref = VirtualFileRef.of("vfile") + val code = """import scala.util, util.{Random => Rng} + +val x = 1 +""" + val p = SbtParser(ref, code.linesIterator.toList) + assert(p.imports.size == 2) + assert(p.imports(0)._1 == "import scala.util") + assert(p.imports(1)._1 == "import util.{Random => Rng}") + } + + test("comma separated imports with multiple selectors") { + val ref = VirtualFileRef.of("vfile") + val code = """import scala.util, util.{Random, Properties} + +val x = 1 +""" + val p = SbtParser(ref, code.linesIterator.toList) + assert(p.imports.size == 2) + assert(p.imports(0)._1 == "import scala.util") + assert(p.imports(1)._1 == "import util.{Random, Properties}") + } + test("isIdentifier") { assert(SbtParser.isIdentifier("1a") == false) } diff --git a/sbt-app/src/sbt-test/project/comma-separated-import/build.sbt b/sbt-app/src/sbt-test/project/comma-separated-import/build.sbt new file mode 100644 index 000000000..19ee07032 --- /dev/null +++ b/sbt-app/src/sbt-test/project/comma-separated-import/build.sbt @@ -0,0 +1,11 @@ +import scala.util, util.Random +import scala.collection.mutable, mutable.{ArrayBuffer, ListBuffer} +import scala.concurrent, concurrent.* + +val check = taskKey[Unit]("check comma-separated import works") +check := { + val _ = Random.nextInt() + val _ = ArrayBuffer(1, 2, 3) + val _ = ListBuffer("a", "b") + val _ = Future.successful(1) +} diff --git a/sbt-app/src/sbt-test/project/comma-separated-import/test b/sbt-app/src/sbt-test/project/comma-separated-import/test new file mode 100644 index 000000000..34c0da413 --- /dev/null +++ b/sbt-app/src/sbt-test/project/comma-separated-import/test @@ -0,0 +1,2 @@ +# Verify that comma-separated imports work in build.sbt +> check