Skip to content
This repository has been archived by the owner on Jan 13, 2025. It is now read-only.

Commit

Permalink
Fix mockable macro to support backticks
Browse files Browse the repository at this point in the history
  • Loading branch information
dizinfector committed May 4, 2024
1 parent ed2b59f commit b8ac6f6
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 8 deletions.
9 changes: 9 additions & 0 deletions mock-tests/shared/src/main/scala/zio/mock/modules.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ object modules {
}
}

type BacktickObjectSinglePureValModule = `type`.BacktickObjectSinglePureValModule.Service
object `type` {
object BacktickObjectSinglePureValModule {
trait Service {
val foo: UIO[Unit]
}
}
}

type SimplePureDefsModule = SimplePureDefsModule.Service
object SimplePureDefsModule {
trait Service {
Expand Down
18 changes: 18 additions & 0 deletions mock-tests/shared/src/test/scala-2/zio/mock/MockableSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,24 @@ object MockableSpec extends ZIOSpecDefault {
val Bar: ModuleMock.Method[String, Throwable, String] = ModuleMock.Bar
}

Check
})(anything)
},
test("generates mocks for services that has backtick symbol") {
assert({
@mockable[`type`.BacktickObjectSinglePureValModule.Service]
object ModuleMock {
val someFooHelper: Expectation[`type`.BacktickObjectSinglePureValModule.Service] = Foo().atLeast(1)
}

object Check {
val mock: Mock[BacktickObjectSinglePureValModule] = ModuleMock

val Foo: ModuleMock.Effect[Unit, Nothing, Unit] = ModuleMock.Foo

val someFoo: Expectation[`type`.BacktickObjectSinglePureValModule.Service] = ModuleMock.someFooHelper
}

Check
})(anything)
}
Expand Down
26 changes: 18 additions & 8 deletions mock/shared/src/main/scala-2/zio/mock/MockableMacro.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,24 @@ private[mock] object MockableMacro {
case _ => abort("@mockable macro should only be applied to objects.")
}

val service: Type = c.typecheck(q"(??? : ${c.prefix.tree})").tpe.typeArgs.head
if (service == definitions.NothingTpe)
val serviceType: Type = c.typecheck(q"(??? : ${c.prefix.tree})").tpe.typeArgs.head

val serviceTypeArgument = c.prefix.tree match {
// trying to extract type parameter as it was passed (including ` signs)
case Apply(Select(New(AppliedTypeTree(_, typeParameterArgument :: _)), _), _) =>
typeParameterArgument.toString
case _ =>
serviceType.toString
}

if (serviceType == definitions.NothingTpe)
abort(s"@mockable macro requires type parameter: @mockable[Module.Service]")

val serviceBaseTypeParameters = service.baseType(service.typeSymbol).typeConstructor.typeParams.map(_.asType)
val serviceTypeParameterSubstitutions = serviceBaseTypeParameters.zip(service.typeArgs).toMap
val serviceBaseTypeParameters =
serviceType.baseType(serviceType.typeSymbol).typeConstructor.typeParams.map(_.asType)
val serviceTypeParameterSubstitutions = serviceBaseTypeParameters.zip(serviceType.typeArgs).toMap

val env: Type = c.typecheck(tq"$service", c.TYPEmode).tpe
val env = TypeName(serviceTypeArgument)
val any: Type = definitions.AnyTpe
val throwable: Type = c.typecheck(q"(??? : _root_.java.lang.Throwable)").tpe
val unit: Type = definitions.UnitTpe
Expand Down Expand Up @@ -279,7 +289,7 @@ private[mock] object MockableMacro {

val ownersToSkip = Set(typeOf[Object], typeOf[Any]).map(_.typeSymbol)

val methods = service.members
val methods = serviceType.members
.filter(member => !ownersToSkip.contains(member.owner.asType) && member.name.toTermName != TermName("$init$"))
.map(symbol => MethodInfo(symbol.asMethod))
.toList
Expand Down Expand Up @@ -329,8 +339,8 @@ private[mock] object MockableMacro {
val compose: $composeAsc =
_root_.zio.ZLayer.fromZIO(
_root_.zio.ZIO.service[_root_.zio.mock.Proxy].flatMap { proxy =>
withRuntime[_root_.zio.mock.Proxy, $service] { rts =>
class $serviceClassName extends $service {
withRuntime[_root_.zio.mock.Proxy, $env] { rts =>
class $serviceClassName extends $env {
..$mocks
}
_root_.zio.ZIO.succeed { new $serviceClassName }
Expand Down

0 comments on commit b8ac6f6

Please sign in to comment.