Skip to content

Commit 66fea8b

Browse files
committed
Print annotation in decompiler
1 parent 39c69c2 commit 66fea8b

File tree

8 files changed

+105
-19
lines changed

8 files changed

+105
-19
lines changed

library/src/scala/tasty/util/ShowSourceCode.scala

Lines changed: 78 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty
6565
printImportSelectors(selectors)
6666

6767
case cdef @ ClassDef(name, DefDef(_, targs, argss, _, _), parents, self, stats) =>
68+
printDefAnnotations(cdef)
69+
6870
val flags = cdef.flags
6971
if (flags.isFinal && !flags.isObject) this += "final "
7072
if (flags.isCase) this += "case "
@@ -146,11 +148,14 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty
146148
}
147149
this
148150

149-
case tdef@TypeDef(name, rhs) =>
151+
case tdef @ TypeDef(name, rhs) =>
152+
printDefAnnotations(tdef)
150153
this += "type "
151154
printTargDef(tdef)
152155

153-
case vdef@ValDef(name, tpt, rhs) =>
156+
case vdef @ ValDef(name, tpt, rhs) =>
157+
printDefAnnotations(vdef)
158+
154159
val flags = vdef.flags
155160
if (flags.isOverride) this += "override "
156161

@@ -201,7 +206,9 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty
201206
printTree(cond)
202207
this += ")"
203208

204-
case ddef@DefDef(name, targs, argss, tpt, rhs) =>
209+
case ddef @ DefDef(name, targs, argss, tpt, rhs) =>
210+
printDefAnnotations(ddef)
211+
205212
val flags = ddef.flags
206213
if (flags.isOverride) sb.append("override ")
207214

@@ -220,8 +227,16 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty
220227
}
221228
this
222229

223-
case tree@Term.Ident(name) =>
224-
printType(tree.tpe)
230+
case tree @ Term.Ident(name) =>
231+
tree.tpe match {
232+
case Type.SymRef(_, Types.EmptyPrefix()) | Type.TermRef(_, Types.EmptyPrefix()) => this += name
233+
case Type.SymRef(_, prefix) =>
234+
printTypeOrBound(prefix)
235+
this += "." += name
236+
case Type.TermRef(_, prefix) =>
237+
printTypeOrBound(prefix)
238+
this += "." += name
239+
}
225240

226241
case Term.Select(qual, name, sig) =>
227242
printTree(qual)
@@ -516,6 +531,19 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty
516531
this += ")"
517532
}
518533

534+
def printAnnotations(trees: List[Term]): Buffer = {
535+
def printSeparated(list: List[Term]): Unit = list match {
536+
case Nil =>
537+
case x :: Nil => printAnnotation(x)
538+
case x :: xs =>
539+
printAnnotation(x)
540+
this += " "
541+
printSeparated(xs)
542+
}
543+
printSeparated(trees)
544+
this
545+
}
546+
519547
def printArgDef(arg: ValDef): Unit = {
520548
val ValDef(name, tpt, rhs) = arg
521549
this += name += ": "
@@ -654,9 +682,11 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty
654682
printTypeTrees(args, ", ")
655683
this += "]"
656684

657-
case TypeTree.Annotated(tpt, annots) =>
685+
case TypeTree.Annotated(tpt, annot) =>
686+
val Annotation(ref, args) = annot
658687
printTypeTree(tpt)
659-
// TODO print annots
688+
this += " "
689+
printAnnotation(annot)
660690

661691
case TypeTree.And(left, right) =>
662692
printTypeTree(left)
@@ -692,14 +722,13 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty
692722

693723
case Type.SymRef(sym, prefix) =>
694724
prefix match {
695-
case Type.ThisType(Types.EmptyPackage() | Types.RootPackage()) =>
725+
case Types.EmptyPrefix() =>
696726
case prefix@Type.SymRef(ClassDef(_, _, _, _, _), _) =>
697727
printType(prefix)
698728
this += "#"
699729
case prefix@Type() =>
700730
printType(prefix)
701731
this += "."
702-
case prefix@NoPrefix() =>
703732
}
704733
printDefinitionName(sym)
705734

@@ -734,7 +763,10 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty
734763
this += "]"
735764

736765
case Type.AnnotatedType(tp, annot) =>
766+
val Annotation(ref, args) = annot
737767
printType(tp)
768+
this += " "
769+
printAnnotation(annot)
738770

739771
case Type.AndType(left, right) =>
740772
printType(left)
@@ -768,13 +800,35 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty
768800
}
769801

770802
def printDefinitionName(sym: Definition): Buffer = sym match {
771-
case ValDef(name, _, _) => this += name
803+
case ValDef(name, _, _) => this += name += ".type"
772804
case DefDef(name, _, _, _, _) => this += name
773805
case ClassDef(name, _, _, _, _) => this += name.stripSuffix("$")
774806
case TypeDef(name, _) => this += name
775807
case PackageDef(name, _) => this += name
776808
}
777809

810+
def printAnnotation(annot: Term): Buffer = {
811+
val Annotation(ref, args) = annot
812+
this += "@"
813+
printTypeTree(ref)
814+
this += "("
815+
printTrees(args, ", ")
816+
this += ")"
817+
}
818+
819+
def printDefAnnotations(definition: Definition): Buffer = {
820+
val annots = definition.annots.filter {
821+
case Annotation(annot, _) =>
822+
annot.tpe match {
823+
case Type.TypeRef(_, Type.SymRef(PackageDef("internal", _), Type.ThisType(Type.SymRef(PackageDef("annotation", _), NoPrefix())))) => false
824+
case _ => true
825+
}
826+
}
827+
printAnnotations(annots)
828+
if (annots.nonEmpty) this += " "
829+
else this
830+
}
831+
778832
def +=(x: Boolean): this.type = { sb.append(x); this }
779833
def +=(x: Byte): this.type = { sb.append(x); this }
780834
def +=(x: Short): this.type = { sb.append(x); this }
@@ -829,6 +883,13 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty
829883
}
830884
}
831885

886+
private object Annotation {
887+
def unapply(arg: Tree)(implicit ctx: Context): Option[(TypeTree, List[Term])] = arg match {
888+
case Term.Apply(Term.Select(Term.New(annot), "<init>", _), args) => Some((annot, args))
889+
case _ => None
890+
}
891+
}
892+
832893
// TODO Provide some of these in scala.tasty.Tasty.scala and implement them using checks on symbols for performance
833894
private object Types {
834895

@@ -866,6 +927,13 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty
866927
case _ => false
867928
}
868929
}
930+
931+
object EmptyPrefix {
932+
def unapply(tpe: TypeOrBounds)(implicit ctx: Context): Boolean = tpe match {
933+
case NoPrefix() | Type.ThisType(Types.EmptyPackage() | Types.RootPackage()) => true
934+
case _ => false
935+
}
936+
}
869937
}
870938

871939

