Skip to content

Commit

Permalink
refactor(model)!: Simplify the DependencyNavigator API
Browse files Browse the repository at this point in the history
Reduce the number of very similar overloads and simplify return types in
favor of calling fewer "orthogonal" functions in combination, if required.
This also aligns the naming of functions to be more consistent.

Signed-off-by: Sebastian Schuberth <[email protected]>
  • Loading branch information
sschuberth committed Nov 21, 2024
1 parent 0ff17e7 commit 532244e
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 157 deletions.
4 changes: 2 additions & 2 deletions model/src/main/kotlin/CompatibilityDependencyNavigator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,12 @@ class CompatibilityDependencyNavigator internal constructor(
override fun directDependencies(project: Project, scopeName: String): Sequence<DependencyNode> =
project.invokeNavigator { directDependencies(it, scopeName) }

override fun dependenciesForScope(
override fun scopeDependencies(
project: Project,
scopeName: String,
maxDepth: Int,
matcher: DependencyMatcher
): Set<Identifier> = project.invokeNavigator { dependenciesForScope(it, scopeName, maxDepth, matcher) }
): Set<Identifier> = project.invokeNavigator { scopeDependencies(it, scopeName, maxDepth, matcher) }

override fun packageDependencies(
project: Project,
Expand Down
2 changes: 1 addition & 1 deletion model/src/main/kotlin/DependencyGraphNavigator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class DependencyGraphNavigator(
return dependenciesSequence(graph, rootDependencies)
}

override fun dependenciesForScope(
override fun scopeDependencies(
project: Project,
scopeName: String,
maxDepth: Int,
Expand Down
48 changes: 12 additions & 36 deletions model/src/main/kotlin/DependencyNavigator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,10 @@ interface DependencyNavigator {
/**
* A pre-defined [DependencyMatcher] that matches only dependencies with a linkage indicating subprojects.
*/
private val MATCH_SUB_PROJECTS: DependencyMatcher = { node ->
val MATCH_SUB_PROJECTS: DependencyMatcher = { node ->
node.linkage in PackageLinkage.PROJECT_LINKAGE
}

/**
* Return a set with all the [Identifier]s contained in the given map of scope dependencies. This is useful if
* all dependencies are needed independent of the scope they belong to.
*/
private fun Map<String, Set<Identifier>>.collectDependencies(): Set<Identifier> =
values.flatMapTo(mutableSetOf()) { it }

/**
* Return a map with all [Issue]s found in the dependency graph spawned by [dependencies] grouped by their
* [Identifier]s.
Expand Down Expand Up @@ -94,28 +87,27 @@ interface DependencyNavigator {
fun directDependencies(project: Project, scopeName: String): Sequence<DependencyNode>

/**
* Return a set with information of the dependencies of a specific [scope][scopeName] of a [project]. With
* [maxDepth] the depth of the dependency tree to be traversed can be restricted; negative values mean that there
* is no restriction. Use the specified [matcher] to filter for specific dependencies.
* Return a set with the [Identifier]s of the dependencies of a [scope][scopeName] of a [project]. With [maxDepth]
* the depth of the dependency tree to be traversed can be restricted; negative values mean that there is no
* restriction. Use the specified [matcher] to filter for specific dependencies.
*/
fun dependenciesForScope(
fun scopeDependencies(
project: Project,
scopeName: String,
maxDepth: Int = -1,
matcher: DependencyMatcher = MATCH_ALL
): Set<Identifier>

/**
* Return a map with information of the dependencies of a [project] grouped by scopes. This is equivalent to
* calling [dependenciesForScope] for all the scopes of the given [project]. (This base implementation does
* exactly this.)
* Return a set with the [Identifier]s of the dependencies of a [project]. This is equivalent to calling
* [scopeDependencies] for all the scopes of the given [project].
*/
fun scopeDependencies(
fun projectDependencies(
project: Project,
maxDepth: Int = -1,
matcher: DependencyMatcher = MATCH_ALL
): Map<String, Set<Identifier>> =
scopeNames(project).associateWith { dependenciesForScope(project, it, maxDepth, matcher) }
): Set<Identifier> =
scopeNames(project).flatMapTo(mutableSetOf()) { scopeDependencies(project, it, maxDepth, matcher) }

/**
* Return a set with the [Identifier]s of packages that are dependencies of the package with the given [packageId]
Expand Down Expand Up @@ -146,22 +138,6 @@ interface DependencyNavigator {
return pathMap
}

/**
* Return the set of [Identifier]s that refer to subprojects of the given [project].
*/
fun collectSubProjects(project: Project): Set<Identifier> =
scopeDependencies(project, matcher = MATCH_SUB_PROJECTS).collectDependencies()

/**
* Return a set with the [Identifier]s of all dependencies of the given [project] across all scopes. As usual,
* it is possible to restrict the dependencies to be fetched with [maxDepth] and [matcher].
*/
fun projectDependencies(
project: Project,
maxDepth: Int = -1,
matcher: DependencyMatcher = MATCH_ALL
): Set<Identifier> = scopeDependencies(project, maxDepth, matcher).collectDependencies()

/**
* Return the depth of the dependency tree rooted at the given [project] associated with this [scopeName]. If the
* scope cannot be resolved, return -1.
Expand All @@ -177,10 +153,10 @@ interface DependencyNavigator {

/**
* Determine the map of the shortest paths for all the dependencies of a [project], given its map of
* [scopeDependencies].
* [projectDependencies].
*/
private fun getShortestPathForScope(project: Project, scope: String): Map<Identifier, List<Identifier>> =
getShortestPathsForScope(directDependencies(project, scope), dependenciesForScope(project, scope))
getShortestPathsForScope(directDependencies(project, scope), scopeDependencies(project, scope))

/**
* Determine the map of the shortest paths for a specific scope given its direct dependency [nodes] and a set with
Expand Down
12 changes: 3 additions & 9 deletions model/src/main/kotlin/DependencyTreeNavigator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,16 @@ object DependencyTreeNavigator : DependencyNavigator {
override fun directDependencies(project: Project, scopeName: String): Sequence<DependencyNode> =
project.findScope(scopeName)?.dependencies?.asSequence().orEmpty()

override fun dependenciesForScope(
override fun scopeDependencies(
project: Project,
scopeName: String,
maxDepth: Int,
matcher: DependencyMatcher
): Set<Identifier> = project.findScope(scopeName)?.collectDependencies(maxDepth) { matcher(it) }.orEmpty()

override fun scopeDependencies(
project: Project,
maxDepth: Int,
matcher: DependencyMatcher
): Map<String, Set<Identifier>> =
override fun projectDependencies(project: Project, maxDepth: Int, matcher: DependencyMatcher): Set<Identifier> =
// Override the base implementation because a more efficient access to single scopes is possible.
project.scopes.associate { scope ->
scope.name to scope.collectDependencies(maxDepth, matcher.forReference())
}
project.scopes.flatMapTo(mutableSetOf()) { it.collectDependencies(maxDepth, matcher.forReference()) }

override fun packageDependencies(
project: Project,
Expand Down
15 changes: 9 additions & 6 deletions model/src/main/kotlin/OrtResult.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import java.lang.invoke.MethodHandles

import org.apache.logging.log4j.kotlin.loggerOf

import org.ossreviewtoolkit.model.DependencyNavigator.Companion.MATCH_SUB_PROJECTS
import org.ossreviewtoolkit.model.ResolvedPackageCurations.Companion.REPOSITORY_CONFIGURATION_PROVIDER_ID
import org.ossreviewtoolkit.model.config.Excludes
import org.ossreviewtoolkit.model.config.IssueResolution
Expand Down Expand Up @@ -129,12 +130,14 @@ data class OrtResult(
val includedDependencies = mutableSetOf<Identifier>()

projects.forEach { project ->
dependencyNavigator.scopeDependencies(project).forEach { (scopeName, dependencies) ->
val isScopeExcluded = getExcludes().isScopeExcluded(scopeName)
allDependencies += dependencies
dependencyNavigator.scopeNames(project).forEach { scopeName ->
dependencyNavigator.scopeDependencies(project, scopeName).forEach { dependencies ->
val isScopeExcluded = getExcludes().isScopeExcluded(scopeName)
allDependencies += dependencies

if (!isProjectExcluded(project.id) && !isScopeExcluded) {
includedDependencies += dependencies
if (!isProjectExcluded(project.id) && !isScopeExcluded) {
includedDependencies += dependencies
}
}
}
}
Expand Down Expand Up @@ -434,7 +437,7 @@ data class OrtResult(

if (!includeSubProjects) {
val subProjectIds = projects.flatMapTo(mutableSetOf()) {
dependencyNavigator.collectSubProjects(it)
dependencyNavigator.projectDependencies(it, matcher = MATCH_SUB_PROJECTS)
}

projects.removeAll { it.id in subProjectIds }
Expand Down
Loading

0 comments on commit 532244e

Please sign in to comment.