18
18
*/
19
19
20
20
package org.ossreviewtoolkit.plugins.scanners.scanoss
21
-
21
+ import com.scanoss.dto.LicenseDetails
22
22
import com.scanoss.dto.ScanFileDetails
23
23
import com.scanoss.dto.ScanFileResult
24
24
import com.scanoss.dto.enums.MatchType
25
+ import com.scanoss.dto.enums.StatusType
25
26
27
+ import java.lang.invoke.MethodHandles
26
28
import java.time.Instant
27
29
30
+ import kotlin.math.min
31
+
32
+ import org.apache.logging.log4j.kotlin.loggerOf
33
+
28
34
import org.ossreviewtoolkit.downloader.VcsHost
29
35
import org.ossreviewtoolkit.model.CopyrightFinding
30
36
import org.ossreviewtoolkit.model.LicenseFinding
@@ -36,7 +42,8 @@ import org.ossreviewtoolkit.model.TextLocation
36
42
import org.ossreviewtoolkit.utils.spdx.SpdxConstants
37
43
import org.ossreviewtoolkit.utils.spdx.SpdxExpression
38
44
import org.ossreviewtoolkit.utils.spdx.SpdxLicenseIdExpression
39
- import org.ossreviewtoolkit.utils.spdx.andOrNull
45
+
46
+ private val logger = loggerOf(MethodHandles .lookup().lookupClass())
40
47
41
48
/* *
42
49
* Generate a summary from the given SCANOSS [result], using [startTime], [endTime] as metadata. This variant can be
@@ -56,16 +63,23 @@ internal fun generateSummary(startTime: Instant, endTime: Instant, results: List
56
63
}
57
64
58
65
MatchType .snippet -> {
59
- val file = requireNotNull(details.file)
60
- val lines = requireNotNull(details.lines)
61
- val sourceLocations = convertLines(file, lines)
62
- val snippets = getSnippets(details)
63
-
64
- snippets.forEach { snippet ->
65
- sourceLocations.forEach { sourceLocation ->
66
- // TODO: Aggregate the snippet by source file location.
67
- snippetFindings + = SnippetFinding (sourceLocation, setOf (snippet))
66
+ val file = requireNotNull(result.filePath)
67
+ if (details.status == StatusType .pending) {
68
+ val lines = requireNotNull(details.lines)
69
+ val sourceLocations = convertLines(file, lines)
70
+ val snippets = getSnippets(details)
71
+
72
+ if (sourceLocations.size != snippets.size) {
73
+ logger.warn(" number of local line ranges does not match with oss lines on file '$file '" )
68
74
}
75
+
76
+ for (i in 0 until min(sourceLocations.size, snippets.size)) {
77
+ snippetFindings + = SnippetFinding (sourceLocations[i], setOf (snippets[i]))
78
+ }
79
+ } else {
80
+ logger.warn(" file '$file ' is identified, not including on snippet findings" )
81
+ licenseFindings + = getLicenseFindings(details)
82
+ copyrightFindings + = getCopyrightFindings(details)
69
83
}
70
84
}
71
85
@@ -84,7 +98,6 @@ internal fun generateSummary(startTime: Instant, endTime: Instant, results: List
84
98
licenseFindings = licenseFindings,
85
99
copyrightFindings = copyrightFindings,
86
100
snippetFindings = snippetFindings
87
-
88
101
)
89
102
}
90
103
@@ -138,16 +151,14 @@ private fun getCopyrightFindings(details: ScanFileDetails): List<CopyrightFindin
138
151
* Get the snippet findings from the given [details]. If a snippet returned by ScanOSS contains several Purls,
139
152
* several snippets are created in ORT each containing a single Purl.
140
153
*/
141
- private fun getSnippets (details : ScanFileDetails ): Set <Snippet > {
154
+ private fun getSnippets (details : ScanFileDetails ): List <Snippet > {
142
155
val matched = requireNotNull(details.matched)
143
156
val fileUrl = requireNotNull(details.fileUrl)
144
157
val ossLines = requireNotNull(details.ossLines)
145
158
val url = requireNotNull(details.url)
146
159
val purls = requireNotNull(details.purls)
147
160
148
- val licenses = details.licenseDetails.orEmpty().mapTo(mutableSetOf ()) { license ->
149
- SpdxExpression .parse(license.name)
150
- }
161
+ val license = getUniqueLicenseExpression(details.licenseDetails)
151
162
152
163
val score = matched.substringBeforeLast(" %" ).toFloat()
153
164
val locations = convertLines(fileUrl, ossLines)
@@ -157,11 +168,9 @@ private fun getSnippets(details: ScanFileDetails): Set<Snippet> {
157
168
158
169
val additionalData = mapOf (" release_date" to details.releaseDate)
159
170
160
- return buildSet {
171
+ return buildList {
161
172
purls.forEach { purl ->
162
173
locations.forEach { snippetLocation ->
163
- val license = licenses.andOrNull()?.sorted() ? : SpdxLicenseIdExpression (SpdxConstants .NOASSERTION )
164
-
165
174
add(Snippet (score, snippetLocation, provenance, purl, license, additionalData))
166
175
}
167
176
}
@@ -181,3 +190,14 @@ private fun convertLines(file: String, lineRanges: String): List<TextLocation> =
181
190
else -> throw IllegalArgumentException (" Unsupported line range '$lineRange '." )
182
191
}
183
192
}
193
+
194
+ fun getUniqueLicenseExpression (licensesDetails : Array <LicenseDetails >): SpdxExpression {
195
+ if (licensesDetails.isEmpty()) {
196
+ return SpdxLicenseIdExpression (SpdxConstants .NOASSERTION )
197
+ }
198
+
199
+ return licensesDetails
200
+ .map { license -> SpdxExpression .parse(license.name) }
201
+ .reduce { acc, expr -> acc.and (expr) }
202
+ .simplify()
203
+ }
0 commit comments