diff --git a/docs/dependencies/dependencies.md b/docs/dependencies/dependencies.md
index e7fe4cd0634..8872c0ecfc0 100644
--- a/docs/dependencies/dependencies.md
+++ b/docs/dependencies/dependencies.md
@@ -1,6 +1,6 @@
-# Dependencies of `io.spine.tools:compiler-api:2.0.0-SNAPSHOT.082`
+# Dependencies of `io.spine.tools:compiler-api:2.0.0-SNAPSHOT.083`
## Runtime
1. **Group** : be.cyberelf.nanoxml. **Name** : nanoxml. **Version** : 2.2.3.
@@ -1817,14 +1817,14 @@
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.
-This report was generated on **Fri Oct 30 16:39:00 WET 2026** using
+This report was generated on **Mon Nov 02 22:24:57 WET 2026** using
[Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under
[Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
-# Dependencies of `io.spine.tools:compiler-api-tests:2.0.0-SNAPSHOT.082`
+# Dependencies of `io.spine.tools:compiler-api-tests:2.0.0-SNAPSHOT.083`
## Runtime
## Compile, tests, and tooling
@@ -2515,14 +2515,14 @@ This report was generated on **Fri Oct 30 16:39:00 WET 2026** using
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.
-This report was generated on **Fri Oct 30 16:39:00 WET 2026** using
+This report was generated on **Mon Nov 02 22:24:57 WET 2026** using
[Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under
[Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
-# Dependencies of `io.spine.tools:compiler-backend:2.0.0-SNAPSHOT.082`
+# Dependencies of `io.spine.tools:compiler-backend:2.0.0-SNAPSHOT.083`
## Runtime
1. **Group** : be.cyberelf.nanoxml. **Name** : nanoxml. **Version** : 2.2.3.
@@ -4343,14 +4343,14 @@ This report was generated on **Fri Oct 30 16:39:00 WET 2026** using
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.
-This report was generated on **Fri Oct 30 16:39:00 WET 2026** using
+This report was generated on **Mon Nov 02 22:24:57 WET 2026** using
[Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under
[Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
-# Dependencies of `io.spine.tools:compiler-cli:2.0.0-SNAPSHOT.082`
+# Dependencies of `io.spine.tools:compiler-cli:2.0.0-SNAPSHOT.083`
## Runtime
1. **Group** : be.cyberelf.nanoxml. **Name** : nanoxml. **Version** : 2.2.3.
@@ -6336,14 +6336,14 @@ This report was generated on **Fri Oct 30 16:39:00 WET 2026** using
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.
-This report was generated on **Fri Oct 30 16:39:00 WET 2026** using
+This report was generated on **Mon Nov 02 22:24:57 WET 2026** using
[Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under
[Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
-# Dependencies of `io.spine.tools:compiler-gradle-api:2.0.0-SNAPSHOT.082`
+# Dependencies of `io.spine.tools:compiler-gradle-api:2.0.0-SNAPSHOT.083`
## Runtime
1. **Group** : be.cyberelf.nanoxml. **Name** : nanoxml. **Version** : 2.2.3.
@@ -8065,14 +8065,14 @@ This report was generated on **Fri Oct 30 16:39:00 WET 2026** using
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.
-This report was generated on **Fri Oct 30 16:39:00 WET 2026** using
+This report was generated on **Mon Nov 02 22:24:57 WET 2026** using
[Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under
[Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
-# Dependencies of `io.spine.tools:compiler-gradle-plugin:2.0.0-SNAPSHOT.082`
+# Dependencies of `io.spine.tools:compiler-gradle-plugin:2.0.0-SNAPSHOT.083`
## Runtime
1. **Group** : be.cyberelf.nanoxml. **Name** : nanoxml. **Version** : 2.2.3.
@@ -9846,14 +9846,14 @@ This report was generated on **Fri Oct 30 16:39:00 WET 2026** using
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.
-This report was generated on **Fri Oct 30 16:39:00 WET 2026** using
+This report was generated on **Mon Nov 02 22:24:57 WET 2026** using
[Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under
[Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
-# Dependencies of `io.spine.tools:compiler-jvm:2.0.0-SNAPSHOT.082`
+# Dependencies of `io.spine.tools:compiler-jvm:2.0.0-SNAPSHOT.083`
## Runtime
1. **Group** : be.cyberelf.nanoxml. **Name** : nanoxml. **Version** : 2.2.3.
@@ -11697,14 +11697,14 @@ This report was generated on **Fri Oct 30 16:39:00 WET 2026** using
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.
-This report was generated on **Fri Oct 30 16:39:00 WET 2026** using
+This report was generated on **Mon Nov 02 22:24:57 WET 2026** using
[Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under
[Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
-# Dependencies of `io.spine.tools:compiler-params:2.0.0-SNAPSHOT.082`
+# Dependencies of `io.spine.tools:compiler-params:2.0.0-SNAPSHOT.083`
## Runtime
1. **Group** : be.cyberelf.nanoxml. **Name** : nanoxml. **Version** : 2.2.3.
@@ -13513,14 +13513,14 @@ This report was generated on **Fri Oct 30 16:39:00 WET 2026** using
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.
-This report was generated on **Fri Oct 30 16:39:00 WET 2026** using
+This report was generated on **Mon Nov 02 22:24:57 WET 2026** using
[Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under
[Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
-# Dependencies of `io.spine.tools:compiler-protoc-plugin:2.0.0-SNAPSHOT.082`
+# Dependencies of `io.spine.tools:compiler-protoc-plugin:2.0.0-SNAPSHOT.083`
## Runtime
1. **Group** : com.google.code.findbugs. **Name** : jsr305. **Version** : 3.0.2.
@@ -14395,14 +14395,14 @@ This report was generated on **Fri Oct 30 16:39:00 WET 2026** using
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.
-This report was generated on **Fri Oct 30 16:39:00 WET 2026** using
+This report was generated on **Mon Nov 02 22:24:57 WET 2026** using
[Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under
[Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
-# Dependencies of `io.spine.tools:compiler-test-env:2.0.0-SNAPSHOT.082`
+# Dependencies of `io.spine.tools:compiler-test-env:2.0.0-SNAPSHOT.083`
## Runtime
1. **Group** : be.cyberelf.nanoxml. **Name** : nanoxml. **Version** : 2.2.3.
@@ -16219,14 +16219,14 @@ This report was generated on **Fri Oct 30 16:39:00 WET 2026** using
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.
-This report was generated on **Fri Oct 30 16:39:00 WET 2026** using
+This report was generated on **Mon Nov 02 22:24:57 WET 2026** using
[Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under
[Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
-# Dependencies of `io.spine.tools:compiler-testlib:2.0.0-SNAPSHOT.082`
+# Dependencies of `io.spine.tools:compiler-testlib:2.0.0-SNAPSHOT.083`
## Runtime
1. **Group** : be.cyberelf.nanoxml. **Name** : nanoxml. **Version** : 2.2.3.
@@ -18148,6 +18148,6 @@ This report was generated on **Fri Oct 30 16:39:00 WET 2026** using
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.
-This report was generated on **Fri Oct 30 16:39:00 WET 2026** using
+This report was generated on **Mon Nov 02 22:24:57 WET 2026** using
[Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under
[Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
\ No newline at end of file
diff --git a/docs/dependencies/pom.xml b/docs/dependencies/pom.xml
index f12af6f7a79..fd4f8b3cfa2 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
compiler
-2.0.0-SNAPSHOT.082
+2.0.0-SNAPSHOT.083
2015
diff --git a/jvm/src/main/kotlin/io/spine/tools/compiler/jvm/ClassName.kt b/jvm/src/main/kotlin/io/spine/tools/compiler/jvm/ClassName.kt
index bb3313dbad9..7e6446076c0 100644
--- a/jvm/src/main/kotlin/io/spine/tools/compiler/jvm/ClassName.kt
+++ b/jvm/src/main/kotlin/io/spine/tools/compiler/jvm/ClassName.kt
@@ -1,27 +1,15 @@
/*
- * Copyright 2026, TeamDev. All rights reserved.
+ * Copyright 2026 CodeMatters, Lda.
*
- * 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
+ * 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.
+ * Unless required by applicable law or agreed to in writing, software distributed under
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language governing permissions
+ * and limitations under the License.
*/
package io.spine.tools.compiler.jvm
@@ -91,6 +79,7 @@ public open class ClassName(
* ```
* val string = ClassName(String::class)
* println(string.clazz) // `java.lang.String.class`
+ * ```
*/
public val clazz: Expression> by lazy {
Expression("$canonical.class")
@@ -196,6 +185,7 @@ public open class ClassName(
* @throws IllegalArgumentException when binary class name separator (`"$"`) is used
* in the given name, or the given value is empty or blank.
*/
+ @JvmStatic
public fun guess(name: @FullyQualifiedName String): ClassName {
require(name.isNotEmpty())
require(name.isNotBlank())
@@ -222,6 +212,7 @@ public open class ClassName(
/**
* A regular expression for a simple Java class name.
*/
+ @JvmStatic
public val simpleNameRegex: Regex = Regex("^[a-zA-Z_$][a-zA-Z\\d_$]*$")
/**
diff --git a/jvm/src/main/kotlin/io/spine/tools/compiler/jvm/FieldConventions.kt b/jvm/src/main/kotlin/io/spine/tools/compiler/jvm/FieldConventions.kt
index 57811e3b6e8..d17317d76f1 100644
--- a/jvm/src/main/kotlin/io/spine/tools/compiler/jvm/FieldConventions.kt
+++ b/jvm/src/main/kotlin/io/spine/tools/compiler/jvm/FieldConventions.kt
@@ -1,27 +1,15 @@
/*
- * Copyright 2026, TeamDev. All rights reserved.
+ * Copyright 2026 CodeMatters, Lda.
*
- * 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
+ * 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.
+ * Unless required by applicable law or agreed to in writing, software distributed under
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language governing permissions
+ * and limitations under the License.
*/
package io.spine.tools.compiler.jvm
@@ -137,6 +125,7 @@ public open class FieldMethods(
/**
* Obtains the name of the getter.
*/
+ @JvmStatic
public fun getterOf(fieldName: String, cardinality: Cardinality): String {
return FieldMethods(fieldName { value = fieldName }, cardinality).getter
}
diff --git a/jvm/src/main/kotlin/io/spine/tools/compiler/jvm/JavaTypeName.kt b/jvm/src/main/kotlin/io/spine/tools/compiler/jvm/JavaTypeName.kt
index d1f16720d19..bbf4b159cdf 100644
--- a/jvm/src/main/kotlin/io/spine/tools/compiler/jvm/JavaTypeName.kt
+++ b/jvm/src/main/kotlin/io/spine/tools/compiler/jvm/JavaTypeName.kt
@@ -1,27 +1,15 @@
/*
- * Copyright 2026, TeamDev. All rights reserved.
+ * Copyright 2026 CodeMatters, Lda.
*
- * 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
+ * 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.
+ * Unless required by applicable law or agreed to in writing, software distributed under
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language governing permissions
+ * and limitations under the License.
*/
package io.spine.tools.compiler.jvm
@@ -92,8 +80,12 @@ public abstract class JavaTypeName : NameElement, JavaElement {
/**
* The built-in Java primitive types.
*/
- public val KnownPrimitives: List = listOf(
- VOID, BOOLEAN, BYTE, SHORT, INT, LONG, CHAR, FLOAT, DOUBLE
- )
+ @JvmStatic
+ public val KnownPrimitives: List by lazy {
+ // Not computed in the static initializer of `JavaTypeName` because the objects
+ // of primitive types may not be initialized yet. E.g., when `INT` is accessed
+ // first, the JVM initializes `JavaTypeName` before assigning `INT.INSTANCE`.
+ listOf(VOID, BOOLEAN, BYTE, SHORT, INT, LONG, CHAR, FLOAT, DOUBLE)
+ }
}
}
diff --git a/jvm/src/main/kotlin/io/spine/tools/compiler/jvm/TypeVariableName.kt b/jvm/src/main/kotlin/io/spine/tools/compiler/jvm/TypeVariableName.kt
index b102b6d0798..9736b3f7409 100644
--- a/jvm/src/main/kotlin/io/spine/tools/compiler/jvm/TypeVariableName.kt
+++ b/jvm/src/main/kotlin/io/spine/tools/compiler/jvm/TypeVariableName.kt
@@ -1,27 +1,15 @@
/*
- * Copyright 2025, TeamDev. All rights reserved.
+ * Copyright 2026 CodeMatters, Lda.
*
- * 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
+ * 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.
+ * Unless required by applicable law or agreed to in writing, software distributed under
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language governing permissions
+ * and limitations under the License.
*/
package io.spine.tools.compiler.jvm
@@ -47,7 +35,17 @@ public class TypeVariableName(value: String) : JavaTypeName() {
override val canonical: String = value
public companion object {
+
+ /**
+ * The type variable named `T`.
+ */
+ @JvmStatic
public val T: TypeVariableName = TypeVariableName("T")
+
+ /**
+ * The type variable named `E`.
+ */
+ @JvmStatic
public val E: TypeVariableName = TypeVariableName("E")
}
}
diff --git a/jvm/src/test/java/io/spine/tools/compiler/jvm/ClassNameJavaSpec.java b/jvm/src/test/java/io/spine/tools/compiler/jvm/ClassNameJavaSpec.java
new file mode 100644
index 00000000000..6cc964680ea
--- /dev/null
+++ b/jvm/src/test/java/io/spine/tools/compiler/jvm/ClassNameJavaSpec.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2026 CodeMatters, Lda.
+ *
+ * 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
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language governing permissions
+ * and limitations under the License.
+ */
+
+package io.spine.tools.compiler.jvm;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import static com.google.common.truth.Truth.assertThat;
+
+@DisplayName("`ClassName` Java API should")
+class ClassNameJavaSpec {
+
+ @Test
+ @DisplayName("guess a class name via static `guess()`")
+ void guessStatic() {
+ var className = ClassName.guess("io.spine.Outer.Nested");
+
+ assertThat(className.getPackageName()).isEqualTo("io.spine");
+ assertThat(className.getSimpleNames()).containsExactly("Outer", "Nested").inOrder();
+ }
+
+ @Test
+ @DisplayName("still guess a class name via the companion object")
+ void guessViaCompanion() {
+ var name = "io.spine.Foo";
+
+ assertThat(ClassName.Companion.guess(name)).isEqualTo(ClassName.guess(name));
+ }
+
+ @Test
+ @DisplayName("expose the simple name regex via static `getSimpleNameRegex()`")
+ void simpleNameRegexStatic() {
+ var regex = ClassName.getSimpleNameRegex();
+
+ assertThat(regex.matches("Foo")).isTrue();
+ assertThat(regex.matches("1Foo")).isFalse();
+ assertThat(regex).isSameInstanceAs(ClassName.Companion.getSimpleNameRegex());
+ }
+
+ @Test
+ @DisplayName("expose separators as static constants")
+ void separatorConstants() {
+ assertThat(ClassName.BINARY_SEPARATOR).isEqualTo("$");
+ assertThat(ClassName.CANONICAL_SEPARATOR).isEqualTo(".");
+ assertThat(ClassName.PACKAGE_SEPARATOR).isEqualTo(".");
+ assertThat(ClassName.PATH_SEPARATOR).isEqualTo("/");
+ }
+}
diff --git a/jvm/src/test/java/io/spine/tools/compiler/jvm/FieldMethodsJavaSpec.java b/jvm/src/test/java/io/spine/tools/compiler/jvm/FieldMethodsJavaSpec.java
new file mode 100644
index 00000000000..6de2f328fd1
--- /dev/null
+++ b/jvm/src/test/java/io/spine/tools/compiler/jvm/FieldMethodsJavaSpec.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2026 CodeMatters, Lda.
+ *
+ * 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
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language governing permissions
+ * and limitations under the License.
+ */
+
+package io.spine.tools.compiler.jvm;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import static com.google.common.truth.Truth.assertThat;
+import static io.spine.tools.compiler.ast.Cardinality.CARDINALITY_LIST;
+import static io.spine.tools.compiler.ast.Cardinality.CARDINALITY_MAP;
+import static io.spine.tools.compiler.ast.Cardinality.CARDINALITY_SINGLE;
+
+@DisplayName("`FieldMethods` Java API should")
+class FieldMethodsJavaSpec {
+
+ private static final String FIELD = "favorite_color";
+
+ @Test
+ @DisplayName("obtain a getter name via static `getterOf()`")
+ void getterOfStatic() {
+ assertThat(FieldMethods.getterOf(FIELD, CARDINALITY_SINGLE))
+ .isEqualTo("getFavoriteColor");
+ assertThat(FieldMethods.getterOf(FIELD, CARDINALITY_LIST))
+ .isEqualTo("getFavoriteColorList");
+ assertThat(FieldMethods.getterOf(FIELD, CARDINALITY_MAP))
+ .isEqualTo("getFavoriteColorMap");
+ }
+
+ @Test
+ @DisplayName("still obtain a getter name via the companion object")
+ void getterOfViaCompanion() {
+ assertThat(FieldMethods.Companion.getterOf(FIELD, CARDINALITY_SINGLE))
+ .isEqualTo(FieldMethods.getterOf(FIELD, CARDINALITY_SINGLE));
+ }
+}
diff --git a/jvm/src/test/java/io/spine/tools/compiler/jvm/JavaTypeNameJavaSpec.java b/jvm/src/test/java/io/spine/tools/compiler/jvm/JavaTypeNameJavaSpec.java
new file mode 100644
index 00000000000..0b44a742e46
--- /dev/null
+++ b/jvm/src/test/java/io/spine/tools/compiler/jvm/JavaTypeNameJavaSpec.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2026 CodeMatters, Lda.
+ *
+ * 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
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language governing permissions
+ * and limitations under the License.
+ */
+
+package io.spine.tools.compiler.jvm;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import static com.google.common.truth.Truth.assertThat;
+
+@DisplayName("`JavaTypeName` Java API should")
+class JavaTypeNameJavaSpec {
+
+ @Test
+ @DisplayName("expose known primitives via static `getKnownPrimitives()`")
+ void knownPrimitivesStatic() {
+ assertThat(JavaTypeName.getKnownPrimitives())
+ .containsExactly(
+ JavaTypeName.VOID.INSTANCE,
+ JavaTypeName.BOOLEAN.INSTANCE,
+ JavaTypeName.BYTE.INSTANCE,
+ JavaTypeName.SHORT.INSTANCE,
+ JavaTypeName.INT.INSTANCE,
+ JavaTypeName.LONG.INSTANCE,
+ JavaTypeName.CHAR.INSTANCE,
+ JavaTypeName.FLOAT.INSTANCE,
+ JavaTypeName.DOUBLE.INSTANCE
+ ).inOrder();
+ }
+
+ @Test
+ @DisplayName("still expose known primitives via the companion object")
+ void knownPrimitivesViaCompanion() {
+ assertThat(JavaTypeName.Companion.getKnownPrimitives())
+ .isSameInstanceAs(JavaTypeName.getKnownPrimitives());
+ }
+}
diff --git a/jvm/src/test/java/io/spine/tools/compiler/jvm/TypeVariableNameJavaSpec.java b/jvm/src/test/java/io/spine/tools/compiler/jvm/TypeVariableNameJavaSpec.java
new file mode 100644
index 00000000000..9be072b3844
--- /dev/null
+++ b/jvm/src/test/java/io/spine/tools/compiler/jvm/TypeVariableNameJavaSpec.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2026 CodeMatters, Lda.
+ *
+ * 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
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language governing permissions
+ * and limitations under the License.
+ */
+
+package io.spine.tools.compiler.jvm;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import static com.google.common.truth.Truth.assertThat;
+
+@DisplayName("`TypeVariableName` Java API should")
+class TypeVariableNameJavaSpec {
+
+ @Test
+ @DisplayName("expose common type variables via static `getT()` and `getE()`")
+ void typeVariablesStatic() {
+ assertThat(TypeVariableName.getT().getCanonical()).isEqualTo("T");
+ assertThat(TypeVariableName.getE().getCanonical()).isEqualTo("E");
+ }
+
+ @Test
+ @DisplayName("still expose common type variables via the companion object")
+ void typeVariablesViaCompanion() {
+ assertThat(TypeVariableName.Companion.getT()).isSameInstanceAs(TypeVariableName.getT());
+ assertThat(TypeVariableName.Companion.getE()).isSameInstanceAs(TypeVariableName.getE());
+ }
+}
diff --git a/jvm/src/test/kotlin/io/spine/tools/compiler/jvm/JavaTypeNameSpec.kt b/jvm/src/test/kotlin/io/spine/tools/compiler/jvm/JavaTypeNameSpec.kt
index febe98df9d1..16c431eb54b 100644
--- a/jvm/src/test/kotlin/io/spine/tools/compiler/jvm/JavaTypeNameSpec.kt
+++ b/jvm/src/test/kotlin/io/spine/tools/compiler/jvm/JavaTypeNameSpec.kt
@@ -1,35 +1,28 @@
/*
- * Copyright 2025, TeamDev. All rights reserved.
+ * Copyright 2026 CodeMatters, Lda.
*
- * 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
+ * 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.
+ * Unless required by applicable law or agreed to in writing, software distributed under
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language governing permissions
+ * and limitations under the License.
*/
package io.spine.tools.compiler.jvm
+import io.kotest.assertions.withClue
import io.kotest.matchers.shouldBe
import io.kotest.matchers.shouldNotBe
+import io.spine.tools.compiler.jvm.given.PrimitiveFirstProgram
+import io.spine.tools.compiler.jvm.given.runInFreshJvm
+import java.nio.file.Path
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.io.TempDir
@DisplayName("`JavaTypeName` should")
internal class JavaTypeNameSpec {
@@ -57,6 +50,16 @@ internal class JavaTypeNameSpec {
myType shouldNotBe anotherType
myType.hashCode() shouldNotBe anotherType.hashCode()
}
+
+ @Test
+ fun `list all known primitives when a primitive is initialized first`(
+ @TempDir workDir: Path
+ ) {
+ val run = runInFreshJvm(PrimitiveFirstProgram::class.java, workDir)
+ withClue(run.output) {
+ run.exitCode shouldBe 0
+ }
+ }
}
private fun typeName(canonical: String) = object : JavaTypeName() {
diff --git a/jvm/src/test/kotlin/io/spine/tools/compiler/jvm/given/JvmRun.kt b/jvm/src/test/kotlin/io/spine/tools/compiler/jvm/given/JvmRun.kt
new file mode 100644
index 00000000000..a8ac72571b8
--- /dev/null
+++ b/jvm/src/test/kotlin/io/spine/tools/compiler/jvm/given/JvmRun.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2026 CodeMatters, Lda.
+ *
+ * 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
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language governing permissions
+ * and limitations under the License.
+ */
+
+package io.spine.tools.compiler.jvm.given
+
+import java.io.File
+import java.nio.file.Path
+import java.util.concurrent.TimeUnit.MINUTES
+import java.util.jar.Attributes
+import java.util.jar.JarOutputStream
+import java.util.jar.Manifest
+import kotlin.io.path.Path
+import kotlin.io.path.outputStream
+import kotlin.io.path.readText
+
+/**
+ * The outcome of a program run in a separate JVM.
+ *
+ * @property exitCode The exit code of the JVM process.
+ * @property output The combined standard output and error of the process.
+ */
+internal data class JvmRun(val exitCode: Int, val output: String)
+
+/**
+ * Runs the `main` method of the given class in a new JVM with the classpath of this JVM.
+ *
+ * The new JVM has no classes initialized by the code of this JVM, which lets a test
+ * control the order of class initialization.
+ *
+ * The classpath is passed via a manifest-only JAR so that the command line stays
+ * within the length limits of all platforms.
+ *
+ * @param mainClass The class declaring the static `main` method to run.
+ * @param workDir The directory for the classpath JAR.
+ */
+internal fun runInFreshJvm(mainClass: Class<*>, workDir: Path): JvmRun {
+ val java = Path(System.getProperty("java.home"), "bin", "java")
+ val classpathJar = writeClasspathJar(workDir)
+ val outputFile = workDir.resolve("output.txt")
+ val process = ProcessBuilder(java.toString(), "-cp", classpathJar.toString(), mainClass.name)
+ .redirectErrorStream(true)
+ .redirectOutput(outputFile.toFile())
+ .start()
+ if (!process.waitFor(1, MINUTES)) {
+ process.destroyForcibly()
+ error("The JVM running `${mainClass.name}` did not exit in time.")
+ }
+ return JvmRun(process.exitValue(), outputFile.readText())
+}
+
+private fun writeClasspathJar(workDir: Path): Path {
+ val entries = System.getProperty("java.class.path")
+ .split(File.pathSeparator)
+ .joinToString(" ") { File(it).toURI().toString() }
+ val manifest = Manifest().apply {
+ mainAttributes[Attributes.Name.MANIFEST_VERSION] = "1.0"
+ mainAttributes[Attributes.Name.CLASS_PATH] = entries
+ }
+ val jar = workDir.resolve("classpath.jar")
+ JarOutputStream(jar.outputStream(), manifest).use { }
+ return jar
+}
diff --git a/jvm/src/test/kotlin/io/spine/tools/compiler/jvm/given/PrimitiveFirstProgram.kt b/jvm/src/test/kotlin/io/spine/tools/compiler/jvm/given/PrimitiveFirstProgram.kt
new file mode 100644
index 00000000000..c304e98799d
--- /dev/null
+++ b/jvm/src/test/kotlin/io/spine/tools/compiler/jvm/given/PrimitiveFirstProgram.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2026 CodeMatters, Lda.
+ *
+ * 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
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language governing permissions
+ * and limitations under the License.
+ */
+
+package io.spine.tools.compiler.jvm.given
+
+import io.spine.tools.compiler.jvm.JavaTypeName
+import io.spine.tools.compiler.jvm.JavaTypeName.BOOLEAN
+import io.spine.tools.compiler.jvm.JavaTypeName.BYTE
+import io.spine.tools.compiler.jvm.JavaTypeName.CHAR
+import io.spine.tools.compiler.jvm.JavaTypeName.DOUBLE
+import io.spine.tools.compiler.jvm.JavaTypeName.FLOAT
+import io.spine.tools.compiler.jvm.JavaTypeName.INT
+import io.spine.tools.compiler.jvm.JavaTypeName.LONG
+import io.spine.tools.compiler.jvm.JavaTypeName.SHORT
+import io.spine.tools.compiler.jvm.JavaTypeName.VOID
+import kotlin.system.exitProcess
+
+/**
+ * A program which initializes [JavaTypeName.INT] before the [JavaTypeName] class.
+ *
+ * The program exits with a non-zero code if [JavaTypeName.KnownPrimitives]
+ * differs from the list of all Java primitive types.
+ *
+ * Run it via [runInFreshJvm] so that no Java code model class is initialized beforehand.
+ */
+internal object PrimitiveFirstProgram {
+
+ @JvmStatic
+ fun main(@Suppress("unused") args: Array) {
+ // This is the first access to the `JavaTypeName` hierarchy in the JVM.
+ val first: JavaTypeName = INT
+ val primitives = JavaTypeName.KnownPrimitives
+ val expected = listOf(VOID, BOOLEAN, BYTE, SHORT, first, LONG, CHAR, FLOAT, DOUBLE)
+ if (primitives != expected) {
+ System.err.println("`KnownPrimitives` is `$primitives` instead of `$expected`.")
+ exitProcess(1)
+ }
+ }
+}
diff --git a/version.gradle.kts b/version.gradle.kts
index 5a73218bab8..9c5b46a54bb 100644
--- a/version.gradle.kts
+++ b/version.gradle.kts
@@ -18,7 +18,7 @@
* This version is also used by integration test projects.
* E.g. see `tests/consumer/build.gradle.kts`.
*/
-private val compilerVersion = "2.0.0-SNAPSHOT.082"
+private val compilerVersion = "2.0.0-SNAPSHOT.083"
extra.set("compilerVersion", compilerVersion)
/**