From c0d2a84e5ea77a3f21726dc39061be81899bf5c6 Mon Sep 17 00:00:00 2001 From: Sebastian Schuberth Date: Mon, 8 Jan 2024 18:39:37 +0100 Subject: [PATCH 01/10] chore(static-html-reporter): Align YAML assets to use unindented lists Signed-off-by: Sebastian Schuberth --- .../src/funTest/assets/reporter-test-input.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/plugins/reporters/static-html/src/funTest/assets/reporter-test-input.yml b/plugins/reporters/static-html/src/funTest/assets/reporter-test-input.yml index e61ced2a3ef74..586ba842c7b9b 100644 --- a/plugins/reporters/static-html/src/funTest/assets/reporter-test-input.yml +++ b/plugins/reporters/static-html/src/funTest/assets/reporter-test-input.yml @@ -592,23 +592,23 @@ scanner: end_time: "1970-01-01T00:00:00Z" scanners: "Gradle:org.ossreviewtoolkit:nested-fake-project:1.0.0": - - "FakeScanner" + - "FakeScanner" "Gradle:org.ossreviewtoolkit.gradle.example:lib:1.0.0": - - "FakeScanner" + - "FakeScanner" "Ant:junit:junit:4.12": - - "Dummy" + - "Dummy" "Maven:com.foobar:foobar:1.0": - - "Dummy" + - "Dummy" "Maven:com.h2database:h2:1.4.200": - - "Dummy" + - "Dummy" "Maven:org.apache.commons:commons-lang3:3.5": - - "Dummy" + - "Dummy" "Maven:org.apache.commons:commons-text:1.1": - - "Dummy" + - "Dummy" "Maven:org.example.test:example-component:1.11": - - "Dummy" + - "Dummy" "Maven:org.hamcrest:hamcrest-core:1.3": - - "Dummy" + - "Dummy" files: - provenance: vcs_info: From 27752307f6ccf7300c4e53a254cea6a7a05a4b98 Mon Sep 17 00:00:00 2001 From: Frank Viernau Date: Thu, 21 Dec 2023 09:03:03 +0100 Subject: [PATCH 02/10] test(reporter): Include all resolutions also in resolved config The reporter command has been changed to ensure that all resolutions are included in the `OrtResult` before passing it around to the reporters. Reflect that also in this test asset. This was left-over by 10c0362. Signed-off-by: Frank Viernau --- .../opossum/src/funTest/assets/reporter-test-input.yml | 5 +++++ .../static-html/src/funTest/assets/reporter-test-input.yml | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/plugins/reporters/opossum/src/funTest/assets/reporter-test-input.yml b/plugins/reporters/opossum/src/funTest/assets/reporter-test-input.yml index 586ba842c7b9b..daa6cc89281b6 100644 --- a/plugins/reporters/opossum/src/funTest/assets/reporter-test-input.yml +++ b/plugins/reporters/opossum/src/funTest/assets/reporter-test-input.yml @@ -758,6 +758,11 @@ resolved_configuration: curations: comment: "H2 database offers a license choice" concluded_license: "MPL-2.0 OR EPL-1.0" + resolutions: + rule_violations: + - message: "Apache-2.0 hint" + reason: "CANT_FIX_EXCEPTION" + comment: "Apache-2 is not an issue." labels: job_parameters.JOB_PARAM_1: "label job param 1" job_parameters.JOB_PARAM_2: "label job param 2" diff --git a/plugins/reporters/static-html/src/funTest/assets/reporter-test-input.yml b/plugins/reporters/static-html/src/funTest/assets/reporter-test-input.yml index 586ba842c7b9b..daa6cc89281b6 100644 --- a/plugins/reporters/static-html/src/funTest/assets/reporter-test-input.yml +++ b/plugins/reporters/static-html/src/funTest/assets/reporter-test-input.yml @@ -758,6 +758,11 @@ resolved_configuration: curations: comment: "H2 database offers a license choice" concluded_license: "MPL-2.0 OR EPL-1.0" + resolutions: + rule_violations: + - message: "Apache-2.0 hint" + reason: "CANT_FIX_EXCEPTION" + comment: "Apache-2 is not an issue." labels: job_parameters.JOB_PARAM_1: "label job param 1" job_parameters.JOB_PARAM_2: "label job param 2" From a58a81a61578bb5b160ef67a3541872940c0654f Mon Sep 17 00:00:00 2001 From: Sebastian Schuberth Date: Mon, 8 Jan 2024 18:46:45 +0100 Subject: [PATCH 03/10] test(reporter): Add issue resolutions to all test assets Align all `reporter-test-input.yml` files to again have the same contents. Signed-off-by: Sebastian Schuberth --- .../opossum/src/funTest/assets/reporter-test-input.yml | 8 ++++++++ .../src/funTest/assets/reporter-test-input.yml | 8 ++++++++ .../assets/static-html-reporter-test-expected-output.html | 4 ++++ 3 files changed, 20 insertions(+) diff --git a/plugins/reporters/opossum/src/funTest/assets/reporter-test-input.yml b/plugins/reporters/opossum/src/funTest/assets/reporter-test-input.yml index daa6cc89281b6..bf9f6dd71981d 100644 --- a/plugins/reporters/opossum/src/funTest/assets/reporter-test-input.yml +++ b/plugins/reporters/opossum/src/funTest/assets/reporter-test-input.yml @@ -30,6 +30,10 @@ repository: reason: "TEST_DEPENDENCY_OF" comment: "The scope only contains test dependencies." resolutions: + issues: + - message: "A test issue\\." + reason: "CANT_FIX_ISSUE" + comment: "A comment explaining why the issue can be ignored." rule_violations: - message: "Apache-2.0 hint" reason: "CANT_FIX_EXCEPTION" @@ -759,6 +763,10 @@ resolved_configuration: comment: "H2 database offers a license choice" concluded_license: "MPL-2.0 OR EPL-1.0" resolutions: + issues: + - message: "A test issue\\." + reason: "CANT_FIX_ISSUE" + comment: "A comment explaining why the issue can be ignored." rule_violations: - message: "Apache-2.0 hint" reason: "CANT_FIX_EXCEPTION" diff --git a/plugins/reporters/static-html/src/funTest/assets/reporter-test-input.yml b/plugins/reporters/static-html/src/funTest/assets/reporter-test-input.yml index daa6cc89281b6..bf9f6dd71981d 100644 --- a/plugins/reporters/static-html/src/funTest/assets/reporter-test-input.yml +++ b/plugins/reporters/static-html/src/funTest/assets/reporter-test-input.yml @@ -30,6 +30,10 @@ repository: reason: "TEST_DEPENDENCY_OF" comment: "The scope only contains test dependencies." resolutions: + issues: + - message: "A test issue\\." + reason: "CANT_FIX_ISSUE" + comment: "A comment explaining why the issue can be ignored." rule_violations: - message: "Apache-2.0 hint" reason: "CANT_FIX_EXCEPTION" @@ -759,6 +763,10 @@ resolved_configuration: comment: "H2 database offers a license choice" concluded_license: "MPL-2.0 OR EPL-1.0" resolutions: + issues: + - message: "A test issue\\." + reason: "CANT_FIX_ISSUE" + comment: "A comment explaining why the issue can be ignored." rule_violations: - message: "Apache-2.0 hint" reason: "CANT_FIX_EXCEPTION" diff --git a/plugins/reporters/static-html/src/funTest/assets/static-html-reporter-test-expected-output.html b/plugins/reporters/static-html/src/funTest/assets/static-html-reporter-test-expected-output.html index ced28e82a3157..a23a13065f75c 100644 --- a/plugins/reporters/static-html/src/funTest/assets/static-html-reporter-test-expected-output.html +++ b/plugins/reporters/static-html/src/funTest/assets/static-html-reporter-test-expected-output.html @@ -918,6 +918,10 @@

Repository Configuration

reason: "TEST_DEPENDENCY_OF" comment: "The scope only contains test dependencies." resolutions: + issues: + - message: "A test issue\\." + reason: "CANT_FIX_ISSUE" + comment: "A comment explaining why the issue can be ignored." rule_violations: - message: "Apache-2.0 hint" reason: "CANT_FIX_EXCEPTION" From 82750599e6df1d4645775d8b0593bb6a7241f0ec Mon Sep 17 00:00:00 2001 From: Frank Viernau Date: Tue, 12 Dec 2023 13:17:20 +0100 Subject: [PATCH 04/10] refactor(StatisticsCalculator)!: Stop using `resolutionProvider` Prepare for the removal of `ReporterInput.resolutionProvider`. The change is non-functional because the reporter command ensures that all relevant resolutions are contained in the `OrtResult`. Signed-off-by: Frank Viernau --- .../src/main/kotlin/EvaluatedModelMapper.kt | 2 +- reporter/src/main/kotlin/ReporterInput.kt | 2 +- .../src/main/kotlin/StatisticsCalculator.kt | 66 ++++++++----------- 3 files changed, 28 insertions(+), 42 deletions(-) diff --git a/plugins/reporters/evaluated-model/src/main/kotlin/EvaluatedModelMapper.kt b/plugins/reporters/evaluated-model/src/main/kotlin/EvaluatedModelMapper.kt index 43bd8b13d1706..e4dff17731e24 100644 --- a/plugins/reporters/evaluated-model/src/main/kotlin/EvaluatedModelMapper.kt +++ b/plugins/reporters/evaluated-model/src/main/kotlin/EvaluatedModelMapper.kt @@ -142,7 +142,7 @@ internal class EvaluatedModelMapper(private val input: ReporterInput) { ruleViolations = ruleViolations, vulnerabilitiesResolutions = vulnerabilitiesResolutions, vulnerabilities = vulnerabilities, - statistics = with(input) { getStatistics(ortResult, resolutionProvider, licenseInfoResolver, ortConfig) }, + statistics = with(input) { getStatistics(ortResult, licenseInfoResolver, ortConfig) }, repository = input.ortResult.repository, severeIssueThreshold = input.ortConfig.severeIssueThreshold, severeRuleViolationThreshold = input.ortConfig.severeRuleViolationThreshold, diff --git a/reporter/src/main/kotlin/ReporterInput.kt b/reporter/src/main/kotlin/ReporterInput.kt index c63d8a63e056e..d3a993956462e 100644 --- a/reporter/src/main/kotlin/ReporterInput.kt +++ b/reporter/src/main/kotlin/ReporterInput.kt @@ -94,5 +94,5 @@ data class ReporterInput( * Statistics for [ortResult]. */ @Suppress("UNUSED") // This can be used from templates. - val statistics: Statistics by lazy { getStatistics(ortResult, resolutionProvider, licenseInfoResolver, ortConfig) } + val statistics: Statistics by lazy { getStatistics(ortResult, licenseInfoResolver, ortConfig) } } diff --git a/reporter/src/main/kotlin/StatisticsCalculator.kt b/reporter/src/main/kotlin/StatisticsCalculator.kt index 79d83414587e6..edabc57f1fae4 100644 --- a/reporter/src/main/kotlin/StatisticsCalculator.kt +++ b/reporter/src/main/kotlin/StatisticsCalculator.kt @@ -31,7 +31,6 @@ import org.ossreviewtoolkit.model.config.OrtConfiguration import org.ossreviewtoolkit.model.config.RuleViolationResolution import org.ossreviewtoolkit.model.licenses.LicenseInfoResolver import org.ossreviewtoolkit.model.licenses.LicenseView -import org.ossreviewtoolkit.model.utils.ResolutionProvider /** * This class calculates [Statistics] for a given [OrtResult] and the applicable [IssueResolution]s and @@ -41,36 +40,28 @@ object StatisticsCalculator { /** * Return the [Statistics] for the given [ortResult]. */ - fun getStatistics( - ortResult: OrtResult, - resolutionProvider: ResolutionProvider, - licenseInfoResolver: LicenseInfoResolver, - ortConfig: OrtConfiguration - ) = Statistics( - repositoryConfiguration = getRepositoryConfigurationStatistics(ortResult), - openIssues = getOpenIssues(ortResult, resolutionProvider, ortConfig), - openRuleViolations = getOpenRuleViolations(ortResult, resolutionProvider, ortConfig), - openVulnerabilities = getOpenVulnerabilities(ortResult, resolutionProvider), - dependencyTree = DependencyTreeStatistics( - includedProjects = ortResult.getProjects().count { !ortResult.isExcluded(it.id) }, - excludedProjects = ortResult.getProjects().count { ortResult.isExcluded(it.id) }, - includedPackages = ortResult.getPackages().count { !ortResult.isExcluded(it.metadata.id) }, - excludesPackages = ortResult.getPackages().count { ortResult.isExcluded(it.metadata.id) }, - totalTreeDepth = getTreeDepth(ortResult), - includedTreeDepth = getTreeDepth(ortResult = ortResult, ignoreExcluded = true), - includedScopes = getIncludedScopes(ortResult), - excludedScopes = getExcludedScopes(ortResult) - ), - licenses = getLicenseStatistics(ortResult, licenseInfoResolver), - executionDurationInSeconds = getExecutionDurationInSeconds(ortResult) - ) - - private fun getOpenRuleViolations( - ortResult: OrtResult, - resolutionProvider: ResolutionProvider, - ortConfig: OrtConfiguration - ): IssueStatistics { - val openRuleViolations = ortResult.getRuleViolations().filterNot { resolutionProvider.isResolved(it) } + fun getStatistics(ortResult: OrtResult, licenseInfoResolver: LicenseInfoResolver, ortConfig: OrtConfiguration) = + Statistics( + repositoryConfiguration = getRepositoryConfigurationStatistics(ortResult), + openIssues = getOpenIssues(ortResult, ortConfig), + openRuleViolations = getOpenRuleViolations(ortResult, ortConfig), + openVulnerabilities = getOpenVulnerabilities(ortResult), + dependencyTree = DependencyTreeStatistics( + includedProjects = ortResult.getProjects().count { !ortResult.isExcluded(it.id) }, + excludedProjects = ortResult.getProjects().count { ortResult.isExcluded(it.id) }, + includedPackages = ortResult.getPackages().count { !ortResult.isExcluded(it.metadata.id) }, + excludesPackages = ortResult.getPackages().count { ortResult.isExcluded(it.metadata.id) }, + totalTreeDepth = getTreeDepth(ortResult), + includedTreeDepth = getTreeDepth(ortResult = ortResult, ignoreExcluded = true), + includedScopes = getIncludedScopes(ortResult), + excludedScopes = getExcludedScopes(ortResult) + ), + licenses = getLicenseStatistics(ortResult, licenseInfoResolver), + executionDurationInSeconds = getExecutionDurationInSeconds(ortResult) + ) + + private fun getOpenRuleViolations(ortResult: OrtResult, ortConfig: OrtConfiguration): IssueStatistics { + val openRuleViolations = ortResult.getRuleViolations(omitResolved = true) return IssueStatistics( errors = openRuleViolations.count { it.severity == Severity.ERROR }, @@ -80,12 +71,8 @@ object StatisticsCalculator { ) } - private fun getOpenIssues( - ortResult: OrtResult, - resolutionProvider: ResolutionProvider, - ortConfig: OrtConfiguration - ): IssueStatistics { - val openIssues = ortResult.getOpenIssues(Severity.HINT).filterNot { resolutionProvider.isResolved(it) } + private fun getOpenIssues(ortResult: OrtResult, ortConfig: OrtConfiguration): IssueStatistics { + val openIssues = ortResult.getOpenIssues(Severity.HINT) return IssueStatistics( errors = openIssues.count { it.severity == Severity.ERROR }, @@ -95,9 +82,8 @@ object StatisticsCalculator { ) } - private fun getOpenVulnerabilities(ortResult: OrtResult, resolutionProvider: ResolutionProvider): Int = - ortResult.getVulnerabilities(omitExcluded = true).values.flatten() - .filterNot { resolutionProvider.isResolved(it) }.size + private fun getOpenVulnerabilities(ortResult: OrtResult): Int = + ortResult.getVulnerabilities(omitExcluded = true, omitResolved = true).values.flatten().size private fun getTreeDepth(ortResult: OrtResult, ignoreExcluded: Boolean = false): Int = ortResult From 63e4255f50c4c6749fa7a69d2f091763a5a74a9a Mon Sep 17 00:00:00 2001 From: Frank Viernau Date: Tue, 12 Dec 2023 13:30:49 +0100 Subject: [PATCH 05/10] refactor(freemarker): Stop using `resolutionProvider` Prepare for the removal of `ReporterInput.resolutionProvider`. The change is non-functional because the reporter command ensures that all relevant resolutions are contained in the `OrtResult`. Signed-off-by: Frank Viernau --- model/src/main/kotlin/OrtResult.kt | 12 ++++++++++ .../kotlin/FreemarkerTemplateProcessor.kt | 22 +++++-------------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/model/src/main/kotlin/OrtResult.kt b/model/src/main/kotlin/OrtResult.kt index 49a18232c3d70..bf72e4c08c5f3 100644 --- a/model/src/main/kotlin/OrtResult.kt +++ b/model/src/main/kotlin/OrtResult.kt @@ -387,6 +387,18 @@ data class OrtResult( @JsonIgnore fun getResolutions(): Resolutions = resolvedConfiguration.resolutions.orEmpty() + /** + * Return true if and only if [ruleViolation] is resolved in this [OrtResult]. + */ + fun isResolved(ruleViolation: RuleViolation): Boolean = + getResolutions().ruleViolations.any { it.matches(ruleViolation) } + + /** + * Return true if and only if [vulnerability] is resolved in this [OrtResult]. + */ + fun isResolved(vulnerability: Vulnerability): Boolean = + getResolutions().vulnerabilities.any { it.matches(vulnerability) } + /** * Return all [RuleViolation]s contained in this [OrtResult]. Optionally exclude resolved violations with * [omitResolved] and remove violations below the [minSeverity]. diff --git a/plugins/reporters/freemarker/src/main/kotlin/FreemarkerTemplateProcessor.kt b/plugins/reporters/freemarker/src/main/kotlin/FreemarkerTemplateProcessor.kt index 5402b57379acb..35e6205fc2546 100644 --- a/plugins/reporters/freemarker/src/main/kotlin/FreemarkerTemplateProcessor.kt +++ b/plugins/reporters/freemarker/src/main/kotlin/FreemarkerTemplateProcessor.kt @@ -275,14 +275,7 @@ class FreemarkerTemplateProcessor( @JvmOverloads @Suppress("UNUSED") // This function is used in the templates. fun hasUnresolvedIssues(threshold: Severity = input.ortConfig.severeIssueThreshold) = - input.ortResult.getIssues().any { (identifier, issues) -> - issues.any { issue -> - val isResolved = input.resolutionProvider.isResolved(issue) - val isExcluded = input.ortResult.isExcluded(identifier) - - issue.severity >= threshold && !isResolved && !isExcluded - } - } + input.ortResult.getOpenIssues(minSeverity = threshold).isNotEmpty() /** * Return `true` if there are any unresolved and non-excluded [RuleViolation]s whose severity is equal to or @@ -291,26 +284,23 @@ class FreemarkerTemplateProcessor( @JvmOverloads @Suppress("UNUSED") // This function is used in the templates. fun hasUnresolvedRuleViolations(threshold: Severity = input.ortConfig.severeRuleViolationThreshold) = - input.ortResult.evaluator?.violations?.any { violation -> - val isResolved = input.resolutionProvider.isResolved(violation) - val isExcluded = violation.pkg?.let { input.ortResult.isExcluded(it) } ?: false - - violation.severity >= threshold && !isResolved && !isExcluded - } ?: false + input.ortResult.getRuleViolations(omitResolved = true, minSeverity = threshold).any { violation -> + violation.pkg?.let { input.ortResult.isExcluded(it) } ?: false + } /** * Return a list of [RuleViolation]s for which no [RuleViolationResolution] is provided. */ @Suppress("UNUSED") // This function is used in the templates. fun filterForUnresolvedRuleViolations(ruleViolation: List): List = - ruleViolation.filterNot { input.resolutionProvider.isResolved(it) } + ruleViolation.filterNot { input.ortResult.isResolved(it) } /** * Return a list of [Vulnerability]s for which no [VulnerabilityResolution] is provided. */ @Suppress("UNUSED") // This function is used in the templates. fun filterForUnresolvedVulnerabilities(vulnerabilities: List): List = - vulnerabilities.filterNot { input.resolutionProvider.isResolved(it) } + vulnerabilities.filterNot { input.ortResult.isResolved(it) } /** * Return a list of [SnippetFinding]s grouped by the source file being matched by those snippets. From 4d068dca37c77adc7404e0d264af9cdff8fdde14 Mon Sep 17 00:00:00 2001 From: Frank Viernau Date: Tue, 12 Dec 2023 15:33:51 +0100 Subject: [PATCH 06/10] refactor(evaluated-model): Stop using `resolutionProvider` Prepare for the removal of `ReporterInput.resolutionProvider`. The change is non-functional because the reporter command ensures that all relevant resolutions are contained in the `OrtResult`. Signed-off-by: Frank Viernau --- model/src/main/kotlin/OrtResult.kt | 20 +++++++++++ .../src/main/kotlin/EvaluatedModelMapper.kt | 33 ++++++++++++++++--- 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/model/src/main/kotlin/OrtResult.kt b/model/src/main/kotlin/OrtResult.kt index bf72e4c08c5f3..8a60b53ee8da2 100644 --- a/model/src/main/kotlin/OrtResult.kt +++ b/model/src/main/kotlin/OrtResult.kt @@ -28,9 +28,12 @@ import org.apache.logging.log4j.kotlin.loggerOf import org.ossreviewtoolkit.model.ResolvedPackageCurations.Companion.REPOSITORY_CONFIGURATION_PROVIDER_ID import org.ossreviewtoolkit.model.config.Excludes +import org.ossreviewtoolkit.model.config.IssueResolution import org.ossreviewtoolkit.model.config.LicenseFindingCuration import org.ossreviewtoolkit.model.config.RepositoryConfiguration import org.ossreviewtoolkit.model.config.Resolutions +import org.ossreviewtoolkit.model.config.RuleViolationResolution +import org.ossreviewtoolkit.model.config.VulnerabilityResolution import org.ossreviewtoolkit.model.config.orEmpty import org.ossreviewtoolkit.model.vulnerabilities.Vulnerability import org.ossreviewtoolkit.utils.common.zipWithCollections @@ -399,6 +402,23 @@ data class OrtResult( fun isResolved(vulnerability: Vulnerability): Boolean = getResolutions().vulnerabilities.any { it.matches(vulnerability) } + /** + * Return the resolutions matching [issue]. + */ + fun getResolutionsFor(issue: Issue): List = getResolutions().issues.filter { it.matches(issue) } + + /** + * Return the resolutions matching [ruleViolation]. + */ + fun getResolutionsFor(ruleViolation: RuleViolation): List = + getResolutions().ruleViolations.filter { it.matches(ruleViolation) } + + /** + * Return the resolutions matching [vulnerability]. + */ + fun getResolutionsFor(vulnerability: Vulnerability): List = + getResolutions().vulnerabilities.filter { it.matches(vulnerability) } + /** * Return all [RuleViolation]s contained in this [OrtResult]. Optionally exclude resolved violations with * [omitResolved] and remove violations below the [minSeverity]. diff --git a/plugins/reporters/evaluated-model/src/main/kotlin/EvaluatedModelMapper.kt b/plugins/reporters/evaluated-model/src/main/kotlin/EvaluatedModelMapper.kt index e4dff17731e24..12512a3469a98 100644 --- a/plugins/reporters/evaluated-model/src/main/kotlin/EvaluatedModelMapper.kt +++ b/plugins/reporters/evaluated-model/src/main/kotlin/EvaluatedModelMapper.kt @@ -29,6 +29,8 @@ import org.ossreviewtoolkit.model.PackageLinkage import org.ossreviewtoolkit.model.Project import org.ossreviewtoolkit.model.Provenance import org.ossreviewtoolkit.model.RemoteArtifact +import org.ossreviewtoolkit.model.Repository +import org.ossreviewtoolkit.model.ResolvedConfiguration import org.ossreviewtoolkit.model.RuleViolation import org.ossreviewtoolkit.model.ScanResult import org.ossreviewtoolkit.model.TextLocation @@ -36,6 +38,8 @@ import org.ossreviewtoolkit.model.VcsInfo import org.ossreviewtoolkit.model.config.IssueResolution import org.ossreviewtoolkit.model.config.LicenseFindingCuration import org.ossreviewtoolkit.model.config.PathExclude +import org.ossreviewtoolkit.model.config.RepositoryConfiguration +import org.ossreviewtoolkit.model.config.Resolutions import org.ossreviewtoolkit.model.config.RuleViolationResolution import org.ossreviewtoolkit.model.config.ScopeExclude import org.ossreviewtoolkit.model.config.VulnerabilityResolution @@ -143,7 +147,7 @@ internal class EvaluatedModelMapper(private val input: ReporterInput) { vulnerabilitiesResolutions = vulnerabilitiesResolutions, vulnerabilities = vulnerabilities, statistics = with(input) { getStatistics(ortResult, licenseInfoResolver, ortConfig) }, - repository = input.ortResult.repository, + repository = input.ortResult.repository.deduplicateResolutions(), severeIssueThreshold = input.ortConfig.severeIssueThreshold, severeRuleViolationThreshold = input.ortConfig.severeRuleViolationThreshold, repositoryConfiguration = input.ortResult.repository.config.toYaml(), @@ -604,19 +608,19 @@ internal class EvaluatedModelMapper(private val input: ReporterInput) { } private fun addResolutions(issue: Issue): List { - val matchingResolutions = input.resolutionProvider.getResolutionsFor(issue) + val matchingResolutions = input.ortResult.getResolutionsFor(issue) return issueResolutions.addIfRequired(matchingResolutions) } private fun addResolutions(ruleViolation: RuleViolation): List { - val matchingResolutions = input.resolutionProvider.getResolutionsFor(ruleViolation) + val matchingResolutions = input.ortResult.getResolutionsFor(ruleViolation) return ruleViolationResolutions.addIfRequired(matchingResolutions) } private fun addResolutions(vulnerability: Vulnerability): List { - val matchingResolutions = input.resolutionProvider.getResolutionsFor(vulnerability) + val matchingResolutions = input.ortResult.getResolutionsFor(vulnerability) return vulnerabilitiesResolutions.addIfRequired(matchingResolutions) } @@ -718,4 +722,25 @@ internal class EvaluatedModelMapper(private val input: ReporterInput) { */ private fun MutableList.addIfRequired(values: Collection): List = values.map { addIfRequired(it) }.distinct() + + /** + * Return a copy of the [RepositoryConfiguration] with [Resolutions] that refer to the same instances as the + * [ResolvedConfiguration] for equal [Resolutions]. This is required for the [EvaluatedModel] to contained indexed + * references instead of duplicate [Resolutions]. + */ + private fun Repository.deduplicateResolutions(): Repository { + val resolutions = with(config.resolutions) { + copy( + issues = issues.map { resolution -> issueResolutions.find { resolution == it } ?: resolution }, + ruleViolations = ruleViolations.map { resolution -> + ruleViolationResolutions.find { resolution == it } ?: resolution + }, + vulnerabilities = vulnerabilities.map { resolution -> + vulnerabilitiesResolutions.find { resolution == it } ?: resolution + } + ) + } + + return copy(config = config.copy(resolutions = resolutions)) + } } From 90627556dacb725252657ef2374bf9f30b6f98e0 Mon Sep 17 00:00:00 2001 From: Frank Viernau Date: Tue, 12 Dec 2023 15:34:15 +0100 Subject: [PATCH 07/10] refactor(static-html): Stop using `resolutionProvider` Prepare for the removal of `ReporterInput.resolutionProvider`. The change is non-functional because the reporter command ensures that all relevant resolutions are contained in the `OrtResult`. Signed-off-by: Frank Viernau --- .../src/main/kotlin/ReportTableModelMapper.kt | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/plugins/reporters/static-html/src/main/kotlin/ReportTableModelMapper.kt b/plugins/reporters/static-html/src/main/kotlin/ReportTableModelMapper.kt index 01cc076ecad61..afe3175b1148b 100644 --- a/plugins/reporters/static-html/src/main/kotlin/ReportTableModelMapper.kt +++ b/plugins/reporters/static-html/src/main/kotlin/ReportTableModelMapper.kt @@ -30,7 +30,6 @@ import org.ossreviewtoolkit.model.config.Excludes import org.ossreviewtoolkit.model.config.ScopeExclude import org.ossreviewtoolkit.model.licenses.LicenseView import org.ossreviewtoolkit.model.orEmpty -import org.ossreviewtoolkit.model.utils.ResolutionProvider import org.ossreviewtoolkit.plugins.reporters.statichtml.ReportTableModel.DependencyRow import org.ossreviewtoolkit.plugins.reporters.statichtml.ReportTableModel.IssueRow import org.ossreviewtoolkit.plugins.reporters.statichtml.ReportTableModel.IssueTable @@ -91,10 +90,10 @@ internal object ReportTableModelMapper { input.ortResult.getRepositoryLicenseChoices() )?.sorted(), analyzerIssues = analyzerIssues.map { - it.toResolvableIssue(input.resolutionProvider, input.howToFixTextProvider) + it.toResolvableIssue(input.ortResult, input.howToFixTextProvider) }, scanIssues = scanIssues.map { - it.toResolvableIssue(input.resolutionProvider, input.howToFixTextProvider) + it.toResolvableIssue(input.ortResult, input.howToFixTextProvider) } ) @@ -139,7 +138,7 @@ internal object ReportTableModelMapper { val labels = input.ortResult.labels.mapKeys { it.key.substringAfter(".") } val ruleViolations = input.ortResult.getRuleViolations() - .map { it.toResolvableViolation(input.resolutionProvider) } + .map { it.toResolvableViolation(input.ortResult) } .sortedWith(VIOLATION_COMPARATOR) return ReportTableModel( @@ -179,11 +178,8 @@ private fun Project.getScopesForDependencies( return result } -private fun Issue.toResolvableIssue( - resolutionProvider: ResolutionProvider, - howToFixTextProvider: HowToFixTextProvider -): ResolvableIssue { - val resolutions = resolutionProvider.getResolutionsFor(this) +private fun Issue.toResolvableIssue(ortResult: OrtResult, howToFixTextProvider: HowToFixTextProvider): ResolvableIssue { + val resolutions = ortResult.getResolutionsFor(this) return ResolvableIssue( source = source, description = toString(), @@ -202,8 +198,8 @@ private fun Issue.toResolvableIssue( ) } -private fun RuleViolation.toResolvableViolation(resolutionProvider: ResolutionProvider): ResolvableViolation { - val resolutions = resolutionProvider.getResolutionsFor(this) +private fun RuleViolation.toResolvableViolation(ortResult: OrtResult): ResolvableViolation { + val resolutions = ortResult.getResolutionsFor(this) return ResolvableViolation( violation = this, resolutionDescription = buildString { From 9f4c66ce0d3595b3d59837768b3657dbc27d440f Mon Sep 17 00:00:00 2001 From: Frank Viernau Date: Tue, 12 Dec 2023 15:38:26 +0100 Subject: [PATCH 08/10] refactor(reporter)!: Remove `ReporterInput.resolutionProvider` The reporter command ensures that all resolutions are contained in the ORT result. So, the resolution provider is not necessary anymore. Signed-off-by: Frank Viernau --- .../commands/reporter/src/main/kotlin/ReporterCommand.kt | 1 - .../src/funTest/kotlin/EvaluatedModelReporterFunTest.kt | 2 -- .../opossum/src/funTest/kotlin/OpossumReporterFunTest.kt | 8 ++------ .../src/funTest/kotlin/StaticHtmlReporterFunTest.kt | 2 -- reporter/src/main/kotlin/ReporterInput.kt | 8 -------- 5 files changed, 2 insertions(+), 19 deletions(-) diff --git a/plugins/commands/reporter/src/main/kotlin/ReporterCommand.kt b/plugins/commands/reporter/src/main/kotlin/ReporterCommand.kt index 1c3cf50316101..e2379267d4937 100644 --- a/plugins/commands/reporter/src/main/kotlin/ReporterCommand.kt +++ b/plugins/commands/reporter/src/main/kotlin/ReporterCommand.kt @@ -257,7 +257,6 @@ class ReporterCommand : OrtCommand( ortResult, ortConfig, packageConfigurationProvider, - DefaultResolutionProvider(ortResult.getResolutions()), DefaultLicenseTextProvider(licenseTextDirectories), copyrightGarbage, licenseInfoResolver, diff --git a/plugins/reporters/evaluated-model/src/funTest/kotlin/EvaluatedModelReporterFunTest.kt b/plugins/reporters/evaluated-model/src/funTest/kotlin/EvaluatedModelReporterFunTest.kt index c2a7f4f91738f..bd264e71d360c 100644 --- a/plugins/reporters/evaluated-model/src/funTest/kotlin/EvaluatedModelReporterFunTest.kt +++ b/plugins/reporters/evaluated-model/src/funTest/kotlin/EvaluatedModelReporterFunTest.kt @@ -27,7 +27,6 @@ import io.kotest.matchers.shouldBe import org.ossreviewtoolkit.model.FileFormat import org.ossreviewtoolkit.model.OrtResult import org.ossreviewtoolkit.model.config.PluginConfiguration -import org.ossreviewtoolkit.model.utils.DefaultResolutionProvider import org.ossreviewtoolkit.reporter.ReporterInput import org.ossreviewtoolkit.utils.common.normalizeLineBreaks import org.ossreviewtoolkit.utils.test.getAssetAsString @@ -66,7 +65,6 @@ class EvaluatedModelReporterFunTest : WordSpec({ private fun TestConfiguration.generateReport(ortResult: OrtResult, options: Map = emptyMap()): String { val input = ReporterInput( ortResult = ortResult, - resolutionProvider = DefaultResolutionProvider.create(ortResult), howToFixTextProvider = { "Some how to fix text." } ) diff --git a/plugins/reporters/opossum/src/funTest/kotlin/OpossumReporterFunTest.kt b/plugins/reporters/opossum/src/funTest/kotlin/OpossumReporterFunTest.kt index 1751dbc562487..e7c676de5fe28 100644 --- a/plugins/reporters/opossum/src/funTest/kotlin/OpossumReporterFunTest.kt +++ b/plugins/reporters/opossum/src/funTest/kotlin/OpossumReporterFunTest.kt @@ -29,7 +29,6 @@ import io.kotest.matchers.shouldBe import io.kotest.matchers.string.shouldContain import org.ossreviewtoolkit.model.OrtResult -import org.ossreviewtoolkit.model.utils.DefaultResolutionProvider import org.ossreviewtoolkit.reporter.ReporterInput import org.ossreviewtoolkit.utils.common.normalizeLineBreaks import org.ossreviewtoolkit.utils.common.unpackZip @@ -59,12 +58,9 @@ class OpossumReporterFunTest : WordSpec({ }) private fun TestConfiguration.generateReport(ortResult: OrtResult): String { - val input = ReporterInput( - ortResult = ortResult, - resolutionProvider = DefaultResolutionProvider(ortResult.getRepositoryConfigResolutions()) - ) - + val input = ReporterInput(ortResult) val outputDir = tempdir() + OpossumReporter().generateReport(input, outputDir).single().unpackZip(outputDir) return outputDir.resolve("input.json").readText() diff --git a/plugins/reporters/static-html/src/funTest/kotlin/StaticHtmlReporterFunTest.kt b/plugins/reporters/static-html/src/funTest/kotlin/StaticHtmlReporterFunTest.kt index c43863d42c176..71feee5ca53b5 100644 --- a/plugins/reporters/static-html/src/funTest/kotlin/StaticHtmlReporterFunTest.kt +++ b/plugins/reporters/static-html/src/funTest/kotlin/StaticHtmlReporterFunTest.kt @@ -27,7 +27,6 @@ import io.kotest.matchers.shouldBe import javax.xml.transform.TransformerFactory import org.ossreviewtoolkit.model.OrtResult -import org.ossreviewtoolkit.model.utils.DefaultResolutionProvider import org.ossreviewtoolkit.reporter.HowToFixTextProvider import org.ossreviewtoolkit.reporter.ReporterInput import org.ossreviewtoolkit.utils.ort.Environment @@ -70,7 +69,6 @@ class StaticHtmlReporterFunTest : WordSpec({ private fun TestConfiguration.generateReport(ortResult: OrtResult): String { val input = ReporterInput( ortResult = ortResult, - resolutionProvider = DefaultResolutionProvider.create(ortResult), howToFixTextProvider = HOW_TO_FIX_TEXT_PROVIDER ) diff --git a/reporter/src/main/kotlin/ReporterInput.kt b/reporter/src/main/kotlin/ReporterInput.kt index d3a993956462e..0c3eb664e98e7 100644 --- a/reporter/src/main/kotlin/ReporterInput.kt +++ b/reporter/src/main/kotlin/ReporterInput.kt @@ -21,7 +21,6 @@ package org.ossreviewtoolkit.reporter import org.ossreviewtoolkit.model.Issue import org.ossreviewtoolkit.model.OrtResult -import org.ossreviewtoolkit.model.RuleViolation import org.ossreviewtoolkit.model.config.CopyrightGarbage import org.ossreviewtoolkit.model.config.OrtConfiguration import org.ossreviewtoolkit.model.config.PackageConfiguration @@ -29,9 +28,7 @@ import org.ossreviewtoolkit.model.config.createFileArchiver import org.ossreviewtoolkit.model.licenses.DefaultLicenseInfoProvider import org.ossreviewtoolkit.model.licenses.LicenseClassifications import org.ossreviewtoolkit.model.licenses.LicenseInfoResolver -import org.ossreviewtoolkit.model.utils.DefaultResolutionProvider import org.ossreviewtoolkit.model.utils.PackageConfigurationProvider -import org.ossreviewtoolkit.model.utils.ResolutionProvider import org.ossreviewtoolkit.reporter.StatisticsCalculator.getStatistics /** @@ -53,11 +50,6 @@ data class ReporterInput( */ val packageConfigurationProvider: PackageConfigurationProvider = PackageConfigurationProvider.EMPTY, - /** - * A [ResolutionProvider], can be used to check which [Issue]s and [RuleViolation]s are resolved. - */ - val resolutionProvider: ResolutionProvider = DefaultResolutionProvider(), - /** * A [LicenseTextProvider], can be used to integrate licenses texts into reports. */ From 6fcd6f3bbb3e8dd224fe2b03a1596819d012d1cd Mon Sep 17 00:00:00 2001 From: Frank Viernau Date: Mon, 18 Dec 2023 19:04:59 +0100 Subject: [PATCH 09/10] refactor(model): Make `OrtResult` implement `ResolutionProvider` As `OrtResult` meanwhile has all the functions of `ResolutionProvider`, make it implement that interface to document that. Signed-off-by: Frank Viernau --- model/src/main/kotlin/OrtResult.kt | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/model/src/main/kotlin/OrtResult.kt b/model/src/main/kotlin/OrtResult.kt index 8a60b53ee8da2..1165440b21120 100644 --- a/model/src/main/kotlin/OrtResult.kt +++ b/model/src/main/kotlin/OrtResult.kt @@ -35,6 +35,7 @@ import org.ossreviewtoolkit.model.config.Resolutions import org.ossreviewtoolkit.model.config.RuleViolationResolution import org.ossreviewtoolkit.model.config.VulnerabilityResolution import org.ossreviewtoolkit.model.config.orEmpty +import org.ossreviewtoolkit.model.utils.ResolutionProvider import org.ossreviewtoolkit.model.vulnerabilities.Vulnerability import org.ossreviewtoolkit.utils.common.zipWithCollections import org.ossreviewtoolkit.utils.spdx.model.SpdxLicenseChoice @@ -86,7 +87,7 @@ data class OrtResult( */ @JsonInclude(JsonInclude.Include.NON_EMPTY) val labels: Map = emptyMap() -) { +) : ResolutionProvider { companion object { /** * A constant for an [OrtResult] with an empty repository and all other properties `null`. @@ -391,32 +392,33 @@ data class OrtResult( fun getResolutions(): Resolutions = resolvedConfiguration.resolutions.orEmpty() /** - * Return true if and only if [ruleViolation] is resolved in this [OrtResult]. + * Return true if and only if [violation] is resolved in this [OrtResult]. */ - fun isResolved(ruleViolation: RuleViolation): Boolean = - getResolutions().ruleViolations.any { it.matches(ruleViolation) } + override fun isResolved(violation: RuleViolation): Boolean = + getResolutions().ruleViolations.any { it.matches(violation) } /** * Return true if and only if [vulnerability] is resolved in this [OrtResult]. */ - fun isResolved(vulnerability: Vulnerability): Boolean = + override fun isResolved(vulnerability: Vulnerability): Boolean = getResolutions().vulnerabilities.any { it.matches(vulnerability) } /** * Return the resolutions matching [issue]. */ - fun getResolutionsFor(issue: Issue): List = getResolutions().issues.filter { it.matches(issue) } + override fun getResolutionsFor(issue: Issue): List = + getResolutions().issues.filter { it.matches(issue) } /** - * Return the resolutions matching [ruleViolation]. + * Return the resolutions matching [violation]. */ - fun getResolutionsFor(ruleViolation: RuleViolation): List = - getResolutions().ruleViolations.filter { it.matches(ruleViolation) } + override fun getResolutionsFor(violation: RuleViolation): List = + getResolutions().ruleViolations.filter { it.matches(violation) } /** * Return the resolutions matching [vulnerability]. */ - fun getResolutionsFor(vulnerability: Vulnerability): List = + override fun getResolutionsFor(vulnerability: Vulnerability): List = getResolutions().vulnerabilities.filter { it.matches(vulnerability) } /** From ab509520b94a9f9e69d54edf05b23f33d6ad5818 Mon Sep 17 00:00:00 2001 From: Sebastian Schuberth Date: Mon, 8 Jan 2024 21:30:58 +0100 Subject: [PATCH 10/10] docs(evaluated-model-reporter): Use imperative mood in function docs Signed-off-by: Sebastian Schuberth --- .../evaluated-model/src/main/kotlin/EvaluatedModelMapper.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/reporters/evaluated-model/src/main/kotlin/EvaluatedModelMapper.kt b/plugins/reporters/evaluated-model/src/main/kotlin/EvaluatedModelMapper.kt index 12512a3469a98..e199bae063393 100644 --- a/plugins/reporters/evaluated-model/src/main/kotlin/EvaluatedModelMapper.kt +++ b/plugins/reporters/evaluated-model/src/main/kotlin/EvaluatedModelMapper.kt @@ -711,9 +711,9 @@ internal class EvaluatedModelMapper(private val input: ReporterInput) { ) /** - * Adds the [value] to this list if the list does not already contain an equal item. Returns the item that is - * contained in the list. This is important to make sure that there is only one instance of equal items used in the - * model, because when Jackson generates IDs each instance gets a new ID, no matter if they are equal or not. + * Add the [value] to this list if the list does not already contain an equal item. Return the item contained in the + * list. This is important to make sure that there is only one instance of equal items used in the model, because + * when Jackson generates IDs each instance gets a new ID, no matter if they are equal or not. */ private fun MutableList.addIfRequired(value: T): T = find { it == value } ?: value.also { add(it) }