diff --git a/dependency/src/main/scala-2/dependency/literal/LiteralMacros.scala b/dependency/src/main/scala-2/dependency/literal/LiteralMacros.scala index 8fdf89c..0509425 100644 --- a/dependency/src/main/scala-2/dependency/literal/LiteralMacros.scala +++ b/dependency/src/main/scala-2/dependency/literal/LiteralMacros.scala @@ -39,38 +39,34 @@ abstract class LiteralMacros(val c: whitebox.Context) { helper(0) } - private def insertExpr(str: String, idLen: Int, insert: c.Tree, indices: List[Int]): c.Tree = + private def insertExpr(str: String, indices: List[(Int, Int, c.Expr[Any])]): c.Tree = indices match { case Nil => q"$str" - case idx :: tail => + case (idx, idLen, insert) :: tail => val (prefix, suffix) = str.splitAt(idx) - val prefixExpr = insertExpr(prefix, idLen, insert, tail) + val prefixExpr = insertExpr(prefix, tail) q"$prefixExpr + $insert + ${suffix.substring(idLen)}" } protected final type Mappings = Seq[(String, c.Tree)] protected def applyMappings(str: String, mappings: Mappings): c.Expr[String] = { - val matchOpt = mappings + val substitutions = mappings .iterator .zipWithIndex - .map { + .flatMap { case ((id, expr), i) => - val idx = str.indexOf(id) - (id, expr, i, idx) + val indices0 = indices(str, id) + indices0.map(idx => (idx, id.length, c.Expr(expr))) } - .find(_._4 >= 0) - matchOpt match { - case None => c.Expr(q"$str") - case Some((id, expr, i, idx)) => - val indices0 = indices(str, id) - val tree = insertExpr(str, id.length, expr, indices0.reverse) - c.Expr(tree) - } + .toList + .sortBy(-_._1) + val tree = insertExpr(str, substitutions) + c.Expr(tree) } def mappings(args: Seq[c.Tree]): Mappings = args.map(arg => (UUID.randomUUID().toString.filter(_ != '-'), arg)) def input(inputs: Seq[String], mappings: Mappings): String = (inputs.zip(mappings).flatMap { case (s, (id, _)) => Seq(s, id) } ++ inputs.drop(mappings.length)).mkString -} \ No newline at end of file +} diff --git a/dependency/src/main/scala-3/dependency/literal/Mappings.scala b/dependency/src/main/scala-3/dependency/literal/Mappings.scala index 75d0f16..549a2bb 100644 --- a/dependency/src/main/scala-3/dependency/literal/Mappings.scala +++ b/dependency/src/main/scala-3/dependency/literal/Mappings.scala @@ -20,22 +20,27 @@ private[literal] final case class Mappings(mappings: List[(String, QExpr[String] helper(0) } - private def insertExpr(str: String, idLen: Int, insert: QExpr[String], indices: List[Int])(using Quotes): QExpr[String] = - indices match { + private def insertExpr(str: String, substitutions: List[(Int, Int, QExpr[String])])(using Quotes): QExpr[String] = + substitutions match { case Nil => QExpr(str) - case idx :: tail => + case (idx, idLen, insert) :: tail => val (prefix, suffix) = str.splitAt(idx) - val prefixExpr = insertExpr(prefix, idLen, insert, tail) + val prefixExpr = insertExpr(prefix, tail) '{$prefixExpr + $insert + ${QExpr(suffix.substring(idLen))}} } - def Expr(str: String)(using Quotes): QExpr[String] = - mappings match { - case Nil => QExpr(str) - case (id, expr) :: tail => - val indices0 = indices(str, id) - insertExpr(str, id.length, expr, indices0) - } + def Expr(str: String)(using Quotes): QExpr[String] = { + + val substitutions = mappings + .flatMap { + case (id, expr) => + val indices0 = indices(str, id) + indices0.map(idx => (idx, id.length, expr)) + } + .sortBy(-_._1) + + insertExpr(str, substitutions) + } def stringOption(opt: Option[String])(using Quotes): QExpr[Option[String]] = opt match { diff --git a/dependency/src/test/scala/dependency/LiteralTests.scala b/dependency/src/test/scala/dependency/LiteralTests.scala index 9c67465..8f691fb 100644 --- a/dependency/src/test/scala/dependency/LiteralTests.scala +++ b/dependency/src/test/scala/dependency/LiteralTests.scala @@ -74,6 +74,29 @@ class LiteralTests extends munit.FunSuite { val expected = Dependency("org", "name", "1.2").copy( exclude = CovariantSet(Module("fu", "ba")) ) + expect(dep == expected) + } + + test("dependency interpolation") { + val org = "org.org" + val name = "name-name" + val version = "123-version" + val dep = dep"$org::$name:$version" + val expected = Dependency(org, name, version) + expect(dep.name == expected.name) + expect(dep.organization == expected.organization) + expect(dep.version == expected.version) + } + + test("other dependency interpolation") { + val org = "org.org" + val name = "name" + val version = "123-version" + val dep = dep"$org::$name-$name:$version" + val expected = Dependency(org, s"$name-$name", version) + expect(dep.name == expected.name) + expect(dep.organization == expected.organization) + expect(dep.version == expected.version) } }