001/* 002 * Copyright (C) 2022 - 2023, the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package io.github.ascopes.jct.junit; 017 018import io.github.ascopes.jct.compilers.JctCompilerConfigurer; 019import io.github.ascopes.jct.compilers.javac.JavacJctCompilerImpl; 020import java.lang.annotation.Documented; 021import java.lang.annotation.ElementType; 022import java.lang.annotation.Inherited; 023import java.lang.annotation.Retention; 024import java.lang.annotation.RetentionPolicy; 025import java.lang.annotation.Target; 026import org.apiguardian.api.API; 027import org.apiguardian.api.API.Status; 028import org.junit.jupiter.api.Tag; 029import org.junit.jupiter.api.Tags; 030import org.junit.jupiter.api.TestTemplate; 031import org.junit.jupiter.api.condition.DisabledInNativeImage; 032import org.junit.jupiter.params.ParameterizedTest; 033import org.junit.jupiter.params.provider.ArgumentsSource; 034 035/** 036 * Annotation that can be applied to a {@link ParameterizedTest} to enable passing in a range of 037 * {@link JavacJctCompilerImpl} instances with specific configured versions as the first 038 * parameter. 039 * 040 * <p>This will also add the {@code "java-compiler-testing-test"} tag and {@code "javac-test"} 041 * tags to your test method, meaning you can instruct your IDE or build system to optionally only 042 * run tests annotated with this method for development purposes. As an example, Maven Surefire 043 * could be instructed to only run these tests by passing {@code -Dgroup="javac-test"} to Maven. 044 * 045 * <p>If your build is running in a GraalVM Native Image, then this test will not execute, as 046 * the <em>Java Compiler Testing</em> API is not yet tested within Native Images. 047 * 048 * @author Ashley Scopes 049 * @since 0.0.1 050 */ 051@API(since = "0.0.1", status = Status.STABLE) 052@ArgumentsSource(JavacCompilersProvider.class) 053@DisabledInNativeImage 054@Documented 055@Inherited 056@ParameterizedTest(name = "for compiler \"{0}\"") 057@Retention(RetentionPolicy.RUNTIME) 058@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.TYPE}) 059@TestTemplate 060@Tags({ 061 @Tag("java-compiler-testing-test"), 062 @Tag("javac-test") 063}) 064public @interface JavacCompilerTest { 065 066 /** 067 * Minimum version to use (inclusive). 068 * 069 * @return the minimum version. 070 */ 071 int minVersion() default Integer.MIN_VALUE; 072 073 /** 074 * Maximum version to use (inclusive). 075 * 076 * @return the maximum version. 077 */ 078 int maxVersion() default Integer.MAX_VALUE; 079 080 /** 081 * Get an array of compiler configurers to apply in-order before starting the test. 082 * 083 * <p>Each configurer must have a public no-args constructor, and their package must be 084 * open to this module if JPMS modules are in-use. 085 * 086 * @return an array of classes to run to configure the compiler. These run in the given order. 087 */ 088 Class<? extends JctCompilerConfigurer<?>>[] configurers() default {}; 089 090 /** 091 * Whether we need to support modules or not. 092 * 093 * <p>Setting this to true will skip any versions of the compiler that do not support JPMS 094 * modules. 095 * 096 * @return {@code true} if we need to support modules, or {@code false} if we do not. 097 */ 098 boolean modules() default false; 099 100 /** 101 * The version strategy to use. 102 * 103 * <p>This determines whether the version number being iterated across specifies the 104 * release, source, target, or source and target versions. 105 * 106 * <p>The default is to specify the release. 107 * 108 * @return the version strategy to use. 109 */ 110 VersionStrategy versionStrategy() default VersionStrategy.RELEASE; 111}