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")