From 7c1a32db088ccbaab2aa29aed279e2bfdead45f0 Mon Sep 17 00:00:00 2001 From: jxnu-liguobin Date: Thu, 29 Feb 2024 14:47:06 +0800 Subject: [PATCH 1/9] https://github.com/lightbend-labs/scala-logging/issues/354 After wrapping varargs, the user code fails to compile. In Scala 2, there were no inline parameters, and the subtype of args was obtained during compilation. However, this approach may not always be accurate. Regarding https://github.com/lightbend-labs/scala-logging/issues/191 There is an issue with obtaining inline parameters in Scala 3. To address this, we recursively obtain the actual value of inline parameters. This necessitates the ongoing use of inlining in the parameters of the wrapper function. For instance: ```scala class LogWrapper(val underlying: Logger) { inline def info(message: String, inline args: AnyRef*): Unit = underlying.info(message, args: _*) } ``` This ensures compatibility and accurate handling of inline parameters in both Scala 2 and Scala 3. --- .../typesafe/scalalogging/LoggerMacro.scala | 10 ++++- .../typesafe/scalalogging/LoggerMacro.scala | 19 ++++---- .../scalalogging/Scala2LoggerSpec.scala | 45 +++++++++++++++++++ .../scalalogging/Scala3LoggerSpec.scala | 44 ++++++++++++++++++ .../typesafe/scalalogging/LoggerSpec.scala | 8 ++++ 5 files changed, 115 insertions(+), 11 deletions(-) create mode 100644 src/test/scala-2/com/typesafe/scalalogging/Scala2LoggerSpec.scala create mode 100644 src/test/scala-3/com/typesafe/scalalogging/Scala3LoggerSpec.scala diff --git a/src/main/scala-2/com/typesafe/scalalogging/LoggerMacro.scala b/src/main/scala-2/com/typesafe/scalalogging/LoggerMacro.scala index dbef6b28..0a7cb818 100644 --- a/src/main/scala-2/com/typesafe/scalalogging/LoggerMacro.scala +++ b/src/main/scala-2/com/typesafe/scalalogging/LoggerMacro.scala @@ -295,7 +295,15 @@ private[scalalogging] object LoggerMacro { private def formatArgs(c: LoggerContext)(args: c.Expr[Any]*) = { import c.universe._ args.map { arg => - c.Expr[AnyRef](if (arg.tree.tpe <:< weakTypeOf[AnyRef]) q"$arg: _root_.scala.AnyRef" else q"$arg.asInstanceOf[_root_.scala.AnyRef]") + // If arg is a varargs, it is also a AnyRef and we need to check the subtree. + val argument = arg.tree.children.map(_.tpe) match { + case head :: next :: Nil if head <:< weakTypeOf[scala.collection.Seq[_]] && next <:< weakTypeOf[AnyRef] => + q"$arg" + case _ => + if (arg.tree.tpe <:< weakTypeOf[AnyRef]) q"$arg: _root_.scala.AnyRef" + else q"$arg.asInstanceOf[_root_.scala.AnyRef]" + } + c.Expr[AnyRef](argument) } } } diff --git a/src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala b/src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala index a52ff055..368c42e7 100644 --- a/src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala +++ b/src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala @@ -264,19 +264,18 @@ private[scalalogging] object LoggerMacro { def formatArgs(args: Expr[Seq[Any]])(using q: Quotes): Seq[Expr[AnyRef]] = { import quotes.reflect.* import util.* - - args.asTerm match { - case p@Inlined(_, _, Typed(Repeated(v, _),_)) => - v.map{ - case t if t.tpe <:< TypeRepr.of[AnyRef] => t.asExprOf[AnyRef] - case t => '{${t.asExpr}.asInstanceOf[AnyRef]} - } - case Repeated(v, _) => - v.map{ + // we recursively obtain the actual value of inline parameters + def rec(tree: Term): Option[Seq[Expr[AnyRef]]] = tree match { + case Repeated(elems, _) => Some( + elems.map { case t if t.tpe <:< TypeRepr.of[AnyRef] => t.asExprOf[AnyRef] case t => '{${t.asExpr}.asInstanceOf[AnyRef]} } - case _ => Seq.empty + ) + case Typed(e, _) => rec(e) + case Inlined(_, Nil, e) => rec(e) + case _ => None } + rec(args.asTerm).getOrElse(Seq.empty) } } diff --git a/src/test/scala-2/com/typesafe/scalalogging/Scala2LoggerSpec.scala b/src/test/scala-2/com/typesafe/scalalogging/Scala2LoggerSpec.scala new file mode 100644 index 00000000..3486f5d7 --- /dev/null +++ b/src/test/scala-2/com/typesafe/scalalogging/Scala2LoggerSpec.scala @@ -0,0 +1,45 @@ +package com.typesafe.scalalogging + +import org.mockito.Mockito._ +import org.scalatest.matchers.should.Matchers +import org.scalatest.wordspec.AnyWordSpec +import org.scalatestplus.mockito.MockitoSugar +import org.slf4j.{ Logger => Underlying } + +class Scala2LoggerSpec extends AnyWordSpec with Matchers with Varargs with MockitoSugar { + + // Info + "Calling info with an interpolated message, only scala 2" should { + "fix Varargs compilation error issue 354 only scala 2" in { + val f = fixture(_.isInfoEnabled, isEnabled = true) + import f._ + class LogWrapper(val underlying: Logger) { + def info(message: String, args: AnyRef*): Unit = underlying.info(message, args: _*) + } + val logWrapper = new LogWrapper(logger) + logWrapper.info("""Hello {}""", arg5ref) + verify(underlying).info("""Hello {}""", forceVarargs(arg5ref): _*) + } + } + + private def fixture(p: Underlying => Boolean, isEnabled: Boolean) = new LoggerF(p, isEnabled) + + private class LoggerF(p: Underlying => Boolean, isEnabled: Boolean) { + val msg = "msg" + val cause = new RuntimeException("cause") + val arg1 = "arg1" + val arg2: Integer = Integer.valueOf(1) + val arg3 = "arg3" + val arg4 = 4 + val arg4ref: AnyRef = arg4.asInstanceOf[AnyRef] + val arg5 = true + val arg5ref: AnyRef = arg5.asInstanceOf[AnyRef] + val arg6 = 6L + val arg6ref: AnyRef = arg6.asInstanceOf[AnyRef] + val arg7 = new Throwable + val arg7ref: AnyRef = arg7.asInstanceOf[AnyRef] + val underlying: Underlying = mock[org.slf4j.Logger] + when(p(underlying)).thenReturn(isEnabled) + val logger: Logger = Logger(underlying) + } +} diff --git a/src/test/scala-3/com/typesafe/scalalogging/Scala3LoggerSpec.scala b/src/test/scala-3/com/typesafe/scalalogging/Scala3LoggerSpec.scala new file mode 100644 index 00000000..81f55b63 --- /dev/null +++ b/src/test/scala-3/com/typesafe/scalalogging/Scala3LoggerSpec.scala @@ -0,0 +1,44 @@ +package com.typesafe.scalalogging + +import org.mockito.Mockito._ +import org.scalatest.matchers.should.Matchers +import org.scalatest.wordspec.AnyWordSpec +import org.scalatestplus.mockito.MockitoSugar +import org.slf4j.{Logger => Underlying} + +class Scala3LoggerSpec extends AnyWordSpec with Matchers with Varargs with MockitoSugar { + + // Info + "Calling info with an interpolated message, only scala 3" should { + "fix Varargs compilation error issue 354 only scala 3" in { + val f = fixture(_.isInfoEnabled, isEnabled = true) + import f._ + class LogWrapper(val underlying: Logger) { + inline def info(message: String, inline args: AnyRef*): Unit = underlying.info(message, args: _*) + } + val logWrapper = new LogWrapper(logger) + logWrapper.info("""Hello {}""", arg5ref) + verify(underlying).info("""Hello {}""", arg5ref) + } + } + + private def fixture(p: Underlying => Boolean, isEnabled: Boolean) = new LoggerF(p, isEnabled) + private class LoggerF(p: Underlying => Boolean, isEnabled: Boolean) { + val msg = "msg" + val cause = new RuntimeException("cause") + val arg1 = "arg1" + val arg2: Integer = Integer.valueOf(1) + val arg3 = "arg3" + val arg4 = 4 + val arg4ref: AnyRef = arg4.asInstanceOf[AnyRef] + val arg5 = true + val arg5ref: AnyRef = arg5.asInstanceOf[AnyRef] + val arg6 = 6L + val arg6ref: AnyRef = arg6.asInstanceOf[AnyRef] + val arg7 = new Throwable + val arg7ref: AnyRef = arg7.asInstanceOf[AnyRef] + val underlying: Underlying = mock[org.slf4j.Logger] + when(p(underlying)).thenReturn(isEnabled) + val logger: Logger = Logger(underlying) + } +} diff --git a/src/test/scala/com/typesafe/scalalogging/LoggerSpec.scala b/src/test/scala/com/typesafe/scalalogging/LoggerSpec.scala index 0082c6d8..ca8695a1 100644 --- a/src/test/scala/com/typesafe/scalalogging/LoggerSpec.scala +++ b/src/test/scala/com/typesafe/scalalogging/LoggerSpec.scala @@ -207,6 +207,14 @@ class LoggerSpec extends AnyWordSpec with Matchers with Varargs with MockitoSuga logger.info(s"msg $arg1 $arg2") verify(underlying).info("msg {} {}", forceVarargs(arg1, arg2): _*) } + + "fix Varargs compilation error, issue 191" in { + val f = fixture(_.isInfoEnabled, isEnabled = true) + import f._ + val message = "Hello" + logger.info(s"Message with id=$message, submittedAt=$message will be dropped.") + verify(underlying).info("""Message with id={}, submittedAt={} will be dropped.""", forceVarargs(message, message): _*) + } } "Calling info with a message and cause" should { From 1cbde297e3e93cab2ebfa913dbb8c64d125b5064 Mon Sep 17 00:00:00 2001 From: jxnu-liguobin Date: Fri, 1 Mar 2024 08:45:45 +0800 Subject: [PATCH 2/9] Adding case to capture Blocks --- src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala b/src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala index 368c42e7..1e931b7c 100644 --- a/src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala +++ b/src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala @@ -272,6 +272,7 @@ private[scalalogging] object LoggerMacro { case t => '{${t.asExpr}.asInstanceOf[AnyRef]} } ) + case Block(Nil, e) => rec(e) case Typed(e, _) => rec(e) case Inlined(_, Nil, e) => rec(e) case _ => None From ac2ed10210d85ffeeb192aa5c7f671f6621c61fc Mon Sep 17 00:00:00 2001 From: jxnu-liguobin Date: Fri, 1 Mar 2024 17:42:49 +0800 Subject: [PATCH 3/9] Fix for varargs --- .../typesafe/scalalogging/LoggerMacro.scala | 19 ++++++++++++------- .../scalalogging/Scala3LoggerSpec.scala | 7 +++++++ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala b/src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala index 1e931b7c..abf943e6 100644 --- a/src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala +++ b/src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala @@ -265,17 +265,22 @@ private[scalalogging] object LoggerMacro { import quotes.reflect.* import util.* // we recursively obtain the actual value of inline parameters + def map(term:Term) = { + term match { + case t if t.tpe <:< TypeRepr.of[AnyRef] => t.asExprOf[AnyRef] + case t => '{${t.asExpr}.asInstanceOf[AnyRef]} + } + } def rec(tree: Term): Option[Seq[Expr[AnyRef]]] = tree match { - case Repeated(elems, _) => Some( - elems.map { - case t if t.tpe <:< TypeRepr.of[AnyRef] => t.asExprOf[AnyRef] - case t => '{${t.asExpr}.asInstanceOf[AnyRef]} - } - ) + case Repeated(elems, _) => Some(elems.map(map)) case Block(Nil, e) => rec(e) case Typed(e, _) => rec(e) case Inlined(_, Nil, e) => rec(e) - case _ => None + // Seq():_*, List():_* e.g., + case Apply(TypeApply(Select(Ident(_), "apply"), _), List(Typed(Repeated(elems, _),_))) => + Some(elems.map(map)) + case _ => + None } rec(args.asTerm).getOrElse(Seq.empty) } diff --git a/src/test/scala-3/com/typesafe/scalalogging/Scala3LoggerSpec.scala b/src/test/scala-3/com/typesafe/scalalogging/Scala3LoggerSpec.scala index 81f55b63..53108d5e 100644 --- a/src/test/scala-3/com/typesafe/scalalogging/Scala3LoggerSpec.scala +++ b/src/test/scala-3/com/typesafe/scalalogging/Scala3LoggerSpec.scala @@ -20,6 +20,13 @@ class Scala3LoggerSpec extends AnyWordSpec with Matchers with Varargs with Mocki logWrapper.info("""Hello {}""", arg5ref) verify(underlying).info("""Hello {}""", arg5ref) } + + "work when passing a Seq as repeated arguments" in { + val f = fixture(_.isInfoEnabled, isEnabled = true) + import f._ + logger.info("""Hello {}""", Seq(arg5ref)*) + verify(underlying).info("""Hello {}""", arg5ref) + } } private def fixture(p: Underlying => Boolean, isEnabled: Boolean) = new LoggerF(p, isEnabled) From 14db4cbbc18090f0132389203603e1c866433ecc Mon Sep 17 00:00:00 2001 From: jxnu-liguobin Date: Fri, 1 Mar 2024 17:52:11 +0800 Subject: [PATCH 4/9] Fix for varargs --- .../scala-3/com/typesafe/scalalogging/LoggerMacro.scala | 2 ++ .../com/typesafe/scalalogging/Scala3LoggerSpec.scala | 9 ++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala b/src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala index abf943e6..f2e38a77 100644 --- a/src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala +++ b/src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala @@ -279,6 +279,8 @@ private[scalalogging] object LoggerMacro { // Seq():_*, List():_* e.g., case Apply(TypeApply(Select(Ident(_), "apply"), _), List(Typed(Repeated(elems, _),_))) => Some(elems.map(map)) + // forceVarargs(1,2):_* + case Apply(TypeApply(_, _), List(Typed(Repeated(elems, _),_))) => Some(elems.map(map)) case _ => None } diff --git a/src/test/scala-3/com/typesafe/scalalogging/Scala3LoggerSpec.scala b/src/test/scala-3/com/typesafe/scalalogging/Scala3LoggerSpec.scala index 53108d5e..9cb391da 100644 --- a/src/test/scala-3/com/typesafe/scalalogging/Scala3LoggerSpec.scala +++ b/src/test/scala-3/com/typesafe/scalalogging/Scala3LoggerSpec.scala @@ -24,7 +24,14 @@ class Scala3LoggerSpec extends AnyWordSpec with Matchers with Varargs with Mocki "work when passing a Seq as repeated arguments" in { val f = fixture(_.isInfoEnabled, isEnabled = true) import f._ - logger.info("""Hello {}""", Seq(arg5ref)*) + logger.info("""Hello {}""", Seq(arg5ref):_*) + verify(underlying).info("""Hello {}""", arg5ref) + } + + "work when passing a fun as repeated arguments" in { + val f = fixture(_.isInfoEnabled, isEnabled = true) + import f._ + logger.info("""Hello {}""", forceVarargs(arg5ref):_*) verify(underlying).info("""Hello {}""", arg5ref) } } From a6e2c8b92f4542688cf88276a91156e375ce728b Mon Sep 17 00:00:00 2001 From: jxnu-liguobin Date: Fri, 1 Mar 2024 18:32:58 +0800 Subject: [PATCH 5/9] Fix for varargs --- .../scala-3/com/typesafe/scalalogging/LoggerMacro.scala | 9 +++++---- .../com/typesafe/scalalogging/Scala3LoggerSpec.scala | 8 ++++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala b/src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala index f2e38a77..4d3bf26d 100644 --- a/src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala +++ b/src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala @@ -276,11 +276,12 @@ private[scalalogging] object LoggerMacro { case Block(Nil, e) => rec(e) case Typed(e, _) => rec(e) case Inlined(_, Nil, e) => rec(e) - // Seq():_*, List():_* e.g., - case Apply(TypeApply(Select(Ident(_), "apply"), _), List(Typed(Repeated(elems, _),_))) => + // Seq():_*, List():_* , forceVarargs(1,2):_*e.g., + case Apply(TypeApply(_, _), List(Typed(Repeated(elems, _),_))) => Some(elems.map(map)) - // forceVarargs(1,2):_* - case Apply(TypeApply(_, _), List(Typed(Repeated(elems, _),_))) => Some(elems.map(map)) + case Ident(name) => + // todo + None case _ => None } diff --git a/src/test/scala-3/com/typesafe/scalalogging/Scala3LoggerSpec.scala b/src/test/scala-3/com/typesafe/scalalogging/Scala3LoggerSpec.scala index 9cb391da..3012c80e 100644 --- a/src/test/scala-3/com/typesafe/scalalogging/Scala3LoggerSpec.scala +++ b/src/test/scala-3/com/typesafe/scalalogging/Scala3LoggerSpec.scala @@ -34,6 +34,14 @@ class Scala3LoggerSpec extends AnyWordSpec with Matchers with Varargs with Mocki logger.info("""Hello {}""", forceVarargs(arg5ref):_*) verify(underlying).info("""Hello {}""", arg5ref) } + + "work when passing a inline value as repeated arguments" in { + val f = fixture(_.isInfoEnabled, isEnabled = true) + import f._ + inline def argss = Seq(arg5ref, arg5ref, arg5ref) + logger.info("""Hello {} {} {}""", argss:_*) + verify(underlying).info("""Hello {} {} {}""", Seq(arg5ref, arg5ref, arg5ref):_*) + } } private def fixture(p: Underlying => Boolean, isEnabled: Boolean) = new LoggerF(p, isEnabled) From 59603af66decab2e928bd58ca2614fb98405b6f1 Mon Sep 17 00:00:00 2001 From: jxnu-liguobin Date: Sat, 2 Mar 2024 23:01:49 +0800 Subject: [PATCH 6/9] fixes https://github.com/lightbend-labs/scala-logging/issues/436 --- .../typesafe/scalalogging/LoggerMacro.scala | 31 +++++++++++++------ .../scalalogging/Scala3LoggerSpec.scala | 10 +++++- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala b/src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala index 4d3bf26d..6e71035a 100644 --- a/src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala +++ b/src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala @@ -261,30 +261,41 @@ private[scalalogging] object LoggerMacro { case _ => (message, Seq.empty) } } - def formatArgs(args: Expr[Seq[Any]])(using q: Quotes): Seq[Expr[AnyRef]] = { + + def formatArgs(args: Expr[Seq[Any]])(using q: Quotes + + ): + Seq[Expr[AnyRef]] = { import quotes.reflect.* import util.* - // we recursively obtain the actual value of inline parameters - def map(term:Term) = { + // we recursively obtain the actual value of inline parameters + def map(term: Term) = { term match { case t if t.tpe <:< TypeRepr.of[AnyRef] => t.asExprOf[AnyRef] - case t => '{${t.asExpr}.asInstanceOf[AnyRef]} + case t => '{ + ${ + t.asExpr + }.asInstanceOf[AnyRef] + } } } + def rec(tree: Term): Option[Seq[Expr[AnyRef]]] = tree match { case Repeated(elems, _) => Some(elems.map(map)) case Block(Nil, e) => rec(e) + case tped@Typed(Ident(_), _) => + tped.symbol.tree match { + case ValDef(_, _, Some(rhs)) => rec(rhs) + case _ => None + } case Typed(e, _) => rec(e) case Inlined(_, Nil, e) => rec(e) - // Seq():_*, List():_* , forceVarargs(1,2):_*e.g., - case Apply(TypeApply(_, _), List(Typed(Repeated(elems, _),_))) => + case Apply(TypeApply(_, _), List(Typed(Repeated(elems, _), _))) => Some(elems.map(map)) - case Ident(name) => - // todo - None - case _ => + case _ => None } + rec(args.asTerm).getOrElse(Seq.empty) } } diff --git a/src/test/scala-3/com/typesafe/scalalogging/Scala3LoggerSpec.scala b/src/test/scala-3/com/typesafe/scalalogging/Scala3LoggerSpec.scala index 3012c80e..b0fc3241 100644 --- a/src/test/scala-3/com/typesafe/scalalogging/Scala3LoggerSpec.scala +++ b/src/test/scala-3/com/typesafe/scalalogging/Scala3LoggerSpec.scala @@ -35,7 +35,15 @@ class Scala3LoggerSpec extends AnyWordSpec with Matchers with Varargs with Mocki verify(underlying).info("""Hello {}""", arg5ref) } - "work when passing a inline value as repeated arguments" in { + "work when passing a val as repeated arguments" in { + val f = fixture(_.isInfoEnabled, isEnabled = true) + import f._ + val argss = Seq(arg5ref, arg5ref, arg5ref) + logger.info("""Hello {} {} {}""", argss:_*) + verify(underlying).info("""Hello {} {} {}""", Seq(arg5ref, arg5ref, arg5ref):_*) + } + + "work when passing a inline def as repeated arguments" in { val f = fixture(_.isInfoEnabled, isEnabled = true) import f._ inline def argss = Seq(arg5ref, arg5ref, arg5ref) From eba83bc9d00479e57a83061f056cbe6f3c88ac7d Mon Sep 17 00:00:00 2001 From: jxnu-liguobin Date: Sat, 2 Mar 2024 23:06:19 +0800 Subject: [PATCH 7/9] fix fmt --- .../scala-3/com/typesafe/scalalogging/LoggerMacro.scala | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala b/src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala index 6e71035a..16fabdb3 100644 --- a/src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala +++ b/src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala @@ -272,11 +272,7 @@ private[scalalogging] object LoggerMacro { def map(term: Term) = { term match { case t if t.tpe <:< TypeRepr.of[AnyRef] => t.asExprOf[AnyRef] - case t => '{ - ${ - t.asExpr - }.asInstanceOf[AnyRef] - } + case t => '{ ${ t.asExpr }.asInstanceOf[AnyRef] } } } From 1de9edcdcd99cefafa22d269661062290d998e64 Mon Sep 17 00:00:00 2001 From: jxnu-liguobin Date: Sat, 2 Mar 2024 23:06:36 +0800 Subject: [PATCH 8/9] fix fmt --- src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala b/src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala index 16fabdb3..8f262d22 100644 --- a/src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala +++ b/src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala @@ -262,10 +262,7 @@ private[scalalogging] object LoggerMacro { } } - def formatArgs(args: Expr[Seq[Any]])(using q: Quotes - - ): - Seq[Expr[AnyRef]] = { + def formatArgs(args: Expr[Seq[Any]])(using q: Quotes):Seq[Expr[AnyRef]] = { import quotes.reflect.* import util.* // we recursively obtain the actual value of inline parameters From 84698eab912e5cce496daa46e8fcf6b6bb44308a Mon Sep 17 00:00:00 2001 From: jxnu-liguobin Date: Sun, 3 Mar 2024 11:52:46 +0800 Subject: [PATCH 9/9] fix test --- .../com/typesafe/scalalogging/Scala3LoggerSpec.scala | 8 -------- src/test/scala/com/typesafe/scalalogging/LoggerSpec.scala | 8 ++++++++ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/test/scala-3/com/typesafe/scalalogging/Scala3LoggerSpec.scala b/src/test/scala-3/com/typesafe/scalalogging/Scala3LoggerSpec.scala index b0fc3241..d3094b7d 100644 --- a/src/test/scala-3/com/typesafe/scalalogging/Scala3LoggerSpec.scala +++ b/src/test/scala-3/com/typesafe/scalalogging/Scala3LoggerSpec.scala @@ -35,14 +35,6 @@ class Scala3LoggerSpec extends AnyWordSpec with Matchers with Varargs with Mocki verify(underlying).info("""Hello {}""", arg5ref) } - "work when passing a val as repeated arguments" in { - val f = fixture(_.isInfoEnabled, isEnabled = true) - import f._ - val argss = Seq(arg5ref, arg5ref, arg5ref) - logger.info("""Hello {} {} {}""", argss:_*) - verify(underlying).info("""Hello {} {} {}""", Seq(arg5ref, arg5ref, arg5ref):_*) - } - "work when passing a inline def as repeated arguments" in { val f = fixture(_.isInfoEnabled, isEnabled = true) import f._ diff --git a/src/test/scala/com/typesafe/scalalogging/LoggerSpec.scala b/src/test/scala/com/typesafe/scalalogging/LoggerSpec.scala index ca8695a1..bc0cf424 100644 --- a/src/test/scala/com/typesafe/scalalogging/LoggerSpec.scala +++ b/src/test/scala/com/typesafe/scalalogging/LoggerSpec.scala @@ -215,6 +215,14 @@ class LoggerSpec extends AnyWordSpec with Matchers with Varargs with MockitoSuga logger.info(s"Message with id=$message, submittedAt=$message will be dropped.") verify(underlying).info("""Message with id={}, submittedAt={} will be dropped.""", forceVarargs(message, message): _*) } + + "work when passing a val as repeated arguments, issue 436" in { + val f = fixture(_.isInfoEnabled, isEnabled = true) + import f._ + val argss = Seq(arg5ref, arg5ref, arg5ref) + logger.info("""Hello {} {} {}""", argss: _*) + verify(underlying).info("""Hello {} {} {}""", forceVarargs(arg5ref, arg5ref, arg5ref): _*) + } } "Calling info with a message and cause" should {