diff --git a/.gitignore b/.gitignore index c7431be0..fbc2e096 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ .gradle build/ +.out-of-scope/ +.omo/ !gradle/wrapper/gradle-wrapper.jar !**/src/main/**/build/ !**/src/test/**/build/ diff --git a/build.gradle b/build.gradle index c4fce8dd..676d31ad 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'pmd' id 'checkstyle' id 'org.owasp.dependencycheck' version '13.0.0' - id 'org.cyclonedx.bom' version '3.4.1' + id 'org.cyclonedx.bom' version '3.5.0' id 'info.solidsoft.pitest' version '1.19.0' id 'net.ltgt.errorprone' version '5.1.1' } @@ -47,17 +47,21 @@ tasks.withType(org.gradle.api.publish.maven.tasks.PublishToMavenRepository).conf } java { - // Only enforce toolchain in CI to ensure consistent Java 21 builds + // Only enforce toolchain in CI to ensure consistent Java 17 builds // Locally, use whatever JDK is installed if (System.getenv('CI') == 'true') { toolchain { - languageVersion = JavaLanguageVersion.of(21) + languageVersion = JavaLanguageVersion.of(17) } } withSourcesJar() withJavadocJar() } +tasks.withType(JavaCompile).configureEach { + options.release = 17 +} + repositories { mavenCentral() mavenLocal() @@ -172,6 +176,7 @@ tasks.checkstyleTest { dependencies { implementation 'tools.jackson.core:jackson-databind:3.2.3' implementation 'tools.jackson.module:jackson-module-blackbird:3.2.3' + implementation 'tech.uom.lib:ryu:1.0.0' compileOnly 'com.github.spotbugs:spotbugs-annotations:4.10.4' // NullAway + Error Prone for compile-time null safety diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 47492140..e7f8e36a 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -52,6 +52,11 @@ + + + + + @@ -62,6 +67,11 @@ + + + + + @@ -91,6 +101,14 @@ + + + + + + + + @@ -99,6 +117,14 @@ + + + + + + + + @@ -107,6 +133,14 @@ + + + + + + + + @@ -115,11 +149,24 @@ + + + + + + + + + + + + + @@ -128,6 +175,14 @@ + + + + + + + + @@ -136,16 +191,34 @@ + + + + + + + + + + + + + + + + + + @@ -316,6 +389,14 @@ + + + + + + + + @@ -334,6 +415,11 @@ + + + + + @@ -484,6 +570,14 @@ + + + + + + + + @@ -514,6 +608,11 @@ + + + + + @@ -670,6 +769,11 @@ + + + + + @@ -1018,6 +1122,11 @@ + + + + + @@ -1043,6 +1152,11 @@ + + + + + @@ -1173,6 +1287,11 @@ + + + + + @@ -1292,16 +1411,34 @@ + + + + + + + + + + + + + + + + + + @@ -1325,6 +1462,14 @@ + + + + + + + + @@ -1486,11 +1631,24 @@ + + + + + + + + + + + + + @@ -1499,6 +1657,14 @@ + + + + + + + + @@ -1507,6 +1673,14 @@ + + + + + + + + @@ -1515,6 +1689,14 @@ + + + + + + + + @@ -1523,6 +1705,14 @@ + + + + + + + + @@ -1551,6 +1741,19 @@ + + + + + + + + + + + + + @@ -1559,6 +1762,14 @@ + + + + + + + + @@ -1567,6 +1778,14 @@ + + + + + + + + @@ -1575,6 +1794,14 @@ + + + + + + + + @@ -1583,6 +1810,14 @@ + + + + + + + + @@ -1638,6 +1873,11 @@ + + + + + @@ -1646,6 +1886,22 @@ + + + + + + + + + + + + + + + + @@ -1654,6 +1910,14 @@ + + + + + + + + @@ -1662,6 +1926,14 @@ + + + + + + + + @@ -1670,6 +1942,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -1678,6 +1974,14 @@ + + + + + + + + @@ -1807,6 +2111,11 @@ + + + + + @@ -1833,6 +2142,14 @@ + + + + + + + + @@ -1883,6 +2200,14 @@ + + + + + + + + @@ -1907,6 +2232,14 @@ + + + + + + + + @@ -1923,6 +2256,14 @@ + + + + + + + + @@ -1931,11 +2272,24 @@ + + + + + + + + + + + + + @@ -1962,6 +2316,11 @@ + + + + + @@ -2009,6 +2368,14 @@ + + + + + + + + @@ -2017,11 +2384,24 @@ + + + + + + + + + + + + + @@ -2402,6 +2782,14 @@ + + + + + + + + @@ -2620,6 +3008,14 @@ + + + + + + + + @@ -2652,6 +3048,14 @@ + + + + + + + + @@ -2662,6 +3066,11 @@ + + + + + @@ -2677,6 +3086,11 @@ + + + + + diff --git a/src/main/java/dev/toonformat/jtoon/encoder/PrimitiveEncoder.java b/src/main/java/dev/toonformat/jtoon/encoder/PrimitiveEncoder.java index c674ddd7..ac0e02bf 100644 --- a/src/main/java/dev/toonformat/jtoon/encoder/PrimitiveEncoder.java +++ b/src/main/java/dev/toonformat/jtoon/encoder/PrimitiveEncoder.java @@ -3,6 +3,7 @@ import dev.toonformat.jtoon.util.StringEscaper; import dev.toonformat.jtoon.util.StringValidator; import org.jspecify.annotations.Nullable; +import tech.uom.lib.ryu.Ryu; import tools.jackson.databind.JsonNode; import java.math.BigDecimal; import java.util.Collection; @@ -75,11 +76,11 @@ private static String encodeNumber(final JsonNode value) { return value.asString(); } - // Use decimalValue() for exact precision from Jackson's DecimalNode, - // avoiding precision loss from double conversion. - // BigDecimal.valueOf(double) uses Double.toString which can only - // represent ~15-17 significant digits. - final BigDecimal decimal = value.decimalValue(); + // Use Ryu for shortest round-trip digits (spec ยง4.2). + // BigDecimal.valueOf(double) uses Double.toString which only delivers + // shortest digits from JDK 19+ (JDK-4511638). Ryu provides the same + // output on Java 17. + final BigDecimal decimal = new BigDecimal(Ryu.doubleToString(value.doubleValue())); final String plainString = decimal.toPlainString(); // Strip trailing zeros but preserve the number's mathematical value