Add support for specifying compiler options
This commit is a prerequisite to help suppressing deprecating warnings by allowing tests to validate that the compiler does not encounter them. See gh-29597
This commit is contained in:
parent
2754da1742
commit
4b14a0b42c
|
@ -24,6 +24,7 @@ import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.UnaryOperator;
|
import java.util.function.UnaryOperator;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import javax.annotation.processing.Processor;
|
import javax.annotation.processing.Processor;
|
||||||
import javax.tools.Diagnostic;
|
import javax.tools.Diagnostic;
|
||||||
|
@ -41,6 +42,7 @@ import org.springframework.lang.Nullable;
|
||||||
*
|
*
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Scott Frederick
|
* @author Scott Frederick
|
||||||
|
* @author Stephane Nicoll
|
||||||
* @since 6.0
|
* @since 6.0
|
||||||
* @see #forSystem()
|
* @see #forSystem()
|
||||||
*/
|
*/
|
||||||
|
@ -59,10 +61,12 @@ public final class TestCompiler {
|
||||||
|
|
||||||
private final List<Processor> processors;
|
private final List<Processor> processors;
|
||||||
|
|
||||||
|
private final List<String> compilerOptions;
|
||||||
|
|
||||||
|
|
||||||
private TestCompiler(@Nullable ClassLoader classLoader, JavaCompiler compiler,
|
private TestCompiler(@Nullable ClassLoader classLoader, JavaCompiler compiler,
|
||||||
SourceFiles sourceFiles, ResourceFiles resourceFiles, ClassFiles classFiles,
|
SourceFiles sourceFiles, ResourceFiles resourceFiles, ClassFiles classFiles,
|
||||||
List<Processor> processors) {
|
List<Processor> processors, List<String> compilerOptions) {
|
||||||
|
|
||||||
this.classLoader = classLoader;
|
this.classLoader = classLoader;
|
||||||
this.compiler = compiler;
|
this.compiler = compiler;
|
||||||
|
@ -70,6 +74,7 @@ public final class TestCompiler {
|
||||||
this.resourceFiles = resourceFiles;
|
this.resourceFiles = resourceFiles;
|
||||||
this.classFiles = classFiles;
|
this.classFiles = classFiles;
|
||||||
this.processors = processors;
|
this.processors = processors;
|
||||||
|
this.compilerOptions = compilerOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -88,7 +93,7 @@ public final class TestCompiler {
|
||||||
*/
|
*/
|
||||||
public static TestCompiler forCompiler(JavaCompiler javaCompiler) {
|
public static TestCompiler forCompiler(JavaCompiler javaCompiler) {
|
||||||
return new TestCompiler(null, javaCompiler, SourceFiles.none(),
|
return new TestCompiler(null, javaCompiler, SourceFiles.none(),
|
||||||
ResourceFiles.none(), ClassFiles.none(), Collections.emptyList());
|
ResourceFiles.none(), ClassFiles.none(), Collections.emptyList(), Collections.emptyList());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -108,7 +113,7 @@ public final class TestCompiler {
|
||||||
public TestCompiler withSources(SourceFile... sourceFiles) {
|
public TestCompiler withSources(SourceFile... sourceFiles) {
|
||||||
return new TestCompiler(this.classLoader, this.compiler,
|
return new TestCompiler(this.classLoader, this.compiler,
|
||||||
this.sourceFiles.and(sourceFiles), this.resourceFiles,
|
this.sourceFiles.and(sourceFiles), this.resourceFiles,
|
||||||
this.classFiles, this.processors);
|
this.classFiles, this.processors, this.compilerOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -119,7 +124,7 @@ public final class TestCompiler {
|
||||||
public TestCompiler withSources(Iterable<SourceFile> sourceFiles) {
|
public TestCompiler withSources(Iterable<SourceFile> sourceFiles) {
|
||||||
return new TestCompiler(this.classLoader, this.compiler,
|
return new TestCompiler(this.classLoader, this.compiler,
|
||||||
this.sourceFiles.and(sourceFiles), this.resourceFiles,
|
this.sourceFiles.and(sourceFiles), this.resourceFiles,
|
||||||
this.classFiles, this.processors);
|
this.classFiles, this.processors, this.compilerOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -130,7 +135,7 @@ public final class TestCompiler {
|
||||||
public TestCompiler withSources(SourceFiles sourceFiles) {
|
public TestCompiler withSources(SourceFiles sourceFiles) {
|
||||||
return new TestCompiler(this.classLoader, this.compiler,
|
return new TestCompiler(this.classLoader, this.compiler,
|
||||||
this.sourceFiles.and(sourceFiles), this.resourceFiles,
|
this.sourceFiles.and(sourceFiles), this.resourceFiles,
|
||||||
this.classFiles, this.processors);
|
this.classFiles, this.processors, this.compilerOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -140,7 +145,8 @@ public final class TestCompiler {
|
||||||
*/
|
*/
|
||||||
public TestCompiler withResources(ResourceFile... resourceFiles) {
|
public TestCompiler withResources(ResourceFile... resourceFiles) {
|
||||||
return new TestCompiler(this.classLoader, this.compiler, this.sourceFiles,
|
return new TestCompiler(this.classLoader, this.compiler, this.sourceFiles,
|
||||||
this.resourceFiles.and(resourceFiles), this.classFiles, this.processors);
|
this.resourceFiles.and(resourceFiles), this.classFiles, this.processors,
|
||||||
|
this.compilerOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -150,7 +156,8 @@ public final class TestCompiler {
|
||||||
*/
|
*/
|
||||||
public TestCompiler withResources(Iterable<ResourceFile> resourceFiles) {
|
public TestCompiler withResources(Iterable<ResourceFile> resourceFiles) {
|
||||||
return new TestCompiler(this.classLoader, this.compiler, this.sourceFiles,
|
return new TestCompiler(this.classLoader, this.compiler, this.sourceFiles,
|
||||||
this.resourceFiles.and(resourceFiles), this.classFiles, this.processors);
|
this.resourceFiles.and(resourceFiles), this.classFiles, this.processors,
|
||||||
|
this.compilerOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -160,7 +167,8 @@ public final class TestCompiler {
|
||||||
*/
|
*/
|
||||||
public TestCompiler withResources(ResourceFiles resourceFiles) {
|
public TestCompiler withResources(ResourceFiles resourceFiles) {
|
||||||
return new TestCompiler(this.classLoader, this.compiler, this.sourceFiles,
|
return new TestCompiler(this.classLoader, this.compiler, this.sourceFiles,
|
||||||
this.resourceFiles.and(resourceFiles), this.classFiles, this.processors);
|
this.resourceFiles.and(resourceFiles), this.classFiles, this.processors,
|
||||||
|
this.compilerOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -170,7 +178,8 @@ public final class TestCompiler {
|
||||||
*/
|
*/
|
||||||
public TestCompiler withClasses(Iterable<ClassFile> classFiles) {
|
public TestCompiler withClasses(Iterable<ClassFile> classFiles) {
|
||||||
return new TestCompiler(this.classLoader, this.compiler, this.sourceFiles,
|
return new TestCompiler(this.classLoader, this.compiler, this.sourceFiles,
|
||||||
this.resourceFiles, this.classFiles.and(classFiles), this.processors);
|
this.resourceFiles, this.classFiles.and(classFiles), this.processors,
|
||||||
|
this.compilerOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -182,7 +191,7 @@ public final class TestCompiler {
|
||||||
List<Processor> mergedProcessors = new ArrayList<>(this.processors);
|
List<Processor> mergedProcessors = new ArrayList<>(this.processors);
|
||||||
mergedProcessors.addAll(Arrays.asList(processors));
|
mergedProcessors.addAll(Arrays.asList(processors));
|
||||||
return new TestCompiler(this.classLoader, this.compiler, this.sourceFiles,
|
return new TestCompiler(this.classLoader, this.compiler, this.sourceFiles,
|
||||||
this.resourceFiles, this.classFiles, mergedProcessors);
|
this.resourceFiles, this.classFiles, mergedProcessors, this.compilerOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -194,7 +203,32 @@ public final class TestCompiler {
|
||||||
List<Processor> mergedProcessors = new ArrayList<>(this.processors);
|
List<Processor> mergedProcessors = new ArrayList<>(this.processors);
|
||||||
processors.forEach(mergedProcessors::add);
|
processors.forEach(mergedProcessors::add);
|
||||||
return new TestCompiler(this.classLoader, this.compiler, this.sourceFiles,
|
return new TestCompiler(this.classLoader, this.compiler, this.sourceFiles,
|
||||||
this.resourceFiles, this.classFiles, mergedProcessors);
|
this.resourceFiles, this.classFiles, mergedProcessors, this.compilerOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@link TestCompiler} instance with the additional compiler options.
|
||||||
|
* @param options the additional compiler options
|
||||||
|
* @return a new {@code TestCompiler} instance
|
||||||
|
* @since 6.1
|
||||||
|
*/
|
||||||
|
public TestCompiler withCompilerOptions(String... options) {
|
||||||
|
List<String> mergedCompilerOptions = Stream.concat(this.compilerOptions.stream(),
|
||||||
|
Arrays.stream(options)).distinct().toList();
|
||||||
|
return new TestCompiler(this.classLoader, this.compiler, this.sourceFiles,
|
||||||
|
this.resourceFiles, this.classFiles, this.processors, mergedCompilerOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@link TestCompiler} instance that fails if any warning is
|
||||||
|
* encountered. This sets the {@code -Xlint:all} and {@code -Werror} compiler
|
||||||
|
* options.
|
||||||
|
* @return a new {@code TestCompiler} instance
|
||||||
|
* @since 6.1
|
||||||
|
* @see #withCompilerOptions(String...)
|
||||||
|
*/
|
||||||
|
public TestCompiler failOnWarning() {
|
||||||
|
return withCompilerOptions("-Xlint:all", "-Werror");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -275,8 +309,8 @@ public final class TestCompiler {
|
||||||
standardFileManager, classLoaderToUse, this.classFiles, this.resourceFiles);
|
standardFileManager, classLoaderToUse, this.classFiles, this.resourceFiles);
|
||||||
if (!this.sourceFiles.isEmpty()) {
|
if (!this.sourceFiles.isEmpty()) {
|
||||||
Errors errors = new Errors();
|
Errors errors = new Errors();
|
||||||
CompilationTask task = this.compiler.getTask(null, fileManager, errors, null,
|
CompilationTask task = this.compiler.getTask(null, fileManager, errors,
|
||||||
null, compilationUnits);
|
this.compilerOptions, null, compilationUnits);
|
||||||
if (!this.processors.isEmpty()) {
|
if (!this.processors.isEmpty()) {
|
||||||
task.setProcessors(this.processors);
|
task.setProcessors(this.processors);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2022 the original author or authors.
|
* Copyright 2002-2023 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -43,6 +43,7 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
* @author Scott Frederick
|
* @author Scott Frederick
|
||||||
|
* @author Stephane Nicoll
|
||||||
*/
|
*/
|
||||||
class TestCompilerTests {
|
class TestCompilerTests {
|
||||||
|
|
||||||
|
@ -87,6 +88,20 @@ class TestCompilerTests {
|
||||||
}
|
}
|
||||||
""";
|
""";
|
||||||
|
|
||||||
|
private static final String HELLO_DEPRECATED = """
|
||||||
|
package com.example;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public class Hello implements Supplier<String> {
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public String get() {
|
||||||
|
return "Hello Deprecated";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
@ -119,6 +134,70 @@ class TestCompilerTests {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
void compileWhenSourceUseDeprecateCodeAndNoOptionSet() {
|
||||||
|
SourceFile main = SourceFile.of("""
|
||||||
|
package com.example;
|
||||||
|
|
||||||
|
public class Main {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
new Hello().get();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
""");
|
||||||
|
TestCompiler.forSystem().withSources(
|
||||||
|
SourceFile.of(HELLO_DEPRECATED), main).compile(compiled -> {
|
||||||
|
Supplier<String> supplier = compiled.getInstance(Supplier.class,
|
||||||
|
"com.example.Hello");
|
||||||
|
assertThat(supplier.get()).isEqualTo("Hello Deprecated");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void compileWhenSourceUseDeprecateCodeAndFailOnWarningIsSet() {
|
||||||
|
SourceFile main = SourceFile.of("""
|
||||||
|
package com.example;
|
||||||
|
|
||||||
|
public class Main {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
new Hello().get();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
""");
|
||||||
|
assertThatExceptionOfType(CompilationException.class).isThrownBy(
|
||||||
|
() -> TestCompiler.forSystem().failOnWarning().withSources(
|
||||||
|
SourceFile.of(HELLO_DEPRECATED), main).compile(compiled -> {
|
||||||
|
})).withMessageContaining("warnings found and -Werror specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
void compileWhenSourceUseDeprecateCodeAndFailOnWarningWithSuppressWarnings() {
|
||||||
|
SourceFile main = SourceFile.of("""
|
||||||
|
package com.example;
|
||||||
|
|
||||||
|
public class Main {
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
public static void main(String[] args) {
|
||||||
|
new Hello().get();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
""");
|
||||||
|
TestCompiler.forSystem().failOnWarning().withSources(
|
||||||
|
SourceFile.of(HELLO_DEPRECATED), main).compile(compiled -> {
|
||||||
|
Supplier<String> supplier = compiled.getInstance(Supplier.class,
|
||||||
|
"com.example.Hello");
|
||||||
|
assertThat(supplier.get()).isEqualTo("Hello Deprecated");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void withSourcesArrayAddsSource() {
|
void withSourcesArrayAddsSource() {
|
||||||
SourceFile sourceFile = SourceFile.of(HELLO_WORLD);
|
SourceFile sourceFile = SourceFile.of(HELLO_WORLD);
|
||||||
|
|
Loading…
Reference in New Issue