From 831b113343eab1482149e7a5ca6779c7230c4c11 Mon Sep 17 00:00:00 2001 From: Sebastian Schuberth Date: Fri, 11 Oct 2024 13:45:14 +0200 Subject: [PATCH] refactor(pub): Port the lockfile parsing to KxS Signed-off-by: Frank Viernau Signed-off-by: Sebastian Schuberth --- plugins/package-managers/pub/build.gradle.kts | 3 - .../pub/src/main/kotlin/Lockfile.kt | 67 +++++++++++++------ .../pub/src/main/kotlin/Pub.kt | 10 ++- 3 files changed, 50 insertions(+), 30 deletions(-) diff --git a/plugins/package-managers/pub/build.gradle.kts b/plugins/package-managers/pub/build.gradle.kts index 89cab4ad17341..0485ab2099244 100644 --- a/plugins/package-managers/pub/build.gradle.kts +++ b/plugins/package-managers/pub/build.gradle.kts @@ -40,9 +40,6 @@ dependencies { implementation(projects.utils.ortUtils) implementation(projects.utils.spdxUtils) - implementation(libs.jackson.databind) - implementation(libs.jackson.dataformat.yaml) - implementation(libs.jackson.module.kotlin) implementation(libs.kotlinx.serialization.core) implementation(libs.kotlinx.serialization.yaml) diff --git a/plugins/package-managers/pub/src/main/kotlin/Lockfile.kt b/plugins/package-managers/pub/src/main/kotlin/Lockfile.kt index 1af05c8098548..166e8e3eee14e 100644 --- a/plugins/package-managers/pub/src/main/kotlin/Lockfile.kt +++ b/plugins/package-managers/pub/src/main/kotlin/Lockfile.kt @@ -19,25 +19,36 @@ package org.ossreviewtoolkit.plugins.packagemanagers.pub -import com.fasterxml.jackson.annotation.JsonIgnoreProperties -import com.fasterxml.jackson.annotation.JsonProperty -import com.fasterxml.jackson.core.JsonParser -import com.fasterxml.jackson.databind.DeserializationContext -import com.fasterxml.jackson.databind.annotation.JsonDeserialize -import com.fasterxml.jackson.databind.deser.std.StdDeserializer -import com.fasterxml.jackson.module.kotlin.readValue +import com.charleskorn.kaml.Yaml +import com.charleskorn.kaml.YamlConfiguration +import com.charleskorn.kaml.YamlInput +import com.charleskorn.kaml.YamlScalar import java.io.File -import org.ossreviewtoolkit.model.yamlMapper +import kotlinx.serialization.InternalSerializationApi +import kotlinx.serialization.KSerializer +import kotlinx.serialization.KeepGeneratedSerializer +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.decodeFromString +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.descriptors.SerialKind +import kotlinx.serialization.descriptors.buildSerialDescriptor +import kotlinx.serialization.encoding.Decoder + import org.ossreviewtoolkit.plugins.packagemanagers.pub.PackageInfo.Description -internal fun parseLockfile(lockfile: File) = yamlMapper.readValue(lockfile) +private val YAML = Yaml(configuration = YamlConfiguration(strictMode = false)) + +internal fun parseLockfile(lockfile: File) = YAML.decodeFromString(lockfile.readText()) /** * See https://github.com/dart-lang/pub/blob/d86e3c979a3889fed61b68dae9f9156d0891704d/lib/src/lock_file.dart#L18. */ -@JsonIgnoreProperties(ignoreUnknown = true) +@Serializable internal data class Lockfile( val packages: Map = emptyMap() ) @@ -45,33 +56,47 @@ internal data class Lockfile( /** * See https://github.com/dart-lang/pub/blob/d86e3c979a3889fed61b68dae9f9156d0891704d/lib/src/package_name.dart#L73. */ -@JsonIgnoreProperties(ignoreUnknown = true) +@Serializable internal data class PackageInfo( val dependency: String, - @JsonDeserialize(using = DescriptionDeserializer::class) val description: Description, val source: String? = null, val version: String? = null ) { - @JsonIgnoreProperties(ignoreUnknown = true) + @KeepGeneratedSerializer + @Serializable(DescriptionDeserializer::class) data class Description( val name: String? = null, val url: String? = null, val path: String? = null, - @JsonProperty("resolved-ref") + @SerialName("resolved-ref") val resolvedRef: String? = null, val relative: Boolean? = null, val sha256: String? = null ) } -internal class DescriptionDeserializer : StdDeserializer(Description::class.java) { - override fun deserialize(parser: JsonParser, context: DeserializationContext): Description { - val node = context.readTree(parser) - return if (node.isTextual) { - Description(name = node.textValue()) - } else { - parser.codec.readValue(node.traverse(), Description::class.java) +private class DescriptionDeserializer : KSerializer by Description.generatedSerializer() { + @OptIn(InternalSerializationApi::class) + override val descriptor: SerialDescriptor by lazy { + val serialName = checkNotNull(Description::class.qualifiedName) + + buildSerialDescriptor(serialName, SerialKind.CONTEXTUAL) { + element("object", Description.generatedSerializer().descriptor) + element("string", PrimitiveSerialDescriptor("description", PrimitiveKind.STRING)) } } + + override fun deserialize(decoder: Decoder): Description { + val input = decoder.beginStructure(descriptor) as YamlInput + + val result = when (val node = input.node) { + is YamlScalar -> Description(name = node.content) + else -> Description.generatedSerializer().deserialize(decoder) + } + + input.endStructure(descriptor) + + return result + } } diff --git a/plugins/package-managers/pub/src/main/kotlin/Pub.kt b/plugins/package-managers/pub/src/main/kotlin/Pub.kt index 2b8aa40f52d7a..805e8beac19e3 100644 --- a/plugins/package-managers/pub/src/main/kotlin/Pub.kt +++ b/plugins/package-managers/pub/src/main/kotlin/Pub.kt @@ -19,8 +19,6 @@ package org.ossreviewtoolkit.plugins.packagemanagers.pub -import com.fasterxml.jackson.dataformat.yaml.JacksonYAMLParseException - import java.io.File import java.io.IOException @@ -535,7 +533,7 @@ class Pub( var containsFlutter = false lockfile.packages.forEach { (packageName, packageInfo) -> - try { + runCatching { val version = packageInfo.version.orEmpty() var description = "" var rawName = "" @@ -646,14 +644,14 @@ class Pub( vcs = vcs, vcsProcessed = processPackageVcs(vcs, homepageUrl) ) - } catch (e: JacksonYAMLParseException) { - e.showStackTrace() + }.onFailure { + it.showStackTrace() val packageVersion = packageInfo.version issues += createAndLogIssue( source = managerName, message = "Failed to parse $PUBSPEC_YAML for package $packageName:$packageVersion: " + - e.collectMessages() + it.collectMessages() ) } }