Skip to content

Instantly share code, notes, and snippets.

@sergkh
Created July 5, 2023 12:14
Show Gist options
  • Save sergkh/37448ad06aeef6436917ee1d97a74335 to your computer and use it in GitHub Desktop.
Save sergkh/37448ad06aeef6436917ee1d97a74335 to your computer and use it in GitHub Desktop.
package fix
import scalafix.v1._
import scala.meta._
import scala.reflect.internal.Importers
import scala.collection.mutable
// Scalafix rule to migrate from sp-commons 1.8.X to 2.0.0
class MigrationToV2 extends SyntacticRule("MigrationToV2") {
final val movedModels = List("FieldModels", "BaseModels", "CcmModels", "Models", "CardModels")
final val dropImports = List(
"com.fidesmo.sp.delivery.free.Delivery.DeliveryFailedException",
"com.fidesmo.sp.delivery.free.Delivery.ActionProps"
)
override def fix(implicit doc: SyntacticDocument): Patch = {
//println("Tree.structureLabeled: " + doc.tree.structureLabeled)
val imports = mutable.Map.empty[String, Importer]
def addImporter(importer: Importer, importees: List[Importee] = Nil): Patch = {
var importsRemovalPatch = Patch.empty
imports(importer.syntax) = importer
importees.foreach { i =>
importsRemovalPatch += Patch.removeImportee(i)
}
importsRemovalPatch
}
doc.tree.collect {
case t:Importer if dropImports.exists(t.toString.contains) =>
Patch.replaceTree(t.parent.get, "")
// Free subpackage moved into delivery
case t: Importer if t.toString().contains("com.fidesmo.sp.delivery.free") =>
Patch.replaceTree(t, t.toString().replace("com.fidesmo.sp.delivery.free", "com.fidesmo.sp.delivery"))
case t @ Type.Name("DeliveryFailedException") =>
addImporter(importer"com.fidesmo.sp.delivery.DeliveryFailedException")
case t @ Type.Name("DeliveryException") =>
addImporter(importer"com.fidesmo.sp.delivery.DeliveryException")
// For some reason pattern extraction not always matches exception types
case c: Pat.Extract if c.children.exists(_.syntax == "DeliveryFailedException") =>
addImporter(importer"com.fidesmo.sp.delivery.DeliveryFailedException")
// For some reason pattern extraction not always matches exception types
case c: Pat.Extract if c.children.exists(_.syntax == "DeliveryException") =>
addImporter(importer"com.fidesmo.sp.delivery.DeliveryException")
case t @ Term.Name("ActionProps") =>
addImporter(importer"com.fidesmo.sp.delivery.ActionProps")
// buildStateless is deprecated so let's use simple build
case t @ q"buildStateless" =>
Patch.replaceTree(t, "build")
// replace exact match of any of classes imports, e.g. import com.fidesmo.sp.models.{Models, BaseModels}
case t: Importer if t.toString().contains("com.fidesmo.sp.models") && t.importees.exists(i => movedModels.exists(m => m == i.toString())) =>
addImporter(importer"com.fidesmo.sp.models._", t.importees)
// replace subclass match of any of classes imports, e.g. import com.fidesmo.sp.models.BaseModels.Dgi
case t: Importer if movedModels.map("com.fidesmo.sp.models." + _).exists(path => t.toString().contains(path)) =>
val tokens = t.tokens
val subImports = tokens.takeRightWhile(t => !movedModels.contains(t.toString())) // skip com.fidesmo.sp.models.X part
val tokensNumber = subImports.size
if (tokensNumber > 2) {
// a compound import, something like BaseModels.Operation._, better apply in place fix
val groupObject = tokens(tokens.size - tokensNumber - 1)
val groupObjectDot = tokens(tokens.size - tokensNumber)
Patch.removeTokens(List(groupObject, groupObjectDot))
} else {
// likely a direct import like BaseModels.Dgi or FieldModels._, safe to replace with _
addImporter(importer"com.fidesmo.sp.models._", t.importees)
}
case t @ q"props" if t.parent.exists(_.is[Term.Apply]) =>
addImporter(importer"com.fidesmo.sp.delivery.ActionProps.props", List.empty)
case t @ Term.Name(name) if t.parent.exists(_.is[Term.Select]) && movedModels.contains(name) =>
val select = t.parent.get.asInstanceOf[Term.Select]
val tokens = select.tokens
if (movedModels.contains(tokens.head.toString())) {
Patch.removeTokens(tokens.take(2)) // 2 tokens: FieldModels and .
} else {
Patch.empty
}
}.asPatch ++ imports.values.map(Patch.addGlobalImport)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment