Relationship between ScalaMeta, ScalaFix, and SemanticDB

300 views Asked by At

I have the following information:

  • Scalameta: has the ability to produce ASTs from a source file

  • SemanticDB: Contains information about symbols from a parsed source
    file

  • ScalaFix: is based on ScalaMeta and SemanticDB so it has the ability to access symbol information and traverse ASTs.

Loading a source file using ScalaMeta is as easy as the following:

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

As you can observe from the above code snippet, ScalaMeta parses the source file as type Source.

Now consider the below code snippet where ScalaFix uses a tree of type 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
  }
}

Inspecting the above two code snippets shows that ScalaMeta can parse a Scala source into type Source. ScalaFix seems to parse the same into an implicit SemanticDocument. The SemanticDocument has field tree which is implemented by ScalaMeta which results into a traversable AST data structure just like the one produced by parsing source file as type Source. This shows the relationship between ScalaMeta and ScalaFix. However, my concern is that I need to load a Scala source code and use ScalaFix on it to access symbol.info but the ScalaFix documentation does not show how to do this.

When I attempt to load source file as a SemanticDocument like this in the first code snippet instead of Source:

 val tree = input.parse[SemanticDocument].get

I get an error that no parameters found for parameter parse in parse[SemanticDocument]. Also note that trying to use symbol.info in the first code snippet also produces errors about implicit types. This is not the case with the second code snippet as the loaded doc parameter is an implicit parameter of type SemanticDocument.

So how does ScalaFix load source files as SemanticDocument?

0

There are 0 answers