Skip to content

Commit

Permalink
Implemented equality contract for ClassInfo. Fix lightbend-labs#74
Browse files Browse the repository at this point in the history
Synthetic classes must extend java.lang.Object.

ClassInfo.superClasses is a Set because order is not relevant.
  • Loading branch information
dotta committed Oct 15, 2015
1 parent 2556454 commit e4ee90e
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 18 deletions.
25 changes: 20 additions & 5 deletions core/src/main/scala/com/typesafe/tools/mima/core/ClassInfo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,25 @@ import com.typesafe.tools.mima.core.util.log.{ConsoleLogging, Logging}
class SyntheticClassInfo(owner: PackageInfo, override val bytecodeName: String) extends ClassInfo(owner) {
loaded = true
def file: AbstractFile = throw new UnsupportedOperationException
override lazy val superClasses = Nil
override lazy val superClasses = Set(ClassInfo.ObjectClass)
override lazy val allTraits = Set.empty[ClassInfo]
override lazy val allInterfaces: Set[ClassInfo] = Set.empty[ClassInfo]
override def canEqual(other: Any) = other.isInstanceOf[SyntheticClassInfo]
}

/** As the name implies. */
object NoClass extends SyntheticClassInfo(null, "<noclass>")
object NoClass extends SyntheticClassInfo(null, "<noclass>") {
override def canEqual(other: Any) = other.isInstanceOf[NoClass.type]
override lazy val superClasses = Set.empty[ClassInfo]
}

/** A class for which we have the classfile. */
class ConcreteClassInfo(owner: PackageInfo, val file: AbstractFile) extends ClassInfo(owner) {
override def bytecodeName = PackageInfo.className(file.name)
override def canEqual(other: Any) = other.isInstanceOf[ConcreteClassInfo]
}

abstract class ClassInfo(val owner: PackageInfo) extends HasDeclarationName with WithAccessFlags {
abstract class ClassInfo(val owner: PackageInfo) extends HasDeclarationName with WithAccessFlags with Equals {
import ClassInfo._

def file: AbstractFile
Expand All @@ -51,6 +56,15 @@ abstract class ClassInfo(val owner: PackageInfo) extends HasDeclarationName with
else owner.fullName + "." + bytecodeName
}

final override def equals(other: Any): Boolean = other match {
case that: ClassInfo => (that canEqual this) && this.fullName == that.fullName
case _ => false
}

final override def hashCode = this.fullName.hashCode

override def canEqual(other: Any) = other.isInstanceOf[ClassInfo]

def formattedFullName = formatClassName(if (isObject) fullName.init else fullName)

def declarationPrefix = {
Expand Down Expand Up @@ -97,8 +111,9 @@ abstract class ClassInfo(val owner: PackageInfo) extends HasDeclarationName with
def flags_=(x: Int) = _flags = x
def isScala_=(x: Boolean) = _isScala = x

lazy val superClasses: List[ClassInfo] =
(if (this == ClassInfo.ObjectClass) Nil else superClass :: superClass.superClasses)
lazy val superClasses: Set[ClassInfo] =
if (this == ClassInfo.ObjectClass) Set.empty
else superClass.superClasses + superClass

def lookupClassFields(name: String): Iterator[MemberInfo] =
(Iterator.single(this) ++ superClasses.iterator) flatMap (_.fields.get(name))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,9 @@ import com.typesafe.tools.mima.lib.analyze.Rule
}
}

private[TemplateRules] trait ClassTypesHelper {
def diff(thisTypes: Iterable[ClassInfo], thatTypes: Iterable[ClassInfo]) = {
val thisSuperclasses = thisTypes.map(_.fullName).toSet
val thatSuperclasses = thisTypes.map(_.fullName).toSet

thisTypes.filter(sc => !thatTypes.exists(_.fullName == sc.fullName))
}
}

object Superclasses extends TemplateRule with ClassTypesHelper {
object Superclasses extends TemplateRule {
def apply(thisClass: ClassInfo, thatClass: ClassInfo) = {
val missing = diff(thisClass.superClasses, thatClass.superClasses)
val missing = thisClass.superClasses.diff(thatClass.superClasses)

if(missing.isEmpty)
None
Expand All @@ -62,9 +53,9 @@ import com.typesafe.tools.mima.lib.analyze.Rule
}
}

object Superinterfaces extends TemplateRule with ClassTypesHelper {
object Superinterfaces extends TemplateRule {
def apply(thisClass: ClassInfo, thatClass: ClassInfo) = {
val missing = diff(thisClass.allInterfaces, thatClass.allInterfaces)
val missing = thisClass.allInterfaces.diff(thatClass.allInterfaces)

if(missing.isEmpty)
None
Expand Down

0 comments on commit e4ee90e

Please sign in to comment.