
org.opalj.br.analyses.cg.CallBySignatureKey.scala Maven / Gradle / Ivy
The newest version!
/* BSD 2-Clause License - see OPAL/LICENSE for details. */
package org.opalj.br.analyses.cg
import org.opalj.br.analyses.ProjectIndexKey
import org.opalj.br.analyses.ProjectInformationKey
import org.opalj.br.analyses.ProjectInformationKeys
import org.opalj.br.analyses.SomeProject
import org.opalj.br.Method
import org.opalj.br.ObjectType
import scala.collection.immutable.ArraySeq
import scala.collection.mutable
import scala.collection.mutable.ListBuffer
/**
* The ''key'' object to get the interface methods for which call-by-signature resolution
* needs to be done.
*
* @note To get call-by-signature information use the [[org.opalj.br.analyses.Project]]'s `get`
* method and pass in `this` object.
*
* @see [[CallBySignatureResolution]] for further information.
*
* @author Michael Reif
*/
object CallBySignatureKey extends ProjectInformationKey[CallBySignatureTargets, Nothing] {
override def requirements(project: SomeProject): ProjectInformationKeys = List(
ProjectIndexKey,
ClosedPackagesKey,
ClassExtensibilityKey,
TypeExtensibilityKey,
IsOverridableMethodKey
)
override def compute(p: SomeProject): CallBySignatureTargets = {
val cbsTargets = mutable.HashMap.empty[Method, ArraySeq[ObjectType]]
val index = p.get(ProjectIndexKey)
val isOverridableMethod = p.get(IsOverridableMethodKey)
for {
classFile <- p.allClassFiles if classFile.isInterfaceDeclaration
method <- classFile.methods
if !method.isPrivate &&
!method.isStatic &&
(classFile.isPublic || isOverridableMethod(method).isYesOrUnknown)
} {
val descriptor = method.descriptor
val methodName = method.name
val declType = classFile.thisType
import p.classHierarchy
val potentialMethods = index.findMethods(methodName, descriptor)
var i = 0
val targets = ListBuffer.empty[ObjectType]
while (i < potentialMethods.size) {
val m = potentialMethods(i)
val cf = m.classFile
val targetType = cf.thisType
val qualified = cf.isClassDeclaration &&
isOverridableMethod(m).isYesOrUnknown &&
classHierarchy.isASubtypeOf(targetType, declType).isNoOrUnknown
if (qualified) {
targets += m.declaringClassFile.thisType
}
i = i + 1
}
cbsTargets.put(method, ArraySeq.empty ++ targets)
}
new CallBySignatureTargets(cbsTargets)
}
}
class CallBySignatureTargets private[analyses] (
val data: scala.collection.Map[Method, ArraySeq[ObjectType]]
) {
/**
* Returns all call-by-signature targets of the given method. If the method is not known,
* `null` is returned. If the method is known a non-null (but potentially empty)
* [[scala.collection.immutable.ArraySeq]] is returned.
*/
def apply(m: Method): ArraySeq[ObjectType] = data.getOrElse(m, ArraySeq.empty)
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy