Skip to content
This repository was archived by the owner on Mar 27, 2023. It is now read-only.

Commit d09045e

Browse files
authored
Merge pull request #28 from ShaneDelmore/Issue_27_support_no_implicit_typeclass_found
Implement advice for no implicit typeclass found requested in issue #27
2 parents 1c3981c + 2f3d170 commit d09045e

File tree

3 files changed

+47
-0
lines changed

3 files changed

+47
-0
lines changed

model/src/main/scala/com/softwaremill/clippy/CompilationError.scala

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,26 @@ case class ImplicitNotFoundError[T <: Template](parameter: T, implicitType: T) e
103103
RegexT.fromPattern(implicitType.v))
104104
}
105105

106+
case class TypeclassNotFoundError[T <: Template](typeclass: T, forType: T) extends CompilationError[T] {
107+
108+
override def toString = s"Implicit $typeclass typeclass not found error: for type $forType"
109+
110+
override def toJson =
111+
JObject(
112+
TypeField -> JString("typeclassNotFound"),
113+
"typeclass" -> JString(typeclass.v),
114+
"forType" -> JString(forType.v)
115+
)
116+
117+
override def matches(other: CompilationError[ExactT])(implicit ev: T =:= RegexT) = other match {
118+
case TypeclassNotFoundError(p, i) => typeclass.matches(p) && forType.matches(i)
119+
case _ => false
120+
}
121+
122+
override def asRegex(implicit ev: T =:= ExactT) = TypeclassNotFoundError(RegexT.fromPattern(typeclass.v),
123+
RegexT.fromPattern(forType.v))
124+
}
125+
106126
case class DivergingImplicitExpansionError[T <: Template](forType: T, startingWith: T, in: T) extends CompilationError[T] {
107127

108128
override def toString = s"Diverging implicit expansion error: for type $forType starting with $startingWith in $in"
@@ -203,6 +223,12 @@ object CompilationError {
203223
alternatives <- multipleRegexTFromJson(fields, "alternatives")
204224
} yield TypeArgumentsDoNotConformToOverloadedBoundsError(typeArgs, alternativesOf, alternatives)
205225

226+
case "typeclassNotFound" =>
227+
for {
228+
typeclass <- regexTFromJson(fields, "typeclass")
229+
forType <- regexTFromJson(fields, "forType")
230+
} yield TypeclassNotFoundError(typeclass, forType)
231+
206232
case _ => None
207233
}
208234

model/src/main/scala/com/softwaremill/clippy/CompilationErrorParser.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ object CompilationErrorParser {
1313
private val ImplicitNotFoundRegexp = """could not find implicit value for parameter\s*([^:]+):\s*([^\n]+)""".r
1414
private val DivergingImplicitExpansionRegexp = """diverging implicit expansion for type\s*([^\s]+)\s*.*\s*starting with method\s*([^\s]+)\s*in\s*([^\n]+)""".r
1515
private val TypeArgumentsDoNotConformToOverloadedBoundsRegexp = """type arguments \[([^\]]+)\] conform to the bounds of none of the overloaded alternatives of\s*([^:\n]+)[^:]*: ([^\n]+)""".r
16+
private val TypeclassNotFoundRegexp = """No implicit (.*) defined for (.*)\.""".r
17+
18+
/*
19+
No implicit Ordering defined for java.time.LocalDate.
20+
Seq(java.time.LocalDate.MIN, java.time.LocalDate.MAX).sorted
21+
^
22+
*/
1623

1724
def parse(e: String): Option[CompilationError[ExactT]] = {
1825
val error = e.replaceAll(Pattern.quote("[error]"), "")
@@ -58,6 +65,11 @@ object CompilationErrorParser {
5865
} yield TypeArgumentsDoNotConformToOverloadedBoundsError[ExactT](ExactT(inf.group(1)), ExactT(inf.group(2)),
5966
inf.group(3).split(Pattern.quote(" <and> ")).toSet.map(ExactT.apply))
6067
}
68+
else if (error.contains("No implicit")) {
69+
for {
70+
inf <- TypeclassNotFoundRegexp.findFirstMatchIn(error)
71+
} yield TypeclassNotFoundError(ExactT(inf.group(1)), ExactT(inf.group(2)))
72+
}
6173
else None
6274
}
6375
}

tests/src/test/scala/org/softwaremill/clippy/CompileTests.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@ class CompileTests extends FlatSpec with Matchers with BeforeAndAfterAll {
5555
).asRegex,
5656
"incorrect class name passed to TableQuery",
5757
Library("com.typesafe.slick", "slick", "3.1.1")
58+
),
59+
Advice(
60+
TypeclassNotFoundError(
61+
ExactT("Ordering"),
62+
ExactT("java.time.LocalDate")
63+
).asRegex,
64+
"implicit val localDateOrdering: Ordering[java.time.LocalDate] = Ordering.by(_.toEpochDay)",
65+
Library("java-lang", "time", "8+")
5866
)
5967
)
6068

@@ -91,6 +99,7 @@ class CompileTests extends FlatSpec with Matchers with BeforeAndAfterAll {
9199
|class A()
92100
|val a = wire[A]
93101
""".stripMargin,
102+
"missing_typeclass" -> "Seq(java.time.LocalDate.MIN, java.time.LocalDate.MAX).sorted",
94103
"slick" -> """
95104
|case class User(id1: Long, id2: Long)
96105
|trait TestSchema {

0 commit comments

Comments
 (0)