diff --git a/pom.xml b/pom.xml index 251df4366..d3c57a349 100644 --- a/pom.xml +++ b/pom.xml @@ -23,12 +23,12 @@ under the License. org.apache.maven.plugins maven-plugins - 43 + 45 maven-compiler-plugin - 3.14.0 + 3.14.1 maven-plugin Apache Maven Compiler Plugin @@ -48,7 +48,7 @@ under the License. scm:git:https://github.com/apache/maven-compiler-plugin.git scm:git:https://github.com/apache/maven-compiler-plugin.git - maven-compiler-plugin-3.14.0 + maven-compiler-plugin-3.14.1 https://github.com/apache/maven-compiler-plugin/tree/${project.scm.tag} @@ -67,16 +67,16 @@ under the License. - 3.9.9 + 3.9.11 2.15.0 2.4.21 3.7.0 2.5.14-02 - 1.4.0 + 1.5.0 8 false - 2025-02-17T21:03:09Z + 2025-09-18T23:34:28Z org.apache.maven.plugins.compiler.its @@ -84,6 +84,7 @@ under the License. org.apache.maven.plugin-tools maven-plugin-annotations + ${version.maven-plugin-tools} provided @@ -105,6 +106,12 @@ under the License. ${mavenVersion} provided + + + org.ow2.asm + asm + 9.8 + org.apache.maven.shared maven-shared-utils @@ -238,6 +245,7 @@ under the License. org.apache.maven.plugins maven-invoker-plugin + 3.9.1 integration-test diff --git a/src/it/GH-331-no-module-version/invoker.properties b/src/it/GH-331-no-module-version/invoker.properties new file mode 100644 index 000000000..951171850 --- /dev/null +++ b/src/it/GH-331-no-module-version/invoker.properties @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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 +# +# http://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. + +invoker.java.version = 9+ diff --git a/src/it/GH-331-no-module-version/pom.xml b/src/it/GH-331-no-module-version/pom.xml new file mode 100644 index 000000000..571d4ce6c --- /dev/null +++ b/src/it/GH-331-no-module-version/pom.xml @@ -0,0 +1,45 @@ + + + + 4.0.0 + + org.apache.maven.plugins.compiler.it + GH-331-no-module-version + 1.0-SNAPSHOT + + https://github.com/apache/maven-compiler-plugin/pull/331 + + + UTF-8 + 9 + false + + + + + + maven-compiler-plugin + @project.version@ + + + + diff --git a/src/it/GH-331-no-module-version/src/main/java/com/foo/MyClass.java b/src/it/GH-331-no-module-version/src/main/java/com/foo/MyClass.java new file mode 100644 index 000000000..f646e4ae2 --- /dev/null +++ b/src/it/GH-331-no-module-version/src/main/java/com/foo/MyClass.java @@ -0,0 +1,21 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 + * + * http://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 com.foo; + +public class MyClass {} diff --git a/src/it/GH-331-no-module-version/src/main/java/module-info.java b/src/it/GH-331-no-module-version/src/main/java/module-info.java new file mode 100644 index 000000000..c26850c04 --- /dev/null +++ b/src/it/GH-331-no-module-version/src/main/java/module-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 + * + * http://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. + */ + +module M.N { + exports com.foo; +} diff --git a/src/it/GH-331-no-module-version/verify.groovy b/src/it/GH-331-no-module-version/verify.groovy new file mode 100644 index 000000000..f36ab7031 --- /dev/null +++ b/src/it/GH-331-no-module-version/verify.groovy @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 + * + * http://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. + */ +def log = new File(basedir, 'build.log').text + +assert log.count(' --module-version') == 0 + +def descriptor = java.lang.module.ModuleFinder.of(basedir.toPath().resolve('target/classes')).find('M.N').get().descriptor() +assert descriptor.version().empty +assert 'M.N' == descriptor.toNameAndVersion() diff --git a/src/it/MCOMPILER-538/code/MyAnnotatedClass.bad.java b/src/it/MCOMPILER-538/code/MyAnnotatedClass.bad.java new file mode 100644 index 000000000..765cd64c2 --- /dev/null +++ b/src/it/MCOMPILER-538/code/MyAnnotatedClass.bad.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 + * + * http://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 bar; + +import foo.MyAnnotation; + +@MyAnnotation +public class MyAnnotatedClass { + MyGeneratedClass generatedClass = new MyGeneratedClass(false); + + // foo + +} diff --git a/src/it/MCOMPILER-538/code/MyAnnotatedClass.good.java b/src/it/MCOMPILER-538/code/MyAnnotatedClass.good.java new file mode 100644 index 000000000..cc4126d8f --- /dev/null +++ b/src/it/MCOMPILER-538/code/MyAnnotatedClass.good.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 + * + * http://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 bar; + +import foo.MyAnnotation; + +@MyAnnotation +public class MyAnnotatedClass { + MyGeneratedClass generatedClass = new MyGeneratedClass(); + + // foo + +} diff --git a/src/it/MCOMPILER-538/code/pom.xml b/src/it/MCOMPILER-538/code/pom.xml new file mode 100644 index 000000000..2dd9744fe --- /dev/null +++ b/src/it/MCOMPILER-538/code/pom.xml @@ -0,0 +1,93 @@ + + + + 4.0.0 + + foo + bar + ${revision} + + ${revision} + jar + code + + + + foo + processor + ${revision} + provided + + + + + + + com.kohlschutter.mavenplugins + copy-rename-maven-plugin + 2.0.0 + + + set-source + generate-sources + + copy + + + + + ${basedir}/MyAnnotatedClass.${it.type}.java + ${basedir}/src/main/java/bar/MyAnnotatedClass.java + + + + + + + + + org.apache.maven.plugins + maven-clean-plugin + @version.maven-clean-plugin@ + + + clean-source-file + validate + + clean + + + true + + + src/main/java + + package-info.java + + + + + + + + + + diff --git a/src/it/MCOMPILER-538/code/src/main/java/bar/.gitignore b/src/it/MCOMPILER-538/code/src/main/java/bar/.gitignore new file mode 100644 index 000000000..ebce081a9 --- /dev/null +++ b/src/it/MCOMPILER-538/code/src/main/java/bar/.gitignore @@ -0,0 +1 @@ +MyAnnotatedClass.java diff --git a/src/it/MCOMPILER-538/code/src/main/java/bar/package-info.java b/src/it/MCOMPILER-538/code/src/main/java/bar/package-info.java new file mode 100644 index 000000000..0dde32fa1 --- /dev/null +++ b/src/it/MCOMPILER-538/code/src/main/java/bar/package-info.java @@ -0,0 +1,20 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 + * + * http://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 bar; diff --git a/src/it/MCOMPILER-538/invoker.properties b/src/it/MCOMPILER-538/invoker.properties new file mode 100644 index 000000000..b9f2ae7c5 --- /dev/null +++ b/src/it/MCOMPILER-538/invoker.properties @@ -0,0 +1,24 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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 +# +# http://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. + +# NOTE: The first time, we run up to "integration-test" phase which includes the AntRun execution which saves the +# timestamp of the first JAR for comparison with the timestamp of the JAR from the final "package" invocation. +# Note: +invoker.maven.version = 3.8.8+ +invoker.goals.1 = clean +invoker.goals.2 = compile -Dit.type=bad -Dmaven.compiler.failOnError=false +invoker.goals.3 = compile -Dit.type=good diff --git a/src/it/MCOMPILER-538/pom.xml b/src/it/MCOMPILER-538/pom.xml new file mode 100644 index 000000000..2d53ade7f --- /dev/null +++ b/src/it/MCOMPILER-538/pom.xml @@ -0,0 +1,72 @@ + + + + 4.0.0 + foo + bar + ${revision} + pom + + + 1.0-SNAPSHOT + + UTF-8 + + + + processor + code + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + @project.version@ + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + UTF-8 + true + true + true + false + + -Xlint:all,-processing + -Xdoclint:all,-missing,-accessibility + -Xmaxerrs + 2147483647 + -Xmaxwarns + 2147483647 + + + + + + diff --git a/src/it/MCOMPILER-538/processor/pom.xml b/src/it/MCOMPILER-538/processor/pom.xml new file mode 100644 index 000000000..a666cad91 --- /dev/null +++ b/src/it/MCOMPILER-538/processor/pom.xml @@ -0,0 +1,43 @@ + + + + 4.0.0 + + foo + bar + ${revision} + + ${revision} + processor + jar + + + + + org.apache.maven.plugins + maven-compiler-plugin + + none + + + + + diff --git a/src/it/MCOMPILER-538/processor/src/main/java/foo/MyAnnotation.java b/src/it/MCOMPILER-538/processor/src/main/java/foo/MyAnnotation.java new file mode 100644 index 000000000..88431aef8 --- /dev/null +++ b/src/it/MCOMPILER-538/processor/src/main/java/foo/MyAnnotation.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 + * + * http://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 foo; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.SOURCE) +@Target(ElementType.TYPE) +public @interface MyAnnotation {} diff --git a/src/it/MCOMPILER-538/processor/src/main/java/foo/MyProcessor.java b/src/it/MCOMPILER-538/processor/src/main/java/foo/MyProcessor.java new file mode 100644 index 000000000..3958406b9 --- /dev/null +++ b/src/it/MCOMPILER-538/processor/src/main/java/foo/MyProcessor.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 + * + * http://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 foo; + +import javax.annotation.processing.*; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.TypeElement; +import javax.tools.Diagnostic; +import javax.tools.JavaFileObject; + +import java.io.IOException; +import java.io.Writer; +import java.util.Set; + +@SupportedAnnotationTypes("foo.MyAnnotation") +public class MyProcessor extends AbstractProcessor { + + private int procRun = 0; + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latestSupported(); + } + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + try { + generate(annotations, roundEnv); + } catch (IOException e) { + throw new RuntimeException(e); + } + + return false; + } + + private void generate(Set annotations, RoundEnvironment roundEnv) throws IOException { + Messager msg = processingEnv.getMessager(); + msg.printMessage(Diagnostic.Kind.NOTE, String.format("[%d]: Hello Info", procRun)); + msg.printMessage(Diagnostic.Kind.WARNING, String.format("[%d]: Hello Warning", procRun)); + procRun++; + + if (procRun > 1) { + return; + } + + JavaFileObject file = processingEnv.getFiler().createSourceFile("bar.MyGeneratedClass"); + try (Writer writer = file.openWriter()) { + writer.write("package bar;\n\npublic class MyGeneratedClass {\n}\n"); + } + } +} diff --git a/src/it/MCOMPILER-538/processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/src/it/MCOMPILER-538/processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor new file mode 100644 index 000000000..678af7bad --- /dev/null +++ b/src/it/MCOMPILER-538/processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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 +# +# http://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. + +foo.MyProcessor diff --git a/src/main/java/org/apache/maven/plugin/compiler/AbstractCompilerMojo.java b/src/main/java/org/apache/maven/plugin/compiler/AbstractCompilerMojo.java index 3e73fd965..e9290bcf9 100644 --- a/src/main/java/org/apache/maven/plugin/compiler/AbstractCompilerMojo.java +++ b/src/main/java/org/apache/maven/plugin/compiler/AbstractCompilerMojo.java @@ -703,8 +703,39 @@ protected final Optional getModuleDeclaration(final Set sourceFiles) private boolean targetOrReleaseSet; @Override - @SuppressWarnings("checkstyle:MethodLength") public void execute() throws MojoExecutionException, CompilationFailureException { + try { + executeReal(); + } finally { + addGeneratedSourcesToProject(); + } + } + + private void addGeneratedSourcesToProject() { + File generatedSourcesDirectory = getGeneratedSourcesDirectory(); + if (generatedSourcesDirectory == null) { + return; + } + + String generatedSourcesPath = generatedSourcesDirectory.getAbsolutePath(); + + if (isTestCompile()) { + getLog().debug("Adding " + generatedSourcesPath + + " to the project test-compile source roots but NOT the actual test-compile source roots:\n " + + StringUtils.join(project.getTestCompileSourceRoots().iterator(), "\n ")); + + project.addTestCompileSourceRoot(generatedSourcesPath); + } else { + getLog().debug("Adding " + generatedSourcesPath + + " to the project compile source roots but NOT the actual compile source roots:\n " + + StringUtils.join(project.getCompileSourceRoots().iterator(), "\n ")); + + project.addCompileSourceRoot(generatedSourcesPath); + } + } + + @SuppressWarnings("checkstyle:MethodLength") + private void executeReal() throws MojoExecutionException, CompilationFailureException { // ---------------------------------------------------------------------- // Look up the compiler. This is done before other code than can // cause the mojo to return before the lookup is done possibly resulting @@ -822,28 +853,6 @@ public void execute() throws MojoExecutionException, CompilationFailureException if (!generatedSourcesDirectory.exists()) { generatedSourcesDirectory.mkdirs(); } - - String generatedSourcesPath = generatedSourcesDirectory.getAbsolutePath(); - - compileSourceRoots.add(generatedSourcesPath); - - if (isTestCompile()) { - getLog().debug("Adding " + generatedSourcesPath + " to test-compile source roots:\n " - + StringUtils.join(project.getTestCompileSourceRoots().iterator(), "\n ")); - - project.addTestCompileSourceRoot(generatedSourcesPath); - - getLog().debug("New test-compile source roots:\n " - + StringUtils.join(project.getTestCompileSourceRoots().iterator(), "\n ")); - } else { - getLog().debug("Adding " + generatedSourcesPath + " to compile source roots:\n " - + StringUtils.join(project.getCompileSourceRoots().iterator(), "\n ")); - - project.addCompileSourceRoot(generatedSourcesPath); - - getLog().debug("New compile source roots:\n " - + StringUtils.join(project.getCompileSourceRoots().iterator(), "\n ")); - } } compilerConfiguration.setSourceLocations(compileSourceRoots); @@ -1831,10 +1840,10 @@ private boolean hasInputFileTreeChanged(IncrementalBuildHelper ibh, Set in } Path mojoConfigFile = mojoConfigBase.resolve(INPUT_FILES_LST_FILENAME); - List oldInputFiles = Collections.emptyList(); + Set oldInputFiles = Collections.emptySet(); if (Files.isRegularFile(mojoConfigFile)) { try { - oldInputFiles = Files.readAllLines(mojoConfigFile); + oldInputFiles = new HashSet<>(Files.readAllLines(mojoConfigFile)); } catch (IOException e) { // we cannot read the mojo config file, so don't do anything beside logging getLog().warn("Error while reading old mojo status: " + mojoConfigFile); @@ -1842,8 +1851,10 @@ private boolean hasInputFileTreeChanged(IncrementalBuildHelper ibh, Set in } } - List newInputFiles = - inputFiles.stream().sorted().map(File::getAbsolutePath).collect(Collectors.toList()); + Set newInputFiles = inputFiles.stream() + .sorted() + .map(File::getAbsolutePath) + .collect(Collectors.toCollection(LinkedHashSet::new)); try { Files.write(mojoConfigFile, newInputFiles); diff --git a/src/main/java/org/apache/maven/plugin/compiler/CompilerMojo.java b/src/main/java/org/apache/maven/plugin/compiler/CompilerMojo.java index cd273951a..295ca39d2 100644 --- a/src/main/java/org/apache/maven/plugin/compiler/CompilerMojo.java +++ b/src/main/java/org/apache/maven/plugin/compiler/CompilerMojo.java @@ -172,6 +172,16 @@ public class CompilerMojo extends AbstractCompilerMojo { @Parameter(property = "maven.compiler.moduleVersion", defaultValue = "${project.version}") private String moduleVersion; + /** + * Use the {@code --module-version} argument for the Java compiler. + * This is ignored if not applicable, e.g., in non-modular projects. + * + * @see javac --module-version + * @since 3.15.0 + */ + @Parameter(property = "maven.compiler.useModuleVersion", defaultValue = "true") + private boolean useModuleVersion; + final LocationManager locationManager = new LocationManager(); private List classpathElements; @@ -311,9 +321,10 @@ protected void preparePaths(Set sourceFiles) { modulepathElements.add(file.getPath()); } - compilerArgs.add("--module-version"); - compilerArgs.add(moduleVersion); - + if (useModuleVersion) { + compilerArgs.add("--module-version"); + compilerArgs.add(moduleVersion); + } } catch (IOException e) { getLog().warn(e.getMessage()); } diff --git a/src/main/java/org/apache/maven/plugin/compiler/DeltaList.java b/src/main/java/org/apache/maven/plugin/compiler/DeltaList.java index 18943fab9..a4e7b3daa 100644 --- a/src/main/java/org/apache/maven/plugin/compiler/DeltaList.java +++ b/src/main/java/org/apache/maven/plugin/compiler/DeltaList.java @@ -18,25 +18,31 @@ */ package org.apache.maven.plugin.compiler; -import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.List; +import java.util.Set; +import java.util.TreeSet; /** * Show the modifications between two lists. */ -final class DeltaList { +final class DeltaList> { - private final List added; - private final List removed; + private final Set added = new TreeSet<>(); + private final Set removed = new TreeSet<>(); private final boolean hasChanged; DeltaList(Collection oldList, Collection newList) { - this.added = new ArrayList<>(newList); - this.removed = new ArrayList<>(oldList); - added.removeAll(oldList); - removed.removeAll(newList); + for (E newListItem : newList) { + if (!oldList.contains(newListItem)) { + added.add(newListItem); + } + } + for (E oldListItem : oldList) { + if (!newList.contains(oldListItem)) { + removed.add(oldListItem); + } + } this.hasChanged = !added.isEmpty() || !removed.isEmpty(); } diff --git a/src/test/java/org/apache/maven/plugin/compiler/CompilerMojoTest.java b/src/test/java/org/apache/maven/plugin/compiler/CompilerMojoTest.java index 8d852ba13..70be49394 100644 --- a/src/test/java/org/apache/maven/plugin/compiler/CompilerMojoTest.java +++ b/src/test/java/org/apache/maven/plugin/compiler/CompilerMojoTest.java @@ -37,7 +37,12 @@ import static org.apache.maven.plugin.compiler.MojoTestUtils.getMockMojoExecution; import static org.apache.maven.plugin.compiler.MojoTestUtils.getVariableValueFromObject; import static org.apache.maven.plugin.compiler.MojoTestUtils.setVariableValueToObject; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; import static org.mockito.ArgumentMatchers.startsWith; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; diff --git a/src/test/java/org/apache/maven/plugin/compiler/TestCompilerMojoTest.java b/src/test/java/org/apache/maven/plugin/compiler/TestCompilerMojoTest.java index 31a2e2a33..a415b763e 100644 --- a/src/test/java/org/apache/maven/plugin/compiler/TestCompilerMojoTest.java +++ b/src/test/java/org/apache/maven/plugin/compiler/TestCompilerMojoTest.java @@ -39,7 +39,9 @@ import static org.apache.maven.plugin.compiler.MojoTestUtils.getMockMojoExecution; import static org.apache.maven.plugin.compiler.MojoTestUtils.getVariableValueFromObject; import static org.apache.maven.plugin.compiler.MojoTestUtils.setVariableValueToObject; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; @MojoTest class TestCompilerMojoTest {