diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 30380ee3..7212817a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,20 +9,42 @@ jobs: strategy: fail-fast: false matrix: - java: [8, 11, 17] - scala: [2.11.x, 2.12.x, 2.13.x, 3.x] + java: [ 8, 11, 17, 21 ] + scala: [ 2.11.x, 2.12.x, 2.13.x, 3.x ] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - uses: coursier/cache-action@v6 - - uses: actions/setup-java@v3 - with: - distribution: temurin - java-version: ${{matrix.java}} - - uses: sbt/setup-sbt@v1 - - name: Test - run: | - sbt ++${{matrix.scala}} test - git diff --exit-code # check scalariform + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - uses: coursier/cache-action@v6 + - uses: actions/setup-java@v3 + with: + distribution: temurin + java-version: ${{matrix.java}} + - uses: sbt/setup-sbt@v1 + - name: Test + run: | + sbt ++${{matrix.scala}} test + git diff --exit-code # check scalariform + + integration-test: + strategy: + fail-fast: false + matrix: + java: [ 8, 11, 17, 21 ] + scala: [ 2.13.x, 3.x ] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - uses: coursier/cache-action@v6 + - uses: actions/setup-java@v3 + with: + distribution: temurin + java-version: ${{matrix.java}} + - uses: sbt/setup-sbt@v1 + - name: Test + run: | + sbt ++${{matrix.scala}} integration-test/test + git diff --exit-code # check scalariform diff --git a/build.sbt b/build.sbt index 9107601a..4856a04a 100644 --- a/build.sbt +++ b/build.sbt @@ -1,53 +1,95 @@ +import Library.{logbackClassic, mockitoScala, scalaTest} +import _root_.com.github.sbt.osgi.SbtOsgi +import sbt.url + // basics -name := "scala-logging" -crossScalaVersions := Seq("3.3.5", "2.11.12", "2.12.20", "2.13.16") -scalaVersion := crossScalaVersions.value.head -ThisBuild / versionScheme := Some("early-semver") -scalacOptions ++= Seq( - "-unchecked", - "-deprecation", - "-language:_", - "-encoding", "UTF-8", - "-Ywarn-unused" -) -incOptions := incOptions.value.withLogRecompileOnMacro(false) +val scala213 = "2.13.16" +val scala3 = "3.7.3" +val scala2 = Seq("2.11.12", "2.12.20", scala213) val isScala3 = Def.setting { CrossVersion.partialVersion(scalaVersion.value).exists(_._1 != 2) } -libraryDependencies ++= Dependencies.scalaLogging(scalaVersion.value, isScala3.value) -initialCommands := """|import com.typesafe.scalalogging._ - |import org.slf4j.{ Logger => Underlying, _ }""".stripMargin - -// OSGi - -enablePlugins(SbtOsgi) -osgiSettings -OsgiKeys.bundleSymbolicName := "com.typesafe.scala-logging" -OsgiKeys.privatePackage := Seq() -OsgiKeys.exportPackage := Seq("com.typesafe.scalalogging*") - -// publishing - -organization := "com.typesafe.scala-logging" -licenses := Seq("Apache 2.0 License" -> url("http://www.apache.org/licenses/LICENSE-2.0.html")) -homepage := Some(url("https://github.com/lightbend/scala-logging")) -Test / publishArtifact := false -pomIncludeRepository := (_ => false) -scmInfo := Some( - ScmInfo(url("https://github.com/lightbend/scala-logging"), "scm:git:git@github.com:lightbend/scala-logging.git") -) -developers := List( - Developer( - id = "hseeberger", - name = "Heiko Seeberger", - email = "", - url = url("http://heikoseeberger.de") - ), - Developer( - id = "analytically", - name = "Mathias Bogaert", - email = "", - url = url("http://twitter.com/analytically") + +val scalacOption = Def.setting { + if (isScala3.value) Seq.empty else Seq("-language:_", "-Ywarn-unused") +} + +lazy val root = (project in file(".")).aggregate(core, scala2macros) + +lazy val core = (project in file("core")) + .enablePlugins(SbtOsgi) + .settings( + name := "scala-logging", + organization := "com.typesafe.scala-logging", + crossScalaVersions := Seq(scala3) ++ scala2, + scalaVersion := crossScalaVersions.value.head, + ThisBuild / versionScheme := Some("early-semver"), + scalacOptions ++= Seq( + "-unchecked", + "-deprecation", + "-encoding", "UTF-8" + ) ++ scalacOption.value, + incOptions := incOptions.value.withLogRecompileOnMacro(false), + libraryDependencies ++= Dependencies.scalaLogging(scalaVersion.value, isScala3.value), + initialCommands := + """|import com.typesafe.scalalogging._ + |import org.slf4j.{ Logger => Underlying, _ }""".stripMargin + ).settings( + // OSGi + osgiSettings + ).settings( + OsgiKeys.bundleSymbolicName := "com.typesafe.scala-logging", + OsgiKeys.privatePackage := Seq(), + OsgiKeys.exportPackage := Seq("com.typesafe.scalalogging*"), + + // publishing + licenses := Seq("Apache 2.0 License" -> url("http://www.apache.org/licenses/LICENSE-2.0.html")), + homepage := Some(url("https://github.com/lightbend/scala-logging")), + Test / publishArtifact := false, + pomIncludeRepository := (_ => false), + scmInfo := Some( + ScmInfo(url("https://github.com/lightbend/scala-logging"), "scm:git:git@github.com:lightbend/scala-logging.git") + ), + developers := List( + Developer( + id = "hseeberger", + name = "Heiko Seeberger", + email = "", + url = url("http://heikoseeberger.de") + ), + Developer( + id = "analytically", + name = "Mathias Bogaert", + email = "", + url = url("http://twitter.com/analytically") + ) + )) + .dependsOn(scala2macros) + +lazy val scala2macros = project + .settings( + name := "scala2macros", + scalaVersion := scala213, + crossScalaVersions := scala2, + libraryDependencies ++= Dependencies.scalaLogging(scalaVersion.value, false), + ) + +lazy val `integration-test` = project.in(file("integration-test")) + .settings( + publish / skip := true, + scalaVersion := scala3, + crossScalaVersions := Seq(scala3, scala213), + scalacOptions ++= { + CrossVersion.partialVersion(scalaVersion.value) match { + case Some((2, 13)) => Seq("-Ytasty-reader") + case _ => Seq.empty + } + }, + libraryDependencies ++= Seq( + logbackClassic % "test", + mockitoScala % "test", + scalaTest % "test" + ) ) -) + .dependsOn(core) \ No newline at end of file diff --git a/src/main/resources/LICENSE-2.0.txt b/core/src/main/resources/LICENSE-2.0.txt similarity index 100% rename from src/main/resources/LICENSE-2.0.txt rename to core/src/main/resources/LICENSE-2.0.txt diff --git a/core/src/main/scala-2/com/typesafe/scalalogging/LoggerImpl.scala b/core/src/main/scala-2/com/typesafe/scalalogging/LoggerImpl.scala new file mode 100644 index 00000000..f42a5bb6 --- /dev/null +++ b/core/src/main/scala-2/com/typesafe/scalalogging/LoggerImpl.scala @@ -0,0 +1,85 @@ +package com.typesafe.scalalogging + +import org.slf4j.Marker +class LoggerImpl { + + // Error + + def error(message: String): Unit = macro Scala2LoggerMacro.errorMessage + + def error(message: String, cause: Throwable): Unit = macro Scala2LoggerMacro.errorMessageCause + + def error(message: String, args: Any*): Unit = macro Scala2LoggerMacro.errorMessageArgs + + def error(marker: Marker, message: String): Unit = macro Scala2LoggerMacro.errorMessageMarker + + def error(marker: Marker, message: String, cause: Throwable): Unit = macro Scala2LoggerMacro.errorMessageCauseMarker + + def error(marker: Marker, message: String, args: Any*): Unit = macro Scala2LoggerMacro.errorMessageArgsMarker + + def whenErrorEnabled(body: Unit): Unit = macro Scala2LoggerMacro.errorCode + + // Warn + + def warn(message: String): Unit = macro Scala2LoggerMacro.warnMessage + + def warn(message: String, cause: Throwable): Unit = macro Scala2LoggerMacro.warnMessageCause + + def warn(message: String, args: Any*): Unit = macro Scala2LoggerMacro.warnMessageArgs + + def warn(marker: Marker, message: String): Unit = macro Scala2LoggerMacro.warnMessageMarker + + def warn(marker: Marker, message: String, cause: Throwable): Unit = macro Scala2LoggerMacro.warnMessageCauseMarker + + def warn(marker: Marker, message: String, args: Any*): Unit = macro Scala2LoggerMacro.warnMessageArgsMarker + + def whenWarnEnabled(body: Unit): Unit = macro Scala2LoggerMacro.warnCode + + // Info + + def info(message: String): Unit = macro Scala2LoggerMacro.infoMessage + + def info(message: String, cause: Throwable): Unit = macro Scala2LoggerMacro.infoMessageCause + + def info(message: String, args: Any*): Unit = macro Scala2LoggerMacro.infoMessageArgs + + def info(marker: Marker, message: String): Unit = macro Scala2LoggerMacro.infoMessageMarker + + def info(marker: Marker, message: String, cause: Throwable): Unit = macro Scala2LoggerMacro.infoMessageCauseMarker + + def info(marker: Marker, message: String, args: Any*): Unit = macro Scala2LoggerMacro.infoMessageArgsMarker + + def whenInfoEnabled(body: Unit): Unit = macro Scala2LoggerMacro.infoCode + + // Debug + + def debug(message: String): Unit = macro Scala2LoggerMacro.debugMessage + + def debug(message: String, cause: Throwable): Unit = macro Scala2LoggerMacro.debugMessageCause + + def debug(message: String, args: Any*): Unit = macro Scala2LoggerMacro.debugMessageArgs + + def debug(marker: Marker, message: String): Unit = macro Scala2LoggerMacro.debugMessageMarker + + def debug(marker: Marker, message: String, cause: Throwable): Unit = macro Scala2LoggerMacro.debugMessageCauseMarker + + def debug(marker: Marker, message: String, args: Any*): Unit = macro Scala2LoggerMacro.debugMessageArgsMarker + + def whenDebugEnabled(body: Unit): Unit = macro Scala2LoggerMacro.debugCode + + // Trace + + def trace(message: String): Unit = macro Scala2LoggerMacro.traceMessage + + def trace(message: String, cause: Throwable): Unit = macro Scala2LoggerMacro.traceMessageCause + + def trace(message: String, args: Any*): Unit = macro Scala2LoggerMacro.traceMessageArgs + + def trace(marker: Marker, message: String): Unit = macro Scala2LoggerMacro.traceMessageMarker + + def trace(marker: Marker, message: String, cause: Throwable): Unit = macro Scala2LoggerMacro.traceMessageCauseMarker + + def trace(marker: Marker, message: String, args: Any*): Unit = macro Scala2LoggerMacro.traceMessageArgsMarker + + def whenTraceEnabled(body: Unit): Unit = macro Scala2LoggerMacro.traceCode +} \ No newline at end of file diff --git a/core/src/main/scala-2/com/typesafe/scalalogging/LoggerTakingImplicitImpl.scala b/core/src/main/scala-2/com/typesafe/scalalogging/LoggerTakingImplicitImpl.scala new file mode 100644 index 00000000..24c4dc76 --- /dev/null +++ b/core/src/main/scala-2/com/typesafe/scalalogging/LoggerTakingImplicitImpl.scala @@ -0,0 +1,86 @@ +package com.typesafe.scalalogging + +import org.slf4j.Marker + +class LoggerTakingImplicitImpl[A] private[scalalogging] { + + // Error + + def error(message: String)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.errorMessage[A] + + def error(message: String, cause: Throwable)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.errorMessageCause[A] + + def error(message: String, args: Any*)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.errorMessageArgs[A] + + def error(marker: Marker, message: String)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.errorMessageMarker[A] + + def error(marker: Marker, message: String, cause: Throwable)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.errorMessageCauseMarker[A] + + def error(marker: Marker, message: String, args: Any*)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.errorMessageArgsMarker[A] + + def whenErrorEnabled(body: Unit)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.errorCode[A] + + // Warn + + def warn(message: String)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.warnMessage[A] + + def warn(message: String, cause: Throwable)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.warnMessageCause[A] + + def warn(message: String, args: Any*)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.warnMessageArgs[A] + + def warn(marker: Marker, message: String)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.warnMessageMarker[A] + + def warn(marker: Marker, message: String, cause: Throwable)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.warnMessageCauseMarker[A] + + def warn(marker: Marker, message: String, args: Any*)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.warnMessageArgsMarker[A] + + def whenWarnEnabled(body: Unit)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.warnCode[A] + + // Info + + def info(message: String)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.infoMessage[A] + + def info(message: String, cause: Throwable)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.infoMessageCause[A] + + def info(message: String, args: Any*)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.infoMessageArgs[A] + + def info(marker: Marker, message: String)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.infoMessageMarker[A] + + def info(marker: Marker, message: String, cause: Throwable)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.infoMessageCauseMarker[A] + + def info(marker: Marker, message: String, args: Any*)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.infoMessageArgsMarker[A] + + def whenInfoEnabled(body: Unit)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.infoCode[A] + + // Debug + + def debug(message: String)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.debugMessage[A] + + def debug(message: String, cause: Throwable)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.debugMessageCause[A] + + def debug(message: String, args: Any*)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.debugMessageArgs[A] + + def debug(marker: Marker, message: String)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.debugMessageMarker[A] + + def debug(marker: Marker, message: String, cause: Throwable)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.debugMessageCauseMarker[A] + + def debug(marker: Marker, message: String, args: Any*)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.debugMessageArgsMarker[A] + + def whenDebugEnabled(body: Unit)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.debugCode[A] + + // Trace + + def trace(message: String)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.traceMessage[A] + + def trace(message: String, cause: Throwable)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.traceMessageCause[A] + + def trace(message: String, args: Any*)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.traceMessageArgs[A] + + def trace(marker: Marker, message: String)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.traceMessageMarker[A] + + def trace(marker: Marker, message: String, cause: Throwable)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.traceMessageCauseMarker[A] + + def trace(marker: Marker, message: String, args: Any*)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.traceMessageArgsMarker[A] + + def whenTraceEnabled(body: Unit)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.traceCode[A] +} \ No newline at end of file diff --git a/src/main/scala-3/com/typesafe/scalalogging/LoggerImpl.scala b/core/src/main/scala-3/com/typesafe/scalalogging/LoggerImpl.scala similarity index 59% rename from src/main/scala-3/com/typesafe/scalalogging/LoggerImpl.scala rename to core/src/main/scala-3/com/typesafe/scalalogging/LoggerImpl.scala index 9d328263..f63dc423 100644 --- a/src/main/scala-3/com/typesafe/scalalogging/LoggerImpl.scala +++ b/core/src/main/scala-3/com/typesafe/scalalogging/LoggerImpl.scala @@ -1,6 +1,7 @@ package com.typesafe.scalalogging import org.slf4j.{Marker, Logger as Underlying } +import scala.language.experimental.macros trait LoggerImpl { def underlying: Underlying @@ -54,4 +55,87 @@ trait LoggerImpl { inline def trace(inline marker: Marker, inline message: String, inline cause: Throwable): Unit = ${LoggerMacro.traceMessageCauseMarker('underlying, 'marker, 'message, 'cause)} inline def trace(inline marker: Marker, inline message: String, inline args: Any*): Unit = ${LoggerMacro.traceMessageArgsMarker('underlying, 'marker, 'message, 'args)} inline def whenTraceEnabled(inline body: Unit): Unit = ${LoggerMacro.traceCode('underlying, 'body)} + + //scala 2 + + // Error + + def error(message: String): Unit = macro Scala2LoggerMacro.errorMessage + + def error(message: String, cause: Throwable): Unit = macro Scala2LoggerMacro.errorMessageCause + + def error(message: String, args: Any*): Unit = macro Scala2LoggerMacro.errorMessageArgs + + def error(marker: Marker, message: String): Unit = macro Scala2LoggerMacro.errorMessageMarker + + def error(marker: Marker, message: String, cause: Throwable): Unit = macro Scala2LoggerMacro.errorMessageCauseMarker + + def error(marker: Marker, message: String, args: Any*): Unit = macro Scala2LoggerMacro.errorMessageArgsMarker + + def whenErrorEnabled(body: Unit): Unit = macro Scala2LoggerMacro.errorCode + + // Warn + + def warn(message: String): Unit = macro Scala2LoggerMacro.warnMessage + + def warn(message: String, cause: Throwable): Unit = macro Scala2LoggerMacro.warnMessageCause + + def warn(message: String, args: Any*): Unit = macro Scala2LoggerMacro.warnMessageArgs + + def warn(marker: Marker, message: String): Unit = macro Scala2LoggerMacro.warnMessageMarker + + def warn(marker: Marker, message: String, cause: Throwable): Unit = macro Scala2LoggerMacro.warnMessageCauseMarker + + def warn(marker: Marker, message: String, args: Any*): Unit = macro Scala2LoggerMacro.warnMessageArgsMarker + + def whenWarnEnabled(body: Unit): Unit = macro Scala2LoggerMacro.warnCode + + // Info + + def info(message: String): Unit = macro Scala2LoggerMacro.infoMessage + + def info(message: String, cause: Throwable): Unit = macro Scala2LoggerMacro.infoMessageCause + + def info(message: String, args: Any*): Unit = macro Scala2LoggerMacro.infoMessageArgs + + def info(marker: Marker, message: String): Unit = macro Scala2LoggerMacro.infoMessageMarker + + def info(marker: Marker, message: String, cause: Throwable): Unit = macro Scala2LoggerMacro.infoMessageCauseMarker + + def info(marker: Marker, message: String, args: Any*): Unit = macro Scala2LoggerMacro.infoMessageArgsMarker + + def whenInfoEnabled(body: Unit): Unit = macro Scala2LoggerMacro.infoCode + + // Debug + + def debug(message: String): Unit = macro Scala2LoggerMacro.debugMessage + + def debug(message: String, cause: Throwable): Unit = macro Scala2LoggerMacro.debugMessageCause + + def debug(message: String, args: Any*): Unit = macro Scala2LoggerMacro.debugMessageArgs + + def debug(marker: Marker, message: String): Unit = macro Scala2LoggerMacro.debugMessageMarker + + def debug(marker: Marker, message: String, cause: Throwable): Unit = macro Scala2LoggerMacro.debugMessageCauseMarker + + def debug(marker: Marker, message: String, args: Any*): Unit = macro Scala2LoggerMacro.debugMessageArgsMarker + + def whenDebugEnabled(body: Unit): Unit = macro Scala2LoggerMacro.debugCode + + // Trace + + def trace(message: String): Unit = macro Scala2LoggerMacro.traceMessage + + def trace(message: String, cause: Throwable): Unit = macro Scala2LoggerMacro.traceMessageCause + + def trace(message: String, args: Any*): Unit = macro Scala2LoggerMacro.traceMessageArgs + + def trace(marker: Marker, message: String): Unit = macro Scala2LoggerMacro.traceMessageMarker + + def trace(marker: Marker, message: String, cause: Throwable): Unit = macro Scala2LoggerMacro.traceMessageCauseMarker + + def trace(marker: Marker, message: String, args: Any*): Unit = macro Scala2LoggerMacro.traceMessageArgsMarker + + def whenTraceEnabled(body: Unit): Unit = macro Scala2LoggerMacro.traceCode + } diff --git a/src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala b/core/src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala similarity index 100% rename from src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala rename to core/src/main/scala-3/com/typesafe/scalalogging/LoggerMacro.scala diff --git a/src/main/scala-3/com/typesafe/scalalogging/LoggerTakingImplicitImpl.scala b/core/src/main/scala-3/com/typesafe/scalalogging/LoggerTakingImplicitImpl.scala similarity index 60% rename from src/main/scala-3/com/typesafe/scalalogging/LoggerTakingImplicitImpl.scala rename to core/src/main/scala-3/com/typesafe/scalalogging/LoggerTakingImplicitImpl.scala index 5e99eeca..5dc79d2b 100644 --- a/src/main/scala-3/com/typesafe/scalalogging/LoggerTakingImplicitImpl.scala +++ b/core/src/main/scala-3/com/typesafe/scalalogging/LoggerTakingImplicitImpl.scala @@ -1,6 +1,7 @@ package com.typesafe.scalalogging import org.slf4j.{Marker, Logger as Underlying } +import scala.language.experimental.macros trait LoggerTakingImplicitImpl[A] { def underlying: Underlying @@ -119,4 +120,87 @@ trait LoggerTakingImplicitImpl[A] { ${LoggerTakingImplicitMacro.traceMessageArgsMarker('underlying, 'canLogEv, 'marker,'message, 'args)('a)} inline def whenTraceEnabled(inline body: Unit)(implicit inline a: A): Unit = ${LoggerTakingImplicitMacro.traceCode('underlying, 'canLogEv, 'body)('a)} + + //scala 2 + + // Error + + def error(message: String)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.errorMessage[A] + + def error(message: String, cause: Throwable)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.errorMessageCause[A] + + def error(message: String, args: Any*)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.errorMessageArgs[A] + + def error(marker: Marker, message: String)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.errorMessageMarker[A] + + def error(marker: Marker, message: String, cause: Throwable)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.errorMessageCauseMarker[A] + + def error(marker: Marker, message: String, args: Any*)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.errorMessageArgsMarker[A] + + def whenErrorEnabled(body: Unit)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.errorCode[A] + + // Warn + + def warn(message: String)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.warnMessage[A] + + def warn(message: String, cause: Throwable)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.warnMessageCause[A] + + def warn(message: String, args: Any*)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.warnMessageArgs[A] + + def warn(marker: Marker, message: String)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.warnMessageMarker[A] + + def warn(marker: Marker, message: String, cause: Throwable)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.warnMessageCauseMarker[A] + + def warn(marker: Marker, message: String, args: Any*)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.warnMessageArgsMarker[A] + + def whenWarnEnabled(body: Unit)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.warnCode[A] + + // Info + + def info(message: String)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.infoMessage[A] + + def info(message: String, cause: Throwable)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.infoMessageCause[A] + + def info(message: String, args: Any*)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.infoMessageArgs[A] + + def info(marker: Marker, message: String)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.infoMessageMarker[A] + + def info(marker: Marker, message: String, cause: Throwable)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.infoMessageCauseMarker[A] + + def info(marker: Marker, message: String, args: Any*)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.infoMessageArgsMarker[A] + + def whenInfoEnabled(body: Unit)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.infoCode[A] + + // Debug + + def debug(message: String)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.debugMessage[A] + + def debug(message: String, cause: Throwable)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.debugMessageCause[A] + + def debug(message: String, args: Any*)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.debugMessageArgs[A] + + def debug(marker: Marker, message: String)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.debugMessageMarker[A] + + def debug(marker: Marker, message: String, cause: Throwable)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.debugMessageCauseMarker[A] + + def debug(marker: Marker, message: String, args: Any*)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.debugMessageArgsMarker[A] + + def whenDebugEnabled(body: Unit)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.debugCode[A] + + // Trace + + def trace(message: String)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.traceMessage[A] + + def trace(message: String, cause: Throwable)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.traceMessageCause[A] + + def trace(message: String, args: Any*)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.traceMessageArgs[A] + + def trace(marker: Marker, message: String)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.traceMessageMarker[A] + + def trace(marker: Marker, message: String, cause: Throwable)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.traceMessageCauseMarker[A] + + def trace(marker: Marker, message: String, args: Any*)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.traceMessageArgsMarker[A] + + def whenTraceEnabled(body: Unit)(implicit a: A): Unit = macro Scala2LoggerTakingImplicitMacro.traceCode[A] + } diff --git a/src/main/scala-3/com/typesafe/scalalogging/LoggerTakingImplicitMacro.scala b/core/src/main/scala-3/com/typesafe/scalalogging/LoggerTakingImplicitMacro.scala similarity index 100% rename from src/main/scala-3/com/typesafe/scalalogging/LoggerTakingImplicitMacro.scala rename to core/src/main/scala-3/com/typesafe/scalalogging/LoggerTakingImplicitMacro.scala diff --git a/src/main/scala/com/typesafe/scalalogging/Logger.scala b/core/src/main/scala/com/typesafe/scalalogging/Logger.scala similarity index 100% rename from src/main/scala/com/typesafe/scalalogging/Logger.scala rename to core/src/main/scala/com/typesafe/scalalogging/Logger.scala diff --git a/src/main/scala/com/typesafe/scalalogging/LoggerTakingImplicit.scala b/core/src/main/scala/com/typesafe/scalalogging/LoggerTakingImplicit.scala similarity index 100% rename from src/main/scala/com/typesafe/scalalogging/LoggerTakingImplicit.scala rename to core/src/main/scala/com/typesafe/scalalogging/LoggerTakingImplicit.scala diff --git a/src/main/scala/com/typesafe/scalalogging/Logging.scala b/core/src/main/scala/com/typesafe/scalalogging/Logging.scala similarity index 100% rename from src/main/scala/com/typesafe/scalalogging/Logging.scala rename to core/src/main/scala/com/typesafe/scalalogging/Logging.scala diff --git a/src/main/scala/com/typesafe/scalalogging/package.scala b/core/src/main/scala/com/typesafe/scalalogging/package.scala similarity index 100% rename from src/main/scala/com/typesafe/scalalogging/package.scala rename to core/src/main/scala/com/typesafe/scalalogging/package.scala diff --git a/src/test/resources/logback.xml b/core/src/test/resources/logback.xml similarity index 100% rename from src/test/resources/logback.xml rename to core/src/test/resources/logback.xml diff --git a/src/test/scala/com/typesafe/scalalogging/LoggerSpec.scala b/core/src/test/scala/com/typesafe/scalalogging/LoggerSpec.scala similarity index 100% rename from src/test/scala/com/typesafe/scalalogging/LoggerSpec.scala rename to core/src/test/scala/com/typesafe/scalalogging/LoggerSpec.scala diff --git a/src/test/scala/com/typesafe/scalalogging/LoggerTakingImplicitSpec.scala b/core/src/test/scala/com/typesafe/scalalogging/LoggerTakingImplicitSpec.scala similarity index 100% rename from src/test/scala/com/typesafe/scalalogging/LoggerTakingImplicitSpec.scala rename to core/src/test/scala/com/typesafe/scalalogging/LoggerTakingImplicitSpec.scala diff --git a/src/test/scala/com/typesafe/scalalogging/LoggerWithMarkerSpec.scala b/core/src/test/scala/com/typesafe/scalalogging/LoggerWithMarkerSpec.scala similarity index 100% rename from src/test/scala/com/typesafe/scalalogging/LoggerWithMarkerSpec.scala rename to core/src/test/scala/com/typesafe/scalalogging/LoggerWithMarkerSpec.scala diff --git a/src/test/scala/com/typesafe/scalalogging/LoggerWithTaggedArgsSpec.scala b/core/src/test/scala/com/typesafe/scalalogging/LoggerWithTaggedArgsSpec.scala similarity index 100% rename from src/test/scala/com/typesafe/scalalogging/LoggerWithTaggedArgsSpec.scala rename to core/src/test/scala/com/typesafe/scalalogging/LoggerWithTaggedArgsSpec.scala diff --git a/integration-test/src/test/scala/com/typesafe/scalalogging/LoggerSpec.scala b/integration-test/src/test/scala/com/typesafe/scalalogging/LoggerSpec.scala new file mode 100644 index 00000000..0082c6d8 --- /dev/null +++ b/integration-test/src/test/scala/com/typesafe/scalalogging/LoggerSpec.scala @@ -0,0 +1,603 @@ +package com.typesafe.scalalogging + +import java.io._ +import org.slf4j.{ Logger => Underlying } +import org.scalatest.matchers.should.Matchers +import org.scalatest.wordspec.AnyWordSpec +import org.scalatestplus.mockito.MockitoSugar +import org.mockito.ArgumentMatchers._ +import org.mockito.Mockito._ + +trait Varargs { + // TODO: we used to wrap in List(...): _*, which I assume was to force the varags method to be chosen. + // I encapsulated that here in something that works across 2.12/2.13. + def forceVarargs[T](xs: T*): scala.Seq[T] = scala.Seq(xs: _*) +} + +class LoggerSpec extends AnyWordSpec with Matchers with Varargs with MockitoSugar { + + // Error + + "Calling error with a message" should { + + "call the underlying logger's error method if the error level is enabled" in { + val f = fixture(_.isErrorEnabled, isEnabled = true) + import f._ + logger.error(msg) + verify(underlying).error(msg) + } + + "not call the underlying logger's error method if the error level is not enabled" in { + val f = fixture(_.isErrorEnabled, isEnabled = false) + import f._ + logger.error(msg) + verify(underlying, never).error(any[String]) + } + } + + "Calling error with an interpolated message" should { + + "call the underlying logger's error method with arguments if the error level is enabled" in { + val f = fixture(_.isErrorEnabled, isEnabled = true) + import f._ + logger.error(s"msg $arg1 $arg2 $arg3") + verify(underlying).error("msg {} {} {}", arg1, arg2, arg3) + } + + "call the underlying logger's error method with two arguments if the error level is enabled" in { + val f = fixture(_.isErrorEnabled, isEnabled = true) + import f._ + logger.error(s"msg $arg1 $arg2") + verify(underlying).error("msg {} {}", forceVarargs(arg1, arg2): _*) + } + + } + + "Calling error with a message and cause" should { + + "call the underlying logger's error method if the error level is enabled" in { + val f = fixture(_.isErrorEnabled, isEnabled = true) + import f._ + logger.error(msg, cause) + verify(underlying).error(msg, cause) + } + + "not call the underlying logger's error method if the error level is not enabled" in { + val f = fixture(_.isErrorEnabled, isEnabled = false) + import f._ + logger.error(msg, cause) + verify(underlying, never).error(any[String], any[Object]) + } + } + + "Calling error with a message and parameters" should { + + "call the underlying logger's error method if the error level is enabled" in { + val f = fixture(_.isErrorEnabled, isEnabled = true) + import f._ + logger.error(msg, arg1) + verify(underlying).error(msg, arg1) + logger.error(msg, arg1, arg2) + verify(underlying).error(msg, forceVarargs(arg1, arg2): _*) + logger.error(msg, arg1, arg2, arg3) + verify(underlying).error(msg, arg1, arg2, arg3) + } + + "not call the underlying logger's error method if the error level is not enabled" in { + val f = fixture(_.isErrorEnabled, isEnabled = false) + import f._ + logger.error(msg, arg1) + verify(underlying, never).error(msg, arg1) + logger.error(msg, arg1, arg2) + verify(underlying, never).error(msg, forceVarargs(arg1, arg2): _*) + logger.error(msg, arg1, arg2, arg3) + verify(underlying, never).error(msg, arg1, arg2, arg3) + } + } + + // Warn + + "Calling warn with a message" should { + + "call the underlying logger's warn method if the warn level is enabled" in { + val f = fixture(_.isWarnEnabled, isEnabled = true) + import f._ + logger.warn(msg) + verify(underlying).warn(msg) + } + + "not call the underlying logger's warn method if the warn level is not enabled" in { + val f = fixture(_.isWarnEnabled, isEnabled = false) + import f._ + logger.warn(msg) + verify(underlying, never).warn(any[String]) + } + } + + "Calling warn with an interpolated message" should { + + "call the underlying logger's warn method if the warn level is enabled" in { + val f = fixture(_.isWarnEnabled, isEnabled = true) + import f._ + logger.warn(s"msg $arg1 $arg2 $arg3") + verify(underlying).warn("msg {} {} {}", arg1, arg2, arg3) + } + + "call the underlying logger's warn method with two arguments if the warn level is enabled" in { + val f = fixture(_.isWarnEnabled, isEnabled = true) + import f._ + logger.warn(s"msg $arg1 $arg2") + verify(underlying).warn("msg {} {}", forceVarargs(arg1, arg2): _*) + } + } + + "Calling warn with a message and cause" should { + + "call the underlying logger's warn method if the warn level is enabled" in { + val f = fixture(_.isWarnEnabled, isEnabled = true) + import f._ + logger.warn(msg, cause) + verify(underlying).warn(msg, cause) + } + + "not call the underlying logger's warn method if the warn level is not enabled" in { + val f = fixture(_.isWarnEnabled, isEnabled = false) + import f._ + logger.warn(msg, cause) + verify(underlying, never).warn(any[String], any[Object]) + } + } + + "Calling warn with a message and parameters" should { + + "call the underlying logger's warn method if the warn level is enabled" in { + val f = fixture(_.isWarnEnabled, isEnabled = true) + import f._ + logger.warn(msg, arg1) + verify(underlying).warn(msg, arg1) + logger.warn(msg, arg1, arg2) + verify(underlying).warn(msg, forceVarargs(arg1, arg2): _*) + logger.warn(msg, arg1, arg2, arg3) + verify(underlying).warn(msg, arg1, arg2, arg3) + } + + "not call the underlying logger's warn method if the warn level is not enabled" in { + val f = fixture(_.isWarnEnabled, isEnabled = false) + import f._ + logger.warn(msg, arg1) + verify(underlying, never).warn(msg, arg1) + logger.warn(msg, arg1, arg2) + verify(underlying, never).warn(msg, forceVarargs(arg1, arg2): _*) + logger.warn(msg, arg1, arg2, arg3) + verify(underlying, never).warn(msg, arg1, arg2, arg3) + } + } + + // Info + + "Calling info with a message" should { + + "call the underlying logger's info method if the info level is enabled" in { + val f = fixture(_.isInfoEnabled, isEnabled = true) + import f._ + logger.info(msg) + verify(underlying).info(msg) + } + + "not call the underlying logger's info method if the info level is not enabled" in { + val f = fixture(_.isInfoEnabled, isEnabled = false) + import f._ + logger.info(msg) + verify(underlying, never).info(any[String]) + } + } + + "Calling info with an interpolated message" should { + + "call the underlying logger's info method if the info level is enabled" in { + val f = fixture(_.isInfoEnabled, isEnabled = true) + import f._ + logger.info(s"msg $arg1 $arg2 $arg3") + verify(underlying).info("msg {} {} {}", arg1, arg2, arg3) + } + + "call the underlying logger's info method with two arguments if the info level is enabled" in { + val f = fixture(_.isInfoEnabled, isEnabled = true) + import f._ + logger.info(s"msg $arg1 $arg2") + verify(underlying).info("msg {} {}", forceVarargs(arg1, arg2): _*) + } + } + + "Calling info with a message and cause" should { + + "call the underlying logger's info method if the info level is enabled" in { + val f = fixture(_.isInfoEnabled, isEnabled = true) + import f._ + logger.info(msg, cause) + verify(underlying).info(msg, cause) + } + + "not call the underlying logger's info method if the info level is not enabled" in { + val f = fixture(_.isInfoEnabled, isEnabled = false) + import f._ + logger.info(msg, cause) + verify(underlying, never).info(any[String], any[Object]) + } + } + + "Calling info with a message and parameters" should { + + "call the underlying logger's info method if the info level is enabled" in { + val f = fixture(_.isInfoEnabled, isEnabled = true) + import f._ + logger.info(msg, arg1) + verify(underlying).info(msg, arg1) + logger.info(msg, arg1, arg2) + verify(underlying).info(msg, forceVarargs(arg1, arg2): _*) + logger.info(msg, arg1, arg2, arg3) + verify(underlying).info(msg, arg1, arg2, arg3) + } + + "not call the underlying logger's info method if the info level is not enabled" in { + val f = fixture(_.isInfoEnabled, isEnabled = false) + import f._ + logger.info(msg, arg1) + verify(underlying, never).info(msg, arg1) + logger.info(msg, arg1, arg2) + verify(underlying, never).info(msg, forceVarargs(arg1, arg2): _*) + logger.info(msg, arg1, arg2, arg3) + verify(underlying, never).info(msg, arg1, arg2, arg3) + } + } + + // Debug + + "Calling debug with a message" should { + + "call the underlying logger's debug method if the debug level is enabled" in { + val f = fixture(_.isDebugEnabled, isEnabled = true) + import f._ + logger.debug(msg) + verify(underlying).debug(msg) + } + + "not call the underlying logger's debug method if the debug level is not enabled" in { + val f = fixture(_.isDebugEnabled, isEnabled = false) + import f._ + logger.debug(msg) + verify(underlying, never).debug(any[String]) + } + } + "Calling debug with an interpolated message" should { + + "call the underlying logger's debug method if the debug level is enabled" in { + val f = fixture(_.isDebugEnabled, isEnabled = true) + import f._ + logger.debug(s"msg $arg1 $arg2 $arg3") + verify(underlying).debug("msg {} {} {}", arg1, arg2, arg3) + } + + "call the underlying logger's debug method with two arguments if the debug level is enabled" in { + val f = fixture(_.isDebugEnabled, isEnabled = true) + import f._ + logger.debug(s"msg $arg1 $arg2") + verify(underlying).debug("msg {} {}", forceVarargs(arg1, arg2): _*) + } + } + + "Calling debug with a message and cause" should { + + "call the underlying logger's debug method if the debug level is enabled" in { + val f = fixture(_.isDebugEnabled, isEnabled = true) + import f._ + logger.debug(msg, cause) + verify(underlying).debug(msg, cause) + } + + "not call the underlying logger's debug method if the debug level is not enabled" in { + val f = fixture(_.isDebugEnabled, isEnabled = false) + import f._ + logger.debug(msg, cause) + verify(underlying, never).debug(any[String], any[Object]) + } + } + + "Calling debug with a message and parameters" should { + + "call the underlying logger's debug method if the debug level is enabled" in { + val f = fixture(_.isDebugEnabled, isEnabled = true) + import f._ + logger.debug(msg, arg1) + verify(underlying).debug(msg, arg1) + logger.debug(msg, arg1, arg2) + verify(underlying).debug(msg, forceVarargs(arg1, arg2): _*) + logger.debug(msg, arg1, arg2, arg3) + verify(underlying).debug(msg, arg1, arg2, arg3) + } + + "not call the underlying logger's debug method if the debug level is not enabled" in { + val f = fixture(_.isDebugEnabled, isEnabled = false) + import f._ + logger.debug(msg, arg1) + verify(underlying, never).debug(msg, arg1) + logger.debug(msg, arg1, arg2) + verify(underlying, never).debug(msg, forceVarargs(arg1, arg2): _*) + logger.debug(msg, arg1, arg2, arg3) + verify(underlying, never).debug(msg, arg1, arg2, arg3) + } + } + + // Trace + + "Calling trace with a message" should { + + "call the underlying logger's trace method if the trace level is enabled" in { + val f = fixture(_.isTraceEnabled, isEnabled = true) + import f._ + logger.trace(msg) + verify(underlying).trace(msg) + } + + "not call the underlying logger's trace method if the trace level is not enabled" in { + val f = fixture(_.isTraceEnabled, isEnabled = false) + import f._ + logger.trace(msg) + verify(underlying, never).trace(any[String]) + } + } + + "Calling trace with an interpolated message" should { + + "call the underlying logger's trace method if the trace level is enabled" in { + val f = fixture(_.isTraceEnabled, isEnabled = true) + import f._ + logger.trace(s"msg $arg1 $arg2 $arg3") + verify(underlying).trace("msg {} {} {}", arg1, arg2, arg3) + } + + "call the underlying logger's trace method with two arguments if the trace level is enabled" in { + val f = fixture(_.isTraceEnabled, isEnabled = true) + import f._ + logger.trace(s"msg $arg1 $arg2") + verify(underlying).trace("msg {} {}", forceVarargs(arg1, arg2): _*) + } + } + + "Calling trace with a message and cause" should { + + "call the underlying logger's trace method if the trace level is enabled" in { + val f = fixture(_.isTraceEnabled, isEnabled = true) + import f._ + logger.trace(msg, cause) + verify(underlying).trace(msg, cause) + } + + "not call the underlying logger's trace method if the trace level is not enabled" in { + val f = fixture(_.isTraceEnabled, isEnabled = false) + import f._ + logger.trace(msg, cause) + verify(underlying, never).trace(any[String], any[Object]) + } + } + + "Calling trace with a message and parameters" should { + + "call the underlying logger's trace method if the trace level is enabled" in { + val f = fixture(_.isTraceEnabled, isEnabled = true) + import f._ + logger.trace(msg, arg1) + verify(underlying).trace(msg, arg1) + logger.trace(msg, arg1, arg2) + verify(underlying).trace(msg, forceVarargs(arg1, arg2): _*) + logger.trace(msg, arg1, arg2, arg3) + verify(underlying).trace(msg, arg1, arg2, arg3) + } + + "not call the underlying logger's trace method if the trace level is not enabled" in { + val f = fixture(_.isTraceEnabled, isEnabled = false) + import f._ + logger.trace(msg, arg1) + verify(underlying, never).trace(msg, arg1) + logger.trace(msg, arg1, arg2) + verify(underlying, never).trace(msg, forceVarargs(arg1, arg2): _*) + logger.trace(msg, arg1, arg2, arg3) + verify(underlying, never).trace(msg, arg1, arg2, arg3) + } + } + + // Interpolator destructuring corner cases + + "Logging a message using the standard string interpolator" should { + + "call the underlying format method with boxed versions of value arguments" in { + val f = fixture(_.isErrorEnabled, isEnabled = true) + import f._ + logger.error(s"msg ${1}") + verify(underlying).error("msg {}", 1.asInstanceOf[AnyRef]) + } + + "call the underlying format method with boxed versions of arguments of type Any" in { + val f = fixture(_.isErrorEnabled, isEnabled = true) + import f._ + logger.error(s"msg ${1.asInstanceOf[Any]}") + verify(underlying).error("msg {}", 1.asInstanceOf[AnyRef]) + } + + "call the underlying format method escaping literal format anchors" in { + val f = fixture(_.isErrorEnabled, isEnabled = true) + import f._ + logger.error(s"foo {} bar $arg1") + verify(underlying).error("foo \\{} bar {}", arg1) + } + + "call the underlying method without escaping format anchors when the message has no interpolations" in { + val f = fixture(_.isErrorEnabled, isEnabled = true) + import f._ + logger.error(s"foo {} bar") + verify(underlying).error("foo {} bar") + } + + "call the underlying format method when the interpolated string contains escape sequences" in { + val f = fixture(_.isErrorEnabled, isEnabled = true) + import f._ + logger.error(s"foo\nbar $arg1") + verify(underlying).error(s"foo\nbar {}", arg1) + } + + "call the underlying format method when the interpolated string is triple quoted and contains escape sequences" in { + val f = fixture(_.isErrorEnabled, isEnabled = true) + import f._ + logger.error(s"""foo\nbar $arg1""") + verify(underlying).error(s"""foo\nbar {}""", arg1) + } + + "call the underlying format method when interpolated argument is a Throwable" in { + val f = fixture(_.isErrorEnabled, isEnabled = true) + import f._ + logger.error(s"""foo\nbar $arg7""") + verify(underlying).error(s"""foo\nbar {}""", arg7ref) + } + } + + "Logging a message using slf4 interpolator and Any args" should { + "map args to AnyRef for 2 args" in { + val f = fixture(_.isErrorEnabled, isEnabled = true) + import f._ + logger.error("foo {}, bar {}", arg4, arg5) + verify(underlying).error("foo {}, bar {}", forceVarargs(arg4ref, arg5ref): _*) + } + + "map args to AnyRef for non 2 args" in { + val f = fixture(_.isErrorEnabled, isEnabled = true) + import f._ + logger.error("foo {}", arg4) + verify(underlying).error("foo {}", arg4ref) + logger.error("foo {}, bar {}, {}", arg4, arg5, arg6) + verify(underlying).error("foo {}, bar {}, {}", arg4ref, arg5ref, arg6ref) + } + } + + "Serializing Logger" should { + + def serialize(logger: Logger): Array[Byte] = { + val byteArrayStream = new ByteArrayOutputStream + val out = new ObjectOutputStream(byteArrayStream) + + out.writeObject(logger) + out.close() + byteArrayStream.close() + + byteArrayStream.toByteArray + } + + def deserialize(array: Array[Byte]): Logger = { + val byteArrayStream = new ByteArrayInputStream(array) + val in = new ObjectInputStream(byteArrayStream) + + val logger = in.readObject.asInstanceOf[Logger] + in.close() + byteArrayStream.close() + + logger + } + + "be usable after deserialization" in { + val logger = deserialize(serialize(Logger(org.slf4j.LoggerFactory.getLogger("test")))) + + logger.trace("Back from deserialization") + } + + "constructed by explicit class and be usable after deserialization" in { + val logger = deserialize(serialize(Logger(classOf[LoggerSpec]))) + + logger.trace("Back from deserialization") + } + + "constructed by implicit class tag and be usable after deserialization" in { + val logger = deserialize(serialize(Logger[LoggerSpec])) + + logger.trace("Back from deserialization") + } + } + + "Serializing LoggerTakingImplicit" should { + case class CorrelationId(value: String) + implicit val correlationId: CorrelationId = CorrelationId(value = "correlationId") + + implicit case object canLogCorrelationId extends CanLog[CorrelationId] { + def logMessage(originalMsg: String, a: CorrelationId): String = s"${a.value} $originalMsg" + } + + def serialize[A](logger: LoggerTakingImplicit[A]): Array[Byte] = { + val byteArrayStream = new ByteArrayOutputStream + val out = new ObjectOutputStream(byteArrayStream) + + out.writeObject(logger) + out.close() + byteArrayStream.close() + + byteArrayStream.toByteArray + } + + def deserialize[A](array: Array[Byte]): LoggerTakingImplicit[A] = { + val byteArrayStream = new ByteArrayInputStream(array) + val in = new ObjectInputStream(byteArrayStream) + + val logger = in.readObject.asInstanceOf[LoggerTakingImplicit[A]] + in.close() + byteArrayStream.close() + + logger + } + + "be usable after deserialization" in { + val logger = + deserialize[CorrelationId]( + serialize[CorrelationId]( + Logger.takingImplicit[CorrelationId]( + org.slf4j.LoggerFactory.getLogger("test")))) + + logger.trace("Back from deserialization") + } + + "constructed by explicit class and be usable after deserialization" in { + val logger = + deserialize[CorrelationId]( + serialize[CorrelationId]( + Logger.takingImplicit[CorrelationId]( + classOf[LoggerSpec]))) + + logger.trace("Back from deserialization") + } + + "constructed by implicit class tag and be usable after deserialization" in { + val logger = + deserialize[CorrelationId]( + serialize[CorrelationId]( + Logger.takingImplicit[LoggerSpec, CorrelationId])) + + logger.trace("Back from deserialization") + } + } + + 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/main/scala-2/com/typesafe/scalalogging/LoggerMacro.scala b/scala2macros/src/main/scala/com/typesafe/scalalogging/Scala2LoggerMacro.scala similarity index 98% rename from src/main/scala-2/com/typesafe/scalalogging/LoggerMacro.scala rename to scala2macros/src/main/scala/com/typesafe/scalalogging/Scala2LoggerMacro.scala index dbef6b28..bac8333c 100644 --- a/src/main/scala-2/com/typesafe/scalalogging/LoggerMacro.scala +++ b/scala2macros/src/main/scala/com/typesafe/scalalogging/Scala2LoggerMacro.scala @@ -3,9 +3,9 @@ package com.typesafe.scalalogging import org.slf4j.Marker import scala.reflect.macros.blackbox -private[scalalogging] object LoggerMacro { +private[scalalogging] object Scala2LoggerMacro { - type LoggerContext = blackbox.Context { type PrefixType = Logger } + type LoggerContext = blackbox.Context // Error @@ -258,7 +258,7 @@ private[scalalogging] object LoggerMacro { } /** Checks whether `message` is an interpolated string and transforms it into SLF4J string interpolation. */ - private def deconstructInterpolatedMessage(c: LoggerContext)(message: c.Expr[String]) = { + private def deconstructInterpolatedMessage(c: LoggerContext)(message: c.Expr[String]): (c.Expr[String], Seq[c.Expr[Any]]) = { val u: c.universe.type = c.universe // Eww; gross! In 2.13, the `s` interpolator on StringContext became a macro, so we have to look at the pre-macro // expansion tree to recover what the user wrote... diff --git a/src/main/scala-2/com/typesafe/scalalogging/LoggerTakingImplicitMacro.scala b/scala2macros/src/main/scala/com/typesafe/scalalogging/Scala2LoggerTakingImplicitMacro.scala similarity index 99% rename from src/main/scala-2/com/typesafe/scalalogging/LoggerTakingImplicitMacro.scala rename to scala2macros/src/main/scala/com/typesafe/scalalogging/Scala2LoggerTakingImplicitMacro.scala index dcce88cb..10594fdb 100644 --- a/src/main/scala-2/com/typesafe/scalalogging/LoggerTakingImplicitMacro.scala +++ b/scala2macros/src/main/scala/com/typesafe/scalalogging/Scala2LoggerTakingImplicitMacro.scala @@ -3,9 +3,9 @@ package com.typesafe.scalalogging import org.slf4j.Marker import scala.reflect.macros.blackbox -private[scalalogging] object LoggerTakingImplicitMacro { +private[scalalogging] object Scala2LoggerTakingImplicitMacro { - type LoggerContext[A] = blackbox.Context { type PrefixType = LoggerTakingImplicit[A] } + type LoggerContext[A] = blackbox.Context // Error diff --git a/scalariform.sbt b/scalariform.sbt index df3b933c..a219240a 100644 --- a/scalariform.sbt +++ b/scalariform.sbt @@ -1,6 +1,7 @@ import com.typesafe.sbt.SbtScalariform.ScalariformKeys import scalariform.formatter.preferences.{AlignSingleLineCaseStatements, DoubleIndentConstructorArguments} +// TODO: migrate to scalafmt ScalariformKeys.preferences := ScalariformKeys.preferences.value .setPreference(AlignSingleLineCaseStatements, true) .setPreference(AlignSingleLineCaseStatements.MaxArrowIndent, 100) diff --git a/src/main/scala-2/com/typesafe/scalalogging/LoggerImpl.scala b/src/main/scala-2/com/typesafe/scalalogging/LoggerImpl.scala deleted file mode 100644 index f1bfcb84..00000000 --- a/src/main/scala-2/com/typesafe/scalalogging/LoggerImpl.scala +++ /dev/null @@ -1,85 +0,0 @@ -package com.typesafe.scalalogging - -import org.slf4j.Marker -class LoggerImpl { - - // Error - - def error(message: String): Unit = macro LoggerMacro.errorMessage - - def error(message: String, cause: Throwable): Unit = macro LoggerMacro.errorMessageCause - - def error(message: String, args: Any*): Unit = macro LoggerMacro.errorMessageArgs - - def error(marker: Marker, message: String): Unit = macro LoggerMacro.errorMessageMarker - - def error(marker: Marker, message: String, cause: Throwable): Unit = macro LoggerMacro.errorMessageCauseMarker - - def error(marker: Marker, message: String, args: Any*): Unit = macro LoggerMacro.errorMessageArgsMarker - - def whenErrorEnabled(body: Unit): Unit = macro LoggerMacro.errorCode - - // Warn - - def warn(message: String): Unit = macro LoggerMacro.warnMessage - - def warn(message: String, cause: Throwable): Unit = macro LoggerMacro.warnMessageCause - - def warn(message: String, args: Any*): Unit = macro LoggerMacro.warnMessageArgs - - def warn(marker: Marker, message: String): Unit = macro LoggerMacro.warnMessageMarker - - def warn(marker: Marker, message: String, cause: Throwable): Unit = macro LoggerMacro.warnMessageCauseMarker - - def warn(marker: Marker, message: String, args: Any*): Unit = macro LoggerMacro.warnMessageArgsMarker - - def whenWarnEnabled(body: Unit): Unit = macro LoggerMacro.warnCode - - // Info - - def info(message: String): Unit = macro LoggerMacro.infoMessage - - def info(message: String, cause: Throwable): Unit = macro LoggerMacro.infoMessageCause - - def info(message: String, args: Any*): Unit = macro LoggerMacro.infoMessageArgs - - def info(marker: Marker, message: String): Unit = macro LoggerMacro.infoMessageMarker - - def info(marker: Marker, message: String, cause: Throwable): Unit = macro LoggerMacro.infoMessageCauseMarker - - def info(marker: Marker, message: String, args: Any*): Unit = macro LoggerMacro.infoMessageArgsMarker - - def whenInfoEnabled(body: Unit): Unit = macro LoggerMacro.infoCode - - // Debug - - def debug(message: String): Unit = macro LoggerMacro.debugMessage - - def debug(message: String, cause: Throwable): Unit = macro LoggerMacro.debugMessageCause - - def debug(message: String, args: Any*): Unit = macro LoggerMacro.debugMessageArgs - - def debug(marker: Marker, message: String): Unit = macro LoggerMacro.debugMessageMarker - - def debug(marker: Marker, message: String, cause: Throwable): Unit = macro LoggerMacro.debugMessageCauseMarker - - def debug(marker: Marker, message: String, args: Any*): Unit = macro LoggerMacro.debugMessageArgsMarker - - def whenDebugEnabled(body: Unit): Unit = macro LoggerMacro.debugCode - - // Trace - - def trace(message: String): Unit = macro LoggerMacro.traceMessage - - def trace(message: String, cause: Throwable): Unit = macro LoggerMacro.traceMessageCause - - def trace(message: String, args: Any*): Unit = macro LoggerMacro.traceMessageArgs - - def trace(marker: Marker, message: String): Unit = macro LoggerMacro.traceMessageMarker - - def trace(marker: Marker, message: String, cause: Throwable): Unit = macro LoggerMacro.traceMessageCauseMarker - - def trace(marker: Marker, message: String, args: Any*): Unit = macro LoggerMacro.traceMessageArgsMarker - - def whenTraceEnabled(body: Unit): Unit = macro LoggerMacro.traceCode -} \ No newline at end of file diff --git a/src/main/scala-2/com/typesafe/scalalogging/LoggerTakingImplicitImpl.scala b/src/main/scala-2/com/typesafe/scalalogging/LoggerTakingImplicitImpl.scala deleted file mode 100644 index 070a6973..00000000 --- a/src/main/scala-2/com/typesafe/scalalogging/LoggerTakingImplicitImpl.scala +++ /dev/null @@ -1,86 +0,0 @@ -package com.typesafe.scalalogging - -import org.slf4j.Marker - -class LoggerTakingImplicitImpl[A] private[scalalogging] { - - // Error - - def error(message: String)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.errorMessage[A] - - def error(message: String, cause: Throwable)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.errorMessageCause[A] - - def error(message: String, args: Any*)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.errorMessageArgs[A] - - def error(marker: Marker, message: String)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.errorMessageMarker[A] - - def error(marker: Marker, message: String, cause: Throwable)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.errorMessageCauseMarker[A] - - def error(marker: Marker, message: String, args: Any*)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.errorMessageArgsMarker[A] - - def whenErrorEnabled(body: Unit)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.errorCode[A] - - // Warn - - def warn(message: String)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.warnMessage[A] - - def warn(message: String, cause: Throwable)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.warnMessageCause[A] - - def warn(message: String, args: Any*)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.warnMessageArgs[A] - - def warn(marker: Marker, message: String)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.warnMessageMarker[A] - - def warn(marker: Marker, message: String, cause: Throwable)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.warnMessageCauseMarker[A] - - def warn(marker: Marker, message: String, args: Any*)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.warnMessageArgsMarker[A] - - def whenWarnEnabled(body: Unit)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.warnCode[A] - - // Info - - def info(message: String)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.infoMessage[A] - - def info(message: String, cause: Throwable)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.infoMessageCause[A] - - def info(message: String, args: Any*)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.infoMessageArgs[A] - - def info(marker: Marker, message: String)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.infoMessageMarker[A] - - def info(marker: Marker, message: String, cause: Throwable)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.infoMessageCauseMarker[A] - - def info(marker: Marker, message: String, args: Any*)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.infoMessageArgsMarker[A] - - def whenInfoEnabled(body: Unit)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.infoCode[A] - - // Debug - - def debug(message: String)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.debugMessage[A] - - def debug(message: String, cause: Throwable)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.debugMessageCause[A] - - def debug(message: String, args: Any*)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.debugMessageArgs[A] - - def debug(marker: Marker, message: String)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.debugMessageMarker[A] - - def debug(marker: Marker, message: String, cause: Throwable)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.debugMessageCauseMarker[A] - - def debug(marker: Marker, message: String, args: Any*)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.debugMessageArgsMarker[A] - - def whenDebugEnabled(body: Unit)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.debugCode[A] - - // Trace - - def trace(message: String)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.traceMessage[A] - - def trace(message: String, cause: Throwable)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.traceMessageCause[A] - - def trace(message: String, args: Any*)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.traceMessageArgs[A] - - def trace(marker: Marker, message: String)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.traceMessageMarker[A] - - def trace(marker: Marker, message: String, cause: Throwable)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.traceMessageCauseMarker[A] - - def trace(marker: Marker, message: String, args: Any*)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.traceMessageArgsMarker[A] - - def whenTraceEnabled(body: Unit)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.traceCode[A] -} \ No newline at end of file