in scalafix/rules/src/main/scala/rsc/rules/RscCompat.scala [100:212]
private def collectRewriteTargets(ctx: RuleCtx): List[RewriteTarget] = {
val buf = List.newBuilder[RewriteTarget]
def loop(env: Env, tree: Tree): Env = {
tree match {
case Source(stats) =>
val rootScope = PackageScope(symbols, "_root_/")
val javaLangScope = ImporterScope(symbols, "java/lang/", List(Importee.Wildcard()))
val scalaScope = ImporterScope(symbols, "scala/", List(Importee.Wildcard()))
val predefScope = ImporterScope(symbols, "scala/Predef.", List(Importee.Wildcard()))
val env1 = predefScope :: scalaScope :: javaLangScope :: rootScope :: env
stats.foldLeft(env1)(loop)
case Import(importers) =>
return importers.foldLeft(env)(loop)
case Importer(ref, importees) =>
return ImporterScope(symbols, ref.name.symbol.get.syntax, importees) :: env
case Pkg(ref, stats) =>
val env1 = PackageScope(symbols, ref.name.symbol.get.syntax) :: env
stats.foldLeft(env1)(loop)
case Pkg.Object(_, name, templ) =>
loop(env, templ)
case defn @ Defn.Class(_, _, _, ctor, templ) if defn.isVisible =>
loop(env, ctor)
loop(env, templ)
case ctor: Ctor =>
buf ++= targetsForPolymorphicDefaultParams(env, ctor.name, ctor.tparams, ctor.paramss)
case defn @ Defn.Trait(_, _, _, _, templ) if defn.isVisible =>
loop(env, templ)
case defn @ Defn.Object(_, _, templ) if defn.isVisible =>
loop(env, templ)
case templ @ Template(early, inits, _, stats) =>
val name = templ.name.get
inits.headOption.foreach { init =>
val tokens = init.tpe.tokens
//TODO getOrElse is a workaround for a bug in semanticdb that may cause symbols to
//be incorrect in some cases https://github.com/scalameta/scalameta/issues/1887
lazy val isTrait = (for {
symbol <- init.symbol
info <- symbols.info(symbol.syntax)
} yield info.kind == Kind.TRAIT).getOrElse(false)
// If type params of init may be inferred and init is not a trait
if (!tokens.exists(_.is[Token.LeftBracket]) && !isTrait) {
buf += RewriteInit(env, name, tokens.last)
}
}
val env1 = TemplateScope(symbols, name.symbol.get.syntax) :: env
(early ++ stats).foldLeft(env1)(loop)
case defn @ InferredDefnField(name, body) if defn.isVisible =>
val before = name.tokens.head
val after = name.tokens.last
buf += RewriteDefn(env, before, name, after, body, parens = false, varDefnPat = false)
case defn @ InferredDefnPat(fnames, pnames, body) if defn.isVisible =>
// Apparently, we only need to be worried about patterns with only one symbol
val varDefnPat = defn.is[Defn.Var] && fnames.isEmpty && pnames.size == 1
if (fnames.nonEmpty) {
val name = fnames.head
val before = name.tokens.head
val after = {
val start = name.tokens.head
val end = body.tokens.head
val slice = ctx.tokenList.slice(start, end)
slice.reverse
.find(x => !x.is[Token.Equals] && !x.is[Trivia])
.get
}
buf += RewriteDefn(
env,
before,
name,
after,
body,
parens = false,
varDefnPat = varDefnPat
)
}
pnames.foreach { name =>
val before = name.tokens.head
val after = name.tokens.last
// FIXME: https://github.com/twitter/rsc/issues/142
buf += RewriteDefn(
env,
before,
name,
after,
body,
parens = true,
varDefnPat = varDefnPat
)
}
case defn @ InferredDefnDef(name, body, tparams, paramss) if defn.isVisible =>
val before = name.tokens.head
val after = {
val start = name.tokens.head
val end = body.tokens.head
val slice = ctx.tokenList.slice(start, end)
slice.reverse
.find(x => !x.is[Token.Equals] && !x.is[Trivia])
.get
}
buf += RewriteDefn(env, before, name, after, body, parens = false, varDefnPat = false)
buf ++= targetsForPolymorphicDefaultParams(env, name, tparams, paramss)
// FIXME: https://github.com/twitter/rsc/issues/358
case defn @ Defn.Def(_, name, tparams, paramss, _, _) =>
buf ++= targetsForPolymorphicDefaultParams(env, name, tparams, paramss)
case decl @ Decl.Def(_, name, tparams, paramss, _) =>
buf ++= targetsForPolymorphicDefaultParams(env, name, tparams, paramss)
case _ =>
()
}
env
}
loop(Env(Nil), ctx.tree)
buf.result
}