@@ -14,6 +14,7 @@ import tastyquery.jdk.ClasspathLoaders
14
14
15
15
import java .nio .file .Path
16
16
import scala .util .matching .Regex
17
+ import tastyquery .Exceptions .NonMethodReferenceException
17
18
18
19
object BinaryDecoder :
19
20
def apply (classEntries : Seq [Path ])(using ThrowOrWarn ): BinaryDecoder =
@@ -107,6 +108,75 @@ class BinaryDecoder(using Context, ThrowOrWarn):
107
108
candidates.singleOrThrow(method)
108
109
end decode
109
110
111
+ def decode (field : binary.Field ): DecodedField =
112
+ val decodedClass = decode(field.declaringClass)
113
+ decode(decodedClass, field)
114
+
115
+ def decode (decodedClass : DecodedClass , field : binary.Field ): DecodedField =
116
+ def tryDecode (f : PartialFunction [binary.Field , Seq [DecodedField ]]): Seq [DecodedField ] =
117
+ f.applyOrElse(field, _ => Seq .empty[DecodedField ])
118
+
119
+ extension (xs : Seq [DecodedField ])
120
+ def orTryDecode (f : PartialFunction [binary.Field , Seq [DecodedField ]]): Seq [DecodedField ] =
121
+ if xs.nonEmpty then xs else f.applyOrElse(field, _ => Seq .empty[DecodedField ])
122
+ val decodedFields =
123
+ tryDecode {
124
+ case Patterns .LazyVal (name) =>
125
+ for
126
+ owner <- decodedClass.classSymbol.toSeq ++ decodedClass.linearization.filter(_.isTrait)
127
+ sym <- owner.declarations.collect {
128
+ case sym : TermSymbol if sym.nameStr == name && sym.isModuleOrLazyVal => sym
129
+ }
130
+ yield DecodedField .ValDef (decodedClass, sym)
131
+ case Patterns .Module () =>
132
+ decodedClass.classSymbol.flatMap(_.moduleValue).map(DecodedField .ModuleVal (decodedClass, _)).toSeq
133
+ case Patterns .Offset (nbr) =>
134
+ Seq (DecodedField .LazyValOffset (decodedClass, nbr, defn.LongType ))
135
+ case Patterns .OuterField () =>
136
+ decodedClass.symbolOpt
137
+ .flatMap(_.outerClass)
138
+ .map(outerClass => DecodedField .Outer (decodedClass, outerClass.selfType))
139
+ .toSeq
140
+ case Patterns .SerialVersionUID () =>
141
+ Seq (DecodedField .SerialVersionUID (decodedClass, defn.LongType ))
142
+ case Patterns .LazyValBitmap (name) =>
143
+ Seq (DecodedField .LazyValBitmap (decodedClass, defn.BooleanType , name))
144
+ case Patterns .AnyValCapture () =>
145
+ for
146
+ classSym <- decodedClass.symbolOpt.toSeq
147
+ outerClass <- classSym.outerClass.toSeq
148
+ if outerClass.isSubClass(defn.AnyValClass )
149
+ sym <- outerClass.declarations.collect {
150
+ case sym : TermSymbol if sym.isVal && ! sym.isMethod => sym
151
+ }
152
+ yield DecodedField .Capture (decodedClass, sym)
153
+ case Patterns .Capture (names) =>
154
+ decodedClass.symbolOpt.toSeq
155
+ .flatMap(CaptureCollector .collectCaptures)
156
+ .filter { captureSym =>
157
+ names.exists {
158
+ case Patterns .LazyVal (name) => name == captureSym.nameStr
159
+ case name => name == captureSym.nameStr
160
+ }
161
+ }
162
+ .map(DecodedField .Capture (decodedClass, _))
163
+
164
+ case _ if field.isStatic && decodedClass.isJava =>
165
+ for
166
+ owner <- decodedClass.companionClassSymbol.toSeq
167
+ sym <- owner.declarations.collect { case sym : TermSymbol if sym.nameStr == field.name => sym }
168
+ yield DecodedField .ValDef (decodedClass, sym)
169
+ }.orTryDecode { case _ =>
170
+ for
171
+ owner <- withCompanionIfExtendsJavaLangEnum(decodedClass) ++ decodedClass.linearization.filter(_.isTrait)
172
+ sym <- owner.declarations.collect {
173
+ case sym : TermSymbol if matchTargetName(field, sym) && ! sym.isMethod => sym
174
+ }
175
+ yield DecodedField .ValDef (decodedClass, sym)
176
+ }
177
+ decodedFields.singleOrThrow(field)
178
+ end decode
179
+
110
180
private def reduceAmbiguityOnClasses (syms : Seq [DecodedClass ]): Seq [DecodedClass ] =
111
181
if syms.size > 1 then
112
182
val reduced = syms.filterNot(sym => syms.exists(enclose(sym, _)))
@@ -476,13 +546,8 @@ class BinaryDecoder(using Context, ThrowOrWarn):
476
546
.map(target => DecodedMethod .TraitStaticForwarder (decode(decodedClass, target)))
477
547
478
548
private def decodeOuter (decodedClass : DecodedClass ): Option [DecodedMethod .OuterAccessor ] =
479
- def outerClass (sym : Symbol ): Option [ClassSymbol ] =
480
- sym.owner match
481
- case null => None
482
- case owner if owner.isClass => Some (owner.asClass)
483
- case owner => outerClass(owner)
484
549
decodedClass.symbolOpt
485
- .flatMap(outerClass)
550
+ .flatMap(_. outerClass)
486
551
.map(outerClass => DecodedMethod .OuterAccessor (decodedClass, outerClass.thisType))
487
552
488
553
private def decodeTraitInitializer (
@@ -616,11 +681,18 @@ class BinaryDecoder(using Context, ThrowOrWarn):
616
681
DecodedMethod .MixinForwarder (decodedClass, staticForwarder.target)
617
682
}
618
683
619
- private def withCompanionIfExtendsAnyVal (cls : ClassSymbol ): Seq [ClassSymbol ] =
620
- cls.companionClass match
621
- case Some (companionClass) if companionClass.isSubClass(defn.AnyValClass ) =>
622
- Seq (cls, companionClass)
623
- case _ => Seq (cls)
684
+ private def withCompanionIfExtendsAnyVal (decodedClass : DecodedClass ): Seq [Symbol ] = decodedClass match
685
+ case classDef : DecodedClass .ClassDef =>
686
+ Seq (classDef.symbol) ++ classDef.symbol.companionClass.filter(_.isSubClass(defn.AnyValClass ))
687
+ case _ : DecodedClass .SyntheticCompanionClass => Seq .empty
688
+ case anonFun : DecodedClass .SAMOrPartialFunction => Seq (anonFun.symbol)
689
+ case inlined : DecodedClass .InlinedClass => withCompanionIfExtendsAnyVal(inlined.underlying)
690
+
691
+ private def withCompanionIfExtendsJavaLangEnum (decodedClass : DecodedClass ): Seq [ClassSymbol ] =
692
+ decodedClass.classSymbol.toSeq.flatMap { cls =>
693
+ if cls.isSubClass(defn.javaLangEnumClass) then Seq (cls) ++ cls.companionClass
694
+ else Seq (cls)
695
+ }
624
696
625
697
private def decodeAdaptedAnonFun (decodedClass : DecodedClass , method : binary.Method ): Seq [DecodedMethod ] =
626
698
if method.instructions.nonEmpty then
@@ -786,13 +858,6 @@ class BinaryDecoder(using Context, ThrowOrWarn):
786
858
private def collectLiftedTrees [S ](decodedClass : DecodedClass , method : binary.Method )(
787
859
matcher : PartialFunction [LiftedTree [? ], LiftedTree [S ]]
788
860
): Seq [LiftedTree [S ]] =
789
- def withCompanionIfExtendsAnyVal (decodedClass : DecodedClass ): Seq [Symbol ] = decodedClass match
790
- case classDef : DecodedClass .ClassDef =>
791
- Seq (classDef.symbol) ++ classDef.symbol.companionClass.filter(_.isSubClass(defn.AnyValClass ))
792
- case _ : DecodedClass .SyntheticCompanionClass => Seq .empty
793
- case anonFun : DecodedClass .SAMOrPartialFunction => Seq (anonFun.symbol)
794
- case inlined : DecodedClass .InlinedClass => withCompanionIfExtendsAnyVal(inlined.underlying)
795
-
796
861
val owners = withCompanionIfExtendsAnyVal(decodedClass)
797
862
val sourceLines =
798
863
if owners.size == 2 && method.allParameters.exists(p => p.name.matches(" \\ $this\\ $\\ d+" )) then
@@ -823,6 +888,9 @@ class BinaryDecoder(using Context, ThrowOrWarn):
823
888
private def matchTargetName (method : binary.Method , symbol : TermSymbol ): Boolean =
824
889
method.unexpandedDecodedNames.map(_.stripSuffix(" $" )).contains(symbol.targetNameStr)
825
890
891
+ private def matchTargetName (field : binary.Field , symbol : TermSymbol ): Boolean =
892
+ field.unexpandedDecodedNames.map(_.stripSuffix(" $" )).contains(symbol.targetNameStr)
893
+
826
894
private case class SourceParams (
827
895
declaredParamNames : Seq [UnsignedTermName ],
828
896
declaredParamTypes : Seq [Type ],
0 commit comments