Skip to content

Commit ac6f210

Browse files
authored
Improve macros so they don't leave behind unused code (#372)
1 parent 519f3fb commit ac6f210

File tree

8 files changed

+76
-54
lines changed

8 files changed

+76
-54
lines changed

.bsp/sbt.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"name":"sbt","version":"1.4.7","bspVersion":"2.0.0-M5","languages":["scala"],"argv":["/Library/Java/JavaVirtualMachines/adoptopenjdk-11.jdk/Contents/Home/bin/java","-Xms100m","-Xmx100m","-classpath","/Users/bbonanno/Library/Application Support/JetBrains/IntelliJIdea2020.3/plugins/Scala/launcher/sbt-launch.jar","xsbt.boot.Boot","-bsp"]}
1+
{"name":"sbt","version":"1.4.9","bspVersion":"2.0.0-M5","languages":["scala"],"argv":["/Library/Java/JavaVirtualMachines/adoptopenjdk-11.jdk/Contents/Home/bin/java","-Xms100m","-Xmx100m","-classpath","/usr/local/Cellar/sbt/1.4.7/libexec/bin/sbt-launch.jar","xsbt.boot.Boot","-bsp"]}

build.sbt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ lazy val commonSettings =
1212
//Load version from the file so that Gradle/Shipkit and SBT use the same version
1313
version := {
1414
val versionFromEnv = System.getenv("PROJECT_VERSION")
15-
if (versionFromEnv != null && !versionFromEnv.trim().isEmpty()) {
15+
if (versionFromEnv != null && versionFromEnv.trim().nonEmpty) {
1616
versionFromEnv
1717
} else {
1818
val pattern = """^version=(.+)$""".r
@@ -33,17 +33,17 @@ lazy val commonSettings =
3333
"-encoding",
3434
"UTF-8",
3535
"-Xfatal-warnings",
36+
// "-Xmacro-settings:mockito-print-when,mockito-print-do-something,mockito-print-verify,mockito-print-expect,mockito-print-captor,mockito-print-matcher,mockito-print-extractor,mockito-print-wrapper,mockito-print-lenient",
3637
"-language:reflectiveCalls,implicitConversions,experimental.macros,higherKinds"
37-
// "-Xmacro-settings:mockito-print-when,mockito-print-do-something,mockito-print-verify,mockito-print-expect,mockito-print-captor,mockito-print-matcher,mockito-print-extractor,mockito-print-wrapper,mockito-print-lenient"
3838
),
3939
scalacOptions ++= {
4040
CrossVersion.partialVersion(scalaVersion.value) match {
4141
case Some((2, 11)) =>
4242
Seq("-Xsource:2.12", "-Ypartial-unification")
4343
case Some((2, 12)) =>
44-
Seq("-Ypartial-unification")
44+
Seq("-Ypartial-unification", "-Ywarn-unused:locals")
4545
case _ =>
46-
Nil
46+
Seq("-Ywarn-unused:locals")
4747
}
4848
},
4949
Test / scalacOptions += "-Ywarn-value-discard",
@@ -79,7 +79,7 @@ lazy val publishSettings = Seq(
7979
lazy val noPublishingSettings = Seq(
8080
publish := {},
8181
publishLocal := {},
82-
publishArtifact := false,
82+
publishArtifact := false
8383
)
8484

8585
lazy val noCrossBuildSettings = Seq(
@@ -212,4 +212,4 @@ lazy val macroCommon = (project in file("macro-common"))
212212

213213
lazy val root = (project in file("."))
214214
.settings(noPublishingSettings, noCrossBuildSettings)
215-
.aggregate (common, core, scalatest, specs2, cats, scalaz)
215+
.aggregate(common, core, scalatest, specs2, cats, scalaz)

macro/src/main/scala/org/mockito/DoSomethingMacro.scala

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -187,27 +187,28 @@ object DoSomethingMacro {
187187
if (pf.isDefinedAt(invocation))
188188
pf(invocation)
189189
else if (pf.isDefinedAt(invocation.children.last)) {
190-
val values = invocation.children
191-
.dropRight(1)
192-
.collect { case q"$_ val $name:$_ = $value" =>
193-
name.toString -> value.asInstanceOf[c.Tree]
194-
}
195-
.toMap
196-
197-
val nonMatchers = invocation.children.dropRight(1).collect {
198-
case t @ q"$_ val $_:$_ = $value" if !isMatcher(c)(value) => t
199-
}
190+
val vals = invocation.children.dropRight(1)
191+
val valsByName = vals.collect { case line @ q"$_ val $name:$_ = $value" =>
192+
name.toString -> (value.asInstanceOf[c.Tree], line)
193+
}.toMap
200194

201-
invocation.children.last match {
195+
val inlinedArgsCall = invocation.children.last match {
202196
case q"$obj.$method[..$targs](...$args)" =>
203197
val newArgs = args.map { a =>
204198
transformArgs(c)(a).map {
205-
case p if show(p).startsWith("x$") => transformArg(c)(values(p.toString))
199+
case p if show(p).startsWith("x$") => transformArg(c)(valsByName(p.toString)._1)
206200
case other => other
207201
}
208202
}
209-
q"..$nonMatchers; $action.when($obj).$method[..$targs](...$newArgs)"
203+
q"$action.when($obj).$method[..$targs](...$newArgs)"
204+
}
205+
206+
val call = show(inlinedArgsCall)
207+
val usedVals = valsByName.collect {
208+
case (name, (_, line)) if call.contains(name) => line
210209
}
210+
211+
q"..$usedVals; $inlinedArgsCall"
211212
} else throw new Exception(s"Couldn't recognize invocation ${show(invocation)}")
212213
}
213214
}

macro/src/main/scala/org/mockito/VerifyMacro.scala

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -62,27 +62,28 @@ private[mockito] trait VerificationMacroTransformer {
6262
if (pf.isDefinedAt(invocation))
6363
pf(invocation)
6464
else if (invocation.children.nonEmpty && pf.isDefinedAt(invocation.children.last)) {
65-
val values = invocation.children
66-
.dropRight(1)
67-
.collect { case q"$_ val $name:$_ = $value" =>
68-
name.toString -> value.asInstanceOf[c.Tree]
69-
}
70-
.toMap
71-
72-
val nonMatchers = invocation.children.dropRight(1).collect {
73-
case t @ q"$_ val $_:$_ = $value" if !isMatcher(c)(value) => t
74-
}
65+
val vals = invocation.children.dropRight(1)
66+
val valsByName = vals.collect { case line @ q"$_ val $name:$_ = $value" =>
67+
name.toString -> (value.asInstanceOf[c.Tree], line)
68+
}.toMap
7569

76-
invocation.children.last match {
70+
val inlinedArgsCall = invocation.children.last match {
7771
case q"$obj.$method[..$targs](...$args)" =>
7872
val newArgs = args.map { a =>
7973
transformArgs(c)(a).map {
80-
case p if show(p).startsWith("x$") => transformArg(c)(values(p.toString))
74+
case p if show(p).startsWith("x$") => transformArg(c)(valsByName(p.toString)._1)
8175
case other => other
8276
}
8377
}
84-
q"..$nonMatchers; verification($order.verifyWithMode($obj, $times).$method[..$targs](...$newArgs))"
78+
q"verification($order.verifyWithMode($obj, $times).$method[..$targs](...$newArgs))"
79+
}
80+
81+
val call = show(inlinedArgsCall)
82+
val usedVals = valsByName.collect {
83+
case (name, (_, line)) if call.contains(name) => line
8584
}
85+
86+
q"..$usedVals; $inlinedArgsCall"
8687
} else throw new Exception(s"Couldn't recognize invocation ${show(invocation)}")
8788
}
8889

macro/src/main/scala/org/mockito/WhenMacro.scala

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,27 +22,28 @@ object WhenMacro {
2222
if (pf.isDefinedAt(invocation))
2323
pf(invocation)
2424
else if (pf.isDefinedAt(invocation.children.last)) {
25-
val values = invocation.children
26-
.dropRight(1)
27-
.collect { case q"$_ val $name:$_ = $value" =>
28-
name.toString -> value.asInstanceOf[c.Tree]
29-
}
30-
.toMap
31-
32-
val nonMatchers = invocation.children.dropRight(1).collect {
33-
case t @ q"$_ val $_:$_ = $value" if !isMatcher(c)(value) => t
34-
}
25+
val vals = invocation.children.dropRight(1)
26+
val valsByName = vals.collect { case line @ q"$_ val $name:$_ = $value" =>
27+
name.toString -> (value.asInstanceOf[c.Tree], line)
28+
}.toMap
3529

36-
invocation.children.last match {
30+
val inlinedArgsCall = invocation.children.last match {
3731
case q"$obj.$method[..$targs](...$args)" =>
3832
val newArgs = args.map { a =>
3933
transformArgs(c)(a).map {
40-
case p if show(p).startsWith("x$") => transformArg(c)(values(p.toString))
34+
case p if show(p).startsWith("x$") => transformArg(c)(valsByName(p.toString)._1)
4135
case other => other
4236
}
4337
}
44-
q"..$nonMatchers; $obj.$method[..$targs](...$newArgs)"
38+
q"$obj.$method[..$targs](...$newArgs)"
39+
}
40+
41+
val call = show(inlinedArgsCall)
42+
val usedVals = valsByName.collect {
43+
case (name, (_, line)) if call.contains(name) => line
4544
}
45+
46+
q"..$usedVals; $inlinedArgsCall"
4647
} else throw new Exception(s"Couldn't recognize invocation ${show(invocation)}")
4748
}
4849

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package user.org.mockito
2+
3+
import org.mockito.{ ArgumentMatchersSugar, IdiomaticMockito }
4+
import org.scalatest.flatspec.AnyFlatSpec
5+
import org.scalatest.matchers.should.Matchers
6+
7+
import java.time.Instant
8+
9+
class Issue371 extends AnyFlatSpec with IdiomaticMockito with Matchers with ArgumentMatchersSugar {
10+
11+
trait TestTrait {
12+
def anyRef(a: Instant, b: Instant): Unit
13+
}
14+
15+
it should "deal with matchers on named params" in {
16+
val t = mock[TestTrait]
17+
18+
t.anyRef(Instant.EPOCH, Instant.EPOCH)
19+
20+
t.anyRef(b = Instant.EPOCH, a = Instant.EPOCH).wasCalled(once)
21+
}
22+
23+
}

specs2/src/test/scala/org/mockito/specs2/MockitoScalaNewSyntaxSpec.scala

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -356,8 +356,6 @@ The Mockito trait is reusable in other contexts
356356
}
357357

358358
def verification27 = {
359-
object list extends list
360-
361359
val foo = mock[FooComponent]
362360
val controller = spy(new TestController(foo))
363361

@@ -723,8 +721,8 @@ The Mockito trait is reusable in other contexts
723721
}
724722

725723
def mockitoMatchers2 = {
726-
val m = mock[M]
727-
val shouldReturnOk = m.method(*, *) returns 1
724+
val m = mock[M]
725+
m.method(*, *) returns 1
728726

729727
m.method(new B, b = true)
730728
got {

specs2/src/test/scala/org/mockito/specs2/MockitoScalaSpec.scala

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -355,8 +355,6 @@ The Mockito trait is reusable in other contexts
355355
}
356356

357357
def verification27 = {
358-
object list extends list
359-
360358
val foo = mock[FooComponent]
361359
val controller = spy(new TestController(foo))
362360

@@ -720,8 +718,8 @@ The Mockito trait is reusable in other contexts
720718
}
721719

722720
def mockitoMatchers2 = {
723-
val m = mock[M]
724-
val returnsOk = m.method(*, *) returns 1
721+
val m = mock[M]
722+
m.method(*, *) returns 1
725723

726724
m.method(new B, b = true)
727725
there was one(m).method(any[B], any[Boolean])

0 commit comments

Comments
 (0)