Clean up ShowApi implicit overload

Motivated because we want to make it more robust & configurable.
Original motivation was to diagnose a cyclic type representation,
likely due to an f-bounded existential type, as illustrated by the following:

```
class Dep {
  // The API representation for `bla`'s result type contains a cycle
  // (an existential's type variable's bound is the existential type itself)
  // This results in a stack overflow while showing the API diff.
  // Note that the actual result type in the compiler is not cyclic
  // (the f-bounded existential for Comparable is truncated)
  def bla(c: Boolean) = if (c) new Value else "bla"
}

class Value extends java.lang.Comparable[Value] { def compareTo(that: Value): Int = 1 }
```

Limit nesting (`-Dsbt.inc.apidiff.depth=N`, where N defaults to `2`),
and number of declarations shown for a class/structural type
(via `sbt.inc.apidiff.decls`, which defaults to `0` -- no limit).

Limiting nesting is crucial in keeping the size of api diffs of large programs
within a reasonable amount of RAM...

For example, compiling the Scala library, the API diff with nesting at `4`
exhausts 4G of RAM...
This commit is contained in:
Adriaan Moors 2015-12-01 23:02:25 -08:00 committed by Eugene Yokota
parent 51524055f7
commit 3e03e0d1b5
4 changed files with 142 additions and 282 deletions

View File

