diff --git a/java-compiler-testing/src/main/java/io/github/ascopes/jct/junit/AbstractCompilersProvider.java b/java-compiler-testing/src/main/java/io/github/ascopes/jct/junit/AbstractCompilersProvider.java index 6a8d8e9d4..0ece3f96f 100644 --- a/java-compiler-testing/src/main/java/io/github/ascopes/jct/junit/AbstractCompilersProvider.java +++ b/java-compiler-testing/src/main/java/io/github/ascopes/jct/junit/AbstractCompilersProvider.java @@ -34,22 +34,93 @@ import org.opentest4j.TestAbortedException; /** - * Base for defining a compiler-supplying arguments provider for Junit Jupiter parameterised test + * Base for defining a compiler-supplying arguments-provider for JUnit Jupiter parameterised test * support. * + *

An example annotation would look like the following: + * + *

+ * @ArgumentsSource(MyCompilersProvider.class)
+ * @ParameterizedTest(name = "for {0}")
+ * @Retention(RetentionPolicy.RUNTIME)
+ * @Target({
+ *     ElementType.ANNOTATION_TYPE, 
+ *     ElementType.METHOD,
+ *     ElementType.TYPE,
+ * })
+ * public @interface MyCompilerTest {
+ *     int minVersion() default Integer.MIN_VALUE;
+ *     int maxVersion() default Integer.MAX_VALUE;
+ *     Class[] configurers() default {};
+ * }
+ * 
+ * + *

...with the JUnit5 annotation provider being implemented as: + * + *

+ * public final class MyCompilersProvider
+ *     extends AbstractCompilersProvider
+ *     implements AnnotationConsumer {
+ * 
+ *   @Override
+ *   protected JctCompiler compilerForVersion(int release) {
+ *     return new MyCompilerImpl().release(release);
+ *   }
+ *
+ *   @Override
+ *   protected int minSupportedVersion(boolean modules) {
+ *     return 11;
+ *   }
+ *
+ *   @Override
+ *   protected int maxSupportedVersion(boolean modules) {
+ *     return 19;
+ *   }
+ *
+ *   @Override
+ *   public void accept(MyCompilerTest annotation) {
+ *     super.configure(
+ *         annotation.minVersion(),
+ *         annotation.maxVersion(),
+ *         true,
+ *         annotation.configurers()
+ *     );
+ *   }
+ * }
+ * 
+ * + * This would enable you to define your test cases like so: + * + *
+ * @MyCompilerTest(minVersion=13, maxVersion=17)
+ * void testSomething(JctCompiler compiler) {
+ *   ...
+ * }
+ *
+ * @MyCompilerTest(configurers=WerrorConfigurer.class)
+ * void testSomethingElse(JctCompiler compiler) {
+ *   ...
+ * }
+ *
+ * static class WerrorConfigurer implements JctSimpleCompilerConfigurer {
+ *   @Override
+ *   public void configure(JctCompiler compiler) {
+ *     compiler.failOnErrors(true);
+ *   }
+ * }
+ * 
+ * * @author Ashley Scopes * @since 0.0.1 */ @API(since = "0.0.1", status = Status.STABLE) public abstract class AbstractCompilersProvider implements ArgumentsProvider { - // Configured values by JUnit 5. Volatile in case JUnit ever does this from a different - // thread in the future. - private volatile int minVersion; - private volatile int maxVersion; - - @Nullable - private volatile Class[] configurerClasses; + // Values that are late-bound when configure() is called from the + // AnnotationConsumer. + private int minVersion; + private int maxVersion; + private Class[] configurerClasses; /** * Initialise this provider. @@ -57,7 +128,7 @@ public abstract class AbstractCompilersProvider implements ArgumentsProvider { protected AbstractCompilersProvider() { minVersion = 0; maxVersion = Integer.MAX_VALUE; - configurerClasses = null; + configurerClasses = emptyArray(); } @Override @@ -184,4 +255,8 @@ private JctSimpleCompilerConfigurer initialiseConfigurer( } } + @SuppressWarnings("unchecked") + private static Class[] emptyArray() { + return (Class[]) new Class[0]; + } }