Do not compute name hashes for private members.

The NameHashing classes assumed that extracted API data structure have
private members filtered out already. That assumption was wrong and
resulted in bug #2324.

We fix the bug by simply reusing the same logic as used by SameAPI class.

Fixes #2324.
This commit is contained in:
Grzegorz Kossakowski 2015-12-18 14:32:43 -08:00
parent 81c0d3daa9
commit bad824c0b1
4 changed files with 16 additions and 10 deletions

View File

@ -60,6 +60,15 @@ object APIUtil {
new Structure(lzy(s.parents), filterDefinitions(s.declared, isModule), filterDefinitions(s.inherited, isModule))
def filterDefinitions(ds: Array[Definition], isModule: Boolean): Lazy[Array[Definition]] =
lzy(if (isModule) ds filter Discovery.isMainMethod else Array())
def isNonPrivate(d: Definition): Boolean = isNonPrivate(d.access)
/** Returns false if the `access` is `Private` and qualified, true otherwise.*/
def isNonPrivate(access: Access): Boolean =
access match {
case p: Private if !p.qualifier.isInstanceOf[IdQualifier] => false
case _ => true
}
private[this] def lzy[T <: AnyRef](t: T): Lazy[T] = SafeLazy.strict(t)
private[this] val emptyType = new EmptyType

View File

@ -78,7 +78,9 @@ class NameHashing {
visitDefinition(topLevelDef)
}
}
override def visitDefinition(d: Definition): Unit = {
// if the definition is private, we do not visit because we do
// not want to include any private members or its children
override def visitDefinition(d: Definition): Unit = if (APIUtil.isNonPrivate(d)) {
val locatedDef = LocatedDefinition(currentLocation, d)
locatedDefs += locatedDef
d match {

View File

@ -89,14 +89,9 @@ object SameAPI {
* All top-level definitions are always considered: 'private' only means package-private.
* Other definitions are considered if they are not qualified with 'private[this]' or 'private'.
*/
def filterDefinitions(d: Seq[Definition], topLevel: Boolean, includePrivate: Boolean) = if (topLevel || includePrivate) d else d.filter(isNonPrivate)
def isNonPrivate(d: Definition): Boolean = isNonPrivate(d.access)
/** Returns false if the `access` is `Private` and qualified, true otherwise.*/
def isNonPrivate(access: Access): Boolean =
access match {
case p: Private if !p.qualifier.isInstanceOf[IdQualifier] => false
case _ => true
}
def filterDefinitions(d: Seq[Definition], topLevel: Boolean, includePrivate: Boolean) =
if (topLevel || includePrivate) d else d.filter(APIUtil.isNonPrivate)
}
/**
* Used to implement API equality.

View File

@ -285,7 +285,7 @@ class NameHashingSpecification extends Specification {
val nameHashes = nameHashesForClass(classFoo)
// make sure there's no name hash for the private member "x"
Seq("Foo") === nameHashes.regularMembers.map(_.name).toSeq
}.pendingUntilFixed("The NameHashing calculates name hashes of all members")
}
private def assertNameHashEqualForRegularName(name: String, nameHashes1: _internalOnly_NameHashes,
nameHashes2: _internalOnly_NameHashes) = {