|
| 1 | +package scala.tasty |
| 2 | +package reflect |
| 3 | + |
| 4 | +class ExtractorsPrinter[R <: Reflection & Singleton](val tasty: R) extends Printer[R] { |
| 5 | + import tasty.{_, given} |
| 6 | + |
| 7 | + def showTree(tree: Tree)(given ctx: Context): String = |
| 8 | + new Buffer().visitTree(tree).result() |
| 9 | + |
| 10 | + def showTypeOrBounds(tpe: TypeOrBounds)(given ctx: Context): String = |
| 11 | + new Buffer().visitType(tpe).result() |
| 12 | + |
| 13 | + def showConstant(const: Constant)(given ctx: Context): String = |
| 14 | + new Buffer().visitConstant(const).result() |
| 15 | + |
| 16 | + def showSymbol(symbol: Symbol)(given ctx: Context): String = |
| 17 | + new Buffer().visitSymbol(symbol).result() |
| 18 | + |
| 19 | + def showFlags(flags: Flags)(given ctx: Context): String = { |
| 20 | + val flagList = List.newBuilder[String] |
| 21 | + if (flags.is(Flags.Private)) flagList += "Flags.Private" |
| 22 | + if (flags.is(Flags.Protected)) flagList += "Flags.Protected" |
| 23 | + if (flags.is(Flags.Abstract)) flagList += "Flags.Abstract" |
| 24 | + if (flags.is(Flags.Final)) flagList += "Flags.Final" |
| 25 | + if (flags.is(Flags.Sealed)) flagList += "Flags.Sealed" |
| 26 | + if (flags.is(Flags.Case)) flagList += "Flags.Case" |
| 27 | + if (flags.is(Flags.Implicit)) flagList += "Flags.Implicit" |
| 28 | + if (flags.is(Flags.Erased)) flagList += "Flags.Erased" |
| 29 | + if (flags.is(Flags.Lazy)) flagList += "Flags.Lazy" |
| 30 | + if (flags.is(Flags.Override)) flagList += "Flags.Override" |
| 31 | + if (flags.is(Flags.Inline)) flagList += "Flags.Inline" |
| 32 | + if (flags.is(Flags.Macro)) flagList += "Flags.Macro" |
| 33 | + if (flags.is(Flags.JavaDefined)) flagList += "Flags.JavaDefined" |
| 34 | + if (flags.is(Flags.Static)) flagList += "Flags.javaStatic" |
| 35 | + if (flags.is(Flags.Object)) flagList += "Flags.Object" |
| 36 | + if (flags.is(Flags.Trait)) flagList += "Flags.Trait" |
| 37 | + if (flags.is(Flags.Local)) flagList += "Flags.Local" |
| 38 | + if (flags.is(Flags.Synthetic)) flagList += "Flags.Synthetic" |
| 39 | + if (flags.is(Flags.Artifact)) flagList += "Flags.Artifact" |
| 40 | + if (flags.is(Flags.Mutable)) flagList += "Flags.Mutable" |
| 41 | + if (flags.is(Flags.FieldAccessor)) flagList += "Flags.FieldAccessor" |
| 42 | + if (flags.is(Flags.CaseAcessor)) flagList += "Flags.CaseAcessor" |
| 43 | + if (flags.is(Flags.Covariant)) flagList += "Flags.Covariant" |
| 44 | + if (flags.is(Flags.Contravariant)) flagList += "Flags.Contravariant" |
| 45 | + if (flags.is(Flags.Scala2X)) flagList += "Flags.Scala2X" |
| 46 | + if (flags.is(Flags.DefaultParameterized)) flagList += "Flags.DefaultParameterized" |
| 47 | + if (flags.is(Flags.StableRealizable)) flagList += "Flags.StableRealizable" |
| 48 | + if (flags.is(Flags.Param)) flagList += "Flags.Param" |
| 49 | + if (flags.is(Flags.ParamAccessor)) flagList += "Flags.ParamAccessor" |
| 50 | + if (flags.is(Flags.Enum)) flagList += "Flags.Enum" |
| 51 | + if (flags.is(Flags.ModuleClass)) flagList += "Flags.ModuleClass" |
| 52 | + if (flags.is(Flags.PrivateLocal)) flagList += "Flags.PrivateLocal" |
| 53 | + if (flags.is(Flags.Package)) flagList += "Flags.Package" |
| 54 | + flagList.result().mkString(" | ") |
| 55 | + } |
| 56 | + |
| 57 | + private class Buffer(given ctx: Context) { self => |
| 58 | + |
| 59 | + private val sb: StringBuilder = new StringBuilder |
| 60 | + |
| 61 | + def result(): String = sb.result() |
| 62 | + |
| 63 | + def visitTree(x: Tree): Buffer = x match { |
| 64 | + case Ident(name) => |
| 65 | + this += "Ident(\"" += name += "\")" |
| 66 | + case Select(qualifier, name) => |
| 67 | + this += "Select(" += qualifier += ", \"" += name += "\")" |
| 68 | + case This(qual) => |
| 69 | + this += "This(" += qual += ")" |
| 70 | + case Super(qual, mix) => |
| 71 | + this += "Super(" += qual += ", " += mix += ")" |
| 72 | + case Apply(fun, args) => |
| 73 | + this += "Apply(" += fun += ", " ++= args += ")" |
| 74 | + case TypeApply(fun, args) => |
| 75 | + this += "TypeApply(" += fun += ", " ++= args += ")" |
| 76 | + case Literal(const) => |
| 77 | + this += "Literal(" += const += ")" |
| 78 | + case New(tpt) => |
| 79 | + this += "New(" += tpt += ")" |
| 80 | + case Typed(expr, tpt) => |
| 81 | + this += "Typed(" += expr += ", " += tpt += ")" |
| 82 | + case NamedArg(name, arg) => |
| 83 | + this += "NamedArg(\"" += name += "\", " += arg += ")" |
| 84 | + case Assign(lhs, rhs) => |
| 85 | + this += "Assign(" += lhs += ", " += rhs += ")" |
| 86 | + case Block(stats, expr) => |
| 87 | + this += "Block(" ++= stats += ", " += expr += ")" |
| 88 | + case If(cond, thenp, elsep) => |
| 89 | + this += "If(" += cond += ", " += thenp += ", " += elsep += ")" |
| 90 | + case Closure(meth, tpt) => |
| 91 | + this += "Closure(" += meth += ", " += tpt += ")" |
| 92 | + case Match(selector, cases) => |
| 93 | + this += "Match(" += selector += ", " ++= cases += ")" |
| 94 | + case ImpliedMatch(cases) => |
| 95 | + this += "ImpliedMatch(" ++= cases += ")" |
| 96 | + case Return(expr) => |
| 97 | + this += "Return(" += expr += ")" |
| 98 | + case While(cond, body) => |
| 99 | + this += "While(" += cond += ", " += body += ")" |
| 100 | + case Try(block, handlers, finalizer) => |
| 101 | + this += "Try(" += block += ", " ++= handlers += ", " += finalizer += ")" |
| 102 | + case Repeated(elems, elemtpt) => |
| 103 | + this += "Repeated(" ++= elems += ", " += elemtpt += ")" |
| 104 | + case Inlined(call, bindings, expansion) => |
| 105 | + this += "Inlined(" |
| 106 | + visitOption(call, visitTree) |
| 107 | + this += ", " ++= bindings += ", " += expansion += ")" |
| 108 | + case ValDef(name, tpt, rhs) => |
| 109 | + this += "ValDef(\"" += name += "\", " += tpt += ", " += rhs += ")" |
| 110 | + case DefDef(name, typeParams, paramss, returnTpt, rhs) => |
| 111 | + this += "DefDef(\"" += name += "\", " ++= typeParams += ", " +++= paramss += ", " += returnTpt += ", " += rhs += ")" |
| 112 | + case TypeDef(name, rhs) => |
| 113 | + this += "TypeDef(\"" += name += "\", " += rhs += ")" |
| 114 | + case ClassDef(name, constr, parents, derived, self, body) => |
| 115 | + this += "ClassDef(\"" += name += "\", " += constr += ", " |
| 116 | + visitList[Tree](parents, visitTree) |
| 117 | + this += ", " |
| 118 | + visitList[TypeTree](derived, visitTree) |
| 119 | + this += ", " += self += ", " ++= body += ")" |
| 120 | + case PackageDef(name, owner) => |
| 121 | + this += "PackageDef(\"" += name += "\", " += owner += ")" |
| 122 | + case Import(expr, selectors) => |
| 123 | + this += "Import(" += expr += ", " ++= selectors += ")" |
| 124 | + case PackageClause(pid, stats) => |
| 125 | + this += "PackageClause(" += pid += ", " ++= stats += ")" |
| 126 | + case Inferred() => |
| 127 | + this += "Inferred()" |
| 128 | + case TypeIdent(name) => |
| 129 | + this += "TypeIdent(\"" += name += "\")" |
| 130 | + case TypeSelect(qualifier, name) => |
| 131 | + this += "TypeSelect(" += qualifier += ", \"" += name += "\")" |
| 132 | + case Projection(qualifier, name) => |
| 133 | + this += "Projection(" += qualifier += ", \"" += name += "\")" |
| 134 | + case Singleton(ref) => |
| 135 | + this += "Singleton(" += ref += ")" |
| 136 | + case Refined(tpt, refinements) => |
| 137 | + this += "Refined(" += tpt += ", " ++= refinements += ")" |
| 138 | + case Applied(tpt, args) => |
| 139 | + this += "Applied(" += tpt += ", " ++= args += ")" |
| 140 | + case ByName(result) => |
| 141 | + this += "ByName(" += result += ")" |
| 142 | + case Annotated(arg, annot) => |
| 143 | + this += "Annotated(" += arg += ", " += annot += ")" |
| 144 | + case LambdaTypeTree(tparams, body) => |
| 145 | + this += "LambdaTypeTree(" ++= tparams += ", " += body += ")" |
| 146 | + case TypeBind(name, bounds) => |
| 147 | + this += "TypeBind(" += name += ", " += bounds += ")" |
| 148 | + case TypeBlock(aliases, tpt) => |
| 149 | + this += "TypeBlock(" ++= aliases += ", " += tpt += ")" |
| 150 | + case TypeBoundsTree(lo, hi) => |
| 151 | + this += "TypeBoundsTree(" += lo += ", " += hi += ")" |
| 152 | + case WildcardTypeTree() => |
| 153 | + this += s"WildcardTypeTree()" |
| 154 | + case MatchTypeTree(bound, selector, cases) => |
| 155 | + this += "MatchTypeTree(" += bound += ", " += selector += ", " ++= cases += ")" |
| 156 | + case CaseDef(pat, guard, body) => |
| 157 | + this += "CaseDef(" += pat += ", " += guard += ", " += body += ")" |
| 158 | + case TypeCaseDef(pat, body) => |
| 159 | + this += "TypeCaseDef(" += pat += ", " += body += ")" |
| 160 | + case Bind(name, body) => |
| 161 | + this += "Bind(\"" += name += "\", " += body += ")" |
| 162 | + case Unapply(fun, implicits, patterns) => |
| 163 | + this += "Unapply(" += fun += ", " ++= implicits += ", " ++= patterns += ")" |
| 164 | + case Alternatives(patterns) => |
| 165 | + this += "Alternative(" ++= patterns += ")" |
| 166 | + } |
| 167 | + |
| 168 | + def visitConstant(x: Constant): Buffer = x match { |
| 169 | + case Constant(()) => this += "Constant(())" |
| 170 | + case Constant(null) => this += "Constant(null)" |
| 171 | + case Constant(value: Boolean) => this += "Constant(" += value += ")" |
| 172 | + case Constant(value: Byte) => this += "Constant(" += value += ": Byte)" |
| 173 | + case Constant(value: Short) => this += "Constant(" += value += ": Short)" |
| 174 | + case Constant(value: Char) => this += "Constant('" += value += "')" |
| 175 | + case Constant(value: Int) => this += "Constant(" += value.toString += ")" |
| 176 | + case Constant(value: Long) => this += "Constant(" += value += "L)" |
| 177 | + case Constant(value: Float) => this += "Constant(" += value += "f)" |
| 178 | + case Constant(value: Double) => this += "Constant(" += value += "d)" |
| 179 | + case Constant(value: String) => this += "Constant(\"" += value += "\")" |
| 180 | + case Constant.ClassTag(value) => |
| 181 | + this += "Constant.ClassTag(" |
| 182 | + visitType(value) += ")" |
| 183 | + } |
| 184 | + |
| 185 | + def visitType(x: TypeOrBounds): Buffer = x match { |
| 186 | + case Type.ConstantType(value) => |
| 187 | + this += "Type.ConstantType(" += value += ")" |
| 188 | + case Type.TermRef(qual, name) => |
| 189 | + this += "Type.TermRef(" += qual+= ", \"" += name += "\")" |
| 190 | + case Type.TypeRef(qual, name) => |
| 191 | + this += "Type.TypeRef(" += qual += ", \"" += name += "\")" |
| 192 | + case Type.Refinement(parent, name, info) => |
| 193 | + this += "Type.Refinement(" += parent += ", " += name += ", " += info += ")" |
| 194 | + case Type.AppliedType(tycon, args) => |
| 195 | + this += "Type.AppliedType(" += tycon += ", " ++= args += ")" |
| 196 | + case Type.AnnotatedType(underlying, annot) => |
| 197 | + this += "Type.AnnotatedType(" += underlying += ", " += annot += ")" |
| 198 | + case Type.AndType(left, right) => |
| 199 | + this += "Type.AndType(" += left += ", " += right += ")" |
| 200 | + case Type.OrType(left, right) => |
| 201 | + this += "Type.OrType(" += left += ", " += right += ")" |
| 202 | + case Type.MatchType(bound, scrutinee, cases) => |
| 203 | + this += "Type.MatchType(" += bound += ", " += scrutinee += ", " ++= cases += ")" |
| 204 | + case Type.ByNameType(underlying) => |
| 205 | + this += "Type.ByNameType(" += underlying += ")" |
| 206 | + case Type.ParamRef(binder, idx) => |
| 207 | + this += "Type.ParamRef(" += binder += ", " += idx += ")" |
| 208 | + case Type.ThisType(tp) => |
| 209 | + this += "Type.ThisType(" += tp += ")" |
| 210 | + case Type.SuperType(thistpe, supertpe) => |
| 211 | + this += "Type.SuperType(" += thistpe += ", " += supertpe += ")" |
| 212 | + case Type.RecursiveThis(binder) => |
| 213 | + this += "Type.RecursiveThis(" += binder += ")" |
| 214 | + case Type.RecursiveType(underlying) => |
| 215 | + this += "Type.RecursiveType(" += underlying += ")" |
| 216 | + case Type.MethodType(argNames, argTypes, resType) => |
| 217 | + this += "Type.MethodType(" ++= argNames += ", " ++= argTypes += ", " += resType += ")" |
| 218 | + case Type.PolyType(argNames, argBounds, resType) => |
| 219 | + this += "Type.PolyType(" ++= argNames += ", " ++= argBounds += ", " += resType += ")" |
| 220 | + case Type.TypeLambda(argNames, argBounds, resType) => |
| 221 | + // resType is not printed to avoid cycles |
| 222 | + this += "Type.TypeLambda(" ++= argNames += ", " ++= argBounds += ", _)" |
| 223 | + case TypeBounds(lo, hi) => |
| 224 | + this += "TypeBounds(" += lo += ", " += hi += ")" |
| 225 | + case NoPrefix() => |
| 226 | + this += "NoPrefix()" |
| 227 | + } |
| 228 | + |
| 229 | + def visitId(x: Id): Buffer = { |
| 230 | + val Id(name) = x |
| 231 | + this += "Id(\"" += name += "\")" |
| 232 | + } |
| 233 | + |
| 234 | + def visitSignature(sig: Signature): Buffer = { |
| 235 | + val Signature(params, res) = sig |
| 236 | + this += "Signature(" ++= params.map(_.toString) += ", " += res += ")" |
| 237 | + } |
| 238 | + |
| 239 | + def visitImportSelector(sel: ImportSelector): Buffer = sel match { |
| 240 | + case SimpleSelector(id) => this += "SimpleSelector(" += id += ")" |
| 241 | + case RenameSelector(id1, id2) => this += "RenameSelector(" += id1 += ", " += id2 += ")" |
| 242 | + case OmitSelector(id) => this += "OmitSelector(" += id += ")" |
| 243 | + } |
| 244 | + |
| 245 | + def visitSymbol(x: Symbol): Buffer = |
| 246 | + if x.isPackageDef then this += "IsPackageDefSymbol(<" += x.fullName += ">)" |
| 247 | + else if x.isClassDef then this += "IsClassDefSymbol(<" += x.fullName += ">)" |
| 248 | + else if x.isDefDef then this += "IsDefDefSymbol(<" += x.fullName += ">)" |
| 249 | + else if x.isValDef then this += "IsValDefSymbol(<" += x.fullName += ">)" |
| 250 | + else if x.isTypeDef then this += "IsTypeDefSymbol(<" += x.fullName += ">)" |
| 251 | + else { assert(x.isNoSymbol); this += "NoSymbol()" } |
| 252 | + |
| 253 | + def +=(x: Boolean): Buffer = { sb.append(x); this } |
| 254 | + def +=(x: Byte): Buffer = { sb.append(x); this } |
| 255 | + def +=(x: Short): Buffer = { sb.append(x); this } |
| 256 | + def +=(x: Int): Buffer = { sb.append(x); this } |
| 257 | + def +=(x: Long): Buffer = { sb.append(x); this } |
| 258 | + def +=(x: Float): Buffer = { sb.append(x); this } |
| 259 | + def +=(x: Double): Buffer = { sb.append(x); this } |
| 260 | + def +=(x: Char): Buffer = { sb.append(x); this } |
| 261 | + def +=(x: String): Buffer = { sb.append(x); this } |
| 262 | + |
| 263 | + def ++=(xs: List[String]): Buffer = visitList[String](xs, +=) |
| 264 | + |
| 265 | + private implicit class TreeOps(buff: Buffer) { |
| 266 | + def +=(x: Tree): Buffer = { visitTree(x); buff } |
| 267 | + def +=(x: Option[Tree]): Buffer = { visitOption(x, visitTree); buff } |
| 268 | + def ++=(x: List[Tree]): Buffer = { visitList(x, visitTree); buff } |
| 269 | + def +++=(x: List[List[Tree]]): Buffer = { visitList(x, ++=); buff } |
| 270 | + } |
| 271 | + |
| 272 | + private implicit class ConstantOps(buff: Buffer) { |
| 273 | + def +=(x: Constant): Buffer = { visitConstant(x); buff } |
| 274 | + } |
| 275 | + |
| 276 | + private implicit class TypeOps(buff: Buffer) { |
| 277 | + def +=(x: TypeOrBounds): Buffer = { visitType(x); buff } |
| 278 | + def +=(x: Option[TypeOrBounds]): Buffer = { visitOption(x, visitType); buff } |
| 279 | + def ++=(x: List[TypeOrBounds]): Buffer = { visitList(x, visitType); buff } |
| 280 | + } |
| 281 | + |
| 282 | + private implicit class IdOps(buff: Buffer) { |
| 283 | + def +=(x: Id): Buffer = { visitId(x); buff } |
| 284 | + def +=(x: Option[Id]): Buffer = { visitOption(x, visitId); buff } |
| 285 | + } |
| 286 | + |
| 287 | + private implicit class SignatureOps(buff: Buffer) { |
| 288 | + def +=(x: Option[Signature]): Buffer = { visitOption(x, visitSignature); buff } |
| 289 | + } |
| 290 | + |
| 291 | + private implicit class ImportSelectorOps(buff: Buffer) { |
| 292 | + def ++=(x: List[ImportSelector]): Buffer = { visitList(x, visitImportSelector); buff } |
| 293 | + } |
| 294 | + |
| 295 | + private implicit class SymbolOps(buff: Buffer) { |
| 296 | + def +=(x: Symbol): Buffer = { visitSymbol(x); buff } |
| 297 | + } |
| 298 | + |
| 299 | + private def visitOption[U](opt: Option[U], visit: U => Buffer): Buffer = opt match { |
| 300 | + case Some(x) => |
| 301 | + this += "Some(" |
| 302 | + visit(x) |
| 303 | + this += ")" |
| 304 | + case _ => |
| 305 | + this += "None" |
| 306 | + } |
| 307 | + |
| 308 | + private def visitList[U](list: List[U], visit: U => Buffer): Buffer = list match { |
| 309 | + case x0 :: xs => |
| 310 | + this += "List(" |
| 311 | + visit(x0) |
| 312 | + def visitNext(xs: List[U]): Unit = xs match { |
| 313 | + case y :: ys => |
| 314 | + this += ", " |
| 315 | + visit(y) |
| 316 | + visitNext(ys) |
| 317 | + case Nil => |
| 318 | + } |
| 319 | + visitNext(xs) |
| 320 | + this += ")" |
| 321 | + case Nil => |
| 322 | + this += "Nil" |
| 323 | + } |
| 324 | + } |
| 325 | + |
| 326 | +} |
0 commit comments