Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@

import de.fraunhofer.aisec.cpg.ConfigurationException
import de.fraunhofer.aisec.cpg.passes.*
import de.fraunhofer.aisec.cpg.passes.Pass
import java.util.*
import kotlin.reflect.KClass
import kotlin.reflect.full.findAnnotations
import org.slf4j.LoggerFactory
Expand All @@ -53,7 +51,9 @@
* dependencies) as [PassWithDependencies] containers:
* 1. [ExecuteFirst] and [ExecuteLast] passes are stored in separate lists to keep the
* ordering logic simple.
* 2. Normal passes are stored in the [workingList]
* 2. Normal passes are stored in the [workingList] This step does not yet register any
* dependencies ([PassWithDependencies.dependenciesRemaining]), it just collects the
* passes.
* 2. [ExecuteBefore] passes: "`A` execute before `B`" implies that "`B` depends on `A`" -> the
* dependency is stored in the [PassWithDependencies.dependenciesRemaining] of "`B`". This
* logic is implemented in [populateExecuteBeforeDependencies].
Expand Down Expand Up @@ -101,50 +101,37 @@
populateExecuteBeforeDependencies()

// clean up soft dependencies which are not registered in the workingList
populateNormalDependencies()
populateDependsOnDependencies()

// finally, run a sanity check
sanityCheck()
}

/** Register all (soft and hard) dependencies. */
private fun populateNormalDependencies() {
for (pass in workingList) {
pass.passClass.hardDependencies.forEach { pass.dependenciesRemaining += it }
pass.passClass.softDependencies
.filter { workingList.map { it.passClass }.contains(it) }
.forEach { pass.dependenciesRemaining += it }
}
}

/**
* Add a pass to the internal [workingList], iff it does not exist.
* Add a pass to the internal [workingList], iff it does not exist. The
* [PassWithDependencies.dependenciesRemaining] will be initialized as an empty set and must be
* populated later by [populateDependsOnDependencies] and [populateExecuteBeforeDependencies].
*
* Also, add
* * hard dependencies
* * [ExecuteBefore] dependencies
* Also, this function adds hard dependencies([ExecuteBefore] and [DependsOn]) to the working
* list.
*/
private fun addToWorkingList(newElement: KClass<out Pass<*>>) {
if (
(workingList + firstPassesList + lastPassesList)
.filter { it.passClass == newElement }
.isNotEmpty()
) {
if ((workingList + firstPassesList + lastPassesList).any { it.passClass == newElement }) {
// we already know about this pass
return
}

var firstOrLastPass = false
if (newElement.findAnnotations<ExecuteFirst>().isNotEmpty()) {
firstOrLastPass = true
firstPassesList.add(PassWithDependencies(newElement, mutableSetOf()))
firstPassesList += PassWithDependencies(newElement, mutableSetOf())
}
if (newElement.findAnnotations<ExecuteLast>().isNotEmpty()) {
firstOrLastPass = true
lastPassesList.add(PassWithDependencies(newElement, mutableSetOf()))
lastPassesList += PassWithDependencies(newElement, mutableSetOf())

Check warning on line 131 in cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/configuration/PassOrderingHelper.kt

View check run for this annotation

Codecov / codecov/patch

cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/configuration/PassOrderingHelper.kt#L131

Added line #L131 was not covered by tests
}
if (!firstOrLastPass) {
workingList.add(PassWithDependencies(newElement, mutableSetOf()))
workingList += PassWithDependencies(newElement, mutableSetOf())
}

// take care of hard dependencies
Expand All @@ -162,6 +149,43 @@
}
}

/**
* A pass annotated with [ExecuteBefore] implies that the other pass depends on it. We populate
* the [de.fraunhofer.aisec.cpg.passes.configuration.PassWithDependencies.dependenciesRemaining]
* field in the other pass to make the analysis simpler.
*/
private fun populateExecuteBeforeDependencies() {
for (currentPass in
(workingList + firstPassesList + lastPassesList)) { // iterate over entire workingList
for (executeBeforePass in
(currentPass.passClass.softExecuteBefore +
currentPass.passClass
.hardExecuteBefore)) { // iterate over all executeBefore passes
(workingList + firstPassesList + lastPassesList)
.filter { it.passClass == executeBeforePass } // find the executeBeforePass
.forEach { otherPass ->
otherPass.dependenciesRemaining += currentPass.passClass
} // add the original pass to the dependency list
}
}
}

/**
* Register all (soft and hard) [DependsOn] dependencies in
* [PassWithDependencies.dependenciesRemaining].
*/
private fun populateDependsOnDependencies() {
val allPasses = workingList + firstPassesList + lastPassesList
for (currentPass in allPasses) {
currentPass.passClass.hardDependencies.forEach { dependentPass ->
currentPass.dependenciesRemaining += dependentPass
}
currentPass.passClass.softDependencies
.filter { softDep -> allPasses.map { it.passClass }.contains(softDep) }
.forEach { currentPass.dependenciesRemaining += it }
}
}

/**
* Order the passes. This function honors
* - [DependsOn] with soft and hard dependencies
Expand Down Expand Up @@ -209,27 +233,6 @@
return result
}

/**
* A pass annotated with [ExecuteBefore] implies that the other pass depends on it. We populate
* the [de.fraunhofer.aisec.cpg.passes.configuration.PassWithDependencies.dependenciesRemaining]
* field in the other pass to make the analysis simpler.
*/
private fun populateExecuteBeforeDependencies() {
for (pass in
(workingList + firstPassesList + lastPassesList)) { // iterate over entire workingList
for (executeBeforePass in
(pass.passClass.softExecuteBefore +
pass.passClass.hardExecuteBefore)) { // iterate over all executeBefore passes
(workingList + firstPassesList + lastPassesList)
.map { it }
.filter { it.passClass == executeBeforePass } // find the executeBeforePass
.forEach {
it.dependenciesRemaining += pass.passClass
} // add the original pass to the dependency list
}
}
}

/**
* Iterate through all elements and remove the provided dependency [cls] from all passes in the
* working lists.
Expand Down
Loading