diff --git a/docs/content/docs/validation/developer/build-and-release.md b/docs/content/docs/validation/developer/build-and-release.md index 6ef2ecc511..dc0ca90609 100644 --- a/docs/content/docs/validation/developer/build-and-release.md +++ b/docs/content/docs/validation/developer/build-and-release.md @@ -47,7 +47,7 @@ through Gradle's `extra` properties: end="val validationVersion"> ```kotlin -val validationVersion by extra("2.0.0-SNAPSHOT.420") +val validationVersion by extra("2.0.0-SNAPSHOT.421") ``` The root build script applies this file under `allprojects { … }` and assigns diff --git a/docs/content/docs/validation/user/01-getting-started/adding-to-build.md b/docs/content/docs/validation/user/01-getting-started/adding-to-build.md index d5bf9d49fc..ab88f3805d 100644 --- a/docs/content/docs/validation/user/01-getting-started/adding-to-build.md +++ b/docs/content/docs/validation/user/01-getting-started/adding-to-build.md @@ -90,7 +90,7 @@ Add the Validation plugin to the build. ```kotlin plugins { module - id("io.spine.validation") version "2.0.0-SNAPSHOT.420" + id("io.spine.validation") version "2.0.0-SNAPSHOT.421" } ``` diff --git a/docs/dependencies/dependencies.md b/docs/dependencies/dependencies.md index 041de692fe..ff071b1499 100644 --- a/docs/dependencies/dependencies.md +++ b/docs/dependencies/dependencies.md @@ -1,6 +1,6 @@ -# Dependencies of `io.spine.tools:validation-context:2.0.0-SNAPSHOT.420` +# Dependencies of `io.spine.tools:validation-context:2.0.0-SNAPSHOT.421` ## Runtime 1. **Group** : com.fasterxml.jackson. **Name** : jackson-bom. **Version** : 2.20.0. @@ -1097,7 +1097,7 @@ This report was generated on **Wed May 13 20:44:36 WEST 2026** using -# Dependencies of `io.spine.tools:validation-context-tests:2.0.0-SNAPSHOT.420` +# Dependencies of `io.spine.tools:validation-context-tests:2.0.0-SNAPSHOT.421` ## Runtime 1. **Group** : com.fasterxml.jackson. **Name** : jackson-bom. **Version** : 2.20.0. @@ -1798,7 +1798,7 @@ This report was generated on **Wed May 13 20:44:36 WEST 2026** using -# Dependencies of `io.spine.tools:validation-docs:2.0.0-SNAPSHOT.420` +# Dependencies of `io.spine.tools:validation-docs:2.0.0-SNAPSHOT.421` ## Runtime ## Compile, tests, and tooling @@ -1812,7 +1812,7 @@ This report was generated on **Wed May 13 20:09:04 WEST 2026** using -# Dependencies of `io.spine.tools:validation-gradle-plugin:2.0.0-SNAPSHOT.420` +# Dependencies of `io.spine.tools:validation-gradle-plugin:2.0.0-SNAPSHOT.421` ## Runtime 1. **Group** : com.fasterxml.jackson. **Name** : jackson-bom. **Version** : 2.20.0. @@ -2871,7 +2871,7 @@ This report was generated on **Wed May 13 20:44:36 WEST 2026** using -# Dependencies of `io.spine.tools:validation-java:2.0.0-SNAPSHOT.420` +# Dependencies of `io.spine.tools:validation-java:2.0.0-SNAPSHOT.421` ## Runtime 1. **Group** : com.fasterxml.jackson. **Name** : jackson-bom. **Version** : 2.20.0. @@ -3968,7 +3968,7 @@ This report was generated on **Wed May 13 20:44:36 WEST 2026** using -# Dependencies of `io.spine.tools:validation-java-bundle:2.0.0-SNAPSHOT.420` +# Dependencies of `io.spine.tools:validation-java-bundle:2.0.0-SNAPSHOT.421` ## Runtime 1. **Group** : org.jetbrains. **Name** : annotations. **Version** : 13.0. @@ -4022,7 +4022,7 @@ This report was generated on **Wed May 13 20:44:35 WEST 2026** using -# Dependencies of `io.spine:spine-validation-jvm-runtime:2.0.0-SNAPSHOT.420` +# Dependencies of `io.spine:spine-validation-jvm-runtime:2.0.0-SNAPSHOT.421` ## Runtime 1. **Group** : com.google.code.findbugs. **Name** : jsr305. **Version** : 3.0.2. @@ -4829,7 +4829,7 @@ This report was generated on **Wed May 13 20:44:36 WEST 2026** using -# Dependencies of `io.spine.tools:validation-consumer:2.0.0-SNAPSHOT.420` +# Dependencies of `io.spine.tools:validation-consumer:2.0.0-SNAPSHOT.421` ## Runtime 1. **Group** : com.fasterxml.jackson. **Name** : jackson-bom. **Version** : 2.20.0. @@ -5518,7 +5518,7 @@ This report was generated on **Wed May 13 20:44:36 WEST 2026** using -# Dependencies of `io.spine.tools:validation-consumer-dependency:2.0.0-SNAPSHOT.420` +# Dependencies of `io.spine.tools:validation-consumer-dependency:2.0.0-SNAPSHOT.421` ## Runtime 1. **Group** : com.google.code.findbugs. **Name** : jsr305. **Version** : 3.0.2. @@ -5983,7 +5983,7 @@ This report was generated on **Wed May 13 20:44:36 WEST 2026** using -# Dependencies of `io.spine.tools:validation-extensions:2.0.0-SNAPSHOT.420` +# Dependencies of `io.spine.tools:validation-extensions:2.0.0-SNAPSHOT.421` ## Runtime 1. **Group** : com.fasterxml.jackson. **Name** : jackson-bom. **Version** : 2.20.0. @@ -6609,7 +6609,7 @@ This report was generated on **Wed May 13 20:44:36 WEST 2026** using -# Dependencies of `io.spine.tools:validation-runtime:2.0.0-SNAPSHOT.420` +# Dependencies of `io.spine.tools:validation-runtime:2.0.0-SNAPSHOT.421` ## Runtime 1. **Group** : com.google.code.findbugs. **Name** : jsr305. **Version** : 3.0.2. @@ -7177,7 +7177,7 @@ This report was generated on **Wed May 13 20:44:36 WEST 2026** using -# Dependencies of `io.spine.tools:validation-validating:2.0.0-SNAPSHOT.420` +# Dependencies of `io.spine.tools:validation-validating:2.0.0-SNAPSHOT.421` ## Runtime 1. **Group** : com.google.code.findbugs. **Name** : jsr305. **Version** : 3.0.2. @@ -7788,7 +7788,7 @@ This report was generated on **Wed May 13 20:44:36 WEST 2026** using -# Dependencies of `io.spine.tools:validation-validator:2.0.0-SNAPSHOT.420` +# Dependencies of `io.spine.tools:validation-validator:2.0.0-SNAPSHOT.421` ## Runtime 1. **Group** : com.fasterxml.jackson. **Name** : jackson-bom. **Version** : 2.20.0. @@ -8533,7 +8533,7 @@ This report was generated on **Wed May 13 20:44:36 WEST 2026** using -# Dependencies of `io.spine.tools:validation-validator-dependency:2.0.0-SNAPSHOT.420` +# Dependencies of `io.spine.tools:validation-validator-dependency:2.0.0-SNAPSHOT.421` ## Runtime 1. **Group** : com.google.code.findbugs. **Name** : jsr305. **Version** : 3.0.2. @@ -8773,7 +8773,7 @@ This report was generated on **Wed May 13 20:44:35 WEST 2026** using -# Dependencies of `io.spine.tools:validation-vanilla:2.0.0-SNAPSHOT.420` +# Dependencies of `io.spine.tools:validation-vanilla:2.0.0-SNAPSHOT.421` ## Runtime 1. **Group** : com.google.code.findbugs. **Name** : jsr305. **Version** : 3.0.2. diff --git a/docs/dependencies/pom.xml b/docs/dependencies/pom.xml index c57129ad5c..133b9969ac 100644 --- a/docs/dependencies/pom.xml +++ b/docs/dependencies/pom.xml @@ -10,7 +10,7 @@ all modules and does not describe the project structure per-subproject. --> io.spine.tools validation -2.0.0-SNAPSHOT.420 +2.0.0-SNAPSHOT.421 2015 diff --git a/java/src/main/kotlin/io/spine/tools/validation/java/generate/option/bound/BoundedFieldGenerator.kt b/java/src/main/kotlin/io/spine/tools/validation/java/generate/option/bound/BoundedFieldGenerator.kt index e630732e1c..d6f2caa6d7 100644 --- a/java/src/main/kotlin/io/spine/tools/validation/java/generate/option/bound/BoundedFieldGenerator.kt +++ b/java/src/main/kotlin/io/spine/tools/validation/java/generate/option/bound/BoundedFieldGenerator.kt @@ -26,6 +26,7 @@ package io.spine.tools.validation.java.generate.option.bound +import io.spine.annotation.VisibleForTesting import io.spine.base.FieldPath import io.spine.string.camelCase import io.spine.tools.compiler.Compilation @@ -69,6 +70,7 @@ import io.spine.tools.validation.java.generate.option.bound.Docs.UNSIGNED_API import io.spine.type.TypeName import io.spine.validation.ConstraintViolation import io.spine.validation.ErrorPlaceholder +import java.util.concurrent.ConcurrentHashMap /** * An abstract base for field generators that restrict the range of numeric fields. @@ -120,11 +122,9 @@ internal abstract class BoundedFieldGenerator( * of [ConstraintViolation] and adds it to the [violations] list. */ private fun checkWithinBounds(value: Expression): CodeBlock { - // TODO:2025-05-12:yevhenii.nadtochii: Enable reporting back when we decide upon the format. - // Issue: https://github.com/SpineEventEngine/validation/issues/227. - // if (boundPrimitive in listOf(UINT32_VALUE, UINT64_VALUE)) { - // unsignedIntegerWarning(view.file, field.span) - // } + if (boundPrimitive in listOf(UINT32_VALUE, UINT64_VALUE)) { + unsignedIntegerWarning(view.file, field.span) + } return CodeBlock( """ if (${isOutOfBounds(value)}) { @@ -217,15 +217,16 @@ internal abstract class BoundedFieldGenerator( } } -@Suppress("unused") // https://github.com/SpineEventEngine/validation/issues/227 private fun unsignedIntegerWarning(file: File, span: Span) = - Compilation.warning(file, span) { - "Unsigned integer types are not supported in Java. The Protobuf compiler uses" + - " signed integers to represent unsigned types in Java ($SCALAR_TYPES)." + - " Operations on unsigned values rely on static utility methods from" + - " `$IntegerClass` and `$LongClass` classes ($UNSIGNED_API). Be cautious" + - " when dealing with unsigned values outside of these methods, as Java" + - " treats all primitive integers as signed." + UnsignedIntegerWarnings.report(file, span) { + Compilation.warning(file, span) { + "Unsigned integer types are not supported in Java. The Protobuf compiler uses" + + " signed integers to represent unsigned types in Java ($SCALAR_TYPES)." + + " Operations on unsigned values rely on static utility methods from" + + " `$IntegerClass` and `$LongClass` classes ($UNSIGNED_API). Be cautious" + + " when dealing with unsigned values outside of these methods, as Java" + + " treats all primitive integers as signed." + } } @Suppress("MaxLineLength") // Long links. @@ -234,3 +235,29 @@ private object Docs { const val UNSIGNED_API = "https://www.baeldung.com/java-unsigned-arithmetic#the-unsigned-integer-api" } + +/** + * Reports unsigned-integer warnings once per source location. + */ +internal object UnsignedIntegerWarnings { + + private val reported = ConcurrentHashMap.newKeySet() + + fun report(file: File, span: Span, warning: () -> Unit) { + report(key(file, span), warning) + } + + @VisibleForTesting + fun report(key: String, warning: () -> Unit) { + if (reported.add(key)) { + warning() + } + } + + @VisibleForTesting + fun clear() { + reported.clear() + } + + private fun key(file: File, span: Span): String = "$file:$span" +} diff --git a/java/src/test/kotlin/io/spine/tools/validation/java/generate/option/bound/UnsignedIntegerWarningsSpec.kt b/java/src/test/kotlin/io/spine/tools/validation/java/generate/option/bound/UnsignedIntegerWarningsSpec.kt new file mode 100644 index 0000000000..1c3251ddcb --- /dev/null +++ b/java/src/test/kotlin/io/spine/tools/validation/java/generate/option/bound/UnsignedIntegerWarningsSpec.kt @@ -0,0 +1,69 @@ +/* + * Copyright 2026, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package io.spine.tools.validation.java.generate.option.bound + +import io.kotest.matchers.shouldBe +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test + +@DisplayName("`UnsignedIntegerWarnings` should") +internal class UnsignedIntegerWarningsSpec { + + @BeforeEach + fun setUp() { + UnsignedIntegerWarnings.clear() + } + + @Test + fun `report warning only once for the same location`() { + var reports = 0 + + UnsignedIntegerWarnings.report("same-location") { + reports++ + } + UnsignedIntegerWarnings.report("same-location") { + reports++ + } + + reports shouldBe 1 + } + + @Test + fun `report warning for each distinct location`() { + var reports = 0 + + UnsignedIntegerWarnings.report("location-1") { + reports++ + } + UnsignedIntegerWarnings.report("location-2") { + reports++ + } + + reports shouldBe 2 + } +} diff --git a/version.gradle.kts b/version.gradle.kts index ee62bd3168..82a46bd6ca 100644 --- a/version.gradle.kts +++ b/version.gradle.kts @@ -27,4 +27,4 @@ /** * The version of the Validation library to publish. */ -val validationVersion by extra("2.0.0-SNAPSHOT.420") +val validationVersion by extra("2.0.0-SNAPSHOT.421")