Skip to content

Commit

Permalink
refactor binary decoder
Browse files Browse the repository at this point in the history
  • Loading branch information
adpi2 committed Dec 20, 2023
1 parent 2de8026 commit 078f0c3
Show file tree
Hide file tree
Showing 8 changed files with 185 additions and 128 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ trait Method extends Symbol:
def returnTypeName: String
def isBridge: Boolean
def isStatic: Boolean
def isFinal: Boolean
def instructions: Seq[Instruction]
def isConstructor: Boolean
def signedName: SignedName

def isExtensionMethod: Boolean = name.endsWith("$extension") && !isStatic
def isExtensionMethod: Boolean = name.endsWith("$extension") && !isStatic && !isBridge
def isTraitStaticForwarder: Boolean =
name.endsWith("$") && !isDeserializeLambda && !isTraitInitializer && declaringClass.isInterface && isStatic
declaringClass.isInterface && isStatic && name.endsWith("$") && !isDeserializeLambda && !isTraitInitializer
def isTraitInitializer: Boolean = name == "$init$" && isStatic
def isClassInitializer: Boolean = name == "<init>"
def isPartialFunctionApplyOrElse: Boolean = declaringClass.isPartialFunction && name == "applyOrElse"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ class JavaReflectConstructor(

override def isStatic: Boolean = false

override def isFinal: Boolean = true

override def isConstructor: Boolean = true

override def toString: String = constructor.toString
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ class JavaReflectMethod(

override def isStatic: Boolean = Modifier.isStatic(method.getModifiers)

override def isFinal: Boolean = Modifier.isFinal(method.getModifiers)

override def toString: String =
if showSpan.isEmpty then method.toString else s"$method $showSpan"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ class JdiMethod(val obj: Any) extends JavaReflection(obj, "com.sun.jdi.Method")

override def isStatic: Boolean = invokeMethod("isStatic")

override def isFinal: Boolean = invokeMethod("isFinal")

override def isConstructor: Boolean = invokeMethod("isConstructor")

override def sourceLines: Option[SourceLines] =
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -34,37 +34,37 @@ object Patterns:

object LazyInit:
def unapply(method: binary.Method): Option[String] =
"""(.*)\$lzyINIT\d+""".r.unapplySeq(NameTransformer.decode(method.name)).map(xs => xs(0).stripSuffix("$"))
if method.isBridge || method.isStatic then None
else """(.*)\$lzyINIT\d+""".r.unapplySeq(NameTransformer.decode(method.name)).map(xs => xs(0).stripSuffix("$"))

object TraitLocalStaticForwarder:
def unapply(method: binary.Method): Option[Seq[String]] =
if method.isTraitStaticForwarder then method.extractFromDecodedNames("(.+)\\$\\d+\\$".r)(_(0))
else None

object TraitStaticForwarder:
def unapply(method: binary.Method): Option[Seq[String]] =
if method.isTraitStaticForwarder then Some(method.unexpandedDecodedNames.map(_.stripSuffix("$")))
else None
def unapply(method: binary.Method): Boolean = method.isTraitStaticForwarder

object Outer:
def unapply(method: binary.Method): Option[String] =
"(.*)\\$\\$\\$outer".r.unapplySeq(NameTransformer.decode(method.name)).map(xs => xs(0))
def unapply(method: binary.Method): Boolean =
(!method.isBridge && !method.isStatic) &&
"(.*)\\$\\$\\$outer".r.unapplySeq(NameTransformer.decode(method.name)).isDefined

object AnonFun:
def unapply(method: binary.Method): Option[String] =
"(.*)\\$anonfun\\$\\d+".r.unapplySeq(NameTransformer.decode(method.name)).map(xs => xs(0).stripSuffix("$"))
def unapply(method: binary.Method): Boolean =
!method.isBridge && "(.*)\\$anonfun\\$\\d+".r.unapplySeq(NameTransformer.decode(method.name)).isDefined

object AdaptedAnonFun:
def unapply(method: binary.Method): Option[String] =
"""(.*)\$anonfun\$adapted\$\d+""".r
.unapplySeq(NameTransformer.decode(method.name))
.map(xs => xs(0).stripSuffix("$"))
def unapply(method: binary.Method): Boolean =
// adapted anon funs can be bridges or static or both
(method.isBridge || method.isStatic) &&
"""(.*)\$anonfun\$adapted\$\d+""".r.unapplySeq(NameTransformer.decode(method.name)).isDefined

object LocalMethod:
def unapply(method: binary.Method): Option[Seq[String]] =
method match
case ByNameArgProxy() => None
case DefaultArg(_) => None
case m if m.isBridge => None
case _ => method.extractFromDecodedNames("(.+)\\$\\d+".r)(_(0).stripSuffix("$"))

object DefaultArg:
Expand All @@ -73,17 +73,17 @@ object Patterns:

object LocalLazyInit:
def unapply(method: binary.Method): Option[Seq[String]] =
if !method.allParameters.forall(_.isGenerated) then None
if method.isBridge || !method.allParameters.forall(_.isGenerated) then None
else method.extractFromDecodedNames("""(.+)\$lzyINIT\d+\$(\d+)""".r)(_(0).stripSuffix("$"))

object SuperArg:
def unapply(method: binary.Method): Boolean =
"""(.*)\$superArg\$\d+(\$\d+)?""".r.unapplySeq(method.name).isDefined
!method.isBridge && """(.*)\$superArg\$\d+(\$\d+)?""".r.unapplySeq(method.name).isDefined

object LiftedTree:
def unapply(method: binary.Method): Boolean =
val liftedTree = "liftedTree\\d+\\$\\d+".r
liftedTree.unapplySeq(method.name).isDefined
!method.isBridge && liftedTree.unapplySeq(method.name).isDefined

object TraitInitializer:
def unapply(method: binary.Method): Boolean =
Expand All @@ -99,20 +99,23 @@ object Patterns:

object ParamForwarder:
def unapply(method: binary.Method): Option[Seq[String]] =
method.extractFromDecodedNames("(.+)\\$accessor".r)(xs => xs(0))
if method.isStatic || method.isBridge then None
else method.extractFromDecodedNames("(.+)\\$accessor".r)(xs => xs(0))

object TraitSetter:
def unapply(method: binary.Method): Option[String] =
if method.isStatic then None
if method.isStatic || method.isBridge then None
else """.+\$_setter_\$(.+\$\$)?(.+)_=""".r.unapplySeq(method.decodedName).map(xs => xs(1))

object Setter:
def unapply(method: binary.Method): Option[Seq[String]] =
method.extractFromDecodedNames("(.+)_=".r)(_(0))
if method.isStatic || method.isBridge then None
else method.extractFromDecodedNames("(.+)_=".r)(_(0))

object SuperAccessor:
def unapply(method: binary.Method): Option[Seq[String]] =
method.extractFromDecodedNames("super\\$(.+)".r)(_(0))
if method.isStatic || method.isBridge then None
else method.extractFromDecodedNames("super\\$(.+)".r)(_(0))

object SpecializedMethod:
def unapply(method: binary.Method): Option[Seq[String]] =
Expand All @@ -121,11 +124,11 @@ object Patterns:

object ByNameArgProxy:
def unapply(method: binary.Method): Boolean =
".+\\$proxy\\d+\\$\\d+".r.unapplySeq(method.name).isDefined
!method.isBridge && ".+\\$proxy\\d+\\$\\d+".r.unapplySeq(method.name).isDefined

object InlineAccessor:
def unapply(method: binary.Method): Option[Seq[String]] =
if method.isStatic then None
if method.isStatic || method.isBridge then None
else
method.extractFromDecodedNames("inline\\$(.+)".r) { xs =>
// strip $i1 suffix if exists
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ trait BinaryDecoderSuite extends CommonFunSuite:
else if methodCounter.throwables.nonEmpty then
methodCounter.printThrowables()
methodCounter.printThrowable(0)
// methodCounter.printNotFound()
classCounter.check(expectedClasses)
methodCounter.check(expectedMethods)

Expand Down Expand Up @@ -111,7 +112,7 @@ trait BinaryDecoderSuite extends CommonFunSuite:
private def tryDecode(cls: binary.ClassType, counter: Counter): Option[DecodedClass] =
try
val sym = decoder.decode(cls)
counter.success += cls
counter.success += (cls -> sym)
Some(sym)
catch
case ambiguious: AmbiguousException =>
Expand All @@ -126,8 +127,8 @@ trait BinaryDecoderSuite extends CommonFunSuite:

private def tryDecode(cls: DecodedClass, mthd: binary.Method, counter: Counter): Unit =
try
val sym = decoder.decode(cls, mthd)
counter.success += mthd
val decoded = decoder.decode(cls, mthd)
counter.success += (mthd -> decoded)
catch
case notFound: NotFoundException => counter.notFound += (mthd -> notFound)
case ambiguous: AmbiguousException => counter.ambiguous += ambiguous
Expand Down Expand Up @@ -181,7 +182,7 @@ trait BinaryDecoderSuite extends CommonFunSuite:
end Count

class Counter(val name: String):
val success = mutable.Buffer.empty[binary.Symbol]
val success = mutable.Buffer.empty[(binary.Symbol, DecodedSymbol)]
val notFound = mutable.Buffer.empty[(binary.Symbol, NotFoundException)]
val ambiguous = mutable.Buffer.empty[AmbiguousException]
val ignored = mutable.Buffer.empty[IgnoredException]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1015,9 +1015,9 @@ class BinaryDecoderTests extends BinaryDecoderSuite:
|def foo: String = ???
|""".stripMargin
val decoder = TestingDecoder(source, ScalaVersion.`3.1+`)
decoder.assertDecode("example.example$package$", "java.lang.String foo()", "example.foo: String")
decoder.assertDecode("example.decoder$package$", "java.lang.String foo()", "example.foo: String")
decoder.assertDecode(
"example.example$package",
"example.decoder$package",
"java.lang.String foo()",
"example.foo.<static forwarder>: String",
skip = true
Expand Down Expand Up @@ -1825,6 +1825,35 @@ class BinaryDecoderTests extends BinaryDecoderSuite:
"RefinedPrinter.<inline RefinedPrinter.myCtx_=>(Contexts.Context): Unit",
skip = true
)
decoder.assertDecode(
"dotty.tools.dotc.transform.sjs.PrepJSInterop$OwnerKind",
"int inline$baseKinds$extension(int arg0)",
"PrepJSInterop.OwnerKind.<inline PrepJSInterop.OwnerKind.baseKinds>.<static forwarder>: Int",
skip = true
)
decoder.assertDecode(
"org.scalajs.ir.Trees$OptimizerHints",
"boolean inline$extension(int arg0)",
"Trees.OptimizerHints.inline.<static forwarder>: Boolean",
skip = true
)
decoder.assertDecode(
"dotty.tools.package",
"java.lang.Object unreachable$default$1()",
"tools.unreachable.<default 1>.<static forwarder>: Any",
skip = true
)
// decoder.assertDecode(
// "dotty.tools.dotc.printing.Formatting$StringFormatter",
// "java.lang.String assemble$$anonfun$1(java.lang.String str)",
// ""
// )
decoder.assertDecode(
"dotty.tools.dotc.core.tasty.TreeUnpickler",
"dotty.tools.dotc.ast.Trees$Tree dotty$tools$dotc$core$tasty$TreeUnpickler$TreeReader$$_$_$$anonfun$18(dotty.tools.dotc.core.Contexts$Context x$1$19, dotty.tools.dotc.core.tasty.TreeUnpickler$TreeReader $this$tailLocal1$1)",
"TreeUnpickler.readTpt.<static forwarder>()(using Contexts.Context): tpd.Tree",
skip = true
)

test("tasty-query#412"):
val decoder = initDecoder("dev.zio", "zio-interop-cats_3", "23.1.0.0")(using ThrowOrWarn.ignore)
Expand Down

0 comments on commit 078f0c3

Please sign in to comment.