newFound = new ArrayList<>();
+ if(!dir.isDirectory()) {
+ throw new RuntimeException("file " + dir.getAbsolutePath() + " expected to be a dir");
+ }
+ for (File child : dir.listFiles()) {
+ if (child.isDirectory()) {
+ stream = scanClasses(child, (packageName.isEmpty() ? "" : packageName + ".") + child.getName(), stream);
+
+ } else if (child.isFile() && child.getName().endsWith(".java")) {
+ newFound.add(packageName + "." + child.getName().replace(".java", ""));
+ }
+ }
+ if (!newFound.isEmpty()) {
+ stream = Stream.concat(stream, newFound.stream());
+ }
+ return stream;
+ }
+
+ void applyCandidateClass(String className) {
+ Class> clazz;
+ try {
+ clazz = Class.forName(className);
+ if (clazz.getAnnotation(TestJCM.class) != null) {
+ runGeneration(clazz);
+ }
+ } catch (ClassNotFoundException | IllegalAccessException | IllegalArgumentException
+ | InvocationTargetException | InstantiationException | NoSuchMethodException | SecurityException
+ | IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private void runGeneration(Class> clazz)
+ throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException,
+ NoSuchMethodException, SecurityException, IOException {
+ for (Method m : clazz.getDeclaredMethods()) {
+ // only apply to methods public, with 0 args, and that produce a JCodeModel
+ if ((m.getModifiers() & Modifier.PUBLIC) > 0
+ && m.getParameterCount() == 0) {
+ if (m.getReturnType().equals(JCodeModel.class)) {
+ m.setAccessible(true);
+ JCodeModel produced = null;
+ if ((m.getModifiers() & Modifier.STATIC) > 0) {
+ produced = (JCodeModel) m.invoke(null);
+ } else {
+ Object inst = clazz.getDeclaredConstructor().newInstance();
+ produced = (JCodeModel) m.invoke(inst);
+ }
+ if (produced != null) {
+ new JCMWriter(produced).build(outputDir, (IProgressTracker) null);
+ }
+ }
+ }
+ }
+ }
+
+}
diff --git a/jcodemodeltests/src/main/java/com/helger/jcodemodel/compile/annotation/TestJCM.java b/jcodemodeltests/src/main/java/com/helger/jcodemodel/compile/annotation/TestJCM.java
new file mode 100644
index 00000000..e10bc6dd
--- /dev/null
+++ b/jcodemodeltests/src/main/java/com/helger/jcodemodel/compile/annotation/TestJCM.java
@@ -0,0 +1,12 @@
+package com.helger.jcodemodel.compile.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface TestJCM {
+
+}
diff --git a/jcodemodeltests/src/main/java/com/helger/jcodemodel/tests/basic/SimpleClassGenerating.java b/jcodemodeltests/src/main/java/com/helger/jcodemodel/tests/basic/SimpleClassGenerating.java
new file mode 100644
index 00000000..2b698ce5
--- /dev/null
+++ b/jcodemodeltests/src/main/java/com/helger/jcodemodel/tests/basic/SimpleClassGenerating.java
@@ -0,0 +1,27 @@
+package com.helger.jcodemodel.tests.basic;
+
+import com.helger.jcodemodel.JCodeModel;
+import com.helger.jcodemodel.compile.annotation.TestJCM;
+import com.helger.jcodemodel.exceptions.JCodeModelException;
+
+@TestJCM
+public class SimpleClassGenerating {
+
+ public JCodeModel createSimple1() throws JCodeModelException {
+ JCodeModel cm = new JCodeModel();
+ cm._class("com.helger.jcodemodel.tests.basic.Simple1");
+ return cm;
+ }
+
+ public JCodeModel createSimple2() throws JCodeModelException {
+ JCodeModel cm = new JCodeModel();
+ cm._class("com.helger.jcodemodel.tests.basic.Simple2");
+ return cm;
+ }
+
+ /** protected so should not be selected */
+ protected JCodeModel protectedCall() {
+ return null;
+ }
+
+}
diff --git a/jcodemodeltests/src/main/java/com/helger/jcodemodel/tests/record/JRecordTestGen.java b/jcodemodeltests/src/main/java/com/helger/jcodemodel/tests/record/JRecordTestGen.java
new file mode 100644
index 00000000..91c9d944
--- /dev/null
+++ b/jcodemodeltests/src/main/java/com/helger/jcodemodel/tests/record/JRecordTestGen.java
@@ -0,0 +1,410 @@
+package com.helger.jcodemodel.tests.record;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import com.helger.jcodemodel.JCodeModel;
+import com.helger.jcodemodel.JDefinedClass;
+import com.helger.jcodemodel.JExpr;
+import com.helger.jcodemodel.JMethod;
+import com.helger.jcodemodel.JMod;
+import com.helger.jcodemodel.JRecordComponent;
+import com.helger.jcodemodel.JTypeVar;
+import com.helger.jcodemodel.JVar;
+import com.helger.jcodemodel.compile.annotation.TestJCM;
+import com.helger.jcodemodel.exceptions.JCodeModelException;
+
+@TestJCM
+public class JRecordTestGen {
+
+ public final String rootPackage=getClass().getPackageName();
+
+ /**
+ * Test: Basic record with two components Expected output:
+ *
+ *
+ * package org.example;
+ *
+ * public record Point(int x, int y) {
+ * }
+ *
+ *
+ * @throws JCodeModelException
+ * In case of error
+ */
+ public JCodeModel testBasicRecord() throws JCodeModelException
+ {
+ final JCodeModel cm = new JCodeModel ();
+ final JDefinedClass rec = cm._package (rootPackage)._record ("BasicPoint");
+ rec.recordComponent (cm.INT, "x");
+ rec.recordComponent (cm.INT, "y");
+ return cm;
+ }
+
+ /**
+ * Test: Empty record (no components) Expected output:
+ *
+ *
+ * public record Empty ()
+ * {}
+ *
+ *
+ * @throws JCodeModelException
+ * In case of error
+ */
+ public JCodeModel testEmptyRecord() throws JCodeModelException
+ {
+ final JCodeModel cm = new JCodeModel ();
+ cm._package(rootPackage)._record("Empty");
+ return cm;
+ }
+
+ /**
+ * Test: Record with object type components Expected output:
+ *
+ *
+ * public record Person (String name, Integer age)
+ * {}
+ *
+ *
+ * @throws JCodeModelException
+ * In case of error
+ */
+ public JCodeModel testRecordWithObjectComponents() throws JCodeModelException
+ {
+ final JCodeModel cm = new JCodeModel ();
+ final JDefinedClass rec = cm._package (rootPackage)._record ("Person");
+ rec.recordComponent (cm.ref (String.class), "name");
+ rec.recordComponent (cm.ref (Integer.class), "age");
+ return cm;
+ }
+
+ /**
+ * Test: Record implementing an interface Expected output:
+ *
+ *
+ * public record NamedPoint (int x, int y, String name) implements Comparable <NamedPoint>
+ * {}
+ *
+ *
+ * @throws JCodeModelException
+ * In case of error
+ */
+ public JCodeModel testRecordImplementsInterface() throws JCodeModelException
+ {
+ final JCodeModel cm = new JCodeModel ();
+ final JDefinedClass rec = cm._package (rootPackage)._record ("NamedPoint");
+ rec.recordComponent (cm.INT, "x");
+ rec.recordComponent (cm.INT, "y");
+ rec.recordComponent (cm.ref (String.class), "name");
+ rec._implements (cm.ref (Comparable.class).narrow (rec));
+ JMethod cmp = rec.method(JMod.PUBLIC, cm.INT, "compareTo");
+ cmp.param(rec, "other");
+ cmp.body()._return(JExpr.lit(0));
+ return cm;
+ }
+
+ /**
+ * Test: Generic record with type parameters Expected output:
+ *
+ *
+ * public record Pair<T, U>(T first, U second) {
+ * }
+ *
+ *
+ * @throws JCodeModelException
+ * In case of error
+ */
+ public JCodeModel testGenericRecord() throws JCodeModelException
+ {
+ final JCodeModel cm = new JCodeModel();
+ final JDefinedClass rec = cm._package(rootPackage)._record("Pair");
+ final JTypeVar t = rec.generify("T");
+ final JTypeVar u = rec.generify("U");
+ rec.recordComponent(t, "first");
+ rec.recordComponent(u, "second");
+ return cm;
+ }
+
+ /**
+ * Test: Record with bounded generic type parameter Expected output:
+ *
+ *
+ * public record NumberPair<T extends Number>(T first, T second) {
+ * }
+ *
+ *
+ * @throws JCodeModelException
+ * In case of error
+ */
+ public JCodeModel testRecordWithBoundedTypeParameter() throws JCodeModelException
+ {
+ final JCodeModel cm = new JCodeModel();
+ final JDefinedClass rec = cm._package(rootPackage)._record("PairNumber");
+ final JTypeVar t = rec.generify("T", Number.class);
+ rec.recordComponent(t, "first");
+ rec.recordComponent(t, "second");
+ return cm;
+ }
+
+ /**
+ * Test: Record with annotated component Expected output:
+ *
+ *
+ * public record Person(@NonNull String name, int age) {
+ * }
+ *
+ *
+ * @throws JCodeModelException
+ * In case of error
+ */
+ public JCodeModel testRecordWithAnnotatedComponent() throws JCodeModelException
+ {
+ final JCodeModel cm = new JCodeModel();
+ final JDefinedClass rec = cm._package(rootPackage)._record("AnnotatedPerson");
+ final JRecordComponent nameComponent = rec.recordComponent(cm.ref(String.class), "name");
+ nameComponent.annotate(RecordAnnotationExample.class);
+ rec.recordComponent(cm.INT, "age");
+ return cm;
+ }
+
+ /**
+ * we need a specific record annotation to be kept
+ */
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.RECORD_COMPONENT)
+ public @interface RecordAnnotationExample
+ {
+ }
+
+ /**
+ * Test: Record with compact constructor (validation) Expected output:
+ *
+ *
+ * public record Range(int lo, int hi) {
+ * public Range {
+ * if (lo > hi) {
+ * throw new IllegalArgumentException();
+ * }
+ * }
+ * }
+ *
+ *
+ * @throws JCodeModelException
+ * In case of error
+ */
+ public JCodeModel testRecordWithCompactConstructor() throws JCodeModelException
+ {
+ final JCodeModel cm = new JCodeModel();
+ final JDefinedClass rec = cm._package(rootPackage)._record("Range");
+ final JRecordComponent rcLo = rec.recordComponent(cm.INT, "lo");
+ final JRecordComponent rcHi = rec.recordComponent(cm.INT, "hi");
+
+ // Compact constructor - no parameter list, just validation logic
+ final JMethod compactCtor = rec.compactConstructor(JMod.PUBLIC);
+ compactCtor.body()
+ ._if(JExpr.ref(rcLo).gt(JExpr.ref(rcHi)))
+ ._then()
+ ._throw(cm.ref(IllegalArgumentException.class), JExpr.lit("High must be greater or equal to Low"));
+ return cm;
+ }
+
+ /**
+ * Test: Record with explicit canonical constructor Expected output:
+ *
+ *
+ * public record Range(int lo, int hi) {
+ * public Range(int lo, int hi) {
+ * if (lo > hi) {
+ * throw new IllegalArgumentException();
+ * }
+ * this.lo = lo;
+ * this.hi = hi;
+ * }
+ * }
+ *
+ *
+ * @throws JCodeModelException
+ * In case of error
+ */
+ public JCodeModel testRecordWithCanonicalConstructor() throws JCodeModelException
+ {
+ final JCodeModel cm = new JCodeModel();
+ final JDefinedClass rec = cm._package(rootPackage)._record("RangeCanonical");
+ final JRecordComponent rcLo = rec.recordComponent(cm.INT, "lo");
+ final JRecordComponent rcHi = rec.recordComponent(cm.INT, "hi");
+
+ // Canonical constructor - must have same parameters as record components
+ final JMethod ctor = rec.constructor(JMod.PUBLIC);
+ final JVar loParam = ctor.param(cm.INT, "lo");
+ final JVar hiParam = ctor.param(cm.INT, "hi");
+ ctor.body()._if(loParam.gt(hiParam))._then()
+ ._throw(cm.ref(IllegalArgumentException.class),
+ JExpr.lit("lo must be < hi"));
+ ctor.body().assign(JExpr.refthis(rcLo), loParam);
+ ctor.body().assign(JExpr.refthis(rcHi), hiParam);
+ return cm;
+ }
+
+ /**
+ * Test: Record with additional instance method Expected output:
+ *
+ *
+ * public record Point (int x, int y)
+ * {
+ * public double distance ()
+ * {
+ * return Math.sqrt ((x * x) + (y * y));
+ * }
+ * }
+ *
+ *
+ * @throws JCodeModelException
+ * In case of error
+ */
+ public JCodeModel testRecordWithMethod () throws JCodeModelException
+ {
+ final JCodeModel cm = new JCodeModel ();
+ final JDefinedClass rec = cm._package(rootPackage)._record("PointDistance");
+ final JRecordComponent rcX = rec.recordComponent (cm.INT, "x");
+ final JRecordComponent rcY = rec.recordComponent (cm.INT, "y");
+
+ final JMethod method = rec.method (JMod.PUBLIC, cm.DOUBLE, "distance");
+ method.body ()
+ ._return (cm.ref (Math.class)
+ .staticInvoke ("sqrt")
+ .arg (JExpr.ref (rcX).mul (JExpr.ref (rcX)).plus (JExpr.ref (rcY).mul (JExpr.ref (rcY)))));
+ return cm;
+ }
+
+ /**
+ * Test: Record with static field and method Expected output:
+ *
+ *
+ * public record Point(int x, int y) {
+ * public static final Point ORIGIN = new Point(0, 0);
+ *
+ * public static Point of(int x, int y) {
+ * return new Point(x, y);
+ * }
+ * }
+ *
+ *
+ * @throws JCodeModelException
+ * In case of error
+ */
+ public JCodeModel testRecordWithStaticMembers() throws JCodeModelException
+ {
+ final JCodeModel cm = new JCodeModel();
+ final JDefinedClass rec = cm._package(rootPackage)._record("PointStatic");
+ rec.recordComponent(cm.INT, "x");
+ rec.recordComponent(cm.INT, "y");
+
+ // Static field
+ rec.field(JMod.PUBLIC | JMod.STATIC | JMod.FINAL,
+ rec,
+ "ORIGIN",
+ JExpr._new(rec).arg(JExpr.lit(0)).arg(JExpr.lit(0)));
+
+ // Static factory method
+ final JMethod factory = rec.method(JMod.PUBLIC | JMod.STATIC, rec, "of");
+ final JVar xParam = factory.param(cm.INT, "x");
+ final JVar yParam = factory.param(cm.INT, "y");
+ factory.body()._return(JExpr._new(rec).arg(xParam).arg(yParam));
+ return cm;
+ }
+
+ /**
+ * Test: Nested record inside a class Expected output:
+ *
+ *
+ * public class Outer {
+ * public record Inner(String value) {
+ * }
+ * }
+ *
+ *
+ * @throws JCodeModelException
+ * In case of error
+ */
+ public JCodeModel testNestedRecord() throws JCodeModelException
+ {
+ final JCodeModel cm = new JCodeModel();
+ final JDefinedClass outer = cm._package(rootPackage)._class("Outer");
+ final JDefinedClass inner = outer._record(JMod.PUBLIC, "Inner");
+ inner.recordComponent(cm.ref(String.class), "value");
+ return cm;
+ }
+
+ /**
+ * Test: Record with javadoc Expected output:
+ *
+ *
+ * /**
+ * * Represents a 2D point.
+ * *
+ * * @param x the x coordinate
+ * * @param y the y coordinate
+ * *\/
+ * public record Point(int x, int y) {
+ * }
+ *
+ *
+ * @throws JCodeModelException
+ * In case of error
+ */
+ public JCodeModel testRecordWithJavadoc() throws JCodeModelException
+ {
+ final JCodeModel cm = new JCodeModel();
+ final JDefinedClass rec = cm._package(rootPackage)._record("PointJavadoc");
+ final JRecordComponent rcX = rec.recordComponent(cm.INT, "x");
+ final JRecordComponent rcY = rec.recordComponent(cm.INT, "y");
+ rec.javadoc().add("Represents a 2D point.");
+ rec.javadoc().addParam(rcX).add("the x coordinate");
+ rec.javadoc().addParam(rcY).add("the y coordinate");
+ return cm;
+ }
+
+ /**
+ * Test: Record with varargs component (last component can be varargs) Expected
+ * output:
+ *
+ *
+ * public record VarArgsRecord(String name, int... values) {
+ * }
+ *
+ *
+ * @throws JCodeModelException
+ * In case of error
+ */
+ public JCodeModel testRecordWithVarargsComponent() throws JCodeModelException
+ {
+ final JCodeModel cm = new JCodeModel();
+ final JDefinedClass rec = cm._package(rootPackage)._record("SeriesVarArgs");
+ rec.recordComponent(cm.ref(String.class), "name");
+ rec.recordComponentVararg(cm.INT, "values");
+ return cm;
+ }
+
+ /**
+ * Test: Record with array component Expected output:
+ *
+ *
+ * public record ArrayRecord(String[] names, int[][] matrix) {
+ * }
+ *
+ *
+ * @throws JCodeModelException
+ * In case of error
+ */
+ public JCodeModel testRecordWithArrayComponent() throws JCodeModelException {
+ final JCodeModel cm = new JCodeModel();
+ final JDefinedClass rec = cm._package(rootPackage)._record("ArrayRecord");
+ rec.recordComponent(cm.ref(String.class).array(), "names");
+ rec.recordComponent(cm.INT.array().array(), "matrix");
+ return cm;
+ }
+
+}
diff --git a/jcodemodeltests/src/test/java/com/helger/jcodemodel/tests/basic/TestBasic.java b/jcodemodeltests/src/test/java/com/helger/jcodemodel/tests/basic/TestBasic.java
new file mode 100644
index 00000000..1ae76d35
--- /dev/null
+++ b/jcodemodeltests/src/test/java/com/helger/jcodemodel/tests/basic/TestBasic.java
@@ -0,0 +1,13 @@
+package com.helger.jcodemodel.tests.basic;
+
+import org.junit.Test;
+
+public class TestBasic {
+
+ @Test
+ public void testBasic() {
+ new Simple1();
+ new Simple2();
+ }
+
+}
diff --git a/jcodemodeltests/src/test/java/com/helger/jcodemodel/tests/record/JRecordTest.java b/jcodemodeltests/src/test/java/com/helger/jcodemodel/tests/record/JRecordTest.java
new file mode 100644
index 00000000..79b91d11
--- /dev/null
+++ b/jcodemodeltests/src/test/java/com/helger/jcodemodel/tests/record/JRecordTest.java
@@ -0,0 +1,241 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
+ * Portions Copyright 2013-2026 Philip Helger + contributors
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License"). You
+ * may not use this file except in compliance with the License. You can
+ * obtain a copy of the License at
+ * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
+ * or packager/legal/LICENSE.txt. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at packager/legal/LICENSE.txt.
+ *
+ * GPL Classpath Exception:
+ * Oracle designates this particular file as subject to the "Classpath"
+ * exception as provided by Oracle in the GPL Version 2 section of the License
+ * file that accompanied this code.
+ *
+ * Modifications:
+ * If applicable, add the following below the License Header, with the fields
+ * enclosed by brackets [] replaced by your own identifying information:
+ * "Portions Copyright [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above. However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+package com.helger.jcodemodel.tests.record;
+
+import java.lang.reflect.RecordComponent;
+import java.math.BigDecimal;
+import java.util.stream.Stream;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.helger.jcodemodel.tests.record.*;
+import com.helger.jcodemodel.tests.record.JRecordTestGen.RecordAnnotationExample;
+import com.helger.jcodemodel.tests.record.Outer.Inner;
+
+/**
+ * Test class for Java record support. Java records (JEP 395, Java 16+) are a special kind of class
+ * that acts as a transparent carrier for immutable data. Records automatically provide: - A
+ * canonical constructor - Private final fields for each component - Public accessor methods for
+ * each component (same name as component) - equals(), hashCode(), and toString() implementations
+ */
+public final class JRecordTest
+{
+
+ /**
+ * tests {@link JRecordTestGen#testBasicRecord()}
+ */
+ @Test
+ public void testBasicRecord()
+ {
+ BasicPoint test = new BasicPoint(2, 3);
+ Assert.assertTrue(test instanceof Record);
+ Assert.assertEquals(2, test.x());
+ Assert.assertEquals(3, test.y());
+ }
+
+ /**
+ * tests {@link JRecordTestGen#testEmptyRecord()}
+ */
+ @Test
+ public void testEmptyRecord()
+ {
+ Empty test = new Empty();
+ Assert.assertTrue(test instanceof Record);
+ }
+
+ /**
+ * tests {@link JRecordTestGen#testRecordWithObjectComponents()}
+ */
+ @Test
+ public void testRecordWithObjectComponents()
+ {
+ Person test = new Person("John", 42);
+ Assert.assertTrue(test instanceof Record);
+ Assert.assertEquals((Integer) 42, test.age());
+ Assert.assertEquals("John", test.name());
+ }
+
+ /**
+ * tests {@link JRecordTestGen#testRecordImplementsInterface()}
+ */
+ @Test
+ public void testRecordImplementsInterface()
+ {
+ NamedPoint test = new NamedPoint(5, 10, "15");
+ Assert.assertTrue(test instanceof Record);
+ Assert.assertTrue(test instanceof Comparable);
+ Assert.assertEquals("15", test.name());
+ Assert.assertEquals(5, test.x());
+ Assert.assertEquals(10, test.y());
+ }
+
+ /**
+ * tests {@link JRecordTestGen#testGenericRecord()}
+ */
+ @Test
+ public void testGenericRecord()
+ {
+ Pair test = new Pair<>(666, "BE NOT AFRAID");
+ Assert.assertTrue(test instanceof Record);
+ Assert.assertEquals((Integer) 666, test.first());
+ Assert.assertEquals("BE NOT AFRAID", test.second());
+ }
+
+ /**
+ * tests {@link JRecordTestGen#testRecordWithBoundedTypeParameter()}
+ */
+ @Test
+ public void testRecordWithBoundedTypeParameter()
+ {
+ PairNumber test = new PairNumber<>(BigDecimal.ONE, BigDecimal.ZERO);
+ Assert.assertTrue(test instanceof Record);
+ }
+
+ /**
+ * tests {@link JRecordTestGen#testRecordWithAnnotatedComponent()}
+ *
+ * @throws SecurityException
+ * @throws NoSuchFieldException
+ */
+ @Test
+ public void testRecordWithAnnotatedComponent()
+ {
+ AnnotatedPerson test = new AnnotatedPerson("Salomon", 2000);
+ Assert.assertTrue(test instanceof Record);
+
+ RecordComponent fieldComponent = Stream.of(test.getClass().getRecordComponents())
+ .filter(rc -> rc.getName().equals("name"))
+ .findFirst().get();
+ Assert.assertTrue(fieldComponent.isAnnotationPresent(RecordAnnotationExample.class));
+ }
+
+ /**
+ * tests {@link JRecordTestGen#testRecordWithCompactConstructor()}
+ */
+ @Test
+ public void testRecordWithCompactConstructor()
+ {
+ Range test = new Range(1, 5);
+ Assert.assertTrue(test instanceof Record);
+ Assert.assertThrows(IllegalArgumentException.class, () -> new Range(5, 1));
+ }
+
+ /**
+ * tests {@link JRecordTestGen#testRecordWithCanonicalConstructor()}
+ */
+ @Test
+ public void testRecordWithCanonicalConstructor()
+ {
+ RangeCanonical test = new RangeCanonical(1, 5);
+ Assert.assertTrue(test instanceof Record);
+ Assert.assertThrows(IllegalArgumentException.class, () -> new RangeCanonical(5, 1));
+ }
+
+ /**
+ * tests {@link JRecordTestGen#testRecordWithMethod()}
+ */
+ @Test
+ public void testRecordWithMethod ()
+ {
+ PointDistance test = new PointDistance(0, 0);
+ Assert.assertTrue(test instanceof Record);
+ Assert.assertEquals(0, test.distance(), 0.0);
+ }
+
+ /**
+ * tests {@link JRecordTestGen#testRecordWithStaticMembers()}
+ */
+ @Test
+ public void testRecordWithStaticMembers()
+ {
+ PointStatic test = PointStatic.ORIGIN;
+ Assert.assertTrue(test instanceof Record);
+ test = PointStatic.of(6, 78);
+ Assert.assertEquals(6, test.x());
+ Assert.assertEquals(78, test.y());
+ }
+
+ /**
+ * tests {@link JRecordTestGen#testNestedRecord()}
+ */
+ @Test
+ public void testNestedRecord()
+ {
+ Inner test = new Inner("NaN");
+ Assert.assertTrue(test instanceof Record);
+ Assert.assertEquals("NaN", test.value());
+ }
+
+ /**
+ * tests {@link JRecordTestGen#testRecordWithJavadoc()}
+ */
+ @Test
+ public void testRecordWithJavadoc() {
+ // nothing to do to test javadoc ??
+ PointJavadoc test = new PointJavadoc(0, 0);
+ Assert.assertTrue(test instanceof Record);
+ }
+
+ /**
+ * tests {@link JRecordTestGen#testRecordWithVarargsComponent()}
+ */
+ @Test
+ public void testRecordWithVarargsComponent()
+ {
+ SeriesVarArgs test = new SeriesVarArgs("Fibonacci", 1,1,3,4);
+ Assert.assertTrue(test instanceof Record);
+ Assert.assertArrayEquals(test.values(), new int[] { 1, 1, 3, 4 });
+ }
+
+ /**
+ * tests {@link JRecordTestGen#testRecordWithArrayComponent()}
+ */
+ @Test
+ public void testRecordWithArrayComponent() {
+ ArrayRecord test = new ArrayRecord(new String[] { "id" }, new int[][] { { 1, 2 } });
+ Assert.assertTrue(test instanceof Record);
+ Assert.assertArrayEquals(test.names(), new String[] { "id" });
+ Assert.assertArrayEquals(test.matrix()[0], new int[] { 1, 2 });
+
+ }
+
+}
diff --git a/plugin/generators/json/src/main/java/com/helger/jcodemodel/plugin/generators/json/JsonGenerator.java b/plugin/generators/json/src/main/java/com/helger/jcodemodel/plugin/generators/json/JsonGenerator.java
index cc5e8e0c..2763fa00 100644
--- a/plugin/generators/json/src/main/java/com/helger/jcodemodel/plugin/generators/json/JsonGenerator.java
+++ b/plugin/generators/json/src/main/java/com/helger/jcodemodel/plugin/generators/json/JsonGenerator.java
@@ -56,7 +56,6 @@ protected JsonPackage load (InputStream source) throws IOException
protected Stream visitPackage (JsonPackage pck, String path)
{
- System.err.println ("visit package " + path);
Stream ret = Stream.empty ();
if (pck.isClassInfo ())
{
diff --git a/plugin/pom.xml b/plugin/pom.xml
index 2492d07d..30347dbd 100644
--- a/plugin/pom.xml
+++ b/plugin/pom.xml
@@ -19,8 +19,9 @@
4.0.0
com.helger.jcodemodel
- jcodemodel-parent-pom
+ bom
4.2.0-SNAPSHOT
+ ../bom
plugin
pom
diff --git a/pom.xml b/pom.xml
index 2cd9d6a3..f46d1649 100644
--- a/pom.xml
+++ b/pom.xml
@@ -112,9 +112,11 @@
+ bom
jcodemodel
plugin
examples
+ jcodemodeltests
@@ -127,25 +129,7 @@
pom
import
-
-
-
- com.helger
- jcodemodel
- ${project.version}
-