Scala companion's unapply injected via SyntheticMembersInjector API not picked?

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?

2 comments
Comment actions Permalink
Official 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.

 

Comment actions Permalink

A screenshot of the highlighting.

My IntelliJ version:

0

Please sign in to leave a comment.