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

org.opalj.br.DeclaredMethod.scala Maven / Gradle / Ivy

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

import scala.collection.immutable.ArraySeq

/**
 * Represents a declared method of a class identified by [[declaringClassType]];
 * that is, a method which belongs to the API of the class itself or a super class thereof.
 *
 * @author Michael Eichberg
 * @author Dominik Helm
 */
sealed abstract class DeclaredMethod {

    /**
     * The declaring type; the returned type may not define the method; it could be defined by
     * one or more super classes/interfaces in case of Java 8+.
     */
    def declaringClassType: ObjectType

    def name: String

    def descriptor: MethodDescriptor

    def toJava: String = s"${declaringClassType.toJava}{ ${descriptor.toJava(name)} }"

    def isVirtualOrHasSingleDefinedMethod: Boolean

    /**
     * If `true`, the method which actually defines this method (which may still be abstract!),
     * is unique, known and is available using [[asDefinedMethod]].
     */
    def hasSingleDefinedMethod: Boolean

    /** The definition of this method; defined iff [[hasSingleDefinedMethod]] returns `true`. */
    def asDefinedMethod: DefinedMethod

    /**
     * Returns the defined method related to this declared method. The defined method
     * is always either defined by the same class or a superclass thereof.
     *
     * The behavior of this method is undefined if [[hasSingleDefinedMethod]] returns false.
     */
    def definedMethod: Method

    /**
     * If `true`, there are multiple methods that define this method and they can be iterated over
     * using [[foreachDefinedMethod]].
     */
    def hasMultipleDefinedMethods: Boolean

    /**
     * The definition of this method; defined iff [[hasMultipleDefinedMethods]] returns `true`.
     */
    def asMultipleDefinedMethods: MultipleDefinedMethods

    /**
     * Returns the defined method related to this declared method. The defined method
     * is always either defined by the same class or a superclass thereof.
     *
     * The behavior of this method is undefined if [[hasMultipleDefinedMethods]] returns false.
     */
    def definedMethods: ArraySeq[Method]

    /**
     * Executes the given function for each method definition.
     *
     * The behavior of this method is undefined if neither [[hasSingleDefinedMethod]] nor
     * [[hasMultipleDefinedMethods]] returns true.
     */
    def foreachDefinedMethod[U](f: Method => U): Unit

    /**
     * A unique ID.
     */
    val id: Int

    override def equals(other: Any): Boolean = other match {
        case that: DeclaredMethod => id == that.id
        case _                    => false
    }

    override def hashCode(): Int = id
}

/**
 * Represents a method belonging to the API of the specified class type, where the original
 * method definition is not available (in the context of the current analysis).
 * Note that one VirtualDeclaredMethod may represent more than one actual method, because a class
 * may have several package-private methods with the same signature.
 */
final class VirtualDeclaredMethod private[br] (
        override val declaringClassType: ObjectType,
        override val name:               String,
        override val descriptor:         MethodDescriptor,
        override val id:                 Int
) extends DeclaredMethod {

    override def isVirtualOrHasSingleDefinedMethod: Boolean = true

    override def hasSingleDefinedMethod: Boolean = false
    override def definedMethod: Method = throw new UnsupportedOperationException();
    override def asDefinedMethod: DefinedMethod = throw new ClassCastException();

    override def hasMultipleDefinedMethods: Boolean = false
    override def definedMethods: ArraySeq[Method] = throw new UnsupportedOperationException();
    override def asMultipleDefinedMethods: MultipleDefinedMethods = throw new ClassCastException();

    override def foreachDefinedMethod[U](f: Method => U): Unit = {
        throw new UnsupportedOperationException();
    }

    override def toString: String = {
        s"VirtualDeclaredMethod(${declaringClassType.toJava},$name,$descriptor)"
    }
}

/**
 * Represents a declared method; i.e., a method which belongs to the (public and private) API of a
 * class along with a reference to the original declaration.
 */
final class DefinedMethod private[br] (
        override val declaringClassType: ObjectType,
        override val definedMethod:      Method,
        override val id:                 Int
) extends DeclaredMethod {

    override def name: String = definedMethod.name
    override def descriptor: MethodDescriptor = definedMethod.descriptor

    override def isVirtualOrHasSingleDefinedMethod: Boolean = true

    override def hasSingleDefinedMethod: Boolean = true
    override def asDefinedMethod: DefinedMethod = this

    override def hasMultipleDefinedMethods: Boolean = false
    override def definedMethods: ArraySeq[Method] = throw new UnsupportedOperationException();
    override def asMultipleDefinedMethods: MultipleDefinedMethods = throw new ClassCastException();

    override def foreachDefinedMethod[U](f: Method => U): Unit = f(definedMethod)

    override def toString: String = {
        s"DefinedMethod(declaringClassType=${declaringClassType.toJava},definedMethod=${definedMethod.toJava})"
    }
}

final class MultipleDefinedMethods private[br] (
        override val declaringClassType: ObjectType,
        override val definedMethods:     ArraySeq[Method],
        override val id:                 Int
) extends DeclaredMethod {

    override def name: String = definedMethods.head.name
    override def descriptor: MethodDescriptor = definedMethods.head.descriptor

    override def isVirtualOrHasSingleDefinedMethod: Boolean = false

    override def hasSingleDefinedMethod: Boolean = false
    override def asDefinedMethod: DefinedMethod = throw new ClassCastException();
    override def definedMethod: Method = throw new UnsupportedOperationException();

    override def hasMultipleDefinedMethods: Boolean = true
    override def asMultipleDefinedMethods: MultipleDefinedMethods = this

    override def foreachDefinedMethod[U](f: Method => U): Unit = definedMethods.foreach(f)

    override def toString: String = {
        s"DefinedMethod(${declaringClassType.toJava},definedMethods=${definedMethods.map(_.toJava).mkString("{", ", ", "}")})"
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy