Scala SymbolMatcher failing to match import prefix

95 views Asked by At

I'm using the scalafix library to try to convert a project from scalaz to cats, but one particular attempt at removing imports (the first case in the following code) is failing. The relevant bits of code are:

scalafix code:

package fix

import scala.meta._
import scalafix.v1._

class MigrateList extends SemanticRule("MigrateList") {
  private lazy val std = SymbolMatcher.normalized("scalaz.std.list")
  private lazy val syntax = SymbolMatcher.normalized("scalaz.syntax.std.list")

  override def fix(implicit doc: SemanticDocument): Patch =
    doc.tree.collect {
      case Importer(
          syntax(_),
          List(ip @ Importee.Name(Name("ToListOpsFromList"))),
          ) =>
        Patch.removeImportee(ip)
      case Importer(
          std(_),
          List(ip @ Importee.Name(Name("listInstance"))),
          ) =>
        Patch.removeImportee(ip)
    }.asPatch
}

input file:

package fix

import scalaz.std.list.listInstance
import scalaz.syntax.std.list.ToListOpsFromList

object MigrateList {}

expected output:

package fix

object MigrateList {}

actual output:

package fix

import scalaz.syntax.std.list.ToListOpsFromList

object MigrateList {}

It's the syntax(_) part of the pattern that's the issue. Replacing that with a wildcard causes match to succeed and the import to be removed.
Printing the value of what's there when it matches shows scalaz.syntax.std.list. Replacing the pattern with

Term.Select(
  Term.Select(
    Term.Select(Name("scalaz"), Name("syntax")),
    Name("std"),
  ),
  Name("list"),
)

works too, so I'm pretty sure I'm attempting to match the right thing, just using the SymbolMatcher wrong somehow.

1

There are 1 answers

0
Charles_F On BEST ANSWER

My mistake was assuming that the tree and its associated symbol were structured the same way, with the symbol simply adding metadata.
Actually, the AST is the same as what I was using, but when the SymbolMatcher runs its unapply, it finds that for syntax imports, their path actually gets "resolved" through scalaz.syntax.std.package.list.