Scala companion's unapply injected via SyntheticMembersInjector API not picked? Follow
I'm developing a Scala annotation macro that creates companion objects for all classes inside a "wrapper object". E.g. given the code
@TermHierarchy
object terms {
class Var(name: String)
}
the macro, among other things, rewrites the original class and adds a companion object with apply and unapply methods:
object terms {
class Var private (val name: String)
object Var {
def apply(name: String): Var = new Var(name)
def unapply(v: Var): Option[String] = Some(v.name)
}
}
To make IntelliJ know about the generated code, I'm developing an IntelliJ plugin based on the SyntheticMembersInjector API, which generates the following:
object Var {
def apply(name: String): Var = ???
def unapply(obj: Var): Option[String] = ???
}
The core of the IntelliJ plugin looks as follows:
override def injectInners(source: ScTypeDefinition): Seq[String] = {
source match {
/* Find annotated object */
case obj: ScObject if obj.findAnnotationNoAliases("TermHierarchy") != null =>
obj.extendsBlock.members flatMap ({
case clazz: ScClass =>
val params = clazz.constructor.get.parameterList.params
val applyArgs =
params
.map(p =>s"${p.name}: ${p.`type`().right.get.presentableText}")
.mkString(", ")
val applyDef = s"def apply($applyArgs): ${clazz.getName} = ???"
val unapplyTypes =
params
.map(_.`type`().right.get.presentableText)
.mkString(", ")
val unapplyDef =
if (params.isEmpty) {
s"def unapply(obj: ${clazz.getName}): Boolean) = ???"
} else if (params.lengthCompare(1) == 0) {
s"def unapply(obj: ${clazz.getName}): Option[$unapplyTypes] = ???"
} else {
s"def unapply(obj: ${clazz.getName}): Option[($unapplyTypes)] = ???"
}
val companionObject =
s"""|object ${clazz.getName} {
| $applyDef
| $unapplyDef
|}""".stripMargin
Seq(companionObject)
case _ =>
Seq.empty
})
case _ =>
Seq.empty
}
}
IntelliJ picks up the apply method as expected, i.e.
val v = Var("x")
is highlighted just fine and IntelliJ reports that v is of type Var.
Problem: IntelliJ appears to also pick up the unapply method, but pattern matching on Var is highlighted as erroneous. I.e. the following is highlighted fine
val Some(s) = Var.unapply(Var("x")
and s is known to be a string, but for the snippet
val Var(s) = Var("x")
the part Var(s) is highlighted as erroneous and hovering over it yields "Cannot resolve symbol Var".
Any idea what I could be doing wrong here?
Please sign in to leave a comment.
Hi, Malte,
Please check `idea.log` file, it may contain some exceptions (Help | Show Log in Explorer). From what I can see, you use unsafe `right.get` method on a type result. You may try to use `getOrAny` or `getOrNothing` extension methods instead.
A screenshot of the highlighting.
My IntelliJ version: