我有以下信息:
Scalameta:能够从源文件生成 AST
SemanticDB:包含来自已解析源文件的符号信息ScalaFix:基于 ScalaMeta 和 SemanticDB,因此它具有访问符号信息和遍历 AST 的能力。
使用 ScalaMeta 加载源文件非常简单,如下所示:
val path = java.nio.file.Paths.get("path to source file")
val bytes = java.nio.file.Files.readAllBytes(path)
val text = new String(bytes, "UTF-8")
val input = Input.VirtualFile(path.toString, text)
val tree = input.parse[Source].get
从上面的代码片段可以看出,ScalaMeta 将源文件解析为 type Source
。
现在考虑下面的代码片段,其中 ScalaFix 使用类型树SemanticDocument
:
class NamedLiteralArguments extends SemanticRule("NamedLiteralArguments") {
override def fix(implicit doc: SemanticDocument): Patch = {
doc.tree
.collect {
case Term.Apply(fun, args) =>
args.zipWithIndex.collect {
case (t @ Lit.Boolean(_), i) =>
fun.symbol.info match {
case Some(info) =>
info.signature match {
case method: MethodSignature
if method.parameterLists.nonEmpty =>
val parameter = method.parameterLists.head(i)
val parameterName = parameter.displayName
Patch.addLeft(t, s"$parameterName = ")
case _ =>
// Do nothing, the symbol is not a method
Patch.empty
}
case None =>
// Do nothing, we don't have information about this symbol.
Patch.empty
}
}
}
.flatten
.asPatch
}
}
检查上面的两个代码片段表明 ScalaMeta 可以将 Scala 源解析为 type Source
。ScalaFix 似乎将其解析为implicit SemanticDocument
. SemanticDocument
has 字段由 ScalaMeta 实现,tree
它生成一个可遍历的 AST 数据结构,就像将源文件解析为 type 所产生的一样Source
。这显示了 ScalaMeta 和 ScalaFix 之间的关系。但是,我担心的是我需要加载 Scala 源代码并在其上使用 ScalaFix 来访问symbol.info
,但ScalaFix
文档没有显示如何执行此操作。
当我尝试SemanticDocument
在第一个代码片段中加载源文件时,而不是Source
:
val tree = input.parse[SemanticDocument].get
我得到一个错误no parameters found for parameter parse in parse[SemanticDocument]
。另请注意,尝试symbol.info
在第一个代码片段中使用也会产生有关隐式类型的错误。第二个代码片段不是这种情况,因为加载的doc
参数是implicit parameter of type SemanticDocument
.
那么 ScalaFix 是如何加载源文件的SemanticDocument
呢?