package xsbt
import java.io.File
import java.util.{ Arrays, Comparator }
import scala.tools.nsc.{ io, plugins, symtab, Global, Phase }
import io.{ AbstractFile, PlainFile, ZipArchive }
import plugins.{ Plugin, PluginComponent }
import symtab.Flags
import scala.collection.mutable.{ HashMap, HashSet, ListBuffer }
import xsbti.api.{ ClassLike, DefinitionType, PathComponent, SimpleType }
class [ <: CallbackGlobal](val : GlobalType,
: File) extends Compat {
import global._
private def (: String) = throw new RuntimeException(msg)
private[this] val = new HashMap[(Symbol, Type), xsbti.api.Type]
private[this] val = new HashMap[Symbol, xsbti.api.Structure]
private[this] val = new HashMap[(Symbol, Symbol), xsbti.api.ClassLike]
private[this] val = new HashSet[xsbti.api.Lazy[_]]
private[this] val = new Array[String](0)
private[this] object {
private var : Int = 0
import scala.collection.mutable.Map
private var : Map[Symbol, String] = Map.empty
def (: Seq[Symbol]): Unit = {
nestingLevel -= 1
assert(nestingLevel >= 0)
typeVariables.foreach(renameTo.remove)
}
def (: Seq[Symbol]): Unit = {
nestingLevel += 1
typeVariables.zipWithIndex foreach {
case (, ) =>
val = "existential_" + nestingLevel + "_" + i
renameTo(tv) = newName
}
}
def (: Symbol): Option[String] = renameTo.get(symbol)
}
private[this] val = Class.forName("xsbti.SafeLazy").getMethod("apply", classOf[xsbti.F0[_]])
private def [ <: AnyRef](: => S): xsbti.api.Lazy[S] =
{
val = safeLazy.invoke(null, Message(s)).asInstanceOf[xsbti.api.Lazy[S]]
pending += z
z
}
def (): Unit =
if (pending.isEmpty)
structureCache.clear()
else {
val = pending.toList
pending.clear()
toProcess foreach { _.get() }
forceStructures()
}
private def (: Symbol) = path(pathComponents(sym, Constants.thisPath :: Nil))
private def (: List[PathComponent]) = new xsbti.api.Path(components.toArray[PathComponent])
private def (: Symbol, : List[PathComponent]): List[PathComponent] =
{
if (sym == NoSymbol || sym.isRoot || sym.isEmptyPackageClass || sym.isRootPackage) postfix
else pathComponents(sym.owner, new xsbti.api.Id(simpleName(sym)) :: postfix)
}
private def (: Symbol, : Type): SimpleType =
processType(in, t) match {
case : SimpleType => s
case => log("Not a simple type:\n\tType: " + t + " (" + t.getClass + ")\n\tTransformed: " + x.getClass); Constants.emptyType
}
private def (: Symbol, : List[Type]): Array[xsbti.api.Type] = t.toArray[Type].map(processType(in, _))
private def (: Symbol, : Type, : Symbol) =
{
if (pre == NoPrefix) {
if (sym.isLocalClass || sym.isRoot || sym.isRootPackage) Constants.emptyType
else if (sym.isTypeParameterOrSkolem || sym.isExistentiallyBound) reference(sym)
else {
reference(sym)
}
} else if (sym.isRoot || sym.isRootPackage) Constants.emptyType
else new xsbti.api.Projection(simpleType(in, pre), simpleName(sym))
}
private def (: Symbol): xsbti.api.ParameterRef = new xsbti.api.ParameterRef(tparamID(sym))
private def (: Symbol, : List[AnnotationInfo]): Array[xsbti.api.Annotation] = as.toArray[AnnotationInfo].map(annotation(in, _))
private def (: Symbol, : AnnotationInfo) =
new xsbti.api.Annotation(processType(in, a.atp),
if (a.assocs.isEmpty) Array(new xsbti.api.AnnotationArgument("", a.args.mkString("(", ",", ")")))
else a.assocs.map { case (, ) => new xsbti.api.AnnotationArgument(name.toString, value.toString) }.toArray[xsbti.api.AnnotationArgument]
)
private def (: Symbol, : List[AnnotationInfo], : Type) = new xsbti.api.Annotated(processType(in, tpe), annotations(in, as))
private def (: Symbol) = (if (s.isModule) s.moduleClass else s).thisType
private def (: String, : Symbol, : Type) = println(label + " in " + in + " : " + t + " (debug: " + debugString(t) + " )")
private def (: Symbol, : Symbol) =
{
def (: Type, : Array[xsbti.api.TypeParameter], : List[xsbti.api.ParameterList]): xsbti.api.Def =
{
def (: List[Symbol]): xsbti.api.ParameterList =
{
val = syms match { case :: _ => isImplicit(head); case _ => false }
new xsbti.api.ParameterList(syms.map(parameterS).toArray, isImplicitList)
}
t match {
case PolyType(, ) =>
assert(typeParams.isEmpty)
assert(valueParameters.isEmpty)
build(base, typeParameters(in, typeParams0), Nil)
case MethodType(, resultType) =>
build(resultType, typeParams, parameterList(params) :: valueParameters)
case Nullary(resultType) =>
build(resultType, typeParams, valueParameters)
case =>
val = processType(in, dropConst(returnType))
new xsbti.api.Def(valueParameters.reverse.toArray, t2, typeParams, simpleName(s), getAccess(s), getModifiers(s), annotations(in, s))
}
}
def (: Symbol): xsbti.api.MethodParameter =
makeParameter(simpleName(s), s.info, s.info.typeSymbol, s)
def (: String, : Type, : Symbol, : Symbol): xsbti.api.MethodParameter =
{
import xsbti.api.ParameterModifier._
val (, ) =
if (ts == definitions.RepeatedParamClass)
(tpe.typeArgs(0), Repeated)
else if (ts == definitions.ByNameParamClass)
(tpe.typeArgs(0), ByName)
else
(tpe, Plain)
new xsbti.api.MethodParameter(name, processType(in, t), hasDefault(paramSym), special)
}
val = viewer(in).memberInfo(s)
build(t, Array(), Nil)
}
private def (: Symbol) = s != NoSymbol && s.hasFlag(Flags.DEFAULTPARAM)
private def [](: Symbol, : Symbol, : Boolean, : (xsbti.api.Type, String, xsbti.api.Access, xsbti.api.Modifiers, Array[xsbti.api.Annotation]) => T): T =
{
val = dropNullary(viewer(in).memberType(s))
val = if (keepConst) t else dropConst(t)
create(processType(in, t2), simpleName(s), getAccess(s), getModifiers(s), annotations(in, s))
}
private def (: Type): Type = t match {
case ConstantType() => constant.tpe
case _ => t
}
private def (: Type): Type = t match {
case Nullary() => un
case _ => t
}
private def (: Symbol, : Symbol): xsbti.api.TypeMember =
{
val (, ) =
viewer(in).memberInfo(s) match {
case PolyType(, ) => (typeParameters(in, typeParams0), base)
case => (Array[xsbti.api.TypeParameter](), t)
}
val = simpleName(s)
val = getAccess(s)
val = getModifiers(s)
val = annotations(in, s)
if (s.isAliasType)
new xsbti.api.TypeAlias(processType(in, tpe), typeParams, name, access, modifiers, as)
else if (s.isAbstractType) {
val = tpe.bounds
new xsbti.api.TypeDeclaration(processType(in, bounds.lo), processType(in, bounds.hi), typeParams, name, access, modifiers, as)
} else
error("Unknown type member" + s)
}
private def (: Symbol, : Symbol): xsbti.api.Structure = structure(viewer(in).memberInfo(s), s, true)
private def (: Type): xsbti.api.Structure = structure(info, info.typeSymbol, false)
private def (: Type, : Symbol, : Boolean): xsbti.api.Structure =
structureCache.getOrElseUpdate(s, mkStructure(info, s, inherit))
private def (: List[Symbol]): List[Symbol] = ds filter { !_.isConstructor }
private def (: Type, : Symbol, : Boolean): xsbti.api.Structure =
{
val (, ) = info.members.reverse.partition(_.owner == s)
val = info.baseClasses.tail.map(info.baseType)
val = if (s.isModuleClass) removeConstructors(declared) else declared
val = if (inherit) removeConstructors(inherited) else Nil
mkStructure(s, baseTypes, ds, is)
}
private[this] def (: Symbol): Boolean =
s.isStructuralRefinement ||
!(s.isPrivate && (s.privateWithin == NoSymbol || s.isLocal))
private def (: Symbol, : List[Type], : List[Symbol], : List[Symbol]): xsbti.api.Structure = {
if (isPublicStructure(s))
addInheritedDependencies(sourceFile, bases.map(_.dealias.typeSymbol))
new xsbti.api.Structure(lzy(types(s, bases)), lzy(processDefinitions(s, declared)), lzy(processDefinitions(s, inherited)))
}
private def (: Symbol, : List[Symbol]): Array[xsbti.api.Definition] =
sort(defs.toArray).flatMap((d: Symbol) => definition(in, d))
private[this] def (: Array[Symbol]): Array[Symbol] = {
Arrays.sort(defs, sortClasses)
defs
}
private def (: Symbol, : Symbol): Option[xsbti.api.Definition] =
{
def = Some(fieldDef(in, sym, false, new xsbti.api.Var(_, _, _, _, _)))
def = Some(fieldDef(in, sym, true, new xsbti.api.Val(_, _, _, _, _)))
if (isClass(sym))
if (ignoreClass(sym)) None else Some(classLike(in, sym))
else if (sym.isNonClassType)
Some(typeDef(in, sym))
else if (sym.isVariable)
if (isSourceField(sym)) mkVar else None
else if (sym.isStable)
if (isSourceField(sym)) mkVal else None
else if (sym.isSourceMethod && !sym.isSetter)
if (sym.isGetter) mkVar else Some(defDef(in, sym))
else
None
}
private def (: Symbol): Boolean =
sym.isLocalClass || sym.isAnonymousClass || sym.fullName.endsWith(LocalChild.toString)
private def (: Symbol): Boolean =
{
val = sym.getter(sym.enclClass)
(getter == NoSymbol && !sym.hasFlag(Flags.PARAMACCESSOR)) || (getter eq sym)
}
private def (: Symbol): xsbti.api.Modifiers =
{
import Flags._
val = s.hasFlag(ABSOVERRIDE)
val = s.hasFlag(ABSTRACT) || s.hasFlag(DEFERRED) || absOver
val = s.hasFlag(OVERRIDE) || absOver
new xsbti.api.Modifiers(abs, over, s.isFinal, s.hasFlag(SEALED), isImplicit(s), s.hasFlag(LAZY), hasMacro(s))
}
private def (: Symbol) = s.hasFlag(Flags.IMPLICIT)
private def (: Symbol): xsbti.api.Access =
{
if (c.isPublic) Constants.public
else if (c.isPrivateLocal) Constants.privateLocal
else if (c.isProtectedLocal) Constants.protectedLocal
else {
val = c.privateWithin
val = if (within == NoSymbol) Constants.unqualified else new xsbti.api.IdQualifier(within.fullName)
if (c.hasFlag(Flags.PROTECTED)) new xsbti.api.Protected(qualifier)
else new xsbti.api.Private(qualifier)
}
}
class (: Symbol) extends TypeMap {
def (: Type) =
if (tp.typeSymbolDirect == forbidden) NoType
else mapOver(tp)
}
private def (: Symbol, : Type): xsbti.api.Type = typeCache.getOrElseUpdate((in, t), makeType(in, t))
private def (: Symbol, t: Type): xsbti.api.Type =
{
val = t match {
case TypeRef(_, , _) if sym.isAliasType => t.dealias
case _ => t
}
dealiased match {
case NoPrefix => Constants.emptyType
case ThisType(sym) => new xsbti.api.Singleton(thisPath(sym))
case SingleType(pre, sym) => projectionType(in, pre, sym)
case ConstantType() => new xsbti.api.Constant(processType(in, constant.tpe), constant.stringValue)
case TypeRef(pre, sym, Nil) if sym.isRefinementClass =>
val = pre.memberInfo(sym)
val = new SuppressSymbolRef(sym).mapOver(unrolling)
if (unrolling ne withoutRecursiveRefs)
reporter.warning(sym.pos, "sbt-api: approximated refinement ref" + t + " (== " + unrolling + ") to " + withoutRecursiveRefs + "\nThis is currently untested, please report the code you were compiling.")
structure(withoutRecursiveRefs)
case @ TypeRef(pre, sym, ) =>
val = projectionType(in, pre, sym)
if (args.isEmpty)
if (isRawType(tr))
processType(in, rawToExistential(tr))
else
base
else
new xsbti.api.Parameterized(base, types(in, args))
case SuperType(: Type, : Type) =>
warning("sbt-api: Super type (not implemented): this=" + thistpe + ", super=" + supertpe); Constants.emptyType
case : AnnotatedType => annotatedType(in, at)
case : CompoundType => structure(rt)
case t: ExistentialType => makeExistentialType(in, t)
case NoType => Constants.emptyType
case PolyType(, resultType) => new xsbti.api.Polymorphic(processType(in, resultType), typeParameters(in, typeParams))
case Nullary(resultType) =>
warning("sbt-api: Unexpected nullary method type " + in + " in " + in.owner); Constants.emptyType
case _ => warning("sbt-api: Unhandled type " + t.getClass + " : " + t); Constants.emptyType
}
}
private def (: Symbol, : ExistentialType): xsbti.api.Existential = {
val ExistentialType(, ) = t
existentialRenamings.enterExistentialTypeVariables(typeVariables)
try {
val = typeParameters(in, typeVariables)
val = processType(in, qualified)
new xsbti.api.Existential(qualifiedConverted, typeVariablesConverted)
} finally {
existentialRenamings.leaveExistentialTypeVariables(typeVariables)
}
}
private def (: Symbol, : Symbol): Array[xsbti.api.TypeParameter] = typeParameters(in, s.typeParams)
private def (: Symbol, : List[Symbol]): Array[xsbti.api.TypeParameter] = s.map(typeParameter(in, _)).toArray[xsbti.api.TypeParameter]
private def (: Symbol, : Symbol): xsbti.api.TypeParameter =
{
val = s.variance
import xsbti.api.Variance._
val = annotations(in, s)
val = if (varianceInt < 0) Contravariant else if (varianceInt > 0) Covariant else Invariant
viewer(in).memberInfo(s) match {
case TypeBounds(, ) => new xsbti.api.TypeParameter(tparamID(s), annots, typeParameters(in, s), variance, processType(in, low), processType(in, high))
case PolyType(, ) => new xsbti.api.TypeParameter(tparamID(s), annots, typeParameters(in, typeParams), variance, processType(in, base.bounds.lo), processType(in, base.bounds.hi))
case => error("Unknown type parameter info: " + x.getClass)
}
}
private def (: Symbol): String = {
val = existentialRenamings.renaming(s)
renameTo match {
case Some() =>
if (settings.debug.value)
log("Renaming existential type variable " + s.fullName + " to " + rename)
rename
case None =>
s.fullName
}
}
private def (: Symbol, : Symbol): xsbti.api.Type = processType(in, s.thisSym.typeOfThis)
def (: Symbol, : Symbol): ClassLike = classLikeCache.getOrElseUpdate((in, c), mkClassLike(in, c))
private def (: Symbol, : Symbol): ClassLike =
{
val = c.fullName
val = c.isModuleClass || c.isModule
val = if (isModule) c.moduleClass else c
val =
if (c.isTrait) DefinitionType.Trait
else if (isModule) {
if (c.isPackage) DefinitionType.PackageModule
else DefinitionType.Module
} else DefinitionType.ClassDef
new xsbti.api.ClassLike(defType, lzy(selfType(in, c)), lzy(structure(in, struct)), emptyStringArray, typeParameters(in, c), name, getAccess(c), getModifiers(c), annotations(in, c))
}
private[this] def (: Symbol) = s.isClass || s.isModule
private[this] val = new [Symbol] {
def (: Symbol, : Symbol) = {
val = isClass(a)
val = isClass(b)
if (aIsClass == bIsClass)
if (aIsClass)
if (a.isModule == b.isModule)
a.fullName.compareTo(b.fullName)
else if (a.isModule)
-1
else
1
else
0
else if (aIsClass)
-1
else
1
}
}
private object {
val = new xsbti.api.ThisQualifier
val = new xsbti.api.Public
val = new xsbti.api.Private(local)
val = new xsbti.api.Protected(local)
val = new xsbti.api.Unqualified
val = new xsbti.api.Path(Array())
val = new xsbti.api.This
val = new xsbti.api.EmptyType
}
private def (: Symbol): String =
{
val = s.originalName
val = if (n.toString == "<init>") n else n.decode
n2.toString.trim
}
private def (: Symbol, : Symbol): Array[xsbti.api.Annotation] =
atPhase(currentRun.typerPhase) {
val = if (s.hasFlag(Flags.ACCESSOR)) s.accessed else NoSymbol
val = if (base == NoSymbol) s else base
val = List(b, b.getter(b.enclClass), b.setter(b.enclClass)).filter(_ != NoSymbol)
associated.flatMap( => annotations(in, ss.annotations)).distinct.toArray;
}
private def (: Symbol, : AnnotatedType): xsbti.api.Type =
{
val = at.annotations
if (annots.isEmpty) processType(in, at.underlying) else annotated(in, annots, at.underlying)
}
}