![JAR search and dependency download from the Maven repository](/logo.png)
com.softwaremill.clippy.CompilationErrorParser.scala Maven / Gradle / Ivy
package com.softwaremill.clippy
import java.util.regex.Pattern
object CompilationErrorParser {
private val FoundRegexp = """found\s*:\s*([^\n]+)""".r
private val RequiredPrefixRegexp = """required\s*:""".r
private val AfterRequiredRegexp = """required\s*:\s*([^\n]+)""".r
private val WhichExpandsToRegexp = """\s*\(which expands to\)\s*([^\n]+)""".r
private val NotFoundRegexp = """not found\s*:\s*([^\n]+)""".r
private val NotAMemberRegexp = """:?\s*([^\n:]+) is not a member of""".r
private val NotAMemberOfRegexp = """is not a member of\s*([^\n]+)""".r
private val ImplicitNotFoundRegexp = """could not find implicit value for parameter\s*([^:]+):\s*([^\n]+)""".r
private val DivergingImplicitExpansionRegexp = """diverging implicit expansion for type\s*([^\s]+)\s*.*\s*starting with method\s*([^\s]+)\s*in\s*([^\n]+)""".r
private val TypeArgumentsDoNotConformToOverloadedBoundsRegexp = """type arguments \[([^\]]+)\] conform to the bounds of none of the overloaded alternatives of\s*([^:\n]+)[^:]*: ([^\n]+)""".r
private val TypeclassNotFoundRegexp = """No implicit (.*) defined for ([^\n]+)""".r
def parse(e: String): Option[CompilationError[ExactT]] = {
val error = e.replaceAll(Pattern.quote("[error]"), "")
if (error.contains("type mismatch")) {
RequiredPrefixRegexp.split(error).toList match {
case List(beforeReq, afterReq) =>
for {
found <- FoundRegexp.findFirstMatchIn(beforeReq)
foundExpandsTo = WhichExpandsToRegexp.findFirstMatchIn(beforeReq)
required <- AfterRequiredRegexp.findFirstMatchIn(error)
requiredExpandsTo = WhichExpandsToRegexp.findFirstMatchIn(afterReq)
} yield {
val notes = requiredExpandsTo match {
case Some(et) => getNotesFromIndex(afterReq, et.end)
case None => getNotesFromIndex(error, required.end)
}
TypeMismatchError[ExactT](ExactT(found.group(1)), foundExpandsTo.map(m => ExactT(m.group(1))),
ExactT(required.group(1)), requiredExpandsTo.map(m => ExactT(m.group(1))),
notes)
}
case _ =>
None
}
}
else if (error.contains("not found")) {
for {
what <- NotFoundRegexp.findFirstMatchIn(error)
} yield NotFoundError[ExactT](ExactT(what.group(1)))
}
else if (error.contains("is not a member of")) {
for {
what <- NotAMemberRegexp.findFirstMatchIn(error)
notAMemberOf <- NotAMemberOfRegexp.findFirstMatchIn(error)
} yield NotAMemberError[ExactT](ExactT(what.group(1)), ExactT(notAMemberOf.group(1)))
}
else if (error.contains("could not find implicit value for parameter")) {
for {
inf <- ImplicitNotFoundRegexp.findFirstMatchIn(error)
} yield ImplicitNotFoundError[ExactT](ExactT(inf.group(1)), ExactT(inf.group(2)))
}
else if (error.contains("diverging implicit expansion for type")) {
for {
inf <- DivergingImplicitExpansionRegexp.findFirstMatchIn(error)
} yield DivergingImplicitExpansionError[ExactT](ExactT(inf.group(1)), ExactT(inf.group(2)), ExactT(inf.group(3)))
}
else if (error.contains("conform to the bounds of none of the overloaded alternatives")) {
for {
inf <- TypeArgumentsDoNotConformToOverloadedBoundsRegexp.findFirstMatchIn(error)
} yield TypeArgumentsDoNotConformToOverloadedBoundsError[ExactT](ExactT(inf.group(1)), ExactT(inf.group(2)),
inf.group(3).split(Pattern.quote(" ")).toSet.map(ExactT.apply))
}
else if (error.contains("No implicit")) {
for {
inf <- TypeclassNotFoundRegexp.findFirstMatchIn(error)
group2 = inf.group(2)
} yield TypeclassNotFoundError(ExactT(inf.group(1)), ExactT(if (group2.endsWith(".")) group2.substring(0, group2.length-1) else group2))
}
else None
}
private def getNotesFromIndex(msg: String, afterIdx: Int): Option[String] = {
val fromIdx = afterIdx+1
if (msg.length >= fromIdx+1) {
val notes = msg.substring(fromIdx).trim
if (notes == "") None else Some(notes)
} else None
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy