Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.opalj.br.Signature.scala Maven / Gradle / Ivy
/* BSD 2-Clause License - see OPAL/LICENSE for details. */
package org.opalj
package br
/**
* An element of a [[Signature]] used to encode generic type information.
*
* @author Michael Eichberg
* @author Andre Pacak
*/
trait SignatureElement { // RECALL: Void and the BaseTypes are also subtypes!
def accept[T](sv: SignatureVisitor[T]): T
/**
* Converts this signature into its JVM representation. (See the JVM 5 or later
* specification for further details.)
*/
def toJVMSignature: String
}
trait ReturnTypeSignature extends SignatureElement
trait TypeSignature extends ReturnTypeSignature
sealed trait ThrowsSignature extends SignatureElement
/**
* An attribute-level signature as defined in the JVM specification.
*
* To match `Signature` objects the predefined matchers/extractors can be used.
* * @example
* ==Example 1==
* {{{
* interface Processor extends Function { /*empty*/ }
* }}}
* '''ClassSignature''':
* `Ljava/lang/Object;Ljava/util/function/Function;`
* {{{
* ClassSignature(
* typeParameters=List(),
* superClass=ClassTypeSignature(Some(java/lang/),SimpleClassTypeSignature(Object,List()),List()),
* superInterfaces=List(
* ClassTypeSignature(
* Some(java/util/function/),
* SimpleClassTypeSignature(Function,
* List(ProperTypeArgument(
* None,
* ClassTypeSignature(
* Some(java/lang/),
* SimpleClassTypeSignature(Object,List()),
* List())),
* ProperTypeArgument(
* None,
* ClassTypeSignature(
* Some(java/lang/),
* SimpleClassTypeSignature(Void,List()),
* List())))),
* List())))
* }}}
*
* ==Example 2==
* {{{
* interface Col { /*empty*/ }
* }}}
* '''ClassSignature''':
* `Ljava/lang/Object;`
* {{{
* ClassSignature(
* typeParameters=
* List(
* FormalTypeParameter(
* C,
* Some(ClassTypeSignature(
* Some(java/lang/),SimpleClassTypeSignature(Object,List()),List())),
* List())),
* superClass=ClassTypeSignature(
* Some(java/lang/),SimpleClassTypeSignature(Object,List()),List()),
* superInterfaces=List())
* }}}
*
* ==Example 3==
* {{{
* interface ColObject extends Col { /*empty*/ }
* }}}
* '''ClassSignature''':
* `Ljava/lang/Object;LCol;`
* {{{
* ClassSignature(
* typeParameters=List(),
* superClass=ClassTypeSignature(Some(java/lang/),SimpleClassTypeSignature(Object,List()),List()),
* superInterfaces=List(
* ClassTypeSignature(
* None,
* SimpleClassTypeSignature(
* Col,
* List(ProperTypeArgument(
* variance=None,
* signature=ClassTypeSignature(Some(java/lang/),SimpleClassTypeSignature(Object,List()),List()))
* )),
* List())))
* }}}
*
* ==Example 4==
* {{{
* interface ColError extends Col{/*empty*/}
* }}}
* '''ClassSignature''':
* `Ljava/lang/Object;LCol;`
* {{{
* ClassSignature(
* typeParameters=List(
* FormalTypeParameter(
* E,
* Some(ClassTypeSignature(Some(java/lang/),SimpleClassTypeSignature(Error,List()),List())),List())),
* superClass=ClassTypeSignature(Some(java/lang/),SimpleClassTypeSignature(Object,List()),List()),
* superInterfaces=List(
* ClassTypeSignature(
* None,
* SimpleClassTypeSignature(
* Col,
* List(ProperTypeArgument(variance=None,signature=TypeVariableSignature(E)))),
* List())))
* }}}
*
* ==Example 5==
* {{{
* class Use {
* // The following fields all have "ClassTypeSignatures"
* Col> ce = null; // Signature: LCol<*>;
* Col co = null; // Signature: LCol;
* Col super Serializable> cs = null; // Signature: LCol<-Ljava/io/Serializable;>;
* Col extends Comparable>> cc = null; // Signature: LCol<+Ljava/lang/Comparable<*>;>;
*
* MyCol> mco = new MyCol<>();
* MyCol>.MyInnerCol>> mico = this.mco.new MyInnerCol>>();
* // Signature: LMyCol;>.MyInnerCol;>;>;
* }
* }}}
*
* AST of `mico`:
* {{{
* ClassSignature(
* typeParameters=List(),
* superClass=ClassTypeSignature(
* None,
* SimpleClassTypeSignature(
* MyCol,
* List(ProperTypeArgument(
* variance=None,
* signature=ClassTypeSignature(
* Some(java/util/),
* SimpleClassTypeSignature(
* List,
* List(ProperTypeArgument(
* variance=None,
* signature=ClassTypeSignature(
* Some(java/lang/),
* SimpleClassTypeSignature(Object,List()),
* List())))),
* List())))),
* /*suffic=*/List(SimpleClassTypeSignature(
* MyInnerCol,
* List(ProperTypeArgument(
* variance=None,
* signature=ClassTypeSignature(
* Some(java/lang/),
* SimpleClassTypeSignature(
* Comparable,
* List(ProperTypeArgument(
* variance=None,
* signature=ClassTypeSignature(
* Some(java/util/),
* SimpleClassTypeSignature(
* List,
* List(ProperTypeArgument(
* variance=None,
* signature=ClassTypeSignature(
* Some(java/lang/),
* SimpleClassTypeSignature(Object,List()),
* List())))),
* List())))),
* List())))))),
* superInterfaces=List())
* }}}
*
* ==Matching Signatures==
* '''Scala REPL''':
* {{{
* val SignatureParser = org.opalj.br.reader.SignatureParser
* val GenericType = org.opalj.br.GenericType
* val SimpleGenericType = org.opalj.br.SimpleGenericType
* val BasicClassTypeSignature = org.opalj.br.BasicClassTypeSignature
*
* SignatureParser.parseClassSignature("Ljava/lang/Object;LCol;").superInterfacesSignature.head match { case BasicClassTypeSignature(ot) => ot.toJava; case _ => null}
* // res: String = Col
*
* SignatureParser.parseClassSignature("Ljava/lang/Object;LCol;").superInterfacesSignature.head match { case SimpleGenericType(bt,gt) => bt.toJava+"<"+gt.toJava+">"; case _ => null}
* //res11: String = null
*
* scala> SignatureParser.parseFieldTypeSignature("LCol;") match { case SimpleGenericType(bt,ta) => bt.toJava+"<"+ta+">"; case _ => null}
* res1: String = Col
*
* scala> SignatureParser.parseFieldTypeSignature("LCol;") match { case GenericType(bt,ta) => bt.toJava+"<"+ta+">"; case _ => null}
* res2: String = Col
* }}}
*/
sealed abstract class Signature extends SignatureElement with Attribute {
override def similar(other: Attribute, config: SimilarityTestConfiguration): Boolean = {
this == other
}
}
object Signature {
private[br] def formalTypeParametersToJVMSignature(
formalTypeParameters: List[FormalTypeParameter]
): String = {
if (formalTypeParameters.isEmpty) {
""
} else {
formalTypeParameters.map(_.toJVMSignature).mkString("<", "", ">")
}
}
def unapply(s: Signature): Some[String] = Some(s.toJVMSignature)
}
import Signature.formalTypeParametersToJVMSignature
/**
* @see For matching signatures see [[Signature]].
*/
case class ClassSignature(
formalTypeParameters: List[FormalTypeParameter],
superClassSignature: ClassTypeSignature,
superInterfacesSignature: List[ClassTypeSignature]
) extends Signature {
def accept[T](sv: SignatureVisitor[T]): T = sv.visit(this)
override def kindId: Int = ClassSignature.KindId
override def toJVMSignature: String = {
formalTypeParametersToJVMSignature(formalTypeParameters) +
superClassSignature.toJVMSignature +
superInterfacesSignature.map(_.toJVMSignature).mkString("")
}
override def toString: String = {
"ClassSignature("+
formalTypeParameters.mkString("typeParameters=List(", ",", ")")+
",superClass="+superClassSignature.toString +
superInterfacesSignature.mkString(",superInterfaces=List(", ",", "))")
}
}
object ClassSignature {
final val KindId = 12
}
/**
* @see For matching signatures see [[Signature]].
*/
case class MethodTypeSignature(
formalTypeParameters: List[FormalTypeParameter],
parametersTypeSignatures: List[TypeSignature],
returnTypeSignature: ReturnTypeSignature,
throwsSignature: List[ThrowsSignature]
) extends Signature {
def accept[T](sv: SignatureVisitor[T]): T = sv.visit(this)
override def kindId: Int = MethodTypeSignature.KindId
override def toJVMSignature: String =
formalTypeParametersToJVMSignature(formalTypeParameters) +
parametersTypeSignatures.map(_.toJVMSignature).mkString("(", "", ")") +
returnTypeSignature.toJVMSignature +
throwsSignature.map(s => s"^${s.toJVMSignature}").mkString("")
}
object MethodTypeSignature {
final val KindId = 13
}
/**
* @see For matching signatures see [[Signature]].
*/
sealed trait FieldTypeSignature extends Signature with TypeSignature
object FieldTypeSignature {
def unapply(signature: AnyRef): Boolean = signature.isInstanceOf[FieldTypeSignature]
}
object FieldTypeJVMSignature {
def unapply(signature: FieldTypeSignature): Some[String] = Some(signature.toJVMSignature)
}
/**
* @see For matching signatures see [[Signature]].
*/
case class ArrayTypeSignature(typeSignature: TypeSignature) extends FieldTypeSignature {
def accept[T](sv: SignatureVisitor[T]): T = sv.visit(this)
override def kindId: Int = ArrayTypeSignature.KindId
override def toJVMSignature: String = "["+typeSignature.toJVMSignature
}
object ArrayTypeSignature {
final val KindId = 14
}
/**
* @see For matching signatures see [[Signature]].
*/
case class ClassTypeSignature(
packageIdentifier: Option[String],
simpleClassTypeSignature: SimpleClassTypeSignature,
classTypeSignatureSuffix: List[SimpleClassTypeSignature]
) extends FieldTypeSignature with ThrowsSignature {
def objectType: ObjectType = {
val className =
if (packageIdentifier.isDefined)
new java.lang.StringBuilder(packageIdentifier.get)
else
new java.lang.StringBuilder()
className.append(simpleClassTypeSignature.simpleName)
classTypeSignatureSuffix foreach { ctss =>
className.append('$')
className.append(ctss.simpleName)
}
ObjectType(className.toString)
}
def accept[T](sv: SignatureVisitor[T]) = sv.visit(this)
override def kindId: Int = ClassTypeSignature.KindId
override def toJVMSignature: String = {
val packageName = packageIdentifier.getOrElse("")
"L"+
packageName +
simpleClassTypeSignature.toJVMSignature +
(classTypeSignatureSuffix match {
case Nil => ""
case l => l.map(_.toJVMSignature).mkString(".", ".", "")
})+
";"
}
}
object ClassTypeSignature {
final val KindId = 15
}
/**
* @see For matching signatures see [[Signature]].
*/
case class TypeVariableSignature(
identifier: String
) extends FieldTypeSignature with ThrowsSignature {
def accept[T](sv: SignatureVisitor[T]): T = sv.visit(this)
override def kindId: Int = TypeVariableSignature.KindId
override def toJVMSignature: String = "T"+identifier+";"
}
object TypeVariableSignature {
final val KindId = 16
}
/**
* @see For matching signatures see [[Signature]].
*/
case class SimpleClassTypeSignature(
simpleName: String,
typeArguments: List[TypeArgument]
) {
def accept[T](sv: SignatureVisitor[T]): T = sv.visit(this)
def toJVMSignature: String = {
simpleName +
(typeArguments match {
case Nil => ""
case l => l.map(_.toJVMSignature).mkString("<", "", ">")
})
}
}
/**
* @see For matching signatures see [[Signature]].
*/
case class FormalTypeParameter(
identifier: String,
classBound: Option[FieldTypeSignature],
interfaceBound: List[FieldTypeSignature]
) {
def accept[T](sv: SignatureVisitor[T]): T = sv.visit(this)
def toJVMSignature: String = {
identifier +
(classBound match {
case Some(x) => ":"+x.toJVMSignature
case None => ":"
}) +
(interfaceBound match {
case Nil => ""
case l => ":"+l.map(_.toJVMSignature).mkString(":")
})
}
}
/**
* @see For matching signatures see [[Signature]].
*/
sealed abstract class TypeArgument extends SignatureElement
/**
* @see For matching signatures see [[Signature]].
*/
case class ProperTypeArgument(
varianceIndicator: Option[VarianceIndicator],
fieldTypeSignature: FieldTypeSignature
) extends TypeArgument {
def accept[T](sv: SignatureVisitor[T]): T = sv.visit(this)
override def toJVMSignature: String = {
(varianceIndicator match {
case Some(x) => x.toJVMSignature
case None => ""
}) +
fieldTypeSignature.toJVMSignature
}
override def toString: String = {
"ProperTypeArgument"+
"(variance="+varianceIndicator+
",signature="+fieldTypeSignature+
")"
}
}
/**
* Indicates a TypeArgument's variance.
*/
sealed abstract class VarianceIndicator extends SignatureElement
/**
* If you have a declaration such as <? extends Entry> then the "? extends" part
* is represented by the `CovariantIndicator`.
*
* @see For matching signatures see [[Signature]].
*/
sealed abstract class CovariantIndicator extends VarianceIndicator {
def accept[T](sv: SignatureVisitor[T]): T = sv.visit(this)
override def toJVMSignature: String = "+"
}
case object CovariantIndicator extends CovariantIndicator
/**
* A declaration such as super Entry> is represented in class file signatures
* by the ContravariantIndicator ("? super") and a FieldTypeSignature.
*
* @see For matching signatures see [[Signature]].
*/
sealed abstract class ContravariantIndicator extends VarianceIndicator {
def accept[T](sv: SignatureVisitor[T]): T = sv.visit(this)
override def toJVMSignature: String = "-"
}
case object ContravariantIndicator extends ContravariantIndicator
/**
* If a type argument is not further specified (e.g., List> l = …), then the
* type argument "?" is represented by this object.
*
*
* @see For matching signatures see [[Signature]].
*/
sealed abstract class Wildcard extends TypeArgument {
def accept[T](sv: SignatureVisitor[T]): T = sv.visit(this)
override def toJVMSignature: String = "*"
}
case object Wildcard extends Wildcard
/**
* Extractor/Matcher of the (potentially erased) `ObjectType` that is defined by a
* `ClassTypeSignature`; ignores all further potential type parameters.
*
* @see For matching signatures see [[Signature]].
*/
object BasicClassTypeSignature {
def unapply(cts: ClassTypeSignature): Option[ObjectType] = {
Some(cts.objectType)
}
}
/**
* Matches a [[ClassTypeSignature]] with a [[SimpleClassTypeSignature]] that does not define
* a generic type. For example, `java.lang.Object`.
*
* @see For matching signatures see [[Signature]].
*/
object ConcreteType {
def unapply(cts: ClassTypeSignature): Option[ObjectType] = {
cts match {
case ClassTypeSignature(cpn, SimpleClassTypeSignature(csn, Nil), Nil) =>
Some(ObjectType(cpn.getOrElse("") + csn))
case _ =>
None
}
}
}
/**
* Facilitates matching [[ProperTypeArgument]]s that define a single concrete/invariant
* type that is not a generic type on its own. E.g., it can be used to match the
* type argument of `List` and to extract the concrete type `Integer`. It
* cannot be used to match, e.g., `List>`.
*
* @see For matching signatures see [[Signature]].
*/
object ConcreteTypeArgument {
def unapply(pta: ProperTypeArgument): Option[ObjectType] = {
pta match {
case ProperTypeArgument(None, ConcreteType(ot)) => Some(ot)
case _ => None
}
}
}
/**
* Facilitates matching [[ProperTypeArgument]]s that define an upper type bound. E.g.,
* a type bound which uses a CovarianceIndicator (`? extends`) such as in
* `List extends Number>`.
*
* @example
* {{{
* val scts : SimpleClassTypeSignature = ...
* scts.typeArguments.head match {
* case UpperTypeBound(objectType) => ...
* case _ => ...
* }
* }}}
*
*
* @see For matching signatures see [[Signature]].
*/
object UpperTypeBound {
def unapply(pta: ProperTypeArgument): Option[ObjectType] = pta match {
case ProperTypeArgument(Some(CovariantIndicator), ConcreteType(ot)) => Some(ot)
case _ => None
}
}
/**
* Facilitates matching [[ProperTypeArgument]]s that define a lower type bound. E.g.,
* a type bound which uses a ContravarianceIndicator (`? super`) such as in
* `List super Number>`.
*
* @example
* matches, e.g., `List super Integer>`
* {{{
* val scts : SimpleClassTypeSignature = ...
* scts.typeArguments.head match {
* case LowerTypeBound(objectType) => ...
* case _ => ...
* }
* }}}
*
* @see For matching signatures see [[Signature]].
*/
object LowerTypeBound {
def unapply(pta: ProperTypeArgument): Option[ObjectType] = pta match {
case ProperTypeArgument(Some(ContravariantIndicator), ConcreteType(ot)) => Some(ot)
case _ => None
}
}
/**
* Facilitates matching the (`VarianceIndicator`, `ObjectType`) that is defined
* within a `ProperTypeArgument`. It matches ProperTypeArguments which define
* `TypeArgument`s in the inner ClassTypeSignature.
*
* @example
* matches e.g.: `List>`
* {{{
* val scts : SimpleClassTypeSignature = ...
* scts.typeArguments match {
* case GenericTypeArgument(varInd, objectType) => ...
* case _ => ...
* }
* }}}
*
* @see For matching signatures see [[Signature]].
*/
object GenericTypeArgument {
def unapply(
pta: ProperTypeArgument
): Option[(Option[VarianceIndicator], ClassTypeSignature)] = {
pta match {
case ProperTypeArgument(variance, cts: ClassTypeSignature) => Some((variance, cts))
case _ => None
}
}
}
/**
* Matches all [[ClassTypeSignature]]s which consists of
* a [[SimpleClassTypeSignature]] with a non-empty List of TypeArguments (
* which consists of [[Wildcard]]s or [[ProperTypeArgument]]s)
*
* @see For matching signatures see [[Signature]].
*/
object GenericType {
def unapply(cts: ClassTypeSignature): Option[(ObjectType, List[TypeArgument])] = {
cts match {
case ClassTypeSignature(
_,
SimpleClassTypeSignature(_, typeArgs),
Nil) if typeArgs.nonEmpty =>
Some((cts.objectType, typeArgs))
case _ =>
None
}
}
}
/**
* Matches all [[ClassTypeSignature]]s which consists of
* a [[SimpleClassTypeSignature]] with an optional list of TypeArguments (
* which consists of [[Wildcard]]s or [[ProperTypeArgument]]s) and a non-empty list of
* [[SimpleClassTypeSignature]] (which encodes the suffix of the [[ClassTypeSignature]] for
* inner classes)
*
* @see For matching signatures see [[Signature]].
*/
object GenericTypeWithClassSuffix {
def unapply(
cts: ClassTypeSignature
): Option[(ObjectType, List[TypeArgument], List[SimpleClassTypeSignature])] = {
cts match {
case ClassTypeSignature(
_,
SimpleClassTypeSignature(_, typeArgs),
suffix) if suffix.nonEmpty =>
Some((cts.objectType, typeArgs, suffix))
case _ =>
None
}
}
}
/**
* Facilitates matching [[ClassTypeSignature]]s that define a simple generic type that
* has a single type argument with a concrete type.
*
* @example
* The following can be used to match, e.g., `List`.
* {{{
* val f : Field = ...
* f.fieldTypeSignature match {
* case SimpleGenericType(ContainerType,ElementType) => ...
* case _ => ...
* }
* }}}
*
* @author Michael Eichberg
*/
object SimpleGenericType {
def unapply(cts: ClassTypeSignature): Option[(ObjectType, ObjectType)] = {
cts match {
case ClassTypeSignature(
cpn,
SimpleClassTypeSignature(
csn,
List(ProperTypeArgument(None, ConcreteType(tp)))),
Nil
) =>
Some((ObjectType(cpn.getOrElse("") + csn), tp))
case _ =>
None
}
}
}