in scalafix/rules/src/main/scala/rsc/rules/pretty/SemanticdbPrinter.scala [24:188]
def pprint(tpe: s.Type): Unit = {
def prefix(tpe: s.Type): Unit = {
tpe match {
case s.TypeRef(pre, sym, args) =>
if (sym.startsWith("scala/Tuple")) {
str("(")
rep(args, ", ")(normal)
str(")")
} else if (sym.startsWith("scala/Function")) {
val params :+ ret = args
val hasByNameArg = params.exists(_.isInstanceOf[s.ByNameType])
val hasFunctionArg = params.exists {
case s.TypeRef(pre, sym, args) if sym.startsWith("scala/Function") => true
case _ => false
}
val singleTupleArg = params.length == 1 && (params.head match {
case s.TypeRef(_, argSym, _) => argSym.startsWith("scala/Tuple")
case _ => false
})
val needsExtraParens = hasFunctionArg ||
hasByNameArg ||
singleTupleArg ||
(params.length != 1)
if (needsExtraParens) str("(")
rep(params, ", ") { normal }
if (needsExtraParens) str(")")
str(" => ")
normal(ret)
} else {
// TODO: At the moment, we return None for local symbols, since they don't have a desc.
// The logic to improve on this is left for future work.
val name = sym.desc match {
case d.Term(value) => Some(n.TermName(value))
case d.Type(value) => Some(n.TypeName(value))
case d.Package(value) => Some(n.TermName(value))
case d.Parameter(value) => Some(n.TermName(value))
case d.TypeParameter(value) => Some(n.TypeName(value))
case other => None
}
def printPrettyPrefix: Unit = {
val prettyPre = if (pre == s.NoType) sym.trivialPrefix(env) else pre
prettyPre match {
case _: s.SingleType | _: s.ThisType | _: s.SuperType =>
prefix(prettyPre)
str(".")
case s.NoType =>
()
case _ =>
prefix(prettyPre)
str("#")
}
}
if (config.better) {
name.map(fullEnv.lookup) match {
case Some(x) if !symbols.sameOrTypeAlias(x, sym) =>
if (config.autoimport && x.isEmpty && pre == s.NoType) {
addedImportsScope.addImport(sym)
} else {
printPrettyPrefix
}
case _ =>
()
}
} else {
printPrettyPrefix
}
pprint(sym)
rep("[", args, ", ", "]")(normal)
}
case s.SingleType(pre, sym) =>
lazy val fromEnv = fullEnv.lookup(sym.desc.name)
lazy val renamed = fullEnv.getRename(sym.desc.name)
lazy val isRenamedSymbol = renamed.nonEmpty && renamed != sym.desc.value
if (config.better && symbols.sameOrTypeAlias(fromEnv, sym)) {
str(sym.desc.value)
} else if (config.better && isRenamedSymbol) {
str(fullEnv.getRename(sym.desc.name))
} else if (config.better && config.autoimport && fromEnv.isEmpty) {
addedImportsScope.addImport(sym)
str(sym.desc.value)
} else {
val prettyPre = if (pre == s.NoType) sym.trivialPrefix(env) else pre
opt(prettyPre, ".")(prefix)
pprint(sym)
}
case s.ThisType(sym) =>
opt(sym, ".")(pprint)
str("this")
case s.WithType(types) =>
val filteredTypes = if (config.better) {
types.filter {
case s.TypeRef(_, "scala/AnyRef#", _) | s.TypeRef(_, "java/lang/Object#", _) => false
case _ => true
} match {
case Nil => types
case ts => ts
}
} else {
types
}
rep(filteredTypes, " with ") { tpe =>
// FIXME: https://github.com/twitter/rsc/issues/142
val needsParens = tpe.isInstanceOf[s.ExistentialType]
if (needsParens) str("(")
normal(tpe)
if (needsParens) str(")")
}
case s.StructuralType(utpe, decls) =>
decls.infos.foreach(symbols.append)
opt(utpe)(normal)
if (!config.better) {
if (decls.infos.nonEmpty) {
rep(" { ", decls.infos, "; ", " }")(pprint)
} else {
utpe match {
case s.WithType(tpes) if tpes.length > 1 => ()
case _ => str(" {}")
}
}
}
case s.AnnotatedType(anns, utpe) =>
opt(utpe)(normal)
anns.toList match {
case s.Annotation(s.NoType) :: Nil =>
()
case _ =>
rep(" ", anns, " ", "")(pprint)
}
case s.ExistentialType(utpe, decls) =>
decls.infos.foreach(symbols.append)
opt(utpe)(normal)
rep(" forSome { ", decls.infos, "; ", " }")(pprint)
case s.UniversalType(tparams, utpe) =>
// FIXME: https://github.com/twitter/rsc/issues/150
str("({ type λ")
tparams.infos.foreach(symbols.append)
rep("[", tparams.infos, ", ", "] = ")(pprint)
opt(utpe)(normal)
str(" })#λ")
case s.ByNameType(utpe) =>
str("=> ")
opt(utpe)(normal)
case s.RepeatedType(utpe) =>
opt(utpe)(normal)
str("*")
case _: s.SuperType | _: s.ConstantType | _: s.IntersectionType | _: s.UnionType |
s.NoType =>
val details = tpe.asMessage.toProtoString
sys.error(s"unsupported type: $details")
}
}
def normal(tpe: s.Type): Unit = {
tpe match {
case _: s.SingleType | _: s.ThisType | _: s.SuperType =>
prefix(tpe)
str(".type")
case _ =>
prefix(tpe)
}
}
normal(tpe)
}