Skip to content

Commit

Permalink
feat(spdx-utils): Add a function to simplify SPDX expressions
Browse files Browse the repository at this point in the history
Signed-off-by: Sebastian Schuberth <sebastian@doubleopen.org>
  • Loading branch information
sschuberth committed Nov 6, 2024
1 parent 31b9be8 commit f1da1cf
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 0 deletions.
20 changes: 20 additions & 0 deletions utils/spdx/src/main/kotlin/SpdxExpression.kt
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ sealed class SpdxExpression {
*/
abstract fun normalize(mapDeprecated: Boolean = true): SpdxExpression

/**
* Return a simplified expression that has e.g. redundancies removed.
*/
open fun simplify(): SpdxExpression = this

/**
* Return this expression sorted lexicographically.
*/
Expand Down Expand Up @@ -244,6 +249,21 @@ class SpdxCompoundExpression(
override fun normalize(mapDeprecated: Boolean) =
SpdxCompoundExpression(operator, children.map { it.normalize(mapDeprecated) })

override fun simplify(): SpdxExpression {
val flattenedChildren = children.flatMapTo(mutableSetOf()) { child ->
val simplifiedChild = child.simplify()

if (simplifiedChild is SpdxCompoundExpression && simplifiedChild.operator == operator) {
// Inline nested children of the same operator.
simplifiedChild.children.map { it.simplify() }
} else {
setOf(simplifiedChild)
}
}

return flattenedChildren.singleOrNull() ?: SpdxCompoundExpression(operator, flattenedChildren)
}

override fun sorted(): SpdxExpression {
/**
* Get all transitive children of this expression that are concatenated with the same operator as this compound
Expand Down
46 changes: 46 additions & 0 deletions utils/spdx/src/test/kotlin/SpdxCompoundExpressionTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ package org.ossreviewtoolkit.utils.spdx

import io.kotest.assertions.throwables.shouldThrow
import io.kotest.core.spec.style.WordSpec
import io.kotest.matchers.shouldBe

class SpdxCompoundExpressionTest : WordSpec({
"Creating a compound expression" should {
Expand All @@ -34,4 +35,49 @@ class SpdxCompoundExpressionTest : WordSpec({
}
}
}

"Simplifying a compound expression" should {
"inline nested children of the same operator" {
val expression = SpdxCompoundExpression(
SpdxOperator.AND,
listOf(
SpdxCompoundExpression(
SpdxOperator.AND,
listOf(
SpdxLicenseIdExpression("MIT"),
SpdxCompoundExpression(
SpdxOperator.AND,
listOf(
SpdxLicenseIdExpression("MIT"),
SpdxLicenseIdExpression("Apache-2.0")
)
)
)
),
SpdxLicenseIdExpression("Apache-2.0")
)
)

// Compare string representations to not rely on semantic equality.
expression.simplify().toString() shouldBe SpdxCompoundExpression(
SpdxOperator.AND,
listOf(
SpdxLicenseIdExpression("MIT"),
SpdxLicenseIdExpression("Apache-2.0")
)
).toString()
}

"create a single expression for equal operands" {
val expression = SpdxCompoundExpression(
SpdxOperator.AND,
listOf(
SpdxLicenseIdExpression("MIT"),
SpdxLicenseIdExpression("MIT")
)
)

expression.simplify() shouldBe SpdxLicenseIdExpression("MIT")
}
}
})

0 comments on commit f1da1cf

Please sign in to comment.