基于Scala-Meta的类型推断及跨编译单元全类型名检测方法问询
First: Using Scala-Meta for Type Inference & Full Type Name Detection
Scala-Meta is a syntax-level AST library—out of the box, it doesn’t have access to type information because type inference is the exclusive job of the Scala compiler (scalac). To make it work for type detection, you need to pair it with SemanticDB, the official Scala semantic information database that scalac generates during compilation.
Here’s a step-by-step implementation:
- Enable SemanticDB in your build (add this to
build.sbtfor sbt projects):scalacOptions ++= Seq( "-Yrangepos", "-Xsemanticdb", "-Xsemanticdb-target:semanticdb" ) - Use Scala-Meta to read SemanticDB data and resolve full type names across compilation units:
This works across compilation units because SemanticDB generates data for all compiled files, so you can resolve T’s full name even if it’s defined in a separate module.import scala.meta._ import scala.meta.semanticdb._ // Parse the target compilation unit A val sourceFile = Source.fromFile("path/to/CompilationUnitA.scala").parse[Source].get // Collect all references to your type T (adjust the match logic to your needs) val typeReferences = sourceFile.collect { case typeName: Type.Name if typeName.value == "T" => typeName.symbol // Fetch the semantic symbol for the type } // Print the fully qualified name of each reference typeReferences.foreach { sym => println(s"Full type name: ${sym.fullName}") }
Are There Better Tools Than Scala-Meta for Safe, Easy Type Detection?
You’re right—Scala-Meta is powerful but not always the most straightforward for type-specific tasks. Here are three safer, more convenient alternatives tailored to different use cases:
1. Scalafix (Best for Static Analysis)
Scalafix is built on SemanticDB and provides a higher-level, more intuitive API for static code analysis. It handles all SemanticDB boilerplate for you and integrates seamlessly with sbt/maven.
Example rule to find all references to com.example.T and log their full names:
import scalafix.v1._ import scala.meta._ class FindTypeTRule extends Rule("FindTypeTRule") { override def fix(implicit doc: SemanticDocument): Patch = { doc.tree.collect { case typeRef: Type.Name if typeRef.symbol.fullName == "com.example.T" => println(s"Found reference to full type: ${typeRef.symbol.fullName} at ${typeRef.pos}") Patch.empty }.asPatch } }
2. Scalac Plugins (Most Accurate, For Compile-Time Checks)
If you need the most precise type information (including handling complex cases like path-dependent types, type aliases, and generics), writing a scalac plugin is the gold standard. Plugins run directly in the compiler pipeline, so they have full access to all type inference results.
Example snippet from a scalac plugin to detect T references:
import scala.tools.nsc._ import scala.tools.nsc.plugins.Plugin class TypeDetectionPlugin(val global: Global) extends Plugin { override val name = "type-detector" override val description = "Detects references to type T" override def process(options: List[String]): Boolean = { global.addAnalyzerPhase(new TypeDetectorPhase(global)) true } class TypeDetectorPhase(global: Global) extends global.GlobalPhase(global) { override val phaseName = "type-detector" override def runsAfter = List("typer") // Run after type inference completes override def apply(unit: global.CompilationUnit): Unit = { import global._ new Traverser { override def traverse(tree: Tree): Unit = tree match { case t: TypeTree if t.tpe.typeSymbol.fullName == "com.example.T" => println(s"Found reference to full type: ${t.tpe.typeSymbol.fullName} at ${tree.pos}") case _ => super.traverse(tree) } }.traverse(unit.body) } } }
Note: Scalac plugin APIs are tied to specific Scala versions, so you’ll need to maintain version compatibility.
3. Metals/LSP (For IDE-Integrated Detection)
If you’re building an IDE tool or need interactive type detection, Metals (the Scala LSP implementation) uses SemanticDB to expose type information. Its API lets you query references to a type and get their full qualified names, though this is better suited for IDE workflows than batch analysis.
Key Takeaways for Safe Type Detection
- Avoid pure syntax tools (like Scala-Meta without SemanticDB)—they can’t resolve type aliases, path-dependent types, or imported names correctly.
- SemanticDB is the foundation for most modern Scala static analysis tools; any safe solution will build on it or use the compiler’s internal type system.
- Choose your tool based on use case:
- Use Scalafix for simple, maintainable static analysis.
- Use a scalac plugin for the most accurate compile-time checks.
- Use Scala-Meta + SemanticDB if you need full control over AST manipulation alongside type information.
内容的提问来源于stack exchange,提问作者kostas.kougios

