diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Lifecycle.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Lifecycle.java index c461ef0ad0a..09760f94d06 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Lifecycle.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Lifecycle.java @@ -19,6 +19,7 @@ package org.apache.maven.api; import java.util.*; +import java.util.stream.Stream; import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Immutable; @@ -41,6 +42,13 @@ public interface Lifecycle extends ExtensibleEnum { String WRAPPER = "wrapper"; + String PRE = "pre:"; + String POST = "post:"; + String RUN = "run:"; + + String READY = "ready"; + String PACKAGE = "package"; + /** * Name or identifier of this lifecycle. * @@ -54,6 +62,18 @@ public interface Lifecycle extends ExtensibleEnum { */ Collection phases(); + /** + * Stream of phases containing all child phases recursively. + */ + default Stream allPhases() { + return phases().stream().flatMap(Phase::allPhases); + } + + /** + * Collection of aliases. + */ + Collection aliases(); + /** * Pre-ordered list of phases. * If not provided, a default order will be computed. @@ -69,5 +89,69 @@ interface Phase { String name(); List plugins(); + + Collection links(); + + List phases(); + + Stream allPhases(); + } + + /** + * A phase alias, mostly used to support the Maven 3 phases which are mapped + * to dynamic phases in Maven 4. + */ + interface Alias { + String v3Phase(); + + String v4Phase(); + } + + /** + * A link from a phase to another phase, consisting of a type which can be + * {@link Kind#BEFORE} or {@link Kind#AFTER}, and a {@link Pointer} to + * another phase. + */ + interface Link { + enum Kind { + BEFORE, + AFTER + } + + Kind kind(); + + Pointer pointer(); + } + + interface Pointer { + enum Type { + PROJECT, + DEPENDENCIES, + CHILDREN + } + + String phase(); + + Type type(); + } + + interface PhasePointer extends Pointer { + default Type type() { + return Type.PROJECT; + } + } + + interface DependenciesPointer extends Pointer { + String scope(); // default: all + + default Type type() { + return Type.DEPENDENCIES; + } + } + + interface ChildrenPointer extends Pointer { + default Type type() { + return Type.CHILDREN; + } } } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/After.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/After.java new file mode 100644 index 00000000000..697b9d48020 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/After.java @@ -0,0 +1,66 @@ +/* + * 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 org.apache.maven.api.plugin.annotations; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.apache.maven.api.annotations.Experimental; + +/** + * Specifies that the mojo should be run after the specific phase. + * + * @since 4.0.0 + */ +@Experimental +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@Inherited +public @interface After { + + /** + * Type of pointer. + * @see org.apache.maven.api.Lifecycle.Pointer.Type + */ + enum Type { + PROJECT, + DEPENDENCIES, + CHILDREN + } + + /** + * The phase name. + */ + String phase(); + + /** + * The type of this pointer. + */ + Type type(); + + /** + * The scope for dependencies, only if {@code type() == Type.Dependencies}. + */ + String scope() default ""; +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/LifecycleRegistry.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/LifecycleRegistry.java index 05970e76fce..55efc16ebcd 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/LifecycleRegistry.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/LifecycleRegistry.java @@ -18,6 +18,7 @@ */ package org.apache.maven.api.services; +import java.util.List; import java.util.stream.Stream; import java.util.stream.StreamSupport; @@ -28,4 +29,6 @@ public interface LifecycleRegistry extends ExtensibleEnumRegistry, It default Stream stream() { return StreamSupport.stream(spliterator(), false); } + + List computePhases(Lifecycle lifecycle); } diff --git a/maven-api-impl/src/test/java/org/apache/maven/internal/impl/standalone/ApiRunner.java b/maven-api-impl/src/test/java/org/apache/maven/internal/impl/standalone/ApiRunner.java index 750aa9c084e..3b4079ce501 100644 --- a/maven-api-impl/src/test/java/org/apache/maven/internal/impl/standalone/ApiRunner.java +++ b/maven-api-impl/src/test/java/org/apache/maven/internal/impl/standalone/ApiRunner.java @@ -321,6 +321,11 @@ public Iterator iterator() { public Optional lookup(String id) { return Optional.empty(); } + + @Override + public List computePhases(Lifecycle lifecycle) { + return List.of(); + } }; } diff --git a/maven-compat/src/test/java/org/apache/maven/project/EmptyLifecycleBindingsInjector.java b/maven-compat/src/test/java/org/apache/maven/project/EmptyLifecycleBindingsInjector.java index 513bb0236ba..970b74a7501 100644 --- a/maven-compat/src/test/java/org/apache/maven/project/EmptyLifecycleBindingsInjector.java +++ b/maven-compat/src/test/java/org/apache/maven/project/EmptyLifecycleBindingsInjector.java @@ -62,6 +62,11 @@ public Iterator iterator() { public Optional lookup(String id) { return Optional.empty(); } + + @Override + public List computePhases(Lifecycle lifecycle) { + return List.of(); + } }; private static final PackagingRegistry emptyPackagingRegistry = new PackagingRegistry() { @@ -140,6 +145,11 @@ public Iterator iterator() { protected LifecycleRegistry getDelegate() { return lifecycleRegistry; } + + @Override + public List computePhases(Lifecycle lifecycle) { + return List.of(); + } } static class WrapperPackagingRegistry implements PackagingRegistry { diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLifecycleRegistry.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLifecycleRegistry.java index acd8fd74c2f..a666605b8fe 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLifecycleRegistry.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLifecycleRegistry.java @@ -23,6 +23,7 @@ import javax.inject.Provider; import javax.inject.Singleton; +import java.util.*; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -48,7 +49,11 @@ import org.codehaus.plexus.component.repository.exception.ComponentLookupException; import static java.util.Arrays.asList; +import static java.util.Collections.*; +import static java.util.Collections.emptyList; import static java.util.Collections.singleton; +import static org.apache.maven.internal.impl.Lifecycles.*; +import static org.apache.maven.internal.impl.Lifecycles.after; import static org.apache.maven.internal.impl.Lifecycles.phase; import static org.apache.maven.internal.impl.Lifecycles.plugin; @@ -73,7 +78,7 @@ public DefaultLifecycleRegistry(List providers) { // validate lifecycle for (Lifecycle lifecycle : this) { Set set = new HashSet<>(); - lifecycle.phases().forEach(phase -> { + lifecycle.allPhases().forEach(phase -> { if (!set.add(phase.name())) { throw new IllegalArgumentException( "Found duplicated phase '" + phase.name() + "' in '" + lifecycle.id() + "' lifecycle"); @@ -97,6 +102,75 @@ public Optional lookup(String id) { return stream().filter(lf -> Objects.equals(id, lf.id())).findAny(); } + public List computePhases(Lifecycle lifecycle) { + Graph graph = new Graph(); + lifecycle.phases().forEach(phase -> addPhase(graph, null, null, phase)); + lifecycle.aliases().forEach(alias -> { + String n = alias.v3Phase(); + String a = alias.v4Phase(); + String[] u = a.split(":"); + Graph.Vertex v = graph.addVertex(n); + if (u.length > 1) { + if ("pre".equals(u[0])) { + graph.addEdge(graph.addVertex("$" + u[1]), v); + graph.addEdge(v, graph.addVertex("$$" + u[1])); + } else if ("post".equals(u[0])) { + graph.addEdge(graph.addVertex(u[1]), v); + graph.addEdge(v, graph.addVertex("$$$" + u[1])); + } + } else { + graph.addEdge(graph.addVertex("$$" + u[0]), v); + graph.addEdge(v, graph.addVertex(u[0])); + } + }); + List allPhases = graph.visitAll(); + Collections.reverse(allPhases); + List computed = + allPhases.stream().filter(s -> !s.startsWith("$")).collect(Collectors.toList()); + List given = lifecycle.orderedPhases().orElse(null); + if (given != null) { + if (given.size() != computed.size()) { + Set s1 = + given.stream().filter(s -> !computed.contains(s)).collect(Collectors.toSet()); + Set s2 = + computed.stream().filter(s -> !given.contains(s)).collect(Collectors.toSet()); + throw new IllegalArgumentException( + "List of phases differ in size: expected " + computed.size() + " but received " + given.size() + + (s1.isEmpty() ? "" : ", missing " + s1) + + (s2.isEmpty() ? "" : ", unexpected " + s2)); + } + return given; + } + return computed; + } + + private static void addPhase( + Graph graph, Graph.Vertex before, Graph.Vertex after, org.apache.maven.api.Lifecycle.Phase phase) { + Graph.Vertex ep0 = graph.addVertex("$" + phase.name()); + Graph.Vertex ep1 = graph.addVertex("$$" + phase.name()); + Graph.Vertex ep2 = graph.addVertex(phase.name()); + Graph.Vertex ep3 = graph.addVertex("$$$" + phase.name()); + graph.addEdge(ep0, ep1); + graph.addEdge(ep1, ep2); + graph.addEdge(ep2, ep3); + if (before != null) { + graph.addEdge(before, ep0); + } + if (after != null) { + graph.addEdge(ep3, after); + } + phase.links().forEach(link -> { + if (link.pointer().type() == Lifecycle.Pointer.Type.PROJECT) { + if (link.kind() == Lifecycle.Link.Kind.AFTER) { + graph.addEdge(graph.addVertex(link.pointer().phase()), ep0); + } else { + graph.addEdge(ep3, graph.addVertex("$" + link.pointer().phase())); + } + } + }); + phase.phases().forEach(child -> addPhase(graph, ep1, ep2, child)); + } + @Named @Singleton public static class LifecycleWrapperProvider implements LifecycleProvider { @@ -140,6 +214,17 @@ public String name() { return name; } + @Override + public List phases() { + return List.of(); + } + + @Override + public Stream allPhases() { + return Stream.concat( + Stream.of(this), phases().stream().flatMap(Lifecycle.Phase::allPhases)); + } + @Override public List plugins() { Map lfPhases = lifecycle.getDefaultLifecyclePhases(); @@ -151,16 +236,26 @@ public List plugins() { } return List.of(); } + + @Override + public Collection links() { + return List.of(); + } }) .toList(); } + + @Override + public Collection aliases() { + return Collections.emptyList(); + } }; } } static class WrappedLifecycle extends org.apache.maven.lifecycle.Lifecycle { - WrappedLifecycle(Lifecycle lifecycle) { - super(lifecycle); + WrappedLifecycle(LifecycleRegistry registry, Lifecycle lifecycle) { + super(registry, lifecycle); } } @@ -178,7 +273,7 @@ abstract static class BaseLifecycleProvider implements Provider phases() { - return asList( - phase("pre-clean"), - phase( - "clean", - plugin( - "org.apache.maven.plugins:maven-clean-plugin:" + MAVEN_CLEAN_PLUGIN_VERSION - + ":clean", - "clean")), - phase("post-clean")); + return singleton(phase( + "clean", + plugin( + "org.apache.maven.plugins:maven-clean-plugin:" + MAVEN_CLEAN_PLUGIN_VERSION + ":clean", + "clean"))); + } + + @Override + public Collection aliases() { + return asList(alias("pre-clean", PRE + "clean"), alias("post-clean", POST + "clean")); } } @@ -248,30 +344,89 @@ public String id() { @Override public Collection phases() { + return asList(phase( + "all", + phase( + "build", + phase("initialize", phase("validate")), + phase("sources", after("initialize")), + phase("resources", after("initialize")), + phase("compile", after("sources"), dependencies("compile", READY)), + phase(READY, after("compile"), after("resources")), + phase(PACKAGE, after(READY), dependencies("runtime", PACKAGE))), + phase( + "verify", + phase( + "unit-test", + phase("test-sources"), + phase("test-resources"), + phase( + "test-compile", + after("test-sources"), + after(READY), + dependencies("test-only", READY)), + phase( + "test", + after("test-compile"), + after("test-resources"), + dependencies("test", READY))), + phase("integration-test", after(PACKAGE))), + phase("install", after("verify")), // TODO: this should be after("package") + phase("deploy", after("install")))); // TODO: this should be after("package") + } + + @Override + public Collection aliases() { return asList( - phase("validate"), - phase("initialize"), - phase("generate-sources"), - phase("process-sources"), - phase("generate-resources"), - phase("process-resources"), - phase("compile"), - phase("process-classes"), - phase("generate-test-sources"), - phase("process-test-sources"), - phase("generate-test-resources"), - phase("process-test-resources"), - phase("test-compile"), - phase("process-test-classes"), - phase("test"), - phase("prepare-package"), - phase("package"), - phase("pre-integration-test"), - phase("integration-test"), - phase("post-integration-test"), - phase("verify"), - phase("install"), - phase("deploy")); + alias("generate-sources", RUN + "sources"), + alias("process-sources", POST + "sources"), + alias("generate-resources", RUN + "resources"), + alias("process-resources", POST + "resources"), + alias("process-classes", POST + "compile"), + alias("generate-test-sources", RUN + "test-sources"), + alias("process-test-resources", POST + "test-resources"), + alias("generate-test-resources", "run:test-resources"), + alias("process-test-sources", POST + "test-sources"), + alias("process-test-classes", POST + "test-compile"), + alias("prepare-package", PRE + PACKAGE), + alias("pre-integration-test", PRE + "integration-test"), + alias("post-integration-test", POST + "integration-test")); + } + + @Override + public Optional> orderedPhases() { + return Optional.of(Arrays.asList( + "validate", + "initialize", + "generate-sources", + "process-sources", + "sources", + "generate-resources", + "process-resources", + "resources", + "compile", + "process-classes", + READY, + "generate-test-sources", + "process-test-sources", + "test-sources", + "generate-test-resources", + "process-test-resources", + "test-resources", + "test-compile", + "process-test-classes", + "test", + "unit-test", + "prepare-package", + PACKAGE, + "build", + "pre-integration-test", + "integration-test", + "post-integration-test", + "verify", + "install", + "deploy", + "all")); } } @@ -287,20 +442,24 @@ public String id() { @Override public Collection phases() { return asList( - phase("pre-site"), phase( "site", plugin( "org.apache.maven.plugins:maven-site-plugin:" + MAVEN_SITE_PLUGIN_VERSION + ":site", "site")), - phase("post-site"), phase( "site-deploy", + after("site"), plugin( "org.apache.maven.plugins:maven-site-plugin:" + MAVEN_SITE_PLUGIN_VERSION + ":deploy", "site-deploy"))); } + + @Override + public Collection aliases() { + return asList(alias("pre-site", PRE + "site"), alias("post-site", POST + "site")); + } } static class WrapperLifecycle implements Lifecycle { @@ -321,5 +480,10 @@ public Collection phases() { + ":wrapper", "wrapper"))); } + + @Override + public Collection aliases() { + return emptyList(); + } } } diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/Lifecycles.java b/maven-core/src/main/java/org/apache/maven/internal/impl/Lifecycles.java index 42da23b290f..714194659b8 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/Lifecycles.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/Lifecycles.java @@ -18,21 +18,52 @@ */ package org.apache.maven.internal.impl; +import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.stream.Stream; import org.apache.maven.api.Lifecycle; import org.apache.maven.api.model.Plugin; import org.apache.maven.api.model.PluginExecution; +import static java.util.Arrays.asList; + public class Lifecycles { static Lifecycle.Phase phase(String name) { - return new DefaultPhase(name, Collections.emptyList(), Collections.emptyList()); + return new DefaultPhase(name, Collections.emptyList(), Collections.emptyList(), Collections.emptyList()); + } + + static Lifecycle.Phase phase(String name, Lifecycle.Phase... phases) { + return new DefaultPhase(name, Collections.emptyList(), Collections.emptyList(), asList(phases)); + } + + static Lifecycle.Phase phase(String name, Lifecycle.Link link, Lifecycle.Phase... phases) { + return new DefaultPhase(name, Collections.emptyList(), Collections.singletonList(link), asList(phases)); } static Lifecycle.Phase phase(String name, Plugin plugin) { - return new DefaultPhase(name, Collections.singletonList(plugin), Collections.emptyList()); + return new DefaultPhase( + name, Collections.singletonList(plugin), Collections.emptyList(), Collections.emptyList()); + } + + static Lifecycle.Phase phase(String name, Lifecycle.Link link, Plugin plugin) { + return new DefaultPhase( + name, Collections.singletonList(plugin), Collections.singletonList(link), Collections.emptyList()); + } + + static Lifecycle.Phase phase(String name, Lifecycle.Link link1, Lifecycle.Link link2, Lifecycle.Phase... phases) { + return new DefaultPhase(name, Collections.emptyList(), asList(link1, link2), asList(phases)); + } + + static Lifecycle.Phase phase( + String name, Lifecycle.Link link1, Lifecycle.Link link2, Lifecycle.Link link3, Lifecycle.Phase... phases) { + return new DefaultPhase(name, Collections.emptyList(), asList(link1, link2, link3), asList(phases)); + } + + static Lifecycle.Phase phase(String name, Collection links, Lifecycle.Phase... phases) { + return new DefaultPhase(name, Collections.emptyList(), links, asList(phases)); } static Plugin plugin(String coord, String phase) { @@ -49,14 +80,66 @@ static Plugin plugin(String coord, String phase) { .build(); } + /** Indicates the phase is after the phases given in arguments */ + static Lifecycle.Link after(String b) { + return new Lifecycle.Link() { + @Override + public Kind kind() { + return Kind.AFTER; + } + + @Override + public Lifecycle.Pointer pointer() { + return new Lifecycle.PhasePointer() { + @Override + public String phase() { + return b; + } + }; + } + }; + } + + /** Indicates the phase is after the phases for the dependencies in the given scope */ + static Lifecycle.Link dependencies(String scope, String phase) { + return new Lifecycle.Link() { + @Override + public Kind kind() { + return Kind.AFTER; + } + + @Override + public Lifecycle.Pointer pointer() { + return new Lifecycle.DependenciesPointer() { + @Override + public String phase() { + return phase; + } + + @Override + public String scope() { + return scope; + } + }; + } + }; + } + + static Lifecycle.Alias alias(String v3Phase, String v4Phase) { + return new DefaultAlias(v3Phase, v4Phase); + } + static class DefaultPhase implements Lifecycle.Phase { private final String name; private final List plugins; + private final Collection links; private final List phases; - DefaultPhase(String name, List plugins, List phases) { + DefaultPhase( + String name, List plugins, Collection links, List phases) { this.name = name; this.plugins = plugins; + this.links = links; this.phases = phases; } @@ -69,5 +152,40 @@ public String name() { public List plugins() { return plugins; } + + @Override + public Collection links() { + return links; + } + + @Override + public List phases() { + return phases; + } + + @Override + public Stream allPhases() { + return Stream.concat(Stream.of(this), phases().stream().flatMap(Lifecycle.Phase::allPhases)); + } + } + + static class DefaultAlias implements Lifecycle.Alias { + private final String v3Phase; + private final String v4Phase; + + DefaultAlias(String v3Phase, String v4Phase) { + this.v3Phase = v3Phase; + this.v4Phase = v4Phase; + } + + @Override + public String v3Phase() { + return v3Phase; + } + + @Override + public String v4Phase() { + return v4Phase; + } } } diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycles.java b/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycles.java index 91e1adbc645..e3536df7f92 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycles.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycles.java @@ -156,7 +156,7 @@ private Map lookupLifecycles() { // Lifecycles cannot be cached as extensions might add custom lifecycles later in the execution. try { return registry != null - ? registry.stream().collect(Collectors.toMap(lf -> lf.id(), lf -> new Lifecycle(lf))) + ? registry.stream().collect(Collectors.toMap(lf -> lf.id(), lf -> new Lifecycle(registry, lf))) : Map.of(); } catch (LookupException e) { throw new IllegalStateException("Unable to lookup lifecycles from the plexus container", e); diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/Lifecycle.java b/maven-core/src/main/java/org/apache/maven/lifecycle/Lifecycle.java index a88307459c6..163a56e7d09 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/Lifecycle.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/Lifecycle.java @@ -35,12 +35,11 @@ public Lifecycle(String id, List phases, Map def this.defaultPhases = defaultPhases; } - public Lifecycle(org.apache.maven.api.Lifecycle lifecycle) { + public Lifecycle( + org.apache.maven.api.services.LifecycleRegistry registry, org.apache.maven.api.Lifecycle lifecycle) { this.lifecycle = lifecycle; this.id = lifecycle.id(); - this.phases = lifecycle.phases().stream() - .map(org.apache.maven.api.Lifecycle.Phase::name) - .toList(); + this.phases = registry.computePhases(lifecycle); this.defaultPhases = getDefaultPhases(lifecycle); } @@ -74,7 +73,7 @@ public List getPhases() { static Map getDefaultPhases(org.apache.maven.api.Lifecycle lifecycle) { Map> goals = new HashMap<>(); - lifecycle.phases().forEach(phase -> phase.plugins() + lifecycle.allPhases().forEach(phase -> phase.plugins() .forEach(plugin -> plugin.getExecutions().forEach(exec -> exec.getGoals() .forEach(goal -> goals.computeIfAbsent(phase.name(), n -> new ArrayList<>()) .add(plugin.getGroupId() + ":" + plugin.getArtifactId() + ":" + plugin.getVersion() diff --git a/maven-core/src/test/java/org/apache/maven/lifecycle/DefaultLifecyclesTest.java b/maven-core/src/test/java/org/apache/maven/lifecycle/DefaultLifecyclesTest.java index ba12bcade0e..3e2cf8e8e88 100644 --- a/maven-core/src/test/java/org/apache/maven/lifecycle/DefaultLifecyclesTest.java +++ b/maven-core/src/test/java/org/apache/maven/lifecycle/DefaultLifecyclesTest.java @@ -59,7 +59,7 @@ void testDefaultLifecycles() { void testDefaultLifecycle() { final Lifecycle lifecycle = getLifeCycleById("default"); assertThat(lifecycle.getId(), is("default")); - assertThat(lifecycle.getPhases(), hasSize(23)); + assertThat(lifecycle.getPhases(), hasSize(31)); } @Test diff --git a/maven-core/src/test/java/org/apache/maven/project/EmptyLifecycleBindingsInjector.java b/maven-core/src/test/java/org/apache/maven/project/EmptyLifecycleBindingsInjector.java index 747f2b8c3f9..3a7bc1a2bf1 100644 --- a/maven-core/src/test/java/org/apache/maven/project/EmptyLifecycleBindingsInjector.java +++ b/maven-core/src/test/java/org/apache/maven/project/EmptyLifecycleBindingsInjector.java @@ -61,6 +61,11 @@ public Iterator iterator() { public Optional lookup(String id) { return Optional.empty(); } + + @Override + public List computePhases(Lifecycle lifecycle) { + return List.of(); + } }; private static final PackagingRegistry emptyPackagingRegistry = new PackagingRegistry() { @@ -139,6 +144,11 @@ public Iterator iterator() { protected LifecycleRegistry getDelegate() { return lifecycleRegistry; } + + @Override + public List computePhases(Lifecycle lifecycle) { + return List.of(); + } } static class WrapperPackagingRegistry implements PackagingRegistry {