From cc06667f3edca67fac4e1b24aee52898abdb5d71 Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Mon, 14 Feb 2011 18:59:54 -0500 Subject: [PATCH] handle constant types --- compile/api/SameAPI.scala | 7 ++++++- compile/api/ShowAPI.scala | 6 +++++- compile/api/TagTypeVariables.scala | 4 +++- compile/api/Visit.scala | 6 ++++++ compile/interface/API.scala | 20 +++++++++++++------- compile/persist/APIFormats.scala | 3 +++ interface/type | 3 +++ 7 files changed, 39 insertions(+), 10 deletions(-) diff --git a/compile/api/SameAPI.scala b/compile/api/SameAPI.scala index 211ea4d9d..dbfc15856 100644 --- a/compile/api/SameAPI.scala +++ b/compile/api/SameAPI.scala @@ -119,7 +119,8 @@ class SameAPI(tagsA: TypeVars, tagsB: TypeVars, includePrivate: Boolean, include debug(sameDefinitions(byName(atypes), byName(btypes)), "Type definitions differed") } def sameDefinitions(a: scala.collection.Map[String, List[Definition]], b: scala.collection.Map[String, List[Definition]]): Boolean = - debug(sameStrings(a.keySet, b.keySet), "\tDefinition strings differed") && zippedEntries(a,b).forall(tupled(sameNamedDefinitions)) + debug(sameStrings(a.keySet, b.keySet), "\tDefinition strings differed (a: " + a.keySet + ", b: " + b.keySet + ")") && + zippedEntries(a,b).forall(tupled(sameNamedDefinitions)) /** Removes definitions that should not be considered for API equality. * All top-level definitions are always considered: 'private' only means package-private. @@ -303,6 +304,7 @@ class SameAPI(tagsA: TypeVars, tagsB: TypeVars, includePrivate: Boolean, include (a, b) match { case (sa: SimpleType, sb: SimpleType) => debug(sameSimpleType(sa, sb), "Different simple types: " + DefaultShowAPI(sa) + " and " + DefaultShowAPI(sb)) + case (ca: Constant, cb: Constant) => debug(sameConstantType(ca, cb), "Different constant types: " + DefaultShowAPI(ca) + " and " + DefaultShowAPI(cb)) case (aa: Annotated, ab: Annotated) => debug(sameAnnotatedType(aa, ab), "Different annotated types") case (sa: Structure, sb: Structure) => debug(sameStructure(sa, sb), "Different structure type") case (ea: Existential, eb: Existential) => debug(sameExistentialType(ea, eb), "Different existential type") @@ -310,6 +312,9 @@ class SameAPI(tagsA: TypeVars, tagsB: TypeVars, includePrivate: Boolean, include case _ => false } + def sameConstantType(ca: Constant, cb: Constant): Boolean = + sameType(ca.baseType, cb.baseType) && + ca.value == cb.value def sameExistentialType(a: Existential, b: Existential): Boolean = sameTypeParameters(a.clause, b.clause) && sameType(a.baseType, b.baseType) diff --git a/compile/api/ShowAPI.scala b/compile/api/ShowAPI.scala index 1e38ef57e..570d81117 100644 --- a/compile/api/ShowAPI.scala +++ b/compile/api/ShowAPI.scala @@ -169,13 +169,14 @@ trait ShowDefinition } trait ShowType { - implicit def showType(implicit s: Show[SimpleType], a: Show[Annotated], st: Show[Structure], e: Show[Existential], po: Show[Polymorphic]): Show[Type] = + 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) @@ -219,6 +220,8 @@ trait ShowTypes 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) = @@ -291,6 +294,7 @@ object DefaultShowAPI extends ShowBase with ShowBasicTypes with ShowValueParamet 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) diff --git a/compile/api/TagTypeVariables.scala b/compile/api/TagTypeVariables.scala index 65f4b852f..759486b9d 100644 --- a/compile/api/TagTypeVariables.scala +++ b/compile/api/TagTypeVariables.scala @@ -95,6 +95,7 @@ private class TagTypeVariables { case s: Structure => tagStructure(s) case e: Existential => tagExistential(e) + case c: Constant => tagConstant(c) case p: Polymorphic => tagPolymorphic(p) case a: Annotated => tagAnnotated(a) case p: Parameterized => tagParameterized(p) @@ -102,7 +103,8 @@ private class TagTypeVariables case _: EmptyType | _: Singleton | _: ParameterRef => () } } - + + def tagConstant(c: Constant) = tagType(c.baseType) def tagExistential(e: Existential) = tagParameters(e.clause, e.baseType) def tagPolymorphic(p: Polymorphic) = tagParameters(p.parameters, p.baseType) def tagProjection(p: Projection) = tagType(p.prefix) diff --git a/compile/api/Visit.scala b/compile/api/Visit.scala index ed4497439..ded478380 100644 --- a/compile/api/Visit.scala +++ b/compile/api/Visit.scala @@ -144,6 +144,7 @@ class Visit { case s: Structure => visitStructure(s) case e: Existential => visitExistential(e) + case c: Constant => visitConstant(c) case p: Polymorphic => visitPolymorphic(p) case a: Annotated => visitAnnotated(a) case p: Parameterized => visitParameterized(p) @@ -169,6 +170,11 @@ class Visit def visitIdPath(id: Id) { visitString(id.id) } + def visitConstant(c: Constant) = + { + visitString(c.value) + visitType(c.baseType) + } def visitExistential(e: Existential) = visitParameters(e.clause, e.baseType) def visitPolymorphic(p: Polymorphic) = visitParameters(p.parameters, p.baseType) def visitProjection(p: Projection) = diff --git a/compile/interface/API.scala b/compile/interface/API.scala index f33e2dc23..0d5e9bb52 100644 --- a/compile/interface/API.scala +++ b/compile/interface/API.scala @@ -166,7 +166,8 @@ final class API(val global: Global, val callback: xsbti.AnalysisCallback) extend case Nullary(resultType) => // 2.9 and later build(resultType, typeParams, valueParameters) case returnType => - new xsbti.api.Def(valueParameters.reverse.toArray, processType(in, returnType), typeParams, simpleName(s), getAccess(s), getModifiers(s), annotations(in,s)) + val t2 = processType(in, dropConst(returnType)) + new xsbti.api.Def(valueParameters.reverse.toArray, t2, typeParams, simpleName(s), getAccess(s), getModifiers(s), annotations(in,s)) } } def parameterS(s: Symbol): xsbti.api.MethodParameter = @@ -198,10 +199,15 @@ final class API(val global: Global, val callback: xsbti.AnalysisCallback) extend class WithDefault { val DEFAULTPARAM = 0x00000000 } s != NoSymbol && s.hasFlag(Flags.DEFAULTPARAM) } - private def fieldDef[T](in: Symbol, s: Symbol, create: (xsbti.api.Type, String, xsbti.api.Access, xsbti.api.Modifiers, Array[xsbti.api.Annotation]) => T): T = + private def fieldDef[T](in: Symbol, s: Symbol, keepConst: Boolean, create: (xsbti.api.Type, String, xsbti.api.Access, xsbti.api.Modifiers, Array[xsbti.api.Annotation]) => T): T = { val t = dropNullary(viewer(in).memberType(s)) - create(processType(in, t), simpleName(s), getAccess(s), getModifiers(s), annotations(in, s)) + val t2 = if(keepConst) t else dropConst(t) + create(processType(in, t2), simpleName(s), getAccess(s), getModifiers(s), annotations(in, s)) + } + private def dropConst(t: Type): Type = t match { + case ConstantType(constant) => constant.tpe + case _ => t } private def dropNullary(t: Type): Type = t match { case Nullary(un) => un @@ -254,8 +260,8 @@ final class API(val global: Global, val callback: xsbti.AnalysisCallback) extend defs.toArray.flatMap( (d: Symbol) => definition(in, d)) private def definition(in: Symbol, sym: Symbol): Option[xsbti.api.Definition] = { - def mkVar = Some(fieldDef(in, sym, new xsbti.api.Var(_,_,_,_,_))) - def mkVal = Some(fieldDef(in, sym, new xsbti.api.Val(_,_,_,_,_))) + def mkVar = Some(fieldDef(in, sym, false, new xsbti.api.Var(_,_,_,_,_))) + def mkVal = Some(fieldDef(in, sym, true, new xsbti.api.Val(_,_,_,_,_))) if(sym.isClass || sym.isModule) if(ignoreClass(sym)) None else Some(classLike(in, sym)) else if(isNonClassType(sym)) @@ -312,11 +318,11 @@ final class API(val global: Global, val callback: xsbti.AnalysisCallback) extend case NoPrefix => Constants.emptyType case ThisType(sym) => new xsbti.api.Singleton(thisPath(sym)) case SingleType(pre, sym) => projectionType(in, pre, sym) - case ConstantType(value) => error("Constant type (not implemented)") + case ConstantType(constant) => new xsbti.api.Constant(processType(in, constant.tpe), constant.stringValue) case TypeRef(pre, sym, args) => val base = projectionType(in, pre, sym) if(args.isEmpty) base else new xsbti.api.Parameterized(base, types(in, args)) - case SuperType(thistpe: Type, supertpe: Type) => error("Super type (not implemented)") + case SuperType(thistpe: Type, supertpe: Type) => error("Super type (not implemented): this=" + thistpe + ", super=" + supertpe) case at: AnnotatedType => annotatedType(in, at) case rt: CompoundType => structure(rt) case ExistentialType(tparams, result) => new xsbti.api.Existential(processType(in, result), typeParameters(in, tparams)) diff --git a/compile/persist/APIFormats.scala b/compile/persist/APIFormats.scala index fb36d3712..5c5e23250 100644 --- a/compile/persist/APIFormats.scala +++ b/compile/persist/APIFormats.scala @@ -56,6 +56,9 @@ trait APIFormats extends FormatExtra implicit def formatPolymorphic(implicit t: Format[Type], tps: Format[Array[TypeParameter]]): Format[Polymorphic] = p2( (p: Polymorphic) => (p.baseType, p.parameters) )( new Polymorphic(_,_) )(t, tps) + implicit def formatConstant(implicit t: Format[Type], fs: Format[String]): Format[Constant] = + p2( (c: Constant) => (c.baseType, c.value) )( new Constant(_,_) )(t,fs) + implicit def formatExistential(implicit t: Format[Type], tps: Format[Array[TypeParameter]]): Format[Existential] = p2( (e: Existential) => (e.baseType, e.clause) )( new Existential(_,_) )(t,tps) diff --git a/interface/type b/interface/type index a605f4cd4..ae24f5cc1 100644 --- a/interface/type +++ b/interface/type @@ -12,6 +12,9 @@ Type Parameterized baseType : SimpleType typeArguments: Type* + Constant + baseType: Type + value: String Annotated baseType : SimpleType annotations : Annotation*