@ -5,284 +5,147 @@ package xsbt.api
import xsbti.api._
trait Show[A] {
def show(a: A): String
}
import scala.util.Try
final class ShowLazy[A](delegate: => Show[A]) extends Show[A] {
private lazy val s = delegate
def show(a: A) = s.show(a)
}
object DefaultShowAPI {
private lazy val defaultNesting = Try { java.lang.Integer.parseInt(sys.props.get("sbt.inc.apidiff.depth").get) } getOrElse 2
import ShowAPI._
def apply(d: Definition) = ShowAPI.showDefinition(d)(defaultNesting)
def apply(d: Type) = ShowAPI.showType(d)(defaultNesting)
def apply(a: SourceAPI) = ShowAPI.showApi(a)(defaultNesting)
}
object ShowAPI {
def Show[T](implicit s: Show[T]): Show[T] = s
def show[T](t: T)(implicit s: Show[T]): String = s.show(t)
private lazy val numDecls = Try { java.lang.Integer.parseInt(sys.props.get("sbt.inc.apidiff.decls").get) } getOrElse 0
def bounds(lower: Type, upper: Type)(implicit t: Show[Type]): String =
">: " + t.show(lower) + " <: " + t.show(upper)
private def truncateDecls(decls: Array[Definition]): Array[Definition] = if (numDecls <= 0) decls else decls.take(numDecls)
private def lines(ls: Seq[String]): String = ls.mkString("\n", "\n", "\n")
import ParameterModifier._
def parameterModifier(base: String, pm: ParameterModifier): String =
pm match {
case Plain => base
case Repeated => base + "*"
case ByName => "=> " + base
def showApi(a: SourceAPI)(implicit nesting: Int) =
a.packages.map(pkg => "package " + pkg.name).mkString("\n") + lines(truncateDecls(a.definitions).map(showDefinition))
def showDefinition(d: Definition)(implicit nesting: Int): String = d match {
case v: Val => showMonoDef(v, "val") + ": " + showType(v.tpe)
case v: Var => showMonoDef(v, "var") + ": " + showType(v.tpe)
case d: Def => showPolyDef(d, "def") + showValueParams(d.valueParameters) + ": " + showType(d.returnType)
case ta: TypeAlias => showPolyDef(ta, "type") + " = " + showType(ta.tpe)
case td: TypeDeclaration => showPolyDef(td, "type") + showBounds(td.lowerBound, td.upperBound)
case cl: ClassLike => showPolyDef(cl, showDefinitionType(cl.definitionType)) + " extends " + showTemplate(cl)
}
private def showTemplate(cl: ClassLike)(implicit nesting: Int) =
if (nesting <= 0) "<nesting level reached>"
else {
val showSelf = if (cl.selfType.isInstanceOf[EmptyType]) "" else " self: " + showNestedType(cl.selfType) + " =>"
cl.structure.parents.map(showNestedType).mkString("", " with ", " {") + showSelf +
lines(truncateDecls(cl.structure.inherited).map(d => "^inherited^ " + showNestedDefinition(d))) +
lines(truncateDecls(cl.structure.declared).map(showNestedDefinition)) +
"}"
}
def concat[A](list: Seq[A], as: Show[A], sep: String): String = mapSeq(list, as).mkString(sep)
def commas[A](list: Seq[A], as: Show[A]): String = concat(list, as, ", ")
def spaced[A](list: Seq[A], as: Show[A]): String = concat(list, as, " ")
def lines[A](list: Seq[A], as: Show[A]): String = mapSeq(list, as).mkString("\n")
def mapSeq[A](list: Seq[A], as: Show[A]): Seq[String] = list.map(as.show)
def showType(t: Type)(implicit nesting: Int): String = t match {
case st: Projection => showType(st.prefix) + "#" + st.id
case st: ParameterRef => "<" + st.id + ">"
case st: Singleton => showPath(st.path)
case st: EmptyType => "<empty>"
case p: Parameterized => showType(p.baseType) + p.typeArguments.map(showType).mkString("[", ", ", "]")
case c: Constant => showType(c.baseType) + "(" + c.value + ")"
case a: Annotated => showAnnotations(a.annotations) + " " + showType(a.baseType)
case s: Structure =>
s.parents.map(showType).mkString(" with ") + (
if (nesting <= 0) "{ <nesting level reached> }"
else truncateDecls(s.declared).map(showNestedDefinition).mkString(" {", "\n", "}"))
case e: Existential =>
showType(e.baseType) + (
if (nesting <= 0) " forSome { <nesting level reached> }"
else e.clause.map(t => "type " + showNestedTypeParameter(t)).mkString(" forSome { ", "; ", " }"))
case p: Polymorphic => showType(p.baseType) + (
if (nesting <= 0) " [ <nesting level reached> ]"
else showNestedTypeParameters(p.parameters))
}
private def showPath(p: Path): String = p.components.map(showPathComponent).mkString(".")
private def showPathComponent(pc: PathComponent) = pc match {
case s: Super => "super[" + showPath(s.qualifier) + "]"
case _: This => "this"
case i: Id => i.id
}
private def space(s: String) = if (s.isEmpty) s else s + " "
private def showMonoDef(d: Definition, label: String)(implicit nesting: Int): String =
space(showAnnotations(d.annotations)) + space(showAccess(d.access)) + space(showModifiers(d.modifiers)) + space(label) + d.name
private def showPolyDef(d: ParameterizedDefinition, label: String)(implicit nesting: Int): String =
showMonoDef(d, label) + showTypeParameters(d.typeParameters)
private def showTypeParameters(tps: Seq[TypeParameter])(implicit nesting: Int): String =
if (tps.isEmpty) ""
else tps.map(showTypeParameter).mkString("[", ", ", "]")
private def showTypeParameter(tp: TypeParameter)(implicit nesting: Int): String =
showAnnotations(tp.annotations) + " " + showVariance(tp.variance) + tp.id + showTypeParameters(tp.typeParameters) + " " + showBounds(tp.lowerBound, tp.upperBound)
private def showAnnotations(as: Seq[Annotation])(implicit nesting: Int) = as.map(showAnnotation).mkString(" ")
private def showAnnotation(a: Annotation)(implicit nesting: Int) =
"@" + showType(a.base) + (
if (a.arguments.isEmpty) ""
else a.arguments.map(a => a.name + " = " + a.value).mkString("(", ", ", ")")
)
private def showBounds(lower: Type, upper: Type)(implicit nesting: Int): String = ">: " + showType(lower) + " <: " + showType(upper)
private def showValueParams(ps: Seq[ParameterList])(implicit nesting: Int): String =
ps.map(pl =>
pl.parameters.map(mp =>
mp.name + ": " + showParameterModifier(showType(mp.tpe), mp.modifier) + (if (mp.hasDefault) "= ..." else "")
).mkString(if (pl.isImplicit) "(implicit " else "(", ", ", ")")
).mkString("")
private def showParameterModifier(base: String, pm: ParameterModifier): String = pm match {
case ParameterModifier.Plain => base
case ParameterModifier.Repeated => base + "*"
case ParameterModifier.ByName => "=> " + base
}
private def showDefinitionType(d: DefinitionType) = d match {
case DefinitionType.Trait => "trait"
case DefinitionType.ClassDef => "class"
case DefinitionType.Module => "object"
case DefinitionType.PackageModule => "package object"
}
private def showAccess(a: Access) = a match {
case p: Public => ""
case p: Protected => "protected" + showQualifier(p.qualifier)
case p: Private => "private" + showQualifier(p.qualifier)
}
private def showQualifier(q: Qualifier) = q match {
case _: Unqualified => ""
case _: ThisQualifier => "[this]"
case i: IdQualifier => "[" + i.value + "]"
}
private def showModifiers(m: Modifiers) = List(
(m.isOverride, "override"),
(m.isFinal, "final"),
(m.isSealed, "sealed"),
(m.isImplicit, "implicit"),
(m.isAbstract, "abstract"),
(m.isLazy, "lazy")
).collect { case (true, mod) => mod }.mkString(" ")
private def showVariance(v: Variance) = v match {
case Variance.Invariant => ""
case Variance.Covariant => "+"
case Variance.Contravariant => "-"
}
// limit nesting to prevent cycles and generally keep output from getting humongous
private def showNestedType(tp: Type)(implicit nesting: Int) = showType(tp)(nesting - 1)
private def showNestedTypeParameter(tp: TypeParameter)(implicit nesting: Int) = showTypeParameter(tp)(nesting - 1)
private def showNestedTypeParameters(tps: Seq[TypeParameter])(implicit nesting: Int) = showTypeParameters(tps)(nesting - 1)
private def showNestedDefinition(d: Definition)(implicit nesting: Int) = showDefinition(d)(nesting - 1)
}
trait ShowBase {
implicit def showAnnotation(implicit as: Show[AnnotationArgument], t: Show[Type]): Show[Annotation] =
new Show[Annotation] { def show(a: Annotation) = "@" + t.show(a.base) + (if (a.arguments.isEmpty) "" else "(" + commas(a.arguments, as) + ")") }
implicit def showAnnotationArgument: Show[AnnotationArgument] =
new Show[AnnotationArgument] { def show(a: AnnotationArgument) = a.name + " = " + a.value }
import Variance._
implicit def showVariance: Show[Variance] =
new Show[Variance] { def show(v: Variance) = v match { case Invariant => ""; case Covariant => "+"; case Contravariant => "-" } }
implicit def showSource(implicit ps: Show[Package], ds: Show[Definition]): Show[SourceAPI] =
new Show[SourceAPI] { def show(a: SourceAPI) = lines(a.packages, ps) + "\n" + lines(a.definitions, ds) }
implicit def showPackage: Show[Package] =
new Show[Package] { def show(pkg: Package) = "package " + pkg.name }
implicit def showAccess(implicit sq: Show[Qualified]): Show[Access] =
new Show[Access] {
def show(a: Access) =
a match {
case p: Public => ""
case q: Qualified => sq.show(q)
}
}
implicit def showQualified(implicit sq: Show[Qualifier]): Show[Qualified] =
new Show[Qualified] {
def show(q: Qualified) =
((q match {
case p: Protected => "protected"
case p: Private => "private"
})
+ sq.show(q.qualifier))
}
implicit def showQualifier: Show[Qualifier] =
new Show[Qualifier] {
def show(q: Qualifier) =
q match {
case _: Unqualified => ""
case _: ThisQualifier => "[this]"
case i: IdQualifier => "[" + i.value + "]"
}
}
implicit def showModifiers: Show[Modifiers] =
new Show[Modifiers] {
def show(m: Modifiers) =
{
val mods =
(m.isOverride, "override") ::
(m.isFinal, "final") ::
(m.isSealed, "sealed") ::
(m.isImplicit, "implicit") ::
(m.isAbstract, "abstract") ::
(m.isLazy, "lazy") ::
Nil
mods.filter(_._1).map(_._2).mkString(" ")
}
}
implicit def showDefinitionType: Show[DefinitionType] =
new Show[DefinitionType] {
import DefinitionType._
def show(dt: DefinitionType) =
dt match {
case Trait => "trait"
case ClassDef => "class"
case Module => "object"
case PackageModule => "package object"
}
}
}
trait ShowDefinitions {
implicit def showVal(implicit acs: Show[Access], ms: Show[Modifiers], ans: Show[Annotation], t: Show[Type]): Show[Val] =
new Show[Val] { def show(v: Val) = definitionBase(v, "val")(acs, ms, ans) + ": " + t.show(v.tpe) }
implicit def showVar(implicit acs: Show[Access], ms: Show[Modifiers], ans: Show[Annotation], t: Show[Type]): Show[Var] =
new Show[Var] { def show(v: Var) = definitionBase(v, "var")(acs, ms, ans) + ": " + t.show(v.tpe) }
implicit def showDef(implicit acs: Show[Access], ms: Show[Modifiers], ans: Show[Annotation], tp: Show[Seq[TypeParameter]], vp: Show[Seq[ParameterList]], t: Show[Type]): Show[Def] =
new Show[Def] { def show(d: Def) = parameterizedDef(d, "def")(acs, ms, ans, tp) + vp.show(d.valueParameters) + ": " + t.show(d.returnType) }
implicit def showClassLike(implicit acs: Show[Access], ms: Show[Modifiers], ans: Show[Annotation], tp: Show[Seq[TypeParameter]], dt: Show[DefinitionType], s: Show[Structure], t: Show[Type]): Show[ClassLike] =
new Show[ClassLike] { def show(cl: ClassLike) = parameterizedDef(cl, dt.show(cl.definitionType))(acs, ms, ans, tp) + " requires " + t.show(cl.selfType) + " extends " + s.show(cl.structure) }
implicit def showTypeAlias(implicit acs: Show[Access], ms: Show[Modifiers], ans: Show[Annotation], tp: Show[Seq[TypeParameter]], t: Show[Type]): Show[TypeAlias] =
new Show[TypeAlias] { def show(ta: TypeAlias) = parameterizedDef(ta, "type")(acs, ms, ans, tp) + " = " + t.show(ta.tpe) }
implicit def showTypeDeclaration(implicit acs: Show[Access], ms: Show[Modifiers], ans: Show[Annotation], tp: Show[Seq[TypeParameter]], t: Show[Type]): Show[TypeDeclaration] =
new Show[TypeDeclaration] { def show(td: TypeDeclaration) = parameterizedDef(td, "type")(acs, ms, ans, tp) + bounds(td.lowerBound, td.upperBound) }
def showClassLikeSimple(implicit acs: Show[Access], ms: Show[Modifiers], ans: Show[Annotation], tp: Show[Seq[TypeParameter]], dt: Show[DefinitionType]): Show[ClassLike] =
new Show[ClassLike] { def show(cl: ClassLike) = parameterizedDef(cl, dt.show(cl.definitionType))(acs, ms, ans, tp) }
def parameterizedDef(d: ParameterizedDefinition, label: String)(implicit acs: Show[Access], ms: Show[Modifiers], ans: Show[Annotation], tp: Show[Seq[TypeParameter]]): String =
definitionBase(d, label)(acs, ms, ans) + tp.show(d.typeParameters)
def definitionBase(d: Definition, label: String)(implicit acs: Show[Access], ms: Show[Modifiers], ans: Show[Annotation]): String =
space(spaced(d.annotations, ans)) + space(acs.show(d.access)) + space(ms.show(d.modifiers)) + space(label) + d.name
def space(s: String) = if (s.isEmpty) s else s + " "
}
trait ShowDefinition {
implicit def showDefinition(implicit vl: Show[Val], vr: Show[Var], ds: Show[Def], cl: Show[ClassLike], ta: Show[TypeAlias], td: Show[TypeDeclaration]): Show[Definition] =
new Show[Definition] {
def show(d: Definition) =
d match {
case v: Val => vl.show(v)
case v: Var => vr.show(v)
case d: Def => ds.show(d)
case c: ClassLike => cl.show(c)
case t: TypeAlias => ta.show(t)
case t: TypeDeclaration => td.show(t)
}
}
}
trait ShowType {
implicit def showType(implicit s: Show[SimpleType], a: Show[Annotated], st: Show[Structure], c: Show[Constant], e: Show[Existential], po: Show[Polymorphic]): Show[Type] =
new Show[Type] {
def show(t: Type) =
t match {
case q: SimpleType => s.show(q)
case q: Constant => c.show(q)
case q: Annotated => a.show(q)
case q: Structure => st.show(q)
case q: Existential => e.show(q)
case q: Polymorphic => po.show(q)
}
}
implicit def showSimpleType(implicit pr: Show[Projection], pa: Show[ParameterRef], si: Show[Singleton], et: Show[EmptyType], p: Show[Parameterized]): Show[SimpleType] =
new Show[SimpleType] {
def show(t: SimpleType) =
t match {
case q: Projection => pr.show(q)
case q: ParameterRef => pa.show(q)
case q: Singleton => si.show(q)
case q: EmptyType => et.show(q)
case q: Parameterized => p.show(q)
}
}
}
trait ShowBasicTypes {
implicit def showSingleton(implicit p: Show[Path]): Show[Singleton] =
new Show[Singleton] { def show(s: Singleton) = p.show(s.path) }
implicit def showEmptyType: Show[EmptyType] =
new Show[EmptyType] { def show(e: EmptyType) = "<empty>" }
implicit def showParameterRef: Show[ParameterRef] =
new Show[ParameterRef] { def show(p: ParameterRef) = "<" + p.id + ">" }
}
trait ShowTypes {
implicit def showStructure(implicit t: Show[Type], d: Show[Definition]): Show[Structure] =
new Show[Structure] {
def show(s: Structure) = {
// don't show inherited class like definitions to avoid dealing with cycles
val safeInherited = s.inherited.filterNot(_.isInstanceOf[ClassLike])
val showInherited: Show[Definition] = new Show[Definition] {
def show(deff: Definition): String = "^inherited^ " + d.show(deff)
}
concat(s.parents, t, " with ") + "\n{\n" + lines(safeInherited, showInherited) + "\n" + lines(s.declared, d) + "\n}"
}
}
implicit def showAnnotated(implicit as: Show[Annotation], t: Show[Type]): Show[Annotated] =
new Show[Annotated] { def show(a: Annotated) = spaced(a.annotations, as) + " " + t.show(a.baseType) }
implicit def showProjection(implicit t: Show[SimpleType]): Show[Projection] =
new Show[Projection] { def show(p: Projection) = t.show(p.prefix) + "#" + p.id }
implicit def showParameterized(implicit t: Show[Type]): Show[Parameterized] =
new Show[Parameterized] { def show(p: Parameterized) = t.show(p.baseType) + mapSeq(p.typeArguments, t).mkString("[", ", ", "]") }
implicit def showConstant(implicit t: Show[Type]): Show[Constant] =
new Show[Constant] { def show(c: Constant) = t.show(c.baseType) + "(" + c.value + ")" }
implicit def showExistential(implicit t: Show[Type], tp: Show[TypeParameter]): Show[Existential] =
new Show[Existential] {
def show(e: Existential) =
t.show(e.baseType) + e.clause.map(t => "type " + tp.show(t)).mkString(" forSome { ", "; ", "}")
}
implicit def showPolymorphic(implicit t: Show[Type], tps: Show[Seq[TypeParameter]]): Show[Polymorphic] =
new Show[Polymorphic] { def show(p: Polymorphic) = t.show(p.baseType) + tps.show(p.parameters) }
}
trait ShowPath {
implicit def showPath(implicit pc: Show[PathComponent]): Show[Path] =
new Show[Path] { def show(p: Path) = mapSeq(p.components, pc).mkString(".") }
implicit def showPathComponent(implicit sp: Show[Path]): Show[PathComponent] =
new Show[PathComponent] {
def show(p: PathComponent) =
p match {
case s: Super => "super[" + sp.show(s.qualifier) + "]"
case _: This => "this"
case i: Id => i.id
}
}
}
trait ShowValueParameters {
implicit def showParameterLists(implicit pl: Show[ParameterList]): Show[Seq[ParameterList]] =
new Show[Seq[ParameterList]] { def show(p: Seq[ParameterList]) = concat(p, pl, "") }
implicit def showParameterList(implicit mp: Show[MethodParameter]): Show[ParameterList] =
new Show[ParameterList] { def show(pl: ParameterList) = "(" + (if (pl.isImplicit) "implicit " else "") + commas(pl.parameters, mp) + ")" }
implicit def showMethodParameter(implicit t: Show[Type]): Show[MethodParameter] =
new Show[MethodParameter] {
def show(mp: MethodParameter) =
mp.name + ": " + parameterModifier(t.show(mp.tpe), mp.modifier) + (if (mp.hasDefault) "= ..." else "")
}
}
trait ShowTypeParameters {
implicit def showTypeParameters(implicit as: Show[TypeParameter]): Show[Seq[TypeParameter]] =
new Show[Seq[TypeParameter]] { def show(tps: Seq[TypeParameter]) = if (tps.isEmpty) "" else mapSeq(tps, as).mkString("[", ",", "]") }
implicit def showTypeParameter(implicit as: Show[Annotation], tp: Show[Seq[TypeParameter]], t: Show[Type], v: Show[Variance]): Show[TypeParameter] =
new Show[TypeParameter] {
def show(tps: TypeParameter) =
spaced(tps.annotations, as) + " " + v.show(tps.variance) + tps.id + tp.show(tps.typeParameters) + " " + bounds(tps.lowerBound, tps.upperBound)
}
}
// this class is a hack to resolve some diverging implicit errors.
// I'm pretty sure the cause is the Show[Seq[T]] dominating Show[X] issue.
// It could probably be reduced a bit if that is the case (below was trial and error)
object DefaultShowAPI extends ShowBase with ShowBasicTypes with ShowValueParameters {
def apply(d: Definition) = ShowAPI.show(d)
def apply(d: Type) = ShowAPI.show(d)
implicit lazy val showVal: Show[Val] = Cyclic.showVal
implicit lazy val showVar: Show[Var] = Cyclic.showVar
implicit lazy val showClassLike: Show[ClassLike] = Cyclic.showClassLike
implicit lazy val showTypeDeclaration: Show[TypeDeclaration] = Cyclic.showTypeDeclaration
implicit lazy val showTypeAlias: Show[TypeAlias] = Cyclic.showTypeAlias
implicit lazy val showDef: Show[Def] = Cyclic.showDef
implicit lazy val showProj: Show[Projection] = Cyclic.showProjection
implicit lazy val showPoly: Show[Polymorphic] = Cyclic.showPolymorphic
implicit lazy val showSimple: Show[SimpleType] = new ShowLazy(Cyclic.showSimpleType)
implicit lazy val showAnnotated: Show[Annotated] = Cyclic.showAnnotated
implicit lazy val showExistential: Show[Existential] = Cyclic.showExistential
implicit lazy val showConstant: Show[Constant] = Cyclic.showConstant
implicit lazy val showParameterized: Show[Parameterized] = Cyclic.showParameterized
implicit lazy val showTypeParameters: Show[Seq[TypeParameter]] = new ShowLazy(Cyclic.showTypeParameters)
implicit lazy val showTypeParameter: Show[TypeParameter] = Cyclic.showTypeParameter
implicit lazy val showDefinition: Show[Definition] = new ShowLazy(Cyclic.showDefinition)
implicit lazy val showType: Show[Type] = new ShowLazy(Cyclic.showType)
implicit lazy val showStructure: Show[Structure] = new ShowLazy(Cyclic.showStructure)
implicit lazy val showPath: Show[Path] = new ShowLazy(Cyclic.showPath)
implicit lazy val showPathComponent: Show[PathComponent] = Cyclic.showPathComponent
private object Cyclic extends ShowTypes with ShowType with ShowPath with ShowDefinition with ShowDefinitions with ShowTypeParameters
}

View File

@ -1,8 +1,7 @@
package sbt.inc
import xsbti.api.SourceAPI
import xsbt.api.ShowAPI
import xsbt.api.DefaultShowAPI._
import xsbt.api.DefaultShowAPI
import java.lang.reflect.Method
import java.util.{ List => JList }
@ -39,8 +38,8 @@ private[inc] class APIDiff {
* Generates an unified diff between textual representations of `api1` and `api2`.
*/
def generateApiDiff(fileName: String, api1: SourceAPI, api2: SourceAPI, contextSize: Int): String = {
val api1Str = ShowAPI.show(api1)
val api2Str = ShowAPI.show(api2)
val api1Str = DefaultShowAPI(api1)
val api2Str = DefaultShowAPI(api2)
generateApiDiff(fileName, api1Str, api2Str, contextSize)
}

View File

@ -515,9 +515,8 @@ class ExtractAPI[GlobalType <: CallbackGlobal](val global: GlobalType,
case x => error("Unknown type parameter info: " + x.getClass)
}
}
private def tparamID(s: Symbol): String = {
val renameTo = existentialRenamings.renaming(s)
renameTo match {
private def tparamID(s: Symbol): String =
existentialRenamings.renaming(s) match {
case Some(rename) =>
// can't use debuglog because it doesn't exist in Scala 2.9.x
if (settings.debug.value)
@ -526,7 +525,7 @@ class ExtractAPI[GlobalType <: CallbackGlobal](val global: GlobalType,
case None =>
s.fullName
}
}
/* Representation for the self type of a class symbol `s`, or `emptyType` for an *unascribed* self variable (or no self variable at all).
Only the self variable's explicitly ascribed type is relevant for incremental compilation. */

View File

@ -6,7 +6,6 @@ TaskKey[Unit]("show-apis") <<= (compile in Compile, scalaSource in Compile, java
val aApi = a.apis.internalAPI(scalaSrc / "A.scala").api
val jApi = a.apis.internalAPI(javaSrc / "test/J.java").api
import xsbt.api.DefaultShowAPI
import DefaultShowAPI._
DefaultShowAPI.showSource.show(aApi)
DefaultShowAPI.showSource.show(jApi)
DefaultShowAPI(aApi)
DefaultShowAPI(jApi)
}