pkl-config-java: Migrate nullness to jSpecify (#1528)

This commit is contained in:
odenix
2026-04-17 16:56:12 +01:00
committed by GitHub
parent 2dd0e2de21
commit 1571d72111
29 changed files with 113 additions and 80 deletions
+24 -4
View File
@@ -22,13 +22,30 @@ com.github.ajalt.mordant:mordant-markdown-jvm:3.0.1=pklCodegenJava
com.github.ajalt.mordant:mordant-markdown:3.0.1=pklCodegenJava com.github.ajalt.mordant:mordant-markdown:3.0.1=pklCodegenJava
com.github.ajalt.mordant:mordant:3.0.1=pklCodegenJava com.github.ajalt.mordant:mordant:3.0.1=pklCodegenJava
com.github.ben-manes.caffeine:caffeine:2.9.3=swiftExportClasspathResolvable com.github.ben-manes.caffeine:caffeine:2.9.3=swiftExportClasspathResolvable
com.github.ben-manes.caffeine:caffeine:3.0.5=annotationProcessor,testAnnotationProcessor
com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,testAnnotationProcessor
com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,testAnnotationProcessor
com.google.auto.value:auto-value-annotations:1.9=annotationProcessor,testAnnotationProcessor
com.google.auto:auto-common:1.2.2=annotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_annotation:2.48.0=annotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_annotations:2.28.0=swiftExportClasspathResolvable com.google.errorprone:error_prone_annotations:2.28.0=swiftExportClasspathResolvable
com.google.errorprone:error_prone_annotations:2.48.0=annotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_check_api:2.48.0=annotationProcessor,testAnnotationProcessor
com.google.errorprone:error_prone_core:2.48.0=annotationProcessor,testAnnotationProcessor
com.google.googlejavaformat:google-java-format:1.34.1=annotationProcessor,testAnnotationProcessor
com.google.guava:failureaccess:1.0.3=annotationProcessor,testAnnotationProcessor
com.google.guava:guava:33.5.0-jre=annotationProcessor,testAnnotationProcessor
com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,testAnnotationProcessor
com.google.j2objc:j2objc-annotations:3.1=annotationProcessor,testAnnotationProcessor
com.google.protobuf:protobuf-java:4.33.2=annotationProcessor,testAnnotationProcessor
com.palantir.javapoet:javapoet:0.14.0=pklCodegenJava com.palantir.javapoet:javapoet:0.14.0=pklCodegenJava
io.github.java-diff-utils:java-diff-utils:4.12=kotlinInternalAbiValidation com.uber.nullaway:nullaway:0.13.1=annotationProcessor,testAnnotationProcessor
io.github.eisop:dataflow-errorprone:3.41.0-eisop1=annotationProcessor,testAnnotationProcessor
io.github.java-diff-utils:java-diff-utils:4.12=annotationProcessor,kotlinInternalAbiValidation,testAnnotationProcessor
io.leangen.geantyref:geantyref:1.3.16=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath io.leangen.geantyref:geantyref:1.3.16=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
io.opentelemetry:opentelemetry-api:1.41.0=swiftExportClasspathResolvable io.opentelemetry:opentelemetry-api:1.41.0=swiftExportClasspathResolvable
io.opentelemetry:opentelemetry-context:1.41.0=swiftExportClasspathResolvable io.opentelemetry:opentelemetry-context:1.41.0=swiftExportClasspathResolvable
javax.inject:javax.inject:1=testCompileClasspath,testRuntimeClasspath javax.inject:javax.inject:1=annotationProcessor,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
net.bytebuddy:byte-buddy:1.18.3=testCompileClasspath,testRuntimeClasspath net.bytebuddy:byte-buddy:1.18.3=testCompileClasspath,testRuntimeClasspath
net.java.dev.jna:jna:5.14.0=pklCodegenJava net.java.dev.jna:jna:5.14.0=pklCodegenJava
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
@@ -38,6 +55,8 @@ org.bouncycastle:bcpkix-jdk18on:1.80=kotlinBouncyCastleConfiguration
org.bouncycastle:bcprov-jdk18on:1.80=kotlinBouncyCastleConfiguration org.bouncycastle:bcprov-jdk18on:1.80=kotlinBouncyCastleConfiguration
org.bouncycastle:bcutil-jdk18on:1.80=kotlinBouncyCastleConfiguration org.bouncycastle:bcutil-jdk18on:1.80=kotlinBouncyCastleConfiguration
org.checkerframework:checker-qual:3.43.0=swiftExportClasspathResolvable org.checkerframework:checker-qual:3.43.0=swiftExportClasspathResolvable
org.checkerframework:checker-qual:3.53.0=annotationProcessor,testAnnotationProcessor
org.checkerframework:dataflow-nullaway:3.53.0=annotationProcessor,testAnnotationProcessor
org.graalvm.polyglot:polyglot:25.0.1=pklCodegenJava,runtimeClasspath,testRuntimeClasspath org.graalvm.polyglot:polyglot:25.0.1=pklCodegenJava,runtimeClasspath,testRuntimeClasspath
org.graalvm.sdk:collections:25.0.1=pklCodegenJava,runtimeClasspath,testRuntimeClasspath org.graalvm.sdk:collections:25.0.1=pklCodegenJava,runtimeClasspath,testRuntimeClasspath
org.graalvm.sdk:graal-sdk:25.0.1=pklCodegenJava,runtimeClasspath,testRuntimeClasspath org.graalvm.sdk:graal-sdk:25.0.1=pklCodegenJava,runtimeClasspath,testRuntimeClasspath
@@ -79,7 +98,7 @@ org.jetbrains.kotlinx:kotlinx-serialization-core:1.7.3=swiftExportClasspathResol
org.jetbrains:annotations:13.0=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinInternalAbiValidation,kotlinKlibCommonizerClasspath,pklCodegenJava,swiftExportClasspathResolvable,testCompileClasspath,testRuntimeClasspath org.jetbrains:annotations:13.0=kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinInternalAbiValidation,kotlinKlibCommonizerClasspath,pklCodegenJava,swiftExportClasspathResolvable,testCompileClasspath,testRuntimeClasspath
org.jetbrains:markdown-jvm:0.7.3=pklCodegenJava org.jetbrains:markdown-jvm:0.7.3=pklCodegenJava
org.jetbrains:markdown:0.7.3=pklCodegenJava org.jetbrains:markdown:0.7.3=pklCodegenJava
org.jspecify:jspecify:1.0.0=pklCodegenJava,runtimeClasspath,testCompileClasspath,testRuntimeClasspath org.jspecify:jspecify:1.0.0=annotationProcessor,compileClasspath,pklCodegenJava,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-api:6.0.3=testCompileClasspath,testRuntimeClasspath org.junit.jupiter:junit-jupiter-api:6.0.3=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-engine:6.0.3=testRuntimeClasspath org.junit.jupiter:junit-jupiter-engine:6.0.3=testRuntimeClasspath
org.junit.jupiter:junit-jupiter-params:6.0.3=testCompileClasspath,testRuntimeClasspath org.junit.jupiter:junit-jupiter-params:6.0.3=testCompileClasspath,testRuntimeClasspath
@@ -90,5 +109,6 @@ org.junit:junit-bom:6.0.3=testCompileClasspath,testRuntimeClasspath
org.msgpack:msgpack-core:0.9.11=compileClasspath,pklCodegenJava,runtimeClasspath,testCompileClasspath,testRuntimeClasspath org.msgpack:msgpack-core:0.9.11=compileClasspath,pklCodegenJava,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
org.organicdesign:Paguro:3.10.3=pklCodegenJava,runtimeClasspath,testRuntimeClasspath org.organicdesign:Paguro:3.10.3=pklCodegenJava,runtimeClasspath,testRuntimeClasspath
org.pcollections:pcollections:4.0.1=annotationProcessor,testAnnotationProcessor
org.snakeyaml:snakeyaml-engine:2.10=pklCodegenJava,runtimeClasspath,testRuntimeClasspath org.snakeyaml:snakeyaml-engine:2.10=pklCodegenJava,runtimeClasspath,testRuntimeClasspath
empty=annotationProcessor,apiDependenciesMetadata,compileOnlyDependenciesMetadata,fatJar,firstPartySourcesJars,implementationDependenciesMetadata,intransitiveDependenciesMetadata,kotlinCompilerPluginClasspath,kotlinNativeCompilerPluginClasspath,kotlinScriptDefExtensions,shadow,signatures,sourcesJar,testAnnotationProcessor,testApiDependenciesMetadata,testCompileOnlyDependenciesMetadata,testImplementationDependenciesMetadata,testIntransitiveDependenciesMetadata,testKotlinScriptDefExtensions empty=apiDependenciesMetadata,compileOnlyDependenciesMetadata,fatJar,firstPartySourcesJars,implementationDependenciesMetadata,intransitiveDependenciesMetadata,kotlinCompilerPluginClasspath,kotlinNativeCompilerPluginClasspath,kotlinScriptDefExtensions,shadow,signatures,sourcesJar,testApiDependenciesMetadata,testCompileOnlyDependenciesMetadata,testImplementationDependenciesMetadata,testIntransitiveDependenciesMetadata,testKotlinScriptDefExtensions
@@ -18,6 +18,7 @@ plugins {
id("pklJavaLibrary") id("pklJavaLibrary")
id("pklFatJar") id("pklFatJar")
id("pklPublishLibrary") id("pklPublishLibrary")
id("pklJSpecify")
signing signing
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@ package org.pkl.config.java;
import java.io.InputStream; import java.io.InputStream;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.Map; import java.util.Map;
import org.jspecify.annotations.Nullable;
import org.pkl.config.java.mapper.ConversionException; import org.pkl.config.java.mapper.ConversionException;
import org.pkl.config.java.mapper.ValueMapper; import org.pkl.config.java.mapper.ValueMapper;
import org.pkl.core.Composite; import org.pkl.core.Composite;
@@ -55,7 +56,7 @@ public interface Config {
* *
* @throws ConversionException if the value cannot be converted to the given type * @throws ConversionException if the value cannot be converted to the given type
*/ */
<T> T as(Class<T> type); <T extends @Nullable Object> T as(Class<T> type);
/** /**
* Converts this node's value to the given {@link Type}. * Converts this node's value to the given {@link Type}.
@@ -64,14 +65,14 @@ public interface Config {
* *
* @throws ConversionException if the value cannot be converted to the given type * @throws ConversionException if the value cannot be converted to the given type
*/ */
<T> T as(Type type); <T extends @Nullable Object> T as(Type type);
/** /**
* Converts this node's value to the given {@link JavaType}. * Converts this node's value to the given {@link JavaType}.
* *
* @throws ConversionException if the value cannot be converted to the given type * @throws ConversionException if the value cannot be converted to the given type
*/ */
<T> T as(JavaType<T> type); <T extends @Nullable Object> T as(JavaType<T> type);
/** /**
* Decode a config from the supplied byte array. * Decode a config from the supplied byte array.
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@ import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.jspecify.annotations.Nullable;
import org.pkl.config.java.mapper.ValueMapperBuilder; import org.pkl.config.java.mapper.ValueMapperBuilder;
import org.pkl.core.EvaluatorBuilder; import org.pkl.core.EvaluatorBuilder;
import org.pkl.core.SecurityManager; import org.pkl.core.SecurityManager;
@@ -28,7 +29,6 @@ import org.pkl.core.StackFrameTransformer;
import org.pkl.core.http.HttpClient; import org.pkl.core.http.HttpClient;
import org.pkl.core.project.DeclaredDependencies; import org.pkl.core.project.DeclaredDependencies;
import org.pkl.core.project.Project; import org.pkl.core.project.Project;
import org.pkl.core.util.Nullable;
/** A builder for {@link ConfigEvaluator}s. */ /** A builder for {@link ConfigEvaluator}s. */
@SuppressWarnings({"UnusedReturnValue", "unused"}) @SuppressWarnings({"UnusedReturnValue", "unused"})
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -18,9 +18,9 @@ package org.pkl.config.java;
import java.lang.reflect.ParameterizedType; import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.*; import java.util.*;
import org.jspecify.annotations.Nullable;
import org.pkl.config.java.mapper.Types; import org.pkl.config.java.mapper.Types;
import org.pkl.core.Pair; import org.pkl.core.Pair;
import org.pkl.core.util.Nullable;
/** /**
* Runtime representation of a possibly parameterized Java type. Factory methods are provided to * Runtime representation of a possibly parameterized Java type. Factory methods are provided to
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -20,10 +20,10 @@ import java.io.UncheckedIOException;
import java.util.HashSet; import java.util.HashSet;
import java.util.Properties; import java.util.Properties;
import java.util.Set; import java.util.Set;
import org.jspecify.annotations.Nullable;
import org.pkl.config.java.InvalidMappingException; import org.pkl.config.java.InvalidMappingException;
import org.pkl.core.PClassInfo; import org.pkl.core.PClassInfo;
import org.pkl.core.util.IoUtils; import org.pkl.core.util.IoUtils;
import org.pkl.core.util.Nullable;
/** /**
* Describes mappings of Pkl class names to their corresponding Java classes. * Describes mappings of Pkl class names to their corresponding Java classes.
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -15,13 +15,15 @@
*/ */
package org.pkl.config.java.mapper; package org.pkl.config.java.mapper;
import org.jspecify.annotations.Nullable;
/** Thrown when a {@link ValueMapper} conversion fails. */ /** Thrown when a {@link ValueMapper} conversion fails. */
public class ConversionException extends RuntimeException { public class ConversionException extends RuntimeException {
public ConversionException(String message) { public ConversionException(String message) {
super(message); super(message);
} }
public ConversionException(String message, Throwable cause) { public ConversionException(String message, @Nullable Throwable cause) {
super(message, cause); super(message, cause);
} }
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -15,6 +15,8 @@
*/ */
package org.pkl.config.java.mapper; package org.pkl.config.java.mapper;
import org.jspecify.annotations.Nullable;
/** /**
* Converter for a particular source and target type. * Converter for a particular source and target type.
* *
@@ -22,7 +24,7 @@ package org.pkl.config.java.mapper;
* @param <T> the converter's target type * @param <T> the converter's target type
*/ */
@FunctionalInterface @FunctionalInterface
public interface Converter<S, T> { public interface Converter<S, T extends @Nullable Object> {
/** /**
* Converts the given value. The given {@link ValueMapper} can be used to convert nested values of * Converts the given value. The given {@link ValueMapper} can be used to convert nested values of
* composite values (objects, collections, etc.). * composite values (objects, collections, etc.).
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -19,8 +19,8 @@ import java.lang.reflect.Array;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.Collection; import java.util.Collection;
import java.util.Optional; import java.util.Optional;
import org.jspecify.annotations.Nullable;
import org.pkl.core.PClassInfo; import org.pkl.core.PClassInfo;
import org.pkl.core.util.Nullable;
final class PCollectionToArray implements ConverterFactory { final class PCollectionToArray implements ConverterFactory {
@Override @Override
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -23,8 +23,8 @@ import java.lang.reflect.Type;
import java.util.Collection; import java.util.Collection;
import java.util.Optional; import java.util.Optional;
import java.util.function.Function; import java.util.function.Function;
import org.jspecify.annotations.Nullable;
import org.pkl.core.PClassInfo; import org.pkl.core.PClassInfo;
import org.pkl.core.util.Nullable;
class PCollectionToCollection implements ConverterFactory { class PCollectionToCollection implements ConverterFactory {
private static final Lookup lookup = MethodHandles.lookup(); private static final Lookup lookup = MethodHandles.lookup();
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -24,8 +24,8 @@ import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Properties; import java.util.Properties;
import java.util.function.Function; import java.util.function.Function;
import org.jspecify.annotations.Nullable;
import org.pkl.core.PClassInfo; import org.pkl.core.PClassInfo;
import org.pkl.core.util.Nullable;
class PMapToMap implements ConverterFactory { class PMapToMap implements ConverterFactory {
private static final Lookup lookup = MethodHandles.lookup(); private static final Lookup lookup = MethodHandles.lookup();
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -22,10 +22,10 @@ import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup; import java.lang.invoke.MethodHandles.Lookup;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.util.*; import java.util.*;
import org.jspecify.annotations.Nullable;
import org.pkl.core.Composite; import org.pkl.core.Composite;
import org.pkl.core.PClassInfo; import org.pkl.core.PClassInfo;
import org.pkl.core.PObject; import org.pkl.core.PObject;
import org.pkl.core.util.Nullable;
public class PObjectToDataObject implements ConverterFactory { public class PObjectToDataObject implements ConverterFactory {
private static final Lookup lookup = MethodHandles.lookup(); private static final Lookup lookup = MethodHandles.lookup();
@@ -156,7 +156,7 @@ public class PObjectToDataObject implements ConverterFactory {
private final MethodHandle constructorHandle; private final MethodHandle constructorHandle;
private final Collection<Tuple2<String, Type>> parameters; private final Collection<Tuple2<String, Type>> parameters;
private final PClassInfo<Object>[] cachedPropertyTypes; private final PClassInfo<Object>[] cachedPropertyTypes;
private final Converter<Object, T>[] cachedConverters; private final @Nullable Converter<Object, T>[] cachedConverters;
ConverterImpl( ConverterImpl(
Type targetType, Type targetType,
@@ -172,7 +172,7 @@ public class PObjectToDataObject implements ConverterFactory {
Arrays.fill(cachedPropertyTypes, PClassInfo.Unavailable); Arrays.fill(cachedPropertyTypes, PClassInfo.Unavailable);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Converter<Object, T>[] cachedConverters = new Converter[parameters.size()]; @Nullable Converter<Object, T>[] cachedConverters = new Converter[parameters.size()];
this.cachedConverters = cachedConverters; this.cachedConverters = cachedConverters;
} }
@@ -203,8 +203,9 @@ public class PObjectToDataObject implements ConverterFactory {
cachedPropertyTypes[i] = cachedPropertyType; cachedPropertyTypes[i] = cachedPropertyType;
cachedConverters[i] = valueMapper.getConverter(cachedPropertyType, param.second); cachedConverters[i] = valueMapper.getConverter(cachedPropertyType, param.second);
} }
assert cachedConverters[i] != null; var cachedConverter = cachedConverters[i];
args[i] = cachedConverters[i].convert(property, valueMapper); assert cachedConverter != null;
args[i] = cachedConverter.convert(property, valueMapper);
i += 1; i += 1;
} catch (ConversionException e) { } catch (ConversionException e) {
throw new ConversionException( throw new ConversionException(
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -18,9 +18,9 @@ package org.pkl.config.java.mapper;
import java.lang.reflect.ParameterizedType; import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.Optional; import java.util.Optional;
import org.jspecify.annotations.Nullable;
import org.pkl.core.PClassInfo; import org.pkl.core.PClassInfo;
import org.pkl.core.Pair; import org.pkl.core.Pair;
import org.pkl.core.util.Nullable;
final class PPairToPair implements ConverterFactory { final class PPairToPair implements ConverterFactory {
@Override @Override
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -46,12 +46,16 @@ final class PStringToEnum implements ConverterFactory {
if (enumType == DataSizeUnit.class) { if (enumType == DataSizeUnit.class) {
for (var value : values) { for (var value : values) {
var unit = (DataSizeUnit) value; var unit = (DataSizeUnit) value;
enumValuesByName.put(CodeGeneratorUtils.toEnumConstantName(unit.getSymbol()), value); var name = CodeGeneratorUtils.toEnumConstantName(unit.getSymbol());
assert name != null;
enumValuesByName.put(name, value);
} }
} else if (enumType == DurationUnit.class) { } else if (enumType == DurationUnit.class) {
for (var value : values) { for (var value : values) {
var unit = (DurationUnit) value; var unit = (DurationUnit) value;
enumValuesByName.put(CodeGeneratorUtils.toEnumConstantName(unit.getSymbol()), value); var name = CodeGeneratorUtils.toEnumConstantName(unit.getSymbol());
assert name != null;
enumValuesByName.put(name, value);
} }
} else { } else {
for (Enum<?> value : values) { for (Enum<?> value : values) {
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@ import static java.util.Arrays.stream;
import io.leangen.geantyref.CaptureType; import io.leangen.geantyref.CaptureType;
import io.leangen.geantyref.GenericTypeReflector; import io.leangen.geantyref.GenericTypeReflector;
import java.lang.reflect.*; import java.lang.reflect.*;
import org.pkl.core.util.Nullable; import org.jspecify.annotations.Nullable;
/** /**
* Reflection utilities for implementing {@link ConverterFactory}s. Mostly covers introspection of * Reflection utilities for implementing {@link ConverterFactory}s. Mostly covers introspection of
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -16,7 +16,7 @@
package org.pkl.config.java.mapper; package org.pkl.config.java.mapper;
import java.util.Objects; import java.util.Objects;
import org.pkl.core.util.Nullable; import org.jspecify.annotations.Nullable;
// avoid name clash with org.pkl.core.Pair // avoid name clash with org.pkl.core.Pair
final class Tuple2<S, T> { final class Tuple2<S, T> {
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -16,7 +16,7 @@
package org.pkl.config.java.mapper; package org.pkl.config.java.mapper;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import org.pkl.core.util.Nullable; import org.jspecify.annotations.Nullable;
/** /**
* Maps a type requested during conversion to the implementation type to be instantiated. The * Maps a type requested during conversion to the implementation type to be instantiated. The
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
package org.pkl.config.java.mapper; package org.pkl.config.java.mapper;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import org.jspecify.annotations.Nullable;
import org.pkl.core.PClassInfo; import org.pkl.core.PClassInfo;
import org.pkl.core.PModule; import org.pkl.core.PModule;
@@ -30,38 +31,40 @@ public interface ValueMapper {
} }
/** /**
* Converts the given Pkl object to the given Java target type. The Pkl object can be an entire * Converts the given Pkl value to the given Java target type. The Pkl value can be an entire
* {@link PModule} or any value contained therein. See {@link PClassInfo#forValue} for which Java * {@link PModule} or any value contained therein. See {@link PClassInfo#forValue} for which Java
* types are used to represent Pkl objects. * types are used to represent Pkl values.
* *
* <p>When mapping to a generic target type, a fully parameterized type needs to be passed, e.g. * <p>When mapping to a generic target type, a fully parameterized type needs to be passed, e.g.
* {@code List<String>}. Parameterized type literals can be created using {@link Types}, e.g. * {@code List<String>}. Parameterized type literals can be created using {@link Types}, e.g.
* {@code Types.listOf(String.class)}. * {@code Types.listOf(String.class)}.
* *
* <p>If an error occurs during conversion, or if {@link ValueMapper} does not know how to convert * <p>If an error occurs during conversion, or if {@link ValueMapper} does not know how to convert
* from the given object to the given target type, a {@link ConversionException} is thrown. * from the given Pkl value to the given target type, a {@link ConversionException} is thrown.
*/ */
<S, T> T map(S model, Type targetType); <S, T extends @Nullable Object> T map(S value, Type targetType);
/** /**
* Same as {@link #map(Object, Type)}, except that the target type is narrowed from {@link Type} * Same as {@link #map(Object, Type)}, except that the target type is narrowed from {@link Type}
* to {@link Class} to allow for better type inference. * to {@link Class} to allow for better type inference.
*/ */
default <S, T> T map(S model, Class<T> targetType) { default <S, T extends @Nullable Object> T map(S value, Class<T> targetType) {
return map(model, (Type) targetType); return map(value, (Type) targetType);
} }
/** /**
* Returns the converter with the given source and target types. Throws {@link * Returns the converter with the given source and target types. Throws {@link
* ConversionException} if no such converter exists. * ConversionException} if no such converter exists.
*/ */
<S, T> Converter<S, T> getConverter(PClassInfo<S> sourceType, Type targetType); <S, T extends @Nullable Object> Converter<S, T> getConverter(
PClassInfo<S> sourceType, Type targetType);
/** /**
* Same as {@link #getConverter(PClassInfo, Type)}, except that the target type is narrowed from * Same as {@link #getConverter(PClassInfo, Type)}, except that the target type is narrowed from
* {@link Type} to {@link Class} to allow for better type inference. * {@link Type} to {@link Class} to allow for better type inference.
*/ */
default <S, T> Converter<S, T> getConverter(PClassInfo<S> sourceType, Class<T> targetType) { default <S, T extends @Nullable Object> Converter<S, T> getConverter(
PClassInfo<S> sourceType, Class<T> targetType) {
return getConverter(sourceType, (Type) targetType); return getConverter(sourceType, (Type) targetType);
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -52,9 +52,9 @@ class ValueMapperImpl implements ValueMapper {
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <S, T> T map(S model, Type targetType) { public <S, T> T map(S value, Type targetType) {
var sourceType = PClassInfo.forValue(model); var sourceType = PClassInfo.forValue(value);
return (T) getConverter(sourceType, targetType).convert(model, this); return (T) getConverter(sourceType, targetType).convert(value, this);
} }
private <S> Class<?> getTargetType(PClassInfo<S> sourceType, Type targetType) { private <S> Class<?> getTargetType(PClassInfo<S> sourceType, Type targetType) {
@@ -1,4 +1,4 @@
@NonnullByDefault @NullMarked
package org.pkl.config.java.mapper; package org.pkl.config.java.mapper;
import org.pkl.core.util.NonnullByDefault; import org.jspecify.annotations.NullMarked;
@@ -1,4 +1,4 @@
@NonnullByDefault @NullMarked
package org.pkl.config.java; package org.pkl.config.java;
import org.pkl.core.util.NonnullByDefault; import org.jspecify.annotations.NullMarked;
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -22,11 +22,11 @@ import java.util.EnumSet;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import javax.inject.Named; import javax.inject.Named;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.pkl.core.Evaluator; import org.pkl.core.Evaluator;
import org.pkl.core.PModule; import org.pkl.core.PModule;
import org.pkl.core.util.Nullable;
public class PObjectToDataObjectJavaxInjectTest { public class PObjectToDataObjectJavaxInjectTest {
private static final Evaluator evaluator = Evaluator.preconfigured(); private static final Evaluator evaluator = Evaluator.preconfigured();
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -20,11 +20,11 @@ import static org.pkl.core.ModuleSource.modulePath;
import java.beans.ConstructorProperties; import java.beans.ConstructorProperties;
import java.util.*; import java.util.*;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.pkl.core.Evaluator; import org.pkl.core.Evaluator;
import org.pkl.core.PModule; import org.pkl.core.PModule;
import org.pkl.core.util.Nullable;
public class PObjectToDataObjectTest { public class PObjectToDataObjectTest {
private static final Evaluator evaluator = Evaluator.preconfigured(); private static final Evaluator evaluator = Evaluator.preconfigured();
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -15,7 +15,7 @@
*/ */
package org.pkl.config.java.mapper; package org.pkl.config.java.mapper;
import org.pkl.core.util.Nullable; import org.jspecify.annotations.Nullable;
public class Person { public class Person {
public final String name; public final String name;
+1 -1
View File
@@ -80,7 +80,7 @@ org.jetbrains.kotlinx:kotlinx-serialization-core:1.7.3=swiftExportClasspathResol
org.jetbrains:annotations:13.0=compileClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinInternalAbiValidation,kotlinKlibCommonizerClasspath,pklCodegenKotlin,runtimeClasspath,swiftExportClasspathResolvable,testCompileClasspath,testRuntimeClasspath org.jetbrains:annotations:13.0=compileClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinInternalAbiValidation,kotlinKlibCommonizerClasspath,pklCodegenKotlin,runtimeClasspath,swiftExportClasspathResolvable,testCompileClasspath,testRuntimeClasspath
org.jetbrains:markdown-jvm:0.7.3=pklCodegenKotlin org.jetbrains:markdown-jvm:0.7.3=pklCodegenKotlin
org.jetbrains:markdown:0.7.3=pklCodegenKotlin org.jetbrains:markdown:0.7.3=pklCodegenKotlin
org.jspecify:jspecify:1.0.0=pklCodegenKotlin,testCompileClasspath,testRuntimeClasspath org.jspecify:jspecify:1.0.0=compileClasspath,pklCodegenKotlin,testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-api:6.0.3=testCompileClasspath,testRuntimeClasspath org.junit.jupiter:junit-jupiter-api:6.0.3=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-engine:6.0.3=testRuntimeClasspath org.junit.jupiter:junit-jupiter-engine:6.0.3=testRuntimeClasspath
org.junit.jupiter:junit-jupiter-params:6.0.3=testCompileClasspath,testRuntimeClasspath org.junit.jupiter:junit-jupiter-params:6.0.3=testCompileClasspath,testRuntimeClasspath
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -15,10 +15,11 @@
*/ */
package org.pkl.config.kotlin package org.pkl.config.kotlin
import kotlin.reflect.jvm.javaType
import kotlin.reflect.typeOf
import org.pkl.config.java.Config import org.pkl.config.java.Config
import org.pkl.config.java.ConfigEvaluator import org.pkl.config.java.ConfigEvaluator
import org.pkl.config.java.ConfigEvaluatorBuilder import org.pkl.config.java.ConfigEvaluatorBuilder
import org.pkl.config.java.JavaType
import org.pkl.config.java.mapper.ConversionException import org.pkl.config.java.mapper.ConversionException
import org.pkl.config.java.mapper.ValueMapperBuilder import org.pkl.config.java.mapper.ValueMapperBuilder
import org.pkl.config.kotlin.mapper.KotlinConversions import org.pkl.config.kotlin.mapper.KotlinConversions
@@ -30,23 +31,21 @@ import org.pkl.config.kotlin.mapper.KotlinConverterFactories
* *
* To allow `null` values, specify a nullable type, for example `to<String?>()`. * To allow `null` values, specify a nullable type, for example `to<String?>()`.
* *
* Kotlin code should prefer this method over [Config. as] for the following reasons: * Kotlin code should prefer this method over [Config.as] for the following reasons:
* * does not clash with Kotlin's `as` keyword * * does not clash with Kotlin's `as` keyword
* * throws [ConversionException] if conversion to non-nullable type returns `null` * * throws [ConversionException] if conversion to non-nullable type returns `null`
* * easier to use with parameterized types: `to<List<String>>()` vs. * * easier to use with parameterized types: `to<List<String>>()` vs.
* `as(JavaType.listOf(String::class.java))` * `as(JavaType.listOf(String::class.java))`
*/ */
inline fun <reified T> Config.to(): T { inline fun <reified T> Config.to(): T {
val javaType = object : JavaType<T>() {} val result = `as`<T>(typeOf<T>().javaType)
// `as T?` may no longer be required after switching to JSpecify
val result = `as`<T>(javaType.type) as T?
if (result == null && null !is T) { if (result == null && null !is T) {
throw ConversionException( throw ConversionException(
"Expected a non-null value but got `null`. " + "Expected a non-null value but got `null`. " +
"To allow null values, convert to a nullable Kotlin type, for example `String?`." "To allow null values, convert to a nullable Kotlin type, for example `String?`."
) )
} }
return result as T return result
} }
/** /**
@@ -1,5 +1,5 @@
/* /*
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved. * Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -48,16 +48,16 @@ internal class PPairToKotlinPair : ConverterFactory {
) : Converter<PPair<Any, Any>, Pair<F, S>> { ) : Converter<PPair<Any, Any>, Pair<F, S>> {
private var firstCachedType = PClassInfo.Unavailable private var firstCachedType = PClassInfo.Unavailable
private var firstCachedConverter: Converter<Any, F>? = null private lateinit var firstCachedConverter: Converter<Any, F>
private var secondCachedType = PClassInfo.Unavailable private var secondCachedType = PClassInfo.Unavailable
private var secondCachedConverter: Converter<Any, S>? = null private lateinit var secondCachedConverter: Converter<Any, S>
override fun convert(value: PPair<Any, Any>, valueMapper: ValueMapper): Pair<F, S> { override fun convert(value: PPair<Any, Any>, valueMapper: ValueMapper): Pair<F, S> {
val first = value.first val first = value.first
if (!firstCachedType.isExactClassOf(first)) { if (!firstCachedType.isExactClassOf(first)) {
firstCachedType = PClassInfo.forValue(first) firstCachedType = PClassInfo.forValue(first)
firstCachedConverter = valueMapper.getConverter(firstCachedType, firstTargetType) firstCachedConverter = valueMapper.getConverter<Any, F>(firstCachedType, firstTargetType)
} }
val second = value.second val second = value.second
@@ -67,8 +67,8 @@ internal class PPairToKotlinPair : ConverterFactory {
} }
return Pair( return Pair(
firstCachedConverter!!.convert(first, valueMapper), firstCachedConverter.convert(first, valueMapper),
secondCachedConverter!!.convert(second, valueMapper), secondCachedConverter.convert(second, valueMapper),
) )
} }
} }
+1 -1
View File
@@ -63,7 +63,7 @@ org.jetbrains.kotlinx:kotlinx-serialization-bom:1.7.3=swiftExportClasspathResolv
org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.7.3=swiftExportClasspathResolvable org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.7.3=swiftExportClasspathResolvable
org.jetbrains.kotlinx:kotlinx-serialization-core:1.7.3=swiftExportClasspathResolvable org.jetbrains.kotlinx:kotlinx-serialization-core:1.7.3=swiftExportClasspathResolvable
org.jetbrains:annotations:13.0=compileClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinInternalAbiValidation,kotlinKlibCommonizerClasspath,swiftExportClasspathResolvable,testCompileClasspath,testRuntimeClasspath org.jetbrains:annotations:13.0=compileClasspath,kotlinBuildToolsApiClasspath,kotlinCompilerClasspath,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinInternalAbiValidation,kotlinKlibCommonizerClasspath,swiftExportClasspathResolvable,testCompileClasspath,testRuntimeClasspath
org.jspecify:jspecify:1.0.0=testCompileClasspath org.jspecify:jspecify:1.0.0=compileClasspath,testCompileClasspath
org.junit.jupiter:junit-jupiter-api:6.0.3=testCompileClasspath,testRuntimeClasspath org.junit.jupiter:junit-jupiter-api:6.0.3=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-engine:6.0.3=testCompileClasspath,testRuntimeClasspath org.junit.jupiter:junit-jupiter-engine:6.0.3=testCompileClasspath,testRuntimeClasspath
org.junit.jupiter:junit-jupiter-params:6.0.3=testCompileClasspath,testRuntimeClasspath org.junit.jupiter:junit-jupiter-params:6.0.3=testCompileClasspath,testRuntimeClasspath
+1 -1
View File
@@ -55,7 +55,7 @@ org.jline:jline-native:4.0.12=runtimeClasspath,testRuntimeClasspath
org.jline:jline-reader:4.0.12=runtimeClasspath,testRuntimeClasspath org.jline:jline-reader:4.0.12=runtimeClasspath,testRuntimeClasspath
org.jline:jline-terminal-jni:4.0.12=runtimeClasspath,testRuntimeClasspath org.jline:jline-terminal-jni:4.0.12=runtimeClasspath,testRuntimeClasspath
org.jline:jline-terminal:4.0.12=runtimeClasspath,testRuntimeClasspath org.jline:jline-terminal:4.0.12=runtimeClasspath,testRuntimeClasspath
org.jspecify:jspecify:1.0.0=runtimeClasspath,testRuntimeClasspath org.jspecify:jspecify:1.0.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
org.msgpack:msgpack-core:0.9.11=runtimeClasspath,testRuntimeClasspath org.msgpack:msgpack-core:0.9.11=runtimeClasspath,testRuntimeClasspath
org.organicdesign:Paguro:3.10.3=runtimeClasspath,testRuntimeClasspath org.organicdesign:Paguro:3.10.3=runtimeClasspath,testRuntimeClasspath
org.snakeyaml:snakeyaml-engine:2.10=runtimeClasspath,testRuntimeClasspath org.snakeyaml:snakeyaml-engine:2.10=runtimeClasspath,testRuntimeClasspath