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) /**