All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opalj.bi.AccessFlag.scala Maven / Gradle / Ivy

The newest version!
/* BSD 2-Clause License - see OPAL/LICENSE for details. */
package org.opalj
package bi

import scala.annotation.switch

/**
 * A class, field or method declaration's access flags. An access flag (e.g., `public`
 * or `static`) is basically just a specific bit that can be combined with other
 * access flags to create an integer based bit vector that represents all
 * flags defined for a class, method or field declaration. Access flags are
 * generally context dependent and the same value means different things
 * depending on the context.
 */
sealed trait AccessFlag extends PrimitiveAccessFlagsMatcher {

    /**
     * The Java (source code) name of the access flag if it exists. E.g., Some("public"),
     * Some("native"), etc.
     */
    def javaName: Option[String]

    /**
     * The `Int` mask of this access flag as defined by the JVM specification.
     */
    override def mask: Int

    /**
     * Facilitates pattern matching against this `AccessFlag`.
     *
     * ==Example==
     * {{{
     * case ClassFile(ACC_PUBLIC(),...)
     * }}}
     *
     * To create more complex matchers, use the `&` and `!` methods.
     *
     * @return `True` iff " `this` " flag is set in the given access flags bit vector.
     */
    def unapply(accessFlags: Int): Boolean = (accessFlags & mask) == mask

    /**
     * Checks if `this` access flag is set in the given access flags bit vector.
     *
     * @note This method is just a more intuitively named alias for the [[unapply]] method.
     */
    def isSet(accessFlags: Int): Boolean = unapply(accessFlags)

}

/**
 * Common supertype of all explicit visibility modifiers/access flags.
 *
 * @author Michael Eichberg
 */
sealed trait VisibilityModifier extends AccessFlag {
    val javaName: Some[String]
}

/**
 * Defines extractor methods related to visibility modifiers.
 */
object VisibilityModifier {

    // partial mask: we can't define a mask w.r.t. default visibility
    private[bi] final val mask = ACC_PRIVATE.mask | ACC_PUBLIC.mask | ACC_PROTECTED.mask

    def hasDefaultVisibility(accessFlags: Int): Boolean = (accessFlags & mask) == 0

    final val SOME_PUBLIC = Some(ACC_PUBLIC)
    final val SOME_PRIVATE = Some(ACC_PRIVATE)
    final val SOME_PROTECTED = Some(ACC_PROTECTED)

    /**
     * Returns the specified visibility modifier.
     *
     * @param accessFlags The access flags of a class or a member thereof.
     * @return  The visibility modifier of the respective element or `None` if the
     *          element has default visibility.
     */
    def get(accessFlags: Int): Option[VisibilityModifier] = {
        ((accessFlags & mask): @switch) match {
            case ACC_PUBLIC.mask    ⇒ SOME_PUBLIC
            case ACC_PRIVATE.mask   ⇒ SOME_PRIVATE
            case ACC_PROTECTED.mask ⇒ SOME_PROTECTED
            case _                  ⇒ None /*DEFAULT VISIBILITY*/
        }
    }

    /**
     * `true` if `a` is at least as visible as `b`; for example, true if `a` is public and
     * `b` is just protected.
     */
    def isAtLeastAsVisibleAs(
        a: Option[VisibilityModifier],
        b: Option[VisibilityModifier]
    ): Boolean = {
        a match {
            case Some(ACC_PUBLIC)      ⇒ true
            case Some(ACC_PROTECTED)   ⇒ b.isEmpty || b.get != ACC_PUBLIC
            case None                  ⇒ b.isEmpty || b.get == ACC_PRIVATE
            case a @ Some(ACC_PRIVATE) ⇒ b == a

        }
    }

    def isLessVisibleAs(a: Option[VisibilityModifier], b: Option[VisibilityModifier]): Boolean = {
        !isAtLeastAsVisibleAs(b, a)
    }

    def unapply(accessFlags: Int): Option[VisibilityModifier] = get(accessFlags)
}

object ACC_PUBLIC extends VisibilityModifier {
    final override val javaName: Some[String] = Some("public")
    final override val mask = 0x0001
    override def toString: String = "PUBLIC"
}

object ACC_PRIVATE extends VisibilityModifier {
    final override val javaName: Some[String] = Some("private")
    final override val mask = 0x0002
    override def toString: String = "PRIVATE"
}

object ACC_PROTECTED extends VisibilityModifier {
    final override val javaName: Some[String] = Some("protected")
    final override val mask = 0x0004
    override def toString: String = "PROTECTED"
}

object ACC_STATIC extends AccessFlag {
    final override val javaName: Some[String] = Some("static")
    final override val mask = 0x0008
    override def toString: String = "STATIC"
}

object ACC_FINAL extends AccessFlag {
    final override val javaName: Some[String] = Some("final")
    final override val mask = 0x0010
    override def toString: String = "FINAL"
}

object ACC_SUPER extends AccessFlag {
    final override val javaName: None.type = None
    final override val mask = 0x0020
    override def toString: String = "SUPER"
}

object ACC_SYNCHRONIZED extends AccessFlag {
    final override val javaName: Some[String] = Some("synchronized")
    final override val mask = 0x0020
    override def toString: String = "SYNCHRONIZED"
}

object ACC_VOLATILE extends AccessFlag {
    final override val javaName: Some[String] = Some("volatile")
    final override val mask = 0x0040
    override def toString: String = "VOLATILE"
}

object ACC_BRIDGE extends AccessFlag {
    final override val javaName: None.type = None
    final override val mask = 0x0040
    override def toString: String = "BRIDGE"
}

object ACC_TRANSIENT extends AccessFlag {
    final override val javaName: Some[String] = Some("transient")
    final override val mask = 0x0080
    override def toString: String = "TRANSIENT"
}

object ACC_VARARGS extends AccessFlag {
    final override val javaName: None.type = None
    final override val mask = 0x0080
    override def toString: String = "VARARGS"
}

object ACC_NATIVE extends AccessFlag {
    final override val javaName: Some[String] = Some("native")
    final override val mask = 0x0100
    override def toString: String = "NATIVE"
}

object ACC_INTERFACE extends AccessFlag {
    // this flag modifies the semantics of a class, but it is not an additional flag
    final override val javaName: None.type = None
    final override val mask = 0x0200
    override def toString: String = "INTERFACE"
}

object ACC_ABSTRACT extends AccessFlag {
    final override val javaName: Some[String] = Some("abstract")
    final override val mask = 0x0400
    override def toString: String = "ABSTRACT"
}

object ACC_STRICT extends AccessFlag {
    final override val javaName: Some[String] = Some("strictfp")
    final val mask = 0x0800
    override def toString: String = "STRICT"
}

object ACC_SYNTHETIC extends AccessFlag {
    final override val javaName: None.type = None
    final override val mask = 0x1000
    override def toString: String = "SYNTHETIC"
}

object ACC_ANNOTATION extends AccessFlag {
    final override val javaName: None.type = None
    final override val mask = 0x2000
    override def toString: String = "ANNOTATION"
}

object ACC_ENUM extends AccessFlag {
    final override val javaName: None.type = None
    final override val mask = 0x4000
    override def toString: String = "ENUM"
}

/**
 * Identifies a class as defining a Java 9 module.
 *
 * @note From the specification: "If ACC_MODULE is set in ClassFile.access_flags, then
 *      no other flag in `ClassFile.access_flags` may be set."
 *      The name of the class has to be "/module-info".
 * @note '''super_class, interfaces_count, fields_count, methods_count: zero. I.e.,
 *      a module does not have a super class.'''
 */
object ACC_MODULE extends AccessFlag {
    final override val javaName: None.type = None
    final override val mask = 0x8000 // SAME AS ACC_MANDATED (!)
    override def toString: String = "MODULE"
}

object ACC_OPEN extends AccessFlag {
    final val javaName = Some("open")
    final val mask = 0x0020
    override def toString: String = "OPEN"
}

object ACC_MANDATED extends AccessFlag {
    final override val javaName: None.type = None
    final override val mask = 0x8000
    override def toString: String = "MANDATED"
}

/**
 * @note From the JVM 9 specification: "Indicates that any module which depends on the current
 *       module, implicitly declares a dependence on the module indicated by this entry."
 * @note Only used in combination with Java 9 modules.
 */
object ACC_TRANSITIVE extends AccessFlag {
    final override val javaName = Some("transitive")
    final override val mask = 0x0010
    override def toString: String = "TRANSITIVE"
}

/**
 * @note From the JVM 9 specification: "Indicates that this [inter-module] dependence is
 *       mandatory in the static phase, i.e., at compile time, but is optional in the
 *       dynamic phase, i.e., at run time."
 * @note Only used in combination with Java 9 modules.
 */
object ACC_STATIC_PHASE extends AccessFlag {
    final override val javaName = Some("static")
    final override val mask = 0x0040
    override def toString: String = "STATIC_PHASE"
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy