Skip to content

Commit

Permalink
feat(scanoss): Map ScanOSS snippets to the ScanSummary
Browse files Browse the repository at this point in the history
This commits maps the snippets in a ScanOSS response using the
newly-created snippet data model.

Please note that the snippet's license in the test data file has been
manipulated to be a license not present in the other identifications
of this file. This allows to demonstrate that license findings and
snippet findings are disjoint in ORT, even if they are returned together
by ScanOSS.

Signed-off-by: Nicolas Nobelis <nicolas.nobelis@bosch.io>
  • Loading branch information
nnobelis committed Apr 24, 2023
1 parent 33975d4 commit 09f2b20
Show file tree
Hide file tree
Showing 4 changed files with 564 additions and 10 deletions.
68 changes: 66 additions & 2 deletions scanner/src/main/kotlin/scanners/scanoss/ScanOssResultParser.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,17 @@ import java.io.File
import java.time.Instant

import org.ossreviewtoolkit.clients.scanoss.FullScanResponse
import org.ossreviewtoolkit.clients.scanoss.model.IdentificationType
import org.ossreviewtoolkit.clients.scanoss.model.ScanResponse
import org.ossreviewtoolkit.model.CopyrightFinding
import org.ossreviewtoolkit.model.LicenseFinding
import org.ossreviewtoolkit.model.RepositoryProvenance
import org.ossreviewtoolkit.model.ScanSummary
import org.ossreviewtoolkit.model.TextLocation
import org.ossreviewtoolkit.model.VcsInfo
import org.ossreviewtoolkit.model.VcsType
import org.ossreviewtoolkit.model.utils.Snippet
import org.ossreviewtoolkit.model.utils.SnippetFinding
import org.ossreviewtoolkit.utils.spdx.SpdxConstants
import org.ossreviewtoolkit.utils.spdx.SpdxExpression
import org.ossreviewtoolkit.utils.spdx.calculatePackageVerificationCode
Expand Down Expand Up @@ -64,11 +70,25 @@ internal fun generateSummary(
): ScanSummary {
val licenseFindings = mutableListOf<LicenseFinding>()
val copyrightFindings = mutableListOf<CopyrightFinding>()
val snippetFindings = mutableSetOf<SnippetFinding>()

result.forEach { (_, scanResponses) ->
scanResponses.forEach { scanResponse ->
licenseFindings += getLicenseFindings(scanResponse, detectedLicenseMapping)
copyrightFindings += getCopyrightFindings(scanResponse)
if (scanResponse.id == IdentificationType.FILE) {
licenseFindings += getLicenseFindings(scanResponse, detectedLicenseMapping)
copyrightFindings += getCopyrightFindings(scanResponse)
}

if (scanResponse.id == IdentificationType.SNIPPET) {
val file = requireNotNull(scanResponse.file)
val lines = requireNotNull(scanResponse.lines)
val sourceLocation = convertLines(file, lines)
val snippets = getSnippets(scanResponse)

snippets.forEach {
snippetFindings += SnippetFinding(sourceLocation, it)
}
}
}
}

Expand All @@ -78,6 +98,7 @@ internal fun generateSummary(
packageVerificationCode = verificationCode,
licenseFindings = licenseFindings.toSortedSet(),
copyrightFindings = copyrightFindings.toSortedSet(),
snippetFindings = snippetFindings.toSortedSet(),
issues = emptyList()
)
}
Expand Down Expand Up @@ -131,3 +152,46 @@ private fun getCopyrightFindings(scanResponse: ScanResponse): List<CopyrightFind
)
}
}

/**
* Get the snippet findings from the given [scanResponse]. If a snippet returned by ScanOSS contains several Purls,
* several snippets are created in ORT each containing a single Purl.
*/
private fun getSnippets(scanResponse: ScanResponse): Set<Snippet> {
val matched = requireNotNull(scanResponse.matched)
val fileUrl = requireNotNull(scanResponse.fileUrl)
val ossLines = requireNotNull(scanResponse.ossLines)
val url = requireNotNull(scanResponse.url)
val purls = requireNotNull(scanResponse.purl)

val licenses = scanResponse.licenses.map { license ->
SpdxExpression.parse(license.name)
}.toSet()

val score = matched.substringBeforeLast("%").toFloat()
val snippetLocation = convertLines(fileUrl, ossLines)
// TODO: No resolved revision is available. Should a ArtifactProvenance be created instead ?
val snippetProvenance = RepositoryProvenance(VcsInfo(VcsType.UNKNOWN, url, ""), ".")

return purls.map {
Snippet(
score,
snippetLocation,
snippetProvenance,
it,
licenses.distinct().reduce(SpdxExpression::and).sorted()
)
}.toSortedSet()
}

/**
* Split a [lineRange] returned by ScanOSS such as 1-321 into a [TextLocation] for the given [file].
*/
private fun convertLines(file: String, lineRange: String): TextLocation {
val splitLines = lineRange.split("-")
return if (splitLines.size == 2) {
TextLocation(file, splitLines.first().toInt(), splitLines.last().toInt())
} else {
TextLocation(file, splitLines.first().toInt())
}
}
Loading

0 comments on commit 09f2b20

Please sign in to comment.