Scala 3 dropped class shadowing, so we need to rename some traits to migrate to scala3.
It is not an easy task when there are many such traits.
class Base {
trait Card { }
}
class Sub extends Base {
trait Card extends super.card{ }
}
Stage 1
We should initially refactor the base modules in a way that allows refactoring of the submodules without causing any disruptions.
class Base {
//mark for scalafix
@Scala2Only
trait Card {
//new name
private def useInsted:"BaseCard" = "BaseCard"
}
// type to rename
type BaseCard = Card
}
Stage 2
Run scala fix on submodules.
It will remove deprecated names:
class Sub extends Base {
trait Card extends BaseCard
}
Scalafix example:
package fix
import scalafix.v1.{XtensionTreeScalafix, _}
import scala.meta._
class UpdateAvi extends SemanticRule("UpdateAvi") {
override def fix(implicit doc: SemanticDocument): Patch = {
Patch.fromIterable {
doc.tree.collect { case traitDef: Defn.Trait =>
traitDef.templ.inits.flatMap { init =>
val newInitNameOpt = findReplacementName(
parentSymbol = init.tpe.symbol
)
newInitNameOpt.map { newInitName =>
Patch.replaceTree(init.tpe, newInitName)
}
}
}.flatten
}
}
private def findReplacementName(parentSymbol: Symbol)(implicit doc: SemanticDocument): Option[String] = {
parentSymbol.info.flatMap { info =>
lazy val hasAnnotate = (name: String) => info.annotations.exists(_.tpe.toString() == name)
if (hasAnnotate("Scala2OnlyDvi")) {
Some(s"Dvi${parentSymbol.displayName}")
} else if (hasAnnotate("Scala2Only")) {
info.signature match {
case ClassSignature(_, _, _, declarations) =>
declarations.collectFirst {
case decl if decl.displayName == "useInstead" =>
decl.signature.asInstanceOf[MethodSignature].returnType.asInstanceOf[ConstantType].constant.asInstanceOf[StringConstant].value
}
case _ => None
}
} else None
}
}
}
Stage 3
Remove deprecaded code in base modules:
class Base {
trait BaseCard{ }
}