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

org.opalj.br.analyses.FieldAccessInformation.scala Maven / Gradle / Ivy

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

import scala.collection.Map

/**
 * Stores the information where each field is read and written. If the project
 * is incomplete the results are also necessarily incomplete. Reflective and comparable
 * accesses are not considered.
 *
 * @author Michael Eichberg
 */
class FieldAccessInformation(
        val project:          SomeProject,
        val allReadAccesses:  Map[Field, Seq[(Method, PCs)]],
        val allWriteAccesses: Map[Field, Seq[(Method, PCs)]],
        val unresolved:       Vector[(Method, PCs)]
) {

    private[this] def accesses(
        accessInformation:  Map[Field, Seq[(Method, PCs)]],
        declaringClassType: ObjectType,
        fieldName:          String
    ): Seq[(Method, PCs)] = {
        // FIX We can also use a reference to a subclass to access a field in a supertype
        accessInformation.collectFirst {
            case (field, accesses) if field.name == fieldName &&
                (field.classFile.thisType eq declaringClassType) => accesses
        }.getOrElse(Seq.empty)
    }

    def writeAccesses(declaringClassType: ObjectType, fieldName: String): Seq[(Method, PCs)] = {
        accesses(allWriteAccesses, declaringClassType, fieldName)
    }

    def readAccesses(declaringClassType: ObjectType, fieldName: String): Seq[(Method, PCs)] = {
        accesses(allReadAccesses, declaringClassType, fieldName)
    }

    final def writeAccesses(field: Field): Seq[(Method, PCs)] = {
        allWriteAccesses.getOrElse(field, Seq.empty)
    }

    final def readAccesses(field: Field): Seq[(Method, PCs)] = {
        allReadAccesses.getOrElse(field, Seq.empty)
    }

    def isRead(field: Field): Boolean = {
        allReadAccesses.get(field) match {
            case Some(accesses) => accesses.nonEmpty
            case None           => false
        }
    }

    def isWritten(field: Field): Boolean = {
        allWriteAccesses.get(field) match {
            case Some(accesses) => accesses.nonEmpty
            case None           => false
        }
    }

    final def isAccessed(field: Field): Boolean = isRead(field) || isWritten(field)

    /**
     * Returns a new iterator to iterate over all field access locations.
     */
    def allAccesses(field: Field): Iterator[(Method, PCs)] = {
        readAccesses(field).iterator ++ writeAccesses(field).iterator
    }

    /**
     * Basic statistics about the number of field reads and writes.
     */
    def statistics: Map[String, Int] = {
        Map(
            "field reads" -> allReadAccesses.values.map(_.map(_._2.size).sum).sum,
            "field writes" -> allWriteAccesses.values.map(_.map(_._2.size).sum).sum,
            "unresolved field accesses" -> unresolved.map(_._2.size).sum
        )
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy