Created
December 2, 2022 21:33
-
-
Save gzoller/6cba7462895baa76fd1dc766aa65d68c to your computer and use it in GitHub Desktop.
Attempting to override a method in plugin
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class MyPhase extends PluginPhase { | |
import tpd._ | |
val phaseName = "overrider" | |
override val runsAfter = Set(Pickler.name) | |
override def transformTypeDef(tree: TypeDef)(implicit ctx: Context): Tree = | |
if tree.isClassDef && !tree.rhs.symbol.isStatic then // only look at classes & traits, not objects | |
// 0. Get a FreshContext so we can set the tree to this tree. (for '{} later) | |
implicit val fresh = ctx.fresh | |
fresh.setTree(tree) | |
QuotesCache.init(fresh) | |
implicit val quotes:Quotes = QuotesImpl.apply() // picks up fresh | |
import quotes.reflect.* | |
val s3ReflectionClassSymbol = getClassIfDefined("co.blocke.scala_reflection.Skip_Reflection").asInstanceOf[ClassSymbol] | |
if tree.symbol.getAnnotation(s3ReflectionClassSymbol).isDefined then | |
// 1. Set up method symbol, define parameters and return type | |
val toJsonSymbol = Symbol.newMethod( | |
Symbol.spliceOwner, | |
"toJson", | |
MethodType( | |
List("sb","config"))( // parameter list | |
_ => List( // types of the parameters | |
TypeRepr.of[StringBuilder], | |
TypeRepr.of[SJConfig], | |
), | |
_ => TypeRepr.typeConstructorOf(classOf[Unit]) // return type | |
), | |
Flags.Override, // NOTE: Setting override flag | |
Symbol.noSymbol | |
) | |
// 2. Get our class' Symbol (for ownerhsip reassignment) | |
val classSymbol = tree.tpe.asInstanceOf[quotes.reflect.TypeRef].classSymbol.get | |
// 3. Define our method definition (DefDef) using our method symbol defined above | |
val toJsonMethodDef = DefDef( | |
toJsonSymbol, | |
{ | |
case List(List(sb: Term, config: Term)) => | |
given Quotes = toJsonSymbol.asQuotes | |
Some({ | |
quoted.Expr.ofList(List( | |
'{ println("Hello") }, | |
'{ println("World") } | |
)) | |
}.asTerm.changeOwner(toJsonSymbol)) | |
} | |
).changeOwner(classSymbol) | |
// 4. Add toJsonMethodDef to tree and return | |
val classDef = tree.asInstanceOf[ClassDef] | |
val cd = ClassDef.copy(classDef)( | |
name = classDef.name, | |
constr = classDef.constructor, | |
parents = classDef.parents, | |
selfOpt = classDef.self, | |
body = classDef.body :+ toJsonMethodDef | |
) | |
cd.asInstanceOf[dotty.tools.dotc.ast.tpd.Tree] | |
else | |
tree | |
else | |
tree | |
} | |
/* | |
Produces this error when plugin used to compile a class: | |
Exception in thread "sbt-bg-threads-1" java.lang.ClassFormatError: Duplicate method name "toJson" with signature "(Lscala.collection.mutable.StringBuilder;Lco.blocke.scala_reflection.SJConfig;)V" in class file com/foo/Person | |
at java.base/java.lang.ClassLoader.defineClass1(Native Method) | |
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1013) | |
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150) | |
at java.base/java.net.URLClassLoader.defineClass(URLClassLoader.java:524) | |
at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:427) | |
at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:421) | |
at java.base/java.security.AccessController.doPrivileged(AccessController.java:712) | |
at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:420) | |
at sbt.internal.ManagedClassLoader.findClass(ManagedClassLoader.java:102) | |
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:588) | |
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521) | |
at com.foo.Person$.apply(Main.scala:13) | |
at com.foo.Main$package$.hello(Main.scala:35) | |
at com.foo.hello.main(Main.scala:27) | |
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104) | |
... | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment