I guess it's impossible even with macros:
import scala.reflect.macros.Context
import scala.language.experimental.macros
def showMacroImpl(c: Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
import c.universe._
val inputs = annottees.map(_.tree).toList
println(inputs.map{showRaw(_)})
c.Expr[Any](Block(inputs, Literal(Constant(()))))
}
import scala.annotation.StaticAnnotation
class showMacro extends StaticAnnotation {
def macroTransform(annottees: Any*) = macro showMacroImpl
}
object Test {
@showMacro final val i = 1+1
@showMacro final val j = util.Random.nextInt()
@showMacro final val k = Int.MaxValue / 2
}
// List(ValDef(Modifiers(FINAL), newTermName("i"), TypeTree(), Apply(Select(Literal(Constant(1)), newTermName("$plus")), List(Literal(Constant(1))))))
// List(ValDef(Modifiers(FINAL), newTermName("j"), TypeTree(), Apply(Select(Select(Ident(newTermName("util")), newTermName("Random")), newTermName("nextInt")), List())))
// List(ValDef(Modifiers(FINAL), newTermName("k"), TypeTree(), Apply(Select(Select(Ident(newTermName("Int")), newTermName("MaxValue")), newTermName("$div")), List(Literal(Constant(2))))))
There is no difference between i
, j
and k
here.
You'll get no information even with scalac -Xprint:cleanup test.scala
:
final <stable> <accessor> def i(): Int = 2;
final <stable> <accessor> def j(): Int = Test.this.j;
final <stable> <accessor> def k(): Int = 1073741823;
You could get this information only from .icode
file (scalac -Xprint:all test.scala; cat Test\$.icode
):
def i(): Int(2) {
locals:
startBlock: 1
blocks: [1]
1:
2 CONSTANT(2)
2 RETURN(INT)
}
def k(): Int(1073741823) {
locals:
startBlock: 1
blocks: [1]
1:
4 CONSTANT(1073741823)
4 RETURN(INT)
}
Or from java bytecode (javap -c Test\$.class
):
public final int i();
Code:
0: iconst_2
1: ireturn
public final int k();
Code:
0: ldc #21 // int 1073741823
2: ireturn