
org.opalj.av.checking.ClassMatcher.scala Maven / Gradle / Ivy
The newest version!
/* BSD 2-Clause License - see OPAL/LICENSE for details. */
package org.opalj
package av
package checking
import scala.util.matching.Regex
import org.opalj.br.ClassFile
import org.opalj.br.VirtualSourceElement
import org.opalj.br.VirtualSourceElement.asVirtualSourceElements
import org.opalj.br.analyses.SomeProject
import org.opalj.bi.AccessFlagsMatcher
/**
* A class matcher matches classes defined by the respective classes.
*
* @author Marco Torsello
*/
trait ClassMatcher extends ClassLevelMatcher {
def matchMethods: Boolean
def matchFields: Boolean
}
/**
* Matches all project and library classes including inner elements like methods and fields defined by
* the respective classes.
*
* @author Marco Torsello
*/
case object AllClasses extends ClassMatcher {
def matchMethods: Boolean = true
def matchFields: Boolean = true
def doesMatch(classFile: ClassFile)(implicit project: SomeProject): Boolean = true
def extension(implicit project: SomeProject): Set[VirtualSourceElement] = {
asVirtualSourceElements(project.allClassFiles)
}
}
/**
* Default class matcher matches classes defined by the respective classes.
*
* @author Marco Torsello
*/
case class DefaultClassMatcher(
accessFlagsMatcher: AccessFlagsMatcher = AccessFlagsMatcher.ANY,
namePredicate: NamePredicate = RegexNamePredicate(""".*""".r),
annotationsPredicate: AnnotationsPredicate = AnyAnnotations,
matchSubclasses: Boolean = false,
matchImplementingclasses: Boolean = false,
matchMethods: Boolean = true,
matchFields: Boolean = true
) extends ClassMatcher {
def isSubClass(classFile: ClassFile, project: SomeProject): Boolean = {
var sourceClassFile: ClassFile = classFile
while (sourceClassFile.superclassType.nonEmpty) {
if (namePredicate(sourceClassFile.superclassType.get.fqn))
return true;
project.classFile(sourceClassFile.superclassType.get) match {
case Some(cf) => sourceClassFile = cf
case None =>
return false;
}
}
false
}
def implementsInterface(classFile: ClassFile, project: SomeProject): Boolean = {
classFile.interfaceTypes.exists(i => namePredicate(i.fqn))
}
def doesAnnotationMatch(classFile: ClassFile): Boolean = {
annotationsPredicate(classFile.annotations)
}
def doesMatch(classFile: ClassFile)(implicit project: SomeProject): Boolean = {
val classFileName = classFile.thisType.fqn
(namePredicate(classFileName) ||
(matchSubclasses && isSubClass(classFile, project)) ||
(matchImplementingclasses && implementsInterface(classFile, project))) &&
(doesAnnotationMatch(classFile)) &&
accessFlagsMatcher.unapply(classFile.accessFlags)
}
def extension(implicit project: SomeProject): Set[VirtualSourceElement] = {
asVirtualSourceElements(
project.allClassFiles filter { doesMatch },
matchMethods,
matchFields
)
}
}
/**
* Defines several additional factory methods to facilitate the creation of
* [[ClassMatcher]]s.
*
* @author Marco Torsello
*/
object ClassMatcher {
def apply(namePredicate: NamePredicate): ClassMatcher = {
new DefaultClassMatcher(namePredicate = namePredicate)
}
def apply(annotationsPredicate: AnnotationsPredicate): ClassMatcher = {
new DefaultClassMatcher(annotationsPredicate = annotationsPredicate)
}
def apply(className: String): ClassMatcher = {
require(className.indexOf('*') == -1)
new DefaultClassMatcher(namePredicate = Equals(className))
}
def apply(className: String, matchPrefix: Boolean): ClassMatcher = {
require(className.indexOf('*') == -1)
val namePredicate =
if (matchPrefix)
StartsWith(className)
else
Equals(className)
new DefaultClassMatcher(namePredicate = namePredicate)
}
def apply(
className: String,
matchPrefix: Boolean,
matchMethods: Boolean,
matchFields: Boolean
): ClassMatcher = {
require(className.indexOf('*') == -1)
val namePredicate =
if (matchPrefix)
StartsWith(className)
else
Equals(className)
new DefaultClassMatcher(
namePredicate = namePredicate,
matchMethods = matchMethods,
matchFields = matchFields
)
}
def apply(className: String, matchPrefix: Boolean, matchSubclasses: Boolean): ClassMatcher = {
require(className.indexOf('*') == -1)
val namePredicate =
if (matchPrefix)
StartsWith(className)
else
Equals(className)
new DefaultClassMatcher(
namePredicate = namePredicate,
matchSubclasses = matchSubclasses
)
}
def apply(regex: Regex): ClassMatcher = {
new DefaultClassMatcher(namePredicate = RegexNamePredicate(regex))
}
def apply(regex: Regex, matchSubclasses: Boolean): ClassMatcher = {
new DefaultClassMatcher(
namePredicate = RegexNamePredicate(regex),
matchSubclasses = matchSubclasses
)
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy