How to debug a macro annotation?
<h2>Background</h2>

<p>I'm trying to add a <code>@Prisms</code> annotation to Monocle that will work as follows. Given:</p>

<pre><code>@Prisms sealed trait Foo
case object A extends Foo
case object B extends Foo
</code></pre>

<p>it will generate a companion object for <code>Foo</code>:</p>

<pre><code>object Foo {
  val a = monocle.macros.GenPrism.apply[Foo, A]
  val b = monocle.macros.GenPrism.apply[Foo, B]
}
</code></pre>

<p>(or if the companion object already exists, it will add those methods to it).</p>

<p>The macro relies on <code>directKnownSubclasses</code> to find <code>A</code> and <code>B</code>, so there will be a note in the Monocle readme recommending that people use Typelevel Scala. I've configured Monocle to use TLS on my branch.</p>

<h2>First attempt</h2>

<p>I tried using <code>TypeName</code>s to represent the parent type <code>Foo</code> and child type (<code>A</code> or <code>B</code>):</p>

<pre><code>def findSubclasses(typeName: TypeName): Set[TypeName] = {
  // Note: disable macros to prevent stack overflow caused by infinite typing loop!
  val tpe = c.typecheck(Ident(typeName), mode = c.TYPEmode, silent = true, withMacrosDisabled = true)
  tpe.symbol.asClass.knownDirectSubclasses.map(_.asType.name)
}

def prisms(parentTypename: TypeName, childNames: Set[TypeName]): Set[Tree] = childNames.map { childName =&gt;
  val prismName = TermName(prefix + childName.decodedName.toString.toLowerCase)
  q"""val $prismName = monocle.macros.GenPrism.apply[$parentTypename, $childName]"""
}
</code></pre>

<p>This generates what looks like reasonable code:</p>

<pre><code>{
  sealed trait Foo;
  object Foo {
    val a = monocle.macros.GenPrism.apply[Foo, A];
    val b = monocle.macros.GenPrism.apply[Foo, B]
  };
  ()
}
</code></pre>

<p>But it doesn't seem to work:</p>

<pre><code>[error] /Users/chris/code/Monocle/test/shared/src/test/scala/other/PrismsAnnotationSpec.scala:5: not found: type A
[error] @monocle.macros.Prisms sealed trait Foo
[error]  ^
[error] one error found
</code></pre>

<h2>Second attempt</h2>

<p>I also tried using <code>TypeSymbol</code>s instead of <code>TypeName</code>s:</p>

<pre><code>def prisms(parentTypename: TypeName, childSymbols: Set[TypeSymbol]): Set[Tree] = {
  val parentSymbol: TypeSymbol = 
    c.typecheck(Ident(parentTypename), mode = c.TYPEmode, silent = true, withMacrosDisabled = true)
      .symbol
      .asType
  childSymbols.map { childSymbol =&gt;
    val prismName = TermName(prefix + childSymbol.name.decodedName.toString.toLowerCase)
    q"""val $prismName = monocle.macros.GenPrism.apply[$parentSymbol, $childSymbol]"""
  }
}
</code></pre>

<p>But this gives me the following error, so I'm guessing the generated tree is invalid:</p>

<pre><code>[error] /Users/chris/code/Monocle/test/shared/src/test/scala/other/PrismsAnnotationSpec.scala:5: macro annotation could not be expanded (the most common reason for that is that you need to enable the macro paradise plugin; another possibility is that you try to use macro annotation in the same compilation run that defines it)
[error] @monocle.macros.Prisms sealed trait Foo
[error]  ^
[error] one error found
</code></pre>

<h2>Third attempt</h2>

<p>I also tried turning the <code>TypeSymbol</code>s into <code>Type</code>s:</p>

<pre><code>def prisms(parentTypename: TypeName, childSymbols: Set[TypeSymbol]): Set[Tree] = {
  val parentSymbol: TypeSymbol = 
    c.typecheck(Ident(parentTypename), mode = c.TYPEmode, silent = true, withMacrosDisabled = true)
      .symbol
      .asType
  childSymbols.map { childSymbol =&gt;
    val prismName = TermName(prefix + childSymbol.name.decodedName.toString.toLowerCase)
    q"""val $prismName = monocle.macros.GenPrism.apply[${parentSymbol.toType}, ${childSymbol.toType}]"""
  }
}
</code></pre>

<p>But I get the same error, saying the annotation could not be expanded.</p>

<p>Now I'm out of ideas.</p>

<h2>How to reproduce</h2>

<p>The complete code is available on this branch: <a href="https://github.com/cb372/Monocle/tree/sealed-trait-macro-annotation" rel="nofollow">https://github.com/cb372/Monocle/tree/sealed-trait-macro-annotation</a>.</p>

<ul>
<li><a href="https://github.com/cb372/Monocle/blob/c0185125665d2378275985ba83978f7fa8843cc1/macro/shared/src/main/scala/monocle/macros/Prisms.scala" rel="nofollow">First attempt</a></li>
<li><a href="https://github.com/cb372/Monocle/blob/efd54537f10bd1e0ed7a9764121e8e900de123f1/macro/shared/src/main/scala/monocle/macros/Prisms.scala" rel="nofollow">Second attempt</a></li>
<li><a href="https://github.com/cb372/Monocle/blob/3290ca6e01c57c08ec0ad0fc755efbf774551cb7/macro/shared/src/main/scala/monocle/macros/Prisms.scala" rel="nofollow">Third attempt</a></li>
</ul>

<p>The macro is used in <code>test/shared/src/test/scala/other/PrismsAnnotationSpec.scala</code>. To compile it, run <code>sbt test:compile</code>.</p>