2010-01-01 00:56:37 +01:00
|
|
|
/* sbt -- Simple Build Tool
|
|
|
|
|
* Copyright 2009 Mark Harrah
|
|
|
|
|
*/
|
|
|
|
|
package xsbt.api
|
|
|
|
|
|
|
|
|
|
import xsbti.api._
|
|
|
|
|
|
|
|
|
|
import Function.tupled
|
|
|
|
|
import scala.collection.{immutable, mutable}
|
|
|
|
|
|
|
|
|
|
object SameAPI
|
|
|
|
|
{
|
|
|
|
|
def apply(a: Source, b: Source) =
|
2010-01-08 03:48:56 +01:00
|
|
|
{
|
|
|
|
|
val start = System.currentTimeMillis
|
|
|
|
|
val result = (new SameAPI).check(a,b)
|
|
|
|
|
val end = System.currentTimeMillis
|
|
|
|
|
println(" API comparison took: " + (end - start) / 1000.0 + " s")
|
|
|
|
|
result
|
|
|
|
|
}
|
2010-01-01 00:56:37 +01:00
|
|
|
}
|
|
|
|
|
private class SameAPI
|
|
|
|
|
{
|
2010-01-10 00:22:58 +01:00
|
|
|
abstract class Result(val referencesMap: immutable.Map[Int, Int], val parameterMap: immutable.Map[Int, Int]) extends NotNull
|
2010-01-01 00:56:37 +01:00
|
|
|
{
|
2010-01-10 00:22:58 +01:00
|
|
|
def &&(o: => Result): Result
|
|
|
|
|
def value: Boolean
|
2010-01-01 00:56:37 +01:00
|
|
|
}
|
2010-01-10 00:22:58 +01:00
|
|
|
final object False extends Result(Map.empty, Map.empty)
|
|
|
|
|
{
|
|
|
|
|
def &&(o: => Result): Result = this
|
|
|
|
|
def value = false
|
|
|
|
|
}
|
|
|
|
|
final class True(references: immutable.Map[Int, Int], parameters: immutable.Map[Int, Int]) extends Result(references, parameters)
|
|
|
|
|
{
|
|
|
|
|
def value = true
|
|
|
|
|
def &&(o: => Result): Result = o match { case False => o; case t: True => newTrue(t) }
|
|
|
|
|
private def newTrue(t: True): True =
|
|
|
|
|
{
|
|
|
|
|
def equalIntersection(a: Map[Int, Int], b: Map[Int, Int]) =
|
|
|
|
|
{
|
|
|
|
|
val sameKeys = a.keySet ** b.keySet
|
|
|
|
|
assume(sameKeys.forall(key => a(key) == b(key)))
|
|
|
|
|
}
|
|
|
|
|
equalIntersection(referencesMap, t.referencesMap)
|
|
|
|
|
equalIntersection(parameterMap, t.parameterMap)
|
|
|
|
|
new True(referencesMap ++ t.referencesMap, parameterMap ++ t.parameterMap)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
implicit def b2b(b: Boolean): Result = if(b) new True(Map.empty, Map.empty) else False
|
2010-01-01 00:56:37 +01:00
|
|
|
|
2010-01-10 00:22:58 +01:00
|
|
|
def debug(flag: Result, msg: => String): Result =
|
|
|
|
|
{
|
|
|
|
|
if(!flag.value) println(msg)
|
|
|
|
|
flag
|
|
|
|
|
}
|
2010-01-01 00:56:37 +01:00
|
|
|
|
2010-01-10 00:22:58 +01:00
|
|
|
def printMaps(b: Result) = println(mapStrings(b))
|
|
|
|
|
def mapStrings(b: Result) =
|
|
|
|
|
{
|
|
|
|
|
"parameter map:\n\t" +
|
|
|
|
|
b.parameterMap.mkString("\n\t") +
|
|
|
|
|
"\nreference map:\n\t" +
|
|
|
|
|
b.referencesMap.mkString("\n\t")
|
|
|
|
|
}
|
|
|
|
|
def check(a: Source, b: Source): Boolean =
|
|
|
|
|
{
|
|
|
|
|
val initialResult =
|
|
|
|
|
samePackages(a, b) &&
|
|
|
|
|
debug(sameDefinitions(a, b), "Definitions differed")
|
|
|
|
|
initialResult.value &&
|
|
|
|
|
debug(sameReferences(initialResult.referencesMap, initialResult.parameterMap), "References differed: \n" + mapStrings(initialResult)).value
|
|
|
|
|
}
|
2010-01-01 00:56:37 +01:00
|
|
|
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameReferences(referencesMap: Map[Int,Int], parameterMap: Map[Int,Int]): Boolean =
|
|
|
|
|
referencesMap.forall { case (a, b) => parameterMap(a) == b }
|
2010-01-01 00:56:37 +01:00
|
|
|
|
2010-01-10 00:22:58 +01:00
|
|
|
def samePackages(a: Source, b: Source): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
sameStrings(packages(a), packages(b))
|
|
|
|
|
def packages(s: Source): Set[String] =
|
|
|
|
|
Set() ++ s.packages.map(_.name)
|
|
|
|
|
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameDefinitions(a: Source, b: Source): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
sameDefinitions(a.definitions, b.definitions)
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameDefinitions(a: Seq[Definition], b: Seq[Definition]): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
{
|
|
|
|
|
val (avalues, atypes) = separateDefinitions(a)
|
|
|
|
|
val (bvalues, btypes) = separateDefinitions(b)
|
|
|
|
|
debug(sameDefinitions(byName(avalues), byName(bvalues)), "Value definitions differed") &&
|
|
|
|
|
debug(sameDefinitions(byName(atypes), byName(btypes)), "Type definitions differed")
|
|
|
|
|
}
|
|
|
|
|
def separateDefinitions(s: Seq[Definition]): (Seq[Definition], Seq[Definition]) =
|
|
|
|
|
s.toArray.partition(isValueDefinition)
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameDefinitions(a: scala.collection.Map[String, List[Definition]], b: scala.collection.Map[String, List[Definition]]): Result =
|
|
|
|
|
debug(sameStrings(a.keySet, b.keySet), "\tDefinition strings differed") && forall(zippedEntries(a,b))(tupled(sameNamedDefinitions))
|
2010-01-01 00:56:37 +01:00
|
|
|
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameNamedDefinitions(a: List[Definition], b: List[Definition]): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
{
|
2010-01-10 00:22:58 +01:00
|
|
|
println("Comparing " + a.size + " defs against " + b.size + " defs")
|
|
|
|
|
def sameDefs(a: List[Definition], b: List[Definition], v: Result): Result =
|
|
|
|
|
{
|
|
|
|
|
println("\t " + a.size + " to " + b.size + "")
|
2010-01-01 00:56:37 +01:00
|
|
|
a match
|
|
|
|
|
{
|
2010-01-10 00:22:58 +01:00
|
|
|
case adef :: atail =>
|
|
|
|
|
def sameDef(seen: List[Definition], remaining: List[Definition]): Result =
|
|
|
|
|
remaining match
|
|
|
|
|
{
|
|
|
|
|
case Nil => debug(false, "Definition different in new API: \n" + adef.name )
|
|
|
|
|
case bdef :: btail =>
|
|
|
|
|
val eq = v && sameDefinitionContent(adef, bdef)
|
|
|
|
|
if(eq.value) printMaps(eq)
|
|
|
|
|
if(eq.value) sameDefs(atail, seen ::: btail, eq) else sameDef(bdef :: seen, btail)
|
|
|
|
|
}
|
|
|
|
|
sameDef(Nil, b)
|
|
|
|
|
case Nil => v
|
2010-01-01 00:56:37 +01:00
|
|
|
}
|
2010-01-10 00:22:58 +01:00
|
|
|
}
|
|
|
|
|
//if(a.length > 1) println("Comparing\n" + a.mkString("\n\t") + "\nagainst\n" + b.mkString("\n\t") + "\n\n")
|
|
|
|
|
debug((a.length == b.length), "\t\tLength differed for " + a.headOption.map(_.name).getOrElse("empty")) && sameDefs(a, b, true)
|
2010-01-01 00:56:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def isValueDefinition(d: Definition): Boolean =
|
|
|
|
|
d match
|
|
|
|
|
{
|
|
|
|
|
case _: FieldLike | _: Def=> true
|
|
|
|
|
case c: ClassLike => isValue(c.definitionType)
|
|
|
|
|
case _ => false
|
|
|
|
|
}
|
|
|
|
|
def isValue(d: DefinitionType): Boolean =
|
|
|
|
|
d == DefinitionType.Module || d == DefinitionType.PackageModule
|
|
|
|
|
def byName(s: Seq[Definition]): scala.collection.Map[String, List[Definition]] =
|
|
|
|
|
{
|
|
|
|
|
val map = new mutable.HashMap[String, List[Definition]]
|
|
|
|
|
for(d <- s; name = d.name)
|
|
|
|
|
map(name) = d :: map.getOrElse(name, Nil)
|
|
|
|
|
map.readOnly
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// doesn't check name
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameDefinitionContent(a: Definition, b: Definition): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
//a.name == b.name &&
|
|
|
|
|
debug(sameAccess(a.access, b.access), "Access differed") &&
|
|
|
|
|
debug(sameModifiers(a.modifiers, b.modifiers), "Modifiers differed") &&
|
|
|
|
|
debug(sameAnnotations(a.annotations, b.annotations), "Annotations differed") &&
|
|
|
|
|
debug(sameDefinitionSpecificAPI(a, b), "Definition-specific differed")
|
|
|
|
|
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameAccess(a: Access, b: Access): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
(a, b) match
|
|
|
|
|
{
|
|
|
|
|
case (_: Public, _: Public) => true
|
|
|
|
|
case (qa: Protected, qb: Protected) => sameQualifier(qa, qb)
|
|
|
|
|
case (qa: Private, qb: Private) => sameQualifier(qa, qb)
|
|
|
|
|
case (qa: Pkg, qb: Pkg) => sameQualifier(qa, qb)
|
|
|
|
|
case _ => debug(false, "Different access categories")
|
|
|
|
|
}
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameQualifier(a: Qualified, b: Qualified): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
sameQualifier(a.qualifier, b.qualifier)
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameQualifier(a: Qualifier, b: Qualifier): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
(a, b) match
|
|
|
|
|
{
|
|
|
|
|
case (_: Unqualified, _: Unqualified) => true
|
|
|
|
|
case (_: ThisQualifier, _: ThisQualifier) => true
|
|
|
|
|
case (ia: IdQualifier, ib: IdQualifier) => debug(ia.value == ib.value, "Different qualifiers")
|
|
|
|
|
case _ => debug(false, "Different qualifier categories: " + a.getClass.getName + " -- " +b.getClass.getName)
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameModifiers(a: Modifiers, b: Modifiers): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
bitSet(a) == bitSet(b)
|
|
|
|
|
|
|
|
|
|
def bitSet(m: Modifiers): immutable.BitSet =
|
|
|
|
|
{
|
|
|
|
|
import m._
|
|
|
|
|
val bs = new mutable.BitSet
|
|
|
|
|
setIf(bs, isAbstract, 0)
|
|
|
|
|
setIf(bs, isDeferred, 1)
|
|
|
|
|
setIf(bs, isOverride, 2)
|
|
|
|
|
setIf(bs, isFinal, 3)
|
|
|
|
|
setIf(bs, isSealed, 4)
|
|
|
|
|
setIf(bs, isImplicit, 5)
|
|
|
|
|
setIf(bs, isLazy, 6)
|
|
|
|
|
setIf(bs, isSynthetic, 7)
|
|
|
|
|
bs.toImmutable
|
|
|
|
|
}
|
2010-01-10 00:22:58 +01:00
|
|
|
def setIf(bs: mutable.BitSet, flag: Result, i: Int): Unit =
|
|
|
|
|
if(flag.value) bs += i
|
2010-01-01 00:56:37 +01:00
|
|
|
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameAnnotations(a: Seq[Annotation], b: Seq[Annotation]): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
sameSeq(a, b)(sameAnnotation)
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameAnnotation(a: Annotation, b: Annotation): Result =
|
2010-01-06 01:50:43 +01:00
|
|
|
debug(sameSimpleType(a.base, b.base), "Annotation base type differed") &&
|
|
|
|
|
debug(sameAnnotationArguments(a.arguments, b.arguments), "Annotation arguments differed (" + a + ") and (" + b + ")")
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameAnnotationArguments(a: Seq[AnnotationArgument], b: Seq[AnnotationArgument]): Result =
|
2010-01-06 01:50:43 +01:00
|
|
|
argumentMap(a) == argumentMap(b)
|
|
|
|
|
def argumentMap(a: Seq[AnnotationArgument]): Map[String,String] =
|
|
|
|
|
Map() ++ a.map(arg => (arg.name, arg.value))
|
2010-01-01 00:56:37 +01:00
|
|
|
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameDefinitionSpecificAPI(a: Definition, b: Definition): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
(a, b) match
|
|
|
|
|
{
|
|
|
|
|
case (fa: FieldLike, fb: FieldLike) => sameFieldSpecificAPI(fa, fb)
|
|
|
|
|
case (pa: ParameterizedDefinition, pb: ParameterizedDefinition) => sameParameterizedDefinition(pa, pb)
|
|
|
|
|
case _ => false
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameParameterizedDefinition(a: ParameterizedDefinition, b: ParameterizedDefinition): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
debug(sameTypeParameters(a.typeParameters, b.typeParameters), "Different type parameters for " + a.name) &&
|
|
|
|
|
sameParameterizedSpecificAPI(a, b)
|
|
|
|
|
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameParameterizedSpecificAPI(a: ParameterizedDefinition, b: ParameterizedDefinition): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
(a, b) match
|
|
|
|
|
{
|
|
|
|
|
case (da: Def, db: Def) => sameDefSpecificAPI(da, db)
|
|
|
|
|
case (ca: ClassLike, cb: ClassLike) => sameClassLikeSpecificAPI(ca, cb)
|
|
|
|
|
case (ta: TypeAlias, tb: TypeAlias) => sameAliasSpecificAPI(ta, tb)
|
|
|
|
|
case (ta: TypeDeclaration, tb: TypeDeclaration) => sameDeclarationSpecificAPI(ta, tb)
|
|
|
|
|
case _ => false
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameDefSpecificAPI(a: Def, b: Def): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
debug(sameValueParameters(a.valueParameters, b.valueParameters), "Different def value parameters for " + a.name) &&
|
|
|
|
|
debug(sameType(a.returnType, b.returnType), "Different def return type for " + a.name)
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameAliasSpecificAPI(a: TypeAlias, b: TypeAlias): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
debug(sameType(a.tpe, b.tpe), "Different alias type for " + a.name)
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameDeclarationSpecificAPI(a: TypeDeclaration, b: TypeDeclaration): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
debug(sameType(a.lowerBound, b.lowerBound), "Different lower bound for declaration " + a.name) &&
|
|
|
|
|
debug(sameType(a.upperBound, b.upperBound), "Different upper bound for declaration " + a.name)
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameFieldSpecificAPI(a: FieldLike, b: FieldLike): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
debug(sameFieldCategory(a, b), "Different field categories (" + a.name + "=" + a.getClass.getName + " -- " +a.name + "=" + a.getClass.getName + ")")&&
|
|
|
|
|
debug(sameType(a.tpe, b.tpe), "Different field type for " + a.name)
|
|
|
|
|
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameFieldCategory(a: FieldLike, b: FieldLike): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
(a,b) match
|
|
|
|
|
{
|
|
|
|
|
case (_: Val, _: Val) => true
|
|
|
|
|
case (_: Var, _: Var) => true
|
|
|
|
|
case _=> false
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameClassLikeSpecificAPI(a: ClassLike, b: ClassLike): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
sameDefinitionType(a.definitionType, b.definitionType) &&
|
|
|
|
|
sameType(a.selfType, b.selfType) &&
|
|
|
|
|
sameStructure(a.structure, b.structure)
|
|
|
|
|
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameValueParameters(a: Seq[ParameterList], b: Seq[ParameterList]): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
sameSeq(a, b)(sameParameterList)
|
|
|
|
|
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameParameterList(a: ParameterList, b: ParameterList): Result =
|
|
|
|
|
((a.isImplicit == b.isImplicit): Result) &&
|
2010-01-01 00:56:37 +01:00
|
|
|
sameParameters(a.parameters, b.parameters)
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameParameters(a: Seq[MethodParameter], b: Seq[MethodParameter]): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
sameSeq(a, b)(sameMethodParameter)
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameMethodParameter(a: MethodParameter, b: MethodParameter): Result =
|
|
|
|
|
((a.name == b.name): Result) &&
|
2010-01-01 00:56:37 +01:00
|
|
|
sameType(a.tpe, b.tpe) &&
|
|
|
|
|
(a.hasDefault == b.hasDefault) &&
|
|
|
|
|
sameParameterModifier(a.modifier, b.modifier)
|
|
|
|
|
def sameParameterModifier(a: ParameterModifier, b: ParameterModifier) =
|
|
|
|
|
a == b
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameDefinitionType(a: DefinitionType, b: DefinitionType): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
a == b
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameVariance(a: Variance, b: Variance): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
a == b
|
|
|
|
|
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameTypeParameters(a: Seq[TypeParameter], b: Seq[TypeParameter]): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
debug(sameSeq(a, b)(sameTypeParameter), "Different type parameters")
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameTypeParameter(a: TypeParameter, b: TypeParameter): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
sameTypeParameters(a.typeParameters, b.typeParameters) &&
|
|
|
|
|
debug(sameVariance(a.variance, b.variance), "Different variance") &&
|
|
|
|
|
debug(sameType(a.lowerBound, b.lowerBound), "Different lower bound") &&
|
|
|
|
|
debug(sameType(a.upperBound, b.upperBound), "Different upper bound") &&
|
|
|
|
|
debug(mapSameParameters(a, b), "Different type parameter bindings")
|
|
|
|
|
|
2010-01-10 00:22:58 +01:00
|
|
|
def mapSameParameters(a: TypeParameter, b: TypeParameter): Result =
|
|
|
|
|
mapParameters(a.id, b.id)
|
|
|
|
|
def mapParameters(a: Int, b: Int) = new True(Map.empty, Map( a -> b ))
|
2010-01-01 00:56:37 +01:00
|
|
|
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameType(a: Type, b: Type): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
(a, b) match
|
|
|
|
|
{
|
2010-01-10 00:22:58 +01:00
|
|
|
case (sa: SimpleType, sb: SimpleType) => debug(sameSimpleType(sa, sb), "Different simple types: " + sa + " and " + {Thread.dumpStack; sb})
|
|
|
|
|
case (aa: Annotated, ab: Annotated) => debug(sameAnnotatedType(aa, ab), "Different annotated types")
|
2010-01-01 00:56:37 +01:00
|
|
|
case (sa: Structure, sb: Structure) => debug(sameStructure(sa, sb), "Different structure type")
|
|
|
|
|
case (ea: Existential, eb: Existential) => debug(sameExistentialType(ea, eb), "Different existential type")
|
2010-01-08 03:48:56 +01:00
|
|
|
case (pa: Polymorphic, pb: Polymorphic) => debug(samePolymorphicType(pa, pb), "Different polymorphic type")
|
2010-01-01 00:56:37 +01:00
|
|
|
case _ => false
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameExistentialType(a: Existential, b: Existential): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
sameTypeParameters(a.clause, b.clause) &&
|
|
|
|
|
sameType(a.baseType, b.baseType)
|
2010-01-10 00:22:58 +01:00
|
|
|
def samePolymorphicType(a: Polymorphic, b: Polymorphic): Result =
|
2010-01-08 03:48:56 +01:00
|
|
|
sameTypeParameters(a.parameters, b.parameters) &&
|
|
|
|
|
sameType(a.baseType, b.baseType)
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameAnnotatedType(a: Annotated, b: Annotated): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
sameSimpleType(a.baseType, b.baseType) &&
|
|
|
|
|
sameAnnotations(a.annotations, b.annotations)
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameStructure(a: Structure, b: Structure): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
sameSeq(a.parents, b.parents)(sameType) &&
|
|
|
|
|
sameMembers(a.declarations, b.declarations) &&
|
|
|
|
|
sameMembers(a.inherited, b.inherited)
|
|
|
|
|
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameMembers(a: Seq[Definition], b: Seq[Definition]): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
sameDefinitions(a, b)
|
|
|
|
|
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameSimpleType(a: SimpleType, b: SimpleType): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
(a, b) match
|
|
|
|
|
{
|
|
|
|
|
case (pa: Projection, pb: Projection) => debug(sameProjection(pa, pb), "Different projection")
|
|
|
|
|
case (pa: ParameterRef, pb: ParameterRef) => debug(sameParameterRef(pa, pb), "Different parameter ref")
|
|
|
|
|
case (sa: Singleton, sb: Singleton) => debug(sameSingleton(sa, sb), "Different singleton")
|
|
|
|
|
case (_: EmptyType, _: EmptyType) => true
|
|
|
|
|
case (pa: Parameterized, pb: Parameterized) => debug(sameParameterized(pa, pb), "Different parameterized")
|
2010-01-06 01:50:43 +01:00
|
|
|
case _ => debug(false, "Different category of simple type (" + a.getClass.getName + " and " + b.getClass.getName + ") for (" + a + " and " + b + ")")
|
2010-01-01 00:56:37 +01:00
|
|
|
}
|
|
|
|
|
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameParameterized(a: Parameterized, b: Parameterized): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
sameSimpleType(a.baseType, b.baseType) &&
|
2010-01-08 03:48:56 +01:00
|
|
|
sameSeq(a.typeArguments, b.typeArguments)(sameType)
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameParameterRef(a: ParameterRef, b: ParameterRef): Result =
|
|
|
|
|
mapReferences(a.id, b.id)
|
|
|
|
|
def mapReferences(a: Int, b: Int) = new True(Map( a -> b ), Map.empty)
|
|
|
|
|
def sameSingleton(a: Singleton, b: Singleton): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
samePath(a.path, b.path)
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameProjection(a: Projection, b: Projection): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
sameSimpleType(a.prefix, b.prefix) &&
|
|
|
|
|
(a.id == b.id)
|
|
|
|
|
|
2010-01-10 00:22:58 +01:00
|
|
|
def samePath(a: Path, b: Path): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
samePathComponents(a.components, b.components)
|
2010-01-10 00:22:58 +01:00
|
|
|
def samePathComponents(a: Seq[PathComponent], b: Seq[PathComponent]): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
sameSeq(a, b)(samePathComponent)
|
2010-01-10 00:22:58 +01:00
|
|
|
def samePathComponent(a: PathComponent, b: PathComponent): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
(a, b) match
|
|
|
|
|
{
|
|
|
|
|
case (_: This, _: This) => true
|
|
|
|
|
case (sa: Super, sb: Super) => samePathSuper(sa, sb)
|
|
|
|
|
case (ia: Id, ib: Id) => samePathId(ia, ib)
|
|
|
|
|
case _ => false
|
|
|
|
|
}
|
2010-01-10 00:22:58 +01:00
|
|
|
def samePathSuper(a: Super, b: Super): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
samePath(a.qualifier, b.qualifier)
|
2010-01-10 00:22:58 +01:00
|
|
|
def samePathId(a: Id, b: Id): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
a.id == b.id
|
|
|
|
|
|
|
|
|
|
// precondition: a.keySet == b.keySet
|
|
|
|
|
protected def zippedEntries[A,B](a: scala.collection.Map[A,B], b: scala.collection.Map[A,B]): Iterable[(B,B)] =
|
|
|
|
|
for( (key, avalue) <- a) yield (avalue, b(key))
|
|
|
|
|
|
2010-01-10 00:22:58 +01:00
|
|
|
def sameStrings(a: scala.collection.Set[String], b: scala.collection.Set[String]): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
a == b
|
2010-01-10 00:22:58 +01:00
|
|
|
final def sameSeq[T](a: Seq[T], b: Seq[T])(eq: (T,T) => Result): Result =
|
2010-01-01 00:56:37 +01:00
|
|
|
sameArray(a.toArray, b.toArray)(eq)
|
2010-01-10 00:22:58 +01:00
|
|
|
final def sameArray[T](a: Array[T], b: Array[T])(eq: (T,T) => Result): Result =
|
|
|
|
|
((a.length == b.length): Result) && forall(a.zip(b))(tupled(eq))
|
|
|
|
|
final def forall[T](a: Iterable[T])(f: T => Result): Result = forallList(a.toList, true)(f)
|
|
|
|
|
final def forallList[T](a: List[T], v: Result)(f: T => Result): Result =
|
|
|
|
|
if(v.value) ( a match { case Nil => v; case x :: xs => forallList(xs, v && f(x) )(f) } )
|
|
|
|
|
else v
|
2010-01-01 00:56:37 +01:00
|
|
|
|
|
|
|
|
def defaultEquals[T <: AnyRef] = (a: T, b: T) => a == b
|
|
|
|
|
}
|