tests/pos/i2104b.decompiled

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ case class Pair[A, B](_1: A, _2: B) {
1313
scala.runtime.Statics.finalizeHash(acc, 2)
1414
}
1515
override def equals(x$0: scala.Any): scala.Boolean = this.eq(x$0.asInstanceOf[java.lang.Object]).||(x$0 match {
16-
case x$0: Pair[Pair.this.A, Pair.this.B] =>
16+
case x$0: Pair[Pair.this.A, Pair.this.B] @scala.unchecked() =>
1717
this._1.==(x$0._1).&&(this._2.==(x$0._2))
1818
case _ =>
1919
false
2020
})
2121
override def toString(): java.lang.String = scala.runtime.ScalaRunTime._toString(this)
22-
override def canEqual(that: scala.Any): scala.Boolean = that.isInstanceOf[Pair[Pair.this.A, Pair.this.B]]
22+
override def canEqual(that: scala.Any): scala.Boolean = that.isInstanceOf[Pair[Pair.this.A, Pair.this.B] @scala.unchecked()]
2323
override def productArity: scala.Int = 2
2424
override def productPrefix: java.lang.String = "Pair"
2525
override def productElement(n: scala.Int): scala.Any = n match {

tests/pos/simpleAnnot.decompiled

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/** Decompiled from out/posTestFromTasty/pos/simpleAnnot/Foo.class */
2+
class Foo() {
3+
@annot() type A = scala.Int
4+
@annot() val a: scala.Int = scala.Predef.???
5+
val b: scala.Int @annot() = scala.Predef.???
6+
def c(x: scala.Int): scala.Int = (x: x.type @annot())
7+
}
8+
/** Decompiled from out/posTestFromTasty/pos/simpleAnnot/annot.class */
9+
class annot() extends scala.annotation.Annotation

tests/pos/simpleAnnot.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
class Foo {
3+
@annot type A = Int
4+
@annot val a: Int = ???
5+
val b: Int @annot = ???
6+
def c(x: Int) = (x : @annot)
7+
}
8+
9+
class annot extends scala.annotation.Annotation

tests/pos/simpleCaseClass-1.decompiled

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22
case class A() {
33
override def hashCode(): scala.Int = 1914112431
44
override def equals(x$0: scala.Any): scala.Boolean = this.eq(x$0.asInstanceOf[java.lang.Object]).||(x$0 match {
5-
case x$0: A =>
5+
case x$0: A @scala.unchecked() =>
66
true
77
case _ =>
88
false
99
})
1010
override def toString(): java.lang.String = scala.runtime.ScalaRunTime._toString(this)
11-
override def canEqual(that: scala.Any): scala.Boolean = that.isInstanceOf[A]
11+
override def canEqual(that: scala.Any): scala.Boolean = that.isInstanceOf[A @scala.unchecked()]
1212
override def productArity: scala.Int = 0
1313
override def productPrefix: java.lang.String = "A"
1414
override def productElement(n: scala.Int): scala.Any = n match {

tests/pos/simpleCaseClass-2.decompiled

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ case class A(x: scala.Int) {
66
scala.runtime.Statics.finalizeHash(acc, 1)
77
}
88
override def equals(x$0: scala.Any): scala.Boolean = this.eq(x$0.asInstanceOf[java.lang.Object]).||(x$0 match {
9-
case x$0: A =>
9+
case x$0: A @scala.unchecked() =>
1010
this.x.==(x$0.x)
1111
case _ =>
1212
false
1313
})
1414
override def toString(): java.lang.String = scala.runtime.ScalaRunTime._toString(this)
15-
override def canEqual(that: scala.Any): scala.Boolean = that.isInstanceOf[A]
15+
override def canEqual(that: scala.Any): scala.Boolean = that.isInstanceOf[A @scala.unchecked()]
1616
override def productArity: scala.Int = 1
1717
override def productPrefix: java.lang.String = "A"
1818
override def productElement(n: scala.Int): scala.Any = n match {

tests/pos/simpleCaseClass-3.decompiled

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ case class A[T](x: T) {
66
scala.runtime.Statics.finalizeHash(acc, 1)
77
}
88
override def equals(x$0: scala.Any): scala.Boolean = this.eq(x$0.asInstanceOf[java.lang.Object]).||(x$0 match {
9-
case x$0: A[A.this.T] =>
9+
case x$0: A[A.this.T] @scala.unchecked() =>
1010
this.x.==(x$0.x)
1111
case _ =>
1212
false
1313
})
1414
override def toString(): java.lang.String = scala.runtime.ScalaRunTime._toString(this)
15-
override def canEqual(that: scala.Any): scala.Boolean = that.isInstanceOf[A[A.this.T]]
15+
override def canEqual(that: scala.Any): scala.Boolean = that.isInstanceOf[A[A.this.T] @scala.unchecked()]
1616
override def productArity: scala.Int = 1
1717
override def productPrefix: java.lang.String = "A"
1818
override def productElement(n: scala.Int): scala.Any = n match {

tests/pos/simpleCaseObject.decompiled

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package foo {
33
case object Foo {
44
override def hashCode(): scala.Int = 1045991777
55
override def toString(): java.lang.String = "Foo"
6-
override def canEqual(that: scala.Any): scala.Boolean = that.isInstanceOf[foo.Foo]
6+
override def canEqual(that: scala.Any): scala.Boolean = that.isInstanceOf[foo.Foo @scala.unchecked()]
77
override def productArity: scala.Int = 0
88
override def productPrefix: java.lang.String = "Foo"
99
override def productElement(n: scala.Int): scala.Any = n match {

0 commit comments

Comments
 (0)