How to get default values of class fields in a compiler plugin?

I have an annotation defined in the source, which a compiler plugin shall transform:

class dslRoot(val aConstField: String = "hi") extends StaticAnnotation

I can match this part in the plugin:

override def transformValDef(tree: tpd.ValDef)(using ctx: Context): tpd.Tree =
    if tree.name.toString == "aConstField" then
      report.error(
        s"""${ctx.owner.fullName}
           |${tree.rhs.tpe}
           |""".stripMargin
      )
    tree

And I get NoType instead of a ConstantType

How can I get the default value during the transformation?

“Default getters” for constructor parameters are members of the companion class.

See Applications.findDefaultGetter for example code.

class C(x: String = "hello")

Use -Vprint:typer to see

  final module class C() extends AnyRef() { this: C.type =>
    def $lessinit$greater$default$1: String @uncheckedVariance = "hello"
  }
1 Like

Locating the getter now works; I wonder how to get the right-hand side (in this case, the default value) without introducing another compiler plugin phase.

If you mean how to cope with companions, you can transformStats since companions are always defined together.

An example is my recent PR which examines companions at flatten.

I haven’t taken a second look at that code, so it might be suboptimal or wrong. There may be existing utility methods that simplify everything. Please let me know if you find them.