Skip to content

Instantly share code, notes, and snippets.

@xuwei-k
Last active April 23, 2026 08:16
Show Gist options
  • Select an option

  • Save xuwei-k/e3074ef0c558a33a34a0ab29fc017d16 to your computer and use it in GitHub Desktop.

Select an option

Save xuwei-k/e3074ef0c558a33a34a0ab29fc017d16 to your computer and use it in GitHub Desktop.
import java.io.File
import scala.quoted.Quotes
import scala.reflect.TypeTest
import scala.tasty.inspector.Inspector
import scala.tasty.inspector.Tasty
import scala.tasty.inspector.TastyInspector
object CoherenceTest {
enum TastyOrJar {
case Tasty(value: File)
case Jar(value: File)
}
private def getTastyFileOrJar(clazz: Class[?]): TastyOrJar = {
val base = new File(clazz.getProtectionDomain.getCodeSource.getLocation.getFile)
println(base)
if (base.isDirectory) {
val name = s"${clazz.getName.replace('.', '/')}.tasty"
TastyOrJar.Tasty(new File(base, name))
} else if (base.isFile && base.getName.endsWith(".jar")) {
TastyOrJar.Jar(base)
} else {
sys.error(s"not found $clazz")
}
}
private def runInspector(clazz: Class[?], inspector: Inspector): Unit = {
getTastyFileOrJar(clazz) match {
case TastyOrJar.Tasty(tasty) =>
TastyInspector.inspectAllTastyFiles(
tastyFiles = tasty.getAbsolutePath :: Nil,
jars = Nil,
dependenciesClasspath = Nil
)(inspector)
case TastyOrJar.Jar(jar) =>
TastyInspector.inspectAllTastyFiles(
tastyFiles = Nil,
jars = jar.getAbsolutePath :: Nil,
dependenciesClasspath = Nil
)(inspector)
}
}
val inspector = new Inspector {
override def inspect(using q: Quotes)(tastys: List[Tasty[q.type]]): Unit = {
import q.reflect.*
case class Result(typeString: String, pos: Position)
val accumulator = new TreeAccumulator[List[Result]] {
override def foldTree(result: List[Result], tree: Tree)(owner: Symbol): List[Result] = {
tree match {
case x: ValOrDefDef
if !x.symbol.flags.is(Flags.Param) && (x.symbol.flags.is(Flags.Given) || x.symbol.flags.is(Flags.Implicit)) && summon[
TypeTest[Tree, Applied]
].unapply(x.tpt).isDefined =>
val r = Result(x.tpt.tpe.dealias.show, x.pos) :: result
x.rhs match {
case Some(body) =>
foldTree(r, body)(owner)
case None =>
r
}
case _ =>
foldOverTree(result, tree)(owner)
}
}
}
val result: List[Result] = tastys.flatMap {
t =>
accumulator.foldOverTree(Nil, t.ast)(Symbol.spliceOwner)
}
println(result.size)
val duplicate = result.groupBy(_.typeString).filter(_._2.sizeIs > 1).toList.sortBy(_._2.size)
println(duplicate.size)
duplicate.foreach {
(k, v) =>
println(s"${k} ${v.size}")
}
duplicate.filter(_._2.size < 10).foreach {
(k, v) =>
v.foreach(x =>
report.warning(s"Duplicate ${k} instance", x.pos)
)
}
}
}
def main(args: Array[String]): Unit = {
runInspector(classOf[ここにクラス], inspector)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment