This page is no longer maintained — Please continue to the home page at www.scala-lang.org

How do you create a new ClassDef in compiler a plugin?

4 replies
monster
Joined: 2011-10-22,
User offline. Last seen 42 years 45 weeks ago.

I want to automatically generate an implementation for a trait, based
on an annotation on the trait. I have done this for the Java compiler,
and it was relatively easy. Unfortunately, I can find many example
modifying code on the fly in compiler plugins, but no example creating
completely new classes. The only thing I found was this discussion,
which does not seem to come to any clear solution:

http://www.scala-lang.org/node/1560

And I know that Paul Butcher is creating new classes, but he uses a
sbt plugin, instead of a compiler plugin. So, does anyone know of some
plugin that generate new classes directly?

In the Java compiler, generating new classes is basically the only
thing you can do in a plugin, without "cheating" by accessing the
"internal API", so I find it hard to believe that is it not possible
in a normal Scala compiler plugin.

So far, I have found how to create the new ClassDef, and add it to the
package, but then I get this Exception, which I cannot resolve:

??? base not found in basetypes of type ABCEDF
error: java.util.NoSuchElementException: head of empty list
at scala.collection.immutable.Nil$.head(List.scala:371)
at scala.collection.immutable.Nil$.head(List.scala:368)
at scala.tools.nsc.transform.Erasure$ErasureTransformer$$anonfun$13$
$anon$5.parents(Erasure.scala:836)
at scala.tools.nsc.transform.OverridingPairs
$Cursor.(OverridingPairs.scala:129)
at scala.tools.nsc.transform.Erasure$ErasureTransformer$$anonfun$13$
$anon$5.(Erasure.scala:835)
at scala.tools.nsc.transform.Erasure$ErasureTransformer$$anonfun
$13.apply(Erasure.scala:835)
at scala.tools.nsc.transform.Erasure$ErasureTransformer$$anonfun
$13.apply(Erasure.scala:835)
at scala.tools.nsc.symtab.SymbolTable.atPhase(SymbolTable.scala:96)
at scala.tools.nsc.transform.Erasure
$ErasureTransformer.bridgeDefs(Erasure.scala:834)
at scala.tools.nsc.transform.Erasure
$ErasureTransformer.addBridges(Erasure.scala:910)
at scala.tools.nsc.transform.Erasure$ErasureTransformer$$anon
$3.preErase(Erasure.scala:1073)
at scala.tools.nsc.transform.Erasure$ErasureTransformer$$anon
$3.transform(Erasure.scala:1095)
at scala.tools.nsc.ast.Trees
$Transformer.transformTemplate(Trees.scala:875)
at scala.tools.nsc.ast.Trees$Transformer$$anonfun$transform
$2.apply(Trees.scala:767)
at scala.tools.nsc.ast.Trees$Transformer$$anonfun$transform
$2.apply(Trees.scala:766)
at scala.tools.nsc.ast.Trees$Transformer.atOwner(Trees.scala:899)
at scala.tools.nsc.transform.TypingTransformers
$TypingTransformer.atOwner(TypingTransformers.scala:38)
at scala.tools.nsc.transform.TypingTransformers
$TypingTransformer.atOwner(TypingTransformers.scala:31)
at scala.tools.nsc.ast.Trees$Transformer.transform(Trees.scala:765)
at scala.tools.nsc.transform.TypingTransformers
$TypingTransformer.transform(TypingTransformers.scala:53)
at scala.tools.nsc.transform.Erasure$ErasureTransformer$$anon
$3.transform(Erasure.scala:1104)
at scala.tools.nsc.ast.Trees$Transformer$$anonfun$transformStats
$1.apply(Trees.scala:891)
at scala.tools.nsc.ast.Trees$Transformer$$anonfun$transformStats
$1.apply(Trees.scala:889)
at scala.collection.immutable.List.loop$1(List.scala:117)
at scala.collection.immutable.List.mapConserve(List.scala:133)
at scala.tools.nsc.ast.Trees$Transformer.transformStats(Trees.scala:
889)
at scala.tools.nsc.ast.Trees$Transformer$$anonfun$transform
$1.apply(Trees.scala:761)
at scala.tools.nsc.ast.Trees$Transformer$$anonfun$transform
$1.apply(Trees.scala:761)
at scala.tools.nsc.ast.Trees$Transformer.atOwner(Trees.scala:899)
at scala.tools.nsc.transform.TypingTransformers
$TypingTransformer.atOwner(TypingTransformers.scala:38)
at scala.tools.nsc.transform.TypingTransformers
$TypingTransformer.atOwner(TypingTransformers.scala:31)
at scala.tools.nsc.ast.Trees$Transformer.transform(Trees.scala:760)
at scala.tools.nsc.transform.TypingTransformers
$TypingTransformer.scala$tools$nsc$transform$TypingTransformers
$TypingTransformer$$super$transform(TypingTransformers.scala:49)
at scala.tools.nsc.transform.TypingTransformers$TypingTransformer$
$anonfun$transform$2.apply(TypingTransformers.scala:51)
at scala.tools.nsc.transform.TypingTransformers$TypingTransformer$
$anonfun$transform$2.apply(TypingTransformers.scala:51)
at scala.tools.nsc.ast.Trees$Transformer.atOwner(Trees.scala:899)
at scala.tools.nsc.transform.TypingTransformers
$TypingTransformer.atOwner(TypingTransformers.scala:38)
at scala.tools.nsc.transform.TypingTransformers
$TypingTransformer.atOwner(TypingTransformers.scala:31)
at scala.tools.nsc.transform.TypingTransformers
$TypingTransformer.transform(TypingTransformers.scala:51)
at scala.tools.nsc.transform.Erasure$ErasureTransformer$$anon
$3.transform(Erasure.scala:1104)
at scala.tools.nsc.transform.Erasure
$ErasureTransformer.transform(Erasure.scala:1114)
at scala.tools.nsc.ast.Trees$Transformer.transformUnit(Trees.scala:
892)
at scala.tools.nsc.transform.Transform$Phase.apply(Transform.scala:
30)
at scala.tools.nsc.Global$GlobalPhase$$anonfun$applyPhase
$1.apply(Global.scala:326)
at scala.tools.nsc.Global$GlobalPhase$$anonfun$applyPhase
$1.apply(Global.scala:326)
at scala.tools.nsc.reporters.Reporter.withSource(Reporter.scala:47)
at scala.tools.nsc.Global$GlobalPhase.applyPhase(Global.scala:326)
at scala.tools.nsc.Global$GlobalPhase$$anonfun$run
$1.apply(Global.scala:294)
at scala.tools.nsc.Global$GlobalPhase$$anonfun$run
$1.apply(Global.scala:294)
at scala.collection.Iterator$class.foreach(Iterator.scala:652)
at scala.collection.mutable.ListBuffer$$anon
$1.foreach(ListBuffer.scala:311)
at scala.tools.nsc.Global$GlobalPhase.run(Global.scala:294)
at scala.tools.nsc.Global$Run.compileSources(Global.scala:949)
at scala.tools.nsc.Global$Run.compile(Global.scala:1034)
at scala.tools.nsc.Main$.process(Main.scala:106)
at scala.tools.nsc.Main$.main(Main.scala:123)
at scala.tools.nsc.Main.main(Main.scala)

gkossakowski
Joined: 2010-03-11,
User offline. Last seen 33 weeks 5 days ago.
Re: How do you create a new ClassDef in compiler a plugin?
On 22 October 2011 11:43, monster <skunkiferous [at] googlemail [dot] com> wrote:
I want to automatically generate an implementation for a trait, based
on an annotation on the trait. I have done this for the Java compiler,
and it was relatively easy. Unfortunately, I can find many example
modifying code on the fly in compiler plugins, but no example creating
completely new classes. The only thing I found was this discussion,
which does not seem to come to any clear solution:

http://www.scala-lang.org/node/1560

And I know that Paul Butcher is creating new classes, but he uses a
sbt plugin, instead of a compiler plugin. So, does anyone know of some
plugin that generate new classes directly?

This might help:
https://github.com/gkossakowski/scalagwt-scala/commit/9dba165914616edf701ea5f5ab45e654facffa73 https://github.com/gkossakowski/scalagwt-scala/commit/9dba165914616edf701ea5f5ab45e654facffa73#diff-4
https://github.com/gkossakowski/scalagwt-scala/commit/1173e55dc3ce0cc4ee576ad0738d1ceb34b870a4 https://github.com/gkossakowski/scalagwt-scala/commit/1173e55dc3ce0cc4ee576ad0738d1ceb34b870a4#diff-2
--
Grzegorz Kossakowski

Tymon Tobolski
Joined: 2011-08-10,
User offline. Last seen 42 years 45 weeks ago.
Re: How do you create a new ClassDef in compiler a plugin?
You may want to look at source code of those plugins: https://github.com/gseitz/Lensedhttps://github.com/monterail/knigh
Tymon Tobolski
On Oct 22, 2011, at 12:24 PM, Grzegorz Kossakowski wrote:
On 22 October 2011 11:43, monster <skunkiferous [at] googlemail [dot] com> wrote:
I want to automatically generate an implementation for a trait, based
on an annotation on the trait. I have done this for the Java compiler,
and it was relatively easy. Unfortunately, I can find many example
modifying code on the fly in compiler plugins, but no example creating
completely new classes. The only thing I found was this discussion,
which does not seem to come to any clear solution:

http://www.scala-lang.org/node/1560

And I know that Paul Butcher is creating new classes, but he uses a
sbt plugin, instead of a compiler plugin. So, does anyone know of some
plugin that generate new classes directly?

This might help:
https://github.com/gkossakowski/scalagwt-scala/commit/9dba165914616edf701ea5f5ab45e654facffa73 https://github.com/gkossakowski/scalagwt-scala/commit/9dba165914616edf701ea5f5ab45e654facffa73#diff-4
https://github.com/gkossakowski/scalagwt-scala/commit/1173e55dc3ce0cc4ee576ad0738d1ceb34b870a4 https://github.com/gkossakowski/scalagwt-scala/commit/1173e55dc3ce0cc4ee576ad0738d1ceb34b870a4#diff-2
--
Grzegorz Kossakowski


monster
Joined: 2011-10-22,
User offline. Last seen 42 years 45 weeks ago.
Re: How do you create a new ClassDef in compiler a plugin?

Thanks! I found what I was looking for in your code.

On Oct 22, 12:24 pm, Grzegorz Kossakowski
wrote:
>
> This might help:
>
> https://github.com/gkossakowski/scalagwt-scala/commit/9dba165914616ed.........
>
> https://github.com/gkossakowski/scalagwt-scala/commit/1173e55dc3ce0cc.........
>
> --
> Grzegorz Kossakowski

monster
Joined: 2011-10-22,
User offline. Last seen 42 years 45 weeks ago.
Re: How do you create a new ClassDef in compiler a plugin?

Thank you. I already found the snippet I needed in Grzegorz, but I
looked at knight (the t was missing from the link), and it looks like
I might learn useful things from it too.

On Oct 22, 1:30 pm, Tymon Tobolski
wrote:
> You may want to look at source code of those plugins:https://github.com/gseitz/Lensed,https://github.com/monterail/knigh
>
> Tymon Tobolski

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland