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

org.opalj.br.fpcf.analyses.ConfiguredPurity.scala Maven / Gradle / Ivy

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

import net.ceedubs.ficus.Ficus._
import net.ceedubs.ficus.readers.ArbitraryTypeReader._

import org.opalj.br.analyses.DeclaredMethods
import org.opalj.br.analyses.DeclaredMethodsKey
import org.opalj.br.analyses.ProjectInformationKey
import org.opalj.br.analyses.SomeProject
import org.opalj.br.analyses.cg.ClassExtensibilityKey
import org.opalj.br.analyses.ProjectInformationKeys
import org.opalj.br.fpcf.properties.Purity

/**
 * @author Dominik Helm
 */
class ConfiguredPurity(
        project:         SomeProject,
        declaredMethods: DeclaredMethods
) {

    private case class PurityValue(
            cf:    String,
            m:     String,
            desc:  String,
            p:     String,
            conds: Option[Seq[String]]
    )

    private val classExtensibility = project.get(ClassExtensibilityKey)

    private val toSet = project.config.as[Seq[PurityValue]](
        "org.opalj.fpcf.analyses.ConfiguredPurity.purities"
    )

    private val methods: Map[DeclaredMethod, Purity] = (
        for {
            PurityValue(className, methodName, descriptor, property, conditions) <- toSet.toSet

            po = Purity(property)
            if po.isDefined

            if conditions forall {
                _ forall { typeName =>
                    val ot = ObjectType(typeName)
                    project.classHierarchy.hasSubtypes(ot).isNo && classExtensibility(ot).isNo
                }
            }

            mdo = if (descriptor == "*") None else Some(MethodDescriptor(descriptor))

            ms = if (className == "*") {
                project.allMethods.filter { m =>
                    m.name == methodName && mdo.forall(_ == m.descriptor)
                }.map(declaredMethods(_))
            } else {
                val classType = ObjectType(className)

                mdo match {
                    case Some(md) => Seq(
                        declaredMethods(classType, classType.packageName, classType, methodName, md)
                    )
                    case None => project.classFile(classType).map { cf =>
                        cf.findMethod(methodName).map(declaredMethods(_))
                    }.getOrElse(Seq.empty)

                }
            }

            dm <- ms
        } yield {
            dm -> po.get
        }
    ).toMap

    def wasSet(dm: DeclaredMethod): Boolean = methods.contains(dm)

    def purity(dm: DeclaredMethod): Purity = methods(dm)

}

object ConfiguredPurityKey extends ProjectInformationKey[ConfiguredPurity, Nothing] {

    override def requirements(project: SomeProject): ProjectInformationKeys = Seq(PropertyStoreKey, DeclaredMethodsKey)

    override def compute(project: SomeProject): ConfiguredPurity = {
        val declaredMethods = project.get(DeclaredMethodsKey)
        new ConfiguredPurity(project, declaredMethods)
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy