Skip to content

Commit b76a89c

Browse files
authored
Merge pull request #30 from kubukoz/more-honest-wildcard-error
Show more honest errors when a wildcard name is used in implicit0
2 parents 84a9846 + a4bc267 commit b76a89c

File tree

5 files changed

+58
-6
lines changed

5 files changed

+58
-6
lines changed

better-monadic-for/src/main/scala/com/olegpy/bm4/ImplicitPatterns.scala

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,19 +102,43 @@ trait ImplicitPatterns extends TreeUtils { self =>
102102

103103
object HasImplicitPattern {
104104
def unapply(arg: Tree): Boolean = arg.exists {
105-
case q"implicit0(${Bind(t: TermName, Typed(Ident(termNames.WILDCARD), _))})" if t != termNames.WILDCARD =>
105+
case t@q"implicit0(${WildcardIdentifier(typed)})" =>
106+
val andType = if(typed) " and type" else ""
107+
108+
reporter.error(
109+
arg.pos,
110+
s"implicit pattern requires an identifier, but a wildcard was used: `$t`. " +
111+
s"This doesn't introduce anything into the implicit scope. You might want to remove the implicit0 pattern$andType."
112+
)
113+
false
114+
115+
case q"implicit0(${Bind(t: TermName, Typed(Ident(termNames.WILDCARD), _))})" =>
106116
true
117+
107118
case q"implicit0($_)" =>
108-
reporter.error(arg.pos, "implicit pattern only supports identifier with type pattern")
119+
reporter.error(arg.pos, "implicit pattern only supports identifiers with a type pattern")
109120
false
121+
110122
case q"implicit0(..$_)" =>
111123
reporter.error(arg.pos, "implicit pattern only accepts a single parameter")
112124
false
125+
113126
case _ =>
114127
false
115128
}
116129
}
117130

131+
object WildcardIdentifier {
132+
/**
133+
* Matches the `_: Foo` and `_` patterns, and specifies whether the type annotation was present.
134+
*/
135+
def unapply(arg: Tree): Option[Boolean] = arg match {
136+
case Typed(Ident(termNames.WILDCARD), _) => Some(true)
137+
case Ident(termNames.WILDCARD) => Some(false)
138+
case _ => None
139+
}
140+
}
141+
118142
object StripImplicitZero extends Transformer {
119143
override def transform(tree: Tree): Tree = tree match {
120144
case q"implicit0(${Bind(t: TermName, _)})" => super.transform(Bind(t, Ident(termNames.WILDCARD)))

pcplod-tests/src/test/resources/Arrows.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ object PcTest {
55
x@flatmap@x: Int <- mkRight(66)
66
(_, y@map@y) <- mkRight((11, 42))
77
} yield xx + yy
8-
}
8+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
object Wildcards {
2+
val a = for {
3+
implicit0(_: Int) <- Option(42)
4+
} yield "ok"
5+
6+
val b = for {
7+
implicit0(_) <- Option(42)
8+
} yield "ok"
9+
}

pcplod-tests/src/test/scala/com/olegpy/bm4/PresentationCompiler.scala

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,26 @@ class PresentationCompiler extends FreeSpec {
1818
assert(pc.typeAtPoint('map).contains("Int"))
1919
}
2020
}
21+
22+
"PC should yield errors" - {
23+
"when implicit0(_: Tpe) is used" in {
24+
withMrPlod("Wildcards.scala") { pc =>
25+
val firstError = pc.messages.head
26+
27+
assert(firstError.severity == PcMessageSeverity.Error)
28+
assert(firstError.message == "implicit pattern requires an identifier, but a wildcard was used: `implicit0((_: Int))`. " +
29+
"This doesn't introduce anything into the implicit scope. You might want to remove the implicit0 pattern and type.")
30+
}
31+
}
32+
33+
"when implicit0(_) is used" in {
34+
withMrPlod("Wildcards.scala") { pc =>
35+
val secondError = pc.messages(1)
36+
37+
assert(secondError.severity == PcMessageSeverity.Error)
38+
assert(secondError.message == "implicit pattern requires an identifier, but a wildcard was used: `implicit0(_)`. " +
39+
"This doesn't introduce anything into the implicit scope. You might want to remove the implicit0 pattern.")
40+
}
41+
}
42+
}
2143
}

plugin-tests/src/test/scala/com/olegpy/bm4/TestImplicitPatterns.scala

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@ class TestImplicitPatterns extends FreeSpec {
1313
def typed[A](a: A) = ()
1414
case class ImplicitTest2(id: String)
1515

16-
// Make IDE happy
17-
// object implicit0 { def unapply[A](a: A) = Some(a) }
18-
1916
"Implicit patterns support" - {
2017
"for-comprehensions with plain types" - {
2118
"with type ascription" - {

0 commit comments

Comments
 (0)