You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by kw...@apache.org on 2022/11/01 13:35:03 UTC

[maven-plugin-tools] branch feature/allow-custom-phase-id created (now 1e00a49b)

This is an automated email from the ASF dual-hosted git repository.

kwin pushed a change to branch feature/allow-custom-phase-id
in repository https://gitbox.apache.org/repos/asf/maven-plugin-tools.git


      at 1e00a49b [MPLUGIN-439] Support custom phases in Execute annotation

This branch includes the following new commits:

     new 1e00a49b [MPLUGIN-439] Support custom phases in Execute annotation

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[maven-plugin-tools] 01/01: [MPLUGIN-439] Support custom phases in Execute annotation

Posted by kw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

kwin pushed a commit to branch feature/allow-custom-phase-id
in repository https://gitbox.apache.org/repos/asf/maven-plugin-tools.git

commit 1e00a49bd72b66ff9b831e4519de1e9538c99bc9
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Tue Nov 1 14:34:55 2022 +0100

    [MPLUGIN-439] Support custom phases in Execute annotation
    
    Add Unit test for JavaAnnotationsMojoDescriptorExtractor
---
 .../apache/maven/plugins/annotations/Execute.java  |  17 ++-
 .../JavaAnnotationsMojoDescriptorExtractor.java    |   6 +-
 .../datamodel/ExecuteAnnotationContent.java        |  17 ++-
 .../plugin/extractor/annotations/Execute2Mojo.java |  40 +++++++
 .../plugin/extractor/annotations/ExecuteMojo.java  |  39 +++++++
 ...JavaAnnotationsMojoDescriptorExtractorTest.java |  79 ++++++++++++++
 .../annotations/TestAnnotationsReader.java         | 115 ---------------------
 .../scanner/DefaultMojoAnnotationsScannerTest.java |  73 +++++++++++++
 8 files changed, 266 insertions(+), 120 deletions(-)

diff --git a/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Execute.java b/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Execute.java
index 1482d04e..59325027 100644
--- a/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Execute.java
+++ b/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Execute.java
@@ -39,20 +39,31 @@ import java.lang.annotation.Target;
 public @interface Execute
 {
     /**
-     * lifecycle phase to fork. Note that specifying a phase overrides specifying a goal.
+     * Lifecycle phase to fork. Note that specifying a phase overrides specifying a goal.
+     * For custom lifecycle phase ids use {@link #customPhase()} instead.
+     * This value takes precedence over the {@link #customPhase()}.
      * @return the phase
      */
     LifecyclePhase phase() default LifecyclePhase.NONE;
 
     /**
-     * goal to fork. Note that specifying a phase overrides specifying a goal. The specified <code>goal</code> must be
+     * Custom lifecycle phase to fork. Note that specifying a {@link #phase} overrides the specified custom phase.
+     * Also specifying a custom phase overrides specifying a goal.
+     * This element should only be used for non-standard phases. For standard phases rather use {@link #phase()}.
+     * 
+     * @since 3.8.0
+     */
+    String customPhase() default "";
+
+    /**
+     * Goal to fork. Note that specifying a phase overrides specifying a goal. The specified <code>goal</code> must be
      * another goal of the same plugin.
      * @return the goal
      */
     String goal() default "";
 
     /**
-     * lifecycle id of the lifecycle that defines {@link #phase()}. Only valid in combination with {@link #phase()}. If
+     * Lifecycle id of the lifecycle that defines {@link #phase()}. Only valid in combination with {@link #phase()}. If
      * not specified, Maven will use the lifecycle of the current build.
      *
      * @see <a href="https://maven.apache.org/maven-plugin-api/lifecycle-mappings.html">Lifecycle Mappings</a>
diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/JavaAnnotationsMojoDescriptorExtractor.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/JavaAnnotationsMojoDescriptorExtractor.java
index facfe4a4..5e337f49 100644
--- a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/JavaAnnotationsMojoDescriptorExtractor.java
+++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/JavaAnnotationsMojoDescriptorExtractor.java
@@ -103,7 +103,7 @@ public class JavaAnnotationsMojoDescriptorExtractor
     private static final GroupKey GROUP_KEY = new GroupKey( GroupKey.JAVA_GROUP, 100 );
 
     @Inject
-    private MojoAnnotationsScanner mojoAnnotationsScanner;
+    MojoAnnotationsScanner mojoAnnotationsScanner;
 
     @Inject
     private RepositorySystem repositorySystem;
@@ -724,6 +724,10 @@ public class JavaAnnotationsMojoDescriptorExtractor
                 {
                     mojoDescriptor.setExecutePhase( execute.phase().id() );
                 }
+                else if ( StringUtils.isNotEmpty( execute.customPhase() ) )
+                {
+                    mojoDescriptor.setExecutePhase( execute.customPhase() );
+                }
             }
 
             mojoDescriptor.setExecutionStrategy( mojo.executionStrategy() );
diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/ExecuteAnnotationContent.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/ExecuteAnnotationContent.java
index 14b6b4ef..c5201923 100644
--- a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/ExecuteAnnotationContent.java
+++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/ExecuteAnnotationContent.java
@@ -37,12 +37,20 @@ public class ExecuteAnnotationContent
 
     private LifecyclePhase phase;
 
+    private String customPhase;
+
     @Override
     public LifecyclePhase phase()
     {
         return this.phase;
     }
 
+    @Override
+    public String customPhase()
+    {
+        return customPhase;
+    }
+
     @Override
     public String goal()
     {
@@ -55,12 +63,16 @@ public class ExecuteAnnotationContent
         return this.lifecycle;
     }
 
-
     public void phase( String phase )
     {
         this.phase = LifecyclePhase.valueOf( phase );
     }
 
+    public void customPhase( String customPhase )
+    {
+        this.customPhase = customPhase;
+    }
+
     public void goal( String goal )
     {
         this.goal = goal;
@@ -86,7 +98,10 @@ public class ExecuteAnnotationContent
         sb.append( "{goal='" ).append( goal ).append( '\'' );
         sb.append( ", lifecycle='" ).append( lifecycle ).append( '\'' );
         sb.append( ", phase=" ).append( phase );
+        sb.append( ", customPhase=" ).append( customPhase );
         sb.append( '}' );
         return sb.toString();
     }
+
+    
 }
diff --git a/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/Execute2Mojo.java b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/Execute2Mojo.java
new file mode 100644
index 00000000..556751ed
--- /dev/null
+++ b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/Execute2Mojo.java
@@ -0,0 +1,40 @@
+package org.apache.maven.tools.plugin.extractor.annotations;
+
+/*
+ * 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.
+ */
+
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.Execute;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+
+@Mojo( name = "execute2" )
+@Execute( goal = "compiler", lifecycle = "my-lifecycle", customPhase = "my-phase-id", phase = LifecyclePhase.GENERATE_RESOURCES )
+public class Execute2Mojo extends AbstractMojo
+{
+
+    @Override
+    public void execute()
+        throws MojoExecutionException, MojoFailureException
+    {
+    }
+
+}
diff --git a/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/ExecuteMojo.java b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/ExecuteMojo.java
new file mode 100644
index 00000000..7e55a14f
--- /dev/null
+++ b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/ExecuteMojo.java
@@ -0,0 +1,39 @@
+package org.apache.maven.tools.plugin.extractor.annotations;
+
+/*
+ * 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.
+ */
+
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.Execute;
+import org.apache.maven.plugins.annotations.Mojo;
+
+@Mojo( name = "execute" )
+@Execute( goal = "compiler", lifecycle = "my-lifecycle", customPhase = "my-phase-id" )
+public class ExecuteMojo extends AbstractMojo
+{
+
+    @Override
+    public void execute()
+        throws MojoExecutionException, MojoFailureException
+    {
+    }
+
+}
diff --git a/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/JavaAnnotationsMojoDescriptorExtractorTest.java b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/JavaAnnotationsMojoDescriptorExtractorTest.java
new file mode 100644
index 00000000..25fd7acd
--- /dev/null
+++ b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/JavaAnnotationsMojoDescriptorExtractorTest.java
@@ -0,0 +1,79 @@
+package org.apache.maven.tools.plugin.extractor.annotations;
+
+/*
+ * 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.
+ */
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.DefaultArtifact;
+import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException;
+import org.apache.maven.plugin.descriptor.MojoDescriptor;
+import org.apache.maven.plugin.descriptor.PluginDescriptor;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.tools.plugin.DefaultPluginToolsRequest;
+import org.apache.maven.tools.plugin.extractor.ExtractionException;
+import org.apache.maven.tools.plugin.extractor.annotations.scanner.DefaultMojoAnnotationsScanner;
+import org.codehaus.plexus.logging.Logger;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.mock;
+
+class JavaAnnotationsMojoDescriptorExtractorTest
+{
+
+    @Test
+    void testExecute() throws InvalidPluginDescriptorException, ExtractionException
+    {
+        JavaAnnotationsMojoDescriptorExtractor mojoDescriptorExtractor = new JavaAnnotationsMojoDescriptorExtractor();
+        DefaultMojoAnnotationsScanner scanner = new DefaultMojoAnnotationsScanner();
+        scanner.enableLogging( mock( Logger.class ) );
+        mojoDescriptorExtractor.mojoAnnotationsScanner = scanner;
+        PluginDescriptor pluginDescriptor = new PluginDescriptor();
+        MavenProject mavenProject = new MavenProject();
+        File directoryToScan = new File( FooMojo.class.getResource( "" ).getFile() );
+        Artifact artifact = new DefaultArtifact("groupId", "artifactId", "1.0.0", null, "jar", "classifier", null);
+        mavenProject.setArtifact( artifact );
+        mavenProject.getBuild().setOutputDirectory( directoryToScan.toString() );
+        List<MojoDescriptor> mojoDescriptors = mojoDescriptorExtractor.execute( new DefaultPluginToolsRequest( mavenProject, pluginDescriptor ) );
+        assertEquals( 6, mojoDescriptors.size() );
+        Map<String, MojoDescriptor> descriptorsMap = mojoDescriptors.stream().collect( Collectors.toMap( MojoDescriptor::getGoal, Function.<MojoDescriptor>identity() ) );
+        assertExecuteMojo( descriptorsMap.get( "execute" ) );
+        assertExecute2Mojo( descriptorsMap.get( "execute2" ) );
+    }
+
+    private void assertExecuteMojo( MojoDescriptor mojoDescriptor )
+    {
+        assertEquals( "my-phase-id", mojoDescriptor.getExecutePhase() );
+        assertEquals( "compiler", mojoDescriptor.getExecuteGoal() );
+        assertEquals( "my-lifecyle", mojoDescriptor.getExecuteLifecycle() );
+    }
+    
+    private void assertExecute2Mojo( MojoDescriptor mojoDescriptor )
+    {
+        // standard phase overrides custom phase
+        assertEquals( LifecyclePhase.GENERATE_RESOURCES.id(), mojoDescriptor.getExecutePhase() );
+    }
+}
diff --git a/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/TestAnnotationsReader.java b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/TestAnnotationsReader.java
deleted file mode 100644
index e1ea1543..00000000
--- a/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/TestAnnotationsReader.java
+++ /dev/null
@@ -1,115 +0,0 @@
-package org.apache.maven.tools.plugin.extractor.annotations;
-
-/*
- * 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.
- */
-
-import javax.inject.Inject;
-
-import java.io.File;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.maven.plugins.annotations.Execute;
-import org.apache.maven.plugins.annotations.LifecyclePhase;
-import org.apache.maven.plugins.annotations.Mojo;
-import org.apache.maven.project.MavenProject;
-import org.apache.maven.tools.plugin.extractor.annotations.datamodel.ComponentAnnotationContent;
-import org.apache.maven.tools.plugin.extractor.annotations.datamodel.ParameterAnnotationContent;
-import org.apache.maven.tools.plugin.extractor.annotations.scanner.MojoAnnotatedClass;
-import org.apache.maven.tools.plugin.extractor.annotations.scanner.MojoAnnotationsScanner;
-import org.apache.maven.tools.plugin.extractor.annotations.scanner.MojoAnnotationsScannerRequest;
-import org.codehaus.plexus.testing.PlexusTest;
-import org.junit.jupiter.api.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.codehaus.plexus.testing.PlexusExtension.getBasedir;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-/**
- * @author Olivier Lamy
- */
-@PlexusTest
-class TestAnnotationsReader
-{
-
-    @Inject
-    MojoAnnotationsScanner mojoAnnotationsScanner;
-
-    @Test
-    void testReadMojoClass()
-        throws Exception
-    {
-        MojoAnnotationsScannerRequest request = new MojoAnnotationsScannerRequest();
-        request.setClassesDirectories( Collections.singletonList( new File( getBasedir(), "target/test-classes" ) ) );
-        request.setIncludePatterns( Arrays.asList( "**/FooMojo.class" ) );
-        request.setProject( new MavenProject() );
-
-        Map<String, MojoAnnotatedClass> mojoAnnotatedClasses = mojoAnnotationsScanner.scan( request );
-
-        System.out.println( "mojoAnnotatedClasses:" + mojoAnnotatedClasses );
-
-        assertThat( mojoAnnotatedClasses ).isNotNull().isNotEmpty().hasSize( 1 );
-
-        MojoAnnotatedClass mojoAnnotatedClass = mojoAnnotatedClasses.values().iterator().next();
-
-        assertEquals( FooMojo.class.getName(), mojoAnnotatedClass.getClassName() );
-        assertEquals( AbstractFooMojo.class.getName(), mojoAnnotatedClass.getParentClassName() );
-
-        Mojo mojo = mojoAnnotatedClass.getMojo();
-
-        assertEquals( "foo", mojo.name() );
-        assertTrue( mojo.threadSafe() );
-        assertFalse( mojo.aggregator() );
-        assertEquals( LifecyclePhase.COMPILE, mojo.defaultPhase() );
-
-        Execute execute = mojoAnnotatedClass.getExecute();
-
-        assertEquals( "compiler", execute.goal() );
-        assertEquals( "my-lifecycle", execute.lifecycle() );
-        assertEquals( LifecyclePhase.PACKAGE, execute.phase() );
-
-        Collection<ComponentAnnotationContent> components = mojoAnnotatedClass.getComponents().values();
-        assertThat( components ).isNotNull().isNotEmpty().hasSize( 1 );
-
-        Collection<ParameterAnnotationContent> parameters = mojoAnnotatedClass.getParameters().values();
-        assertThat( parameters ).isNotNull()
-            .isNotEmpty()
-            .hasSize( 5 )
-            .containsExactlyInAnyOrder(
-                new ParameterAnnotationContent( "bar", null, "thebar", "coolbar", true, false,
-                                                String.class.getName(), Collections.emptyList(), false ),
-                new ParameterAnnotationContent( "beer", null, "thebeer", "coolbeer", false, false,
-                                                String.class.getName(), Collections.emptyList(), false ),
-                new ParameterAnnotationContent( "paramFromSetter", null, "props.paramFromSetter", null,
-                                                false,
-                                                false, String.class.getName(), Collections.emptyList(), true ),
-                new ParameterAnnotationContent( "paramFromAdd", null, "props.paramFromAdd", null,
-                                                false,
-                                                false, String.class.getName(), Collections.emptyList(), true ),
-                new ParameterAnnotationContent( "paramFromSetterDeprecated", null, "props.paramFromSetterDeprecated", null,
-                                                false,
-                                                false, List.class.getName(), Collections.singletonList("java.lang.String"), true )
-            );
-    }
-}
diff --git a/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScannerTest.java b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScannerTest.java
index 9c8f0b8d..83d25b53 100644
--- a/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScannerTest.java
+++ b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScannerTest.java
@@ -21,21 +21,35 @@ package org.apache.maven.tools.plugin.extractor.annotations.scanner;
 
 import java.io.File;
 import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
+import java.util.List;
 import java.util.Map;
 
+import org.apache.maven.plugins.annotations.Execute;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.project.MavenProject;
 import org.apache.maven.tools.plugin.extractor.ExtractionException;
+import org.apache.maven.tools.plugin.extractor.annotations.AbstractFooMojo;
 import org.apache.maven.tools.plugin.extractor.annotations.DeprecatedMojo;
+import org.apache.maven.tools.plugin.extractor.annotations.FooMojo;
 import org.apache.maven.tools.plugin.extractor.annotations.ParametersWithGenericsMojo;
+import org.apache.maven.tools.plugin.extractor.annotations.datamodel.ComponentAnnotationContent;
 import org.apache.maven.tools.plugin.extractor.annotations.datamodel.ParameterAnnotationContent;
 import org.codehaus.plexus.logging.Logger;
 import org.junit.jupiter.api.Test;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.codehaus.plexus.testing.PlexusExtension.getBasedir;
 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.assertTrue;
 import static org.mockito.Mockito.mock;
 
+// TODO: merge with {@link TestAnnotationsReader}
 class DefaultMojoAnnotationsScannerTest
 {
     private DefaultMojoAnnotationsScanner scanner = new DefaultMojoAnnotationsScanner();
@@ -124,4 +138,63 @@ class DefaultMojoAnnotationsScannerTest
         assertEquals( "java.util.List", parameter.getClassName() );
         assertThat( parameter.getTypeParameters() ).containsExactly( "java.lang.Number" );
     }
+
+    @Test
+    void scanFooMojoClass()
+        throws Exception
+    {
+        MojoAnnotationsScannerRequest request = new MojoAnnotationsScannerRequest();
+        request.setClassesDirectories( Collections.singletonList( new File( getBasedir(), "target/test-classes" ) ) );
+        request.setIncludePatterns( Arrays.asList( "**/FooMojo.class" ) );
+        request.setProject( new MavenProject() );
+
+        scanner.enableLogging( mock( Logger.class ) );
+        Map<String, MojoAnnotatedClass> mojoAnnotatedClasses = scanner.scan( request );
+
+        System.out.println( "mojoAnnotatedClasses:" + mojoAnnotatedClasses );
+
+        assertThat( mojoAnnotatedClasses ).isNotNull().isNotEmpty().hasSize( 1 );
+
+        MojoAnnotatedClass mojoAnnotatedClass = mojoAnnotatedClasses.values().iterator().next();
+
+        assertEquals( FooMojo.class.getName(), mojoAnnotatedClass.getClassName() );
+        assertEquals( AbstractFooMojo.class.getName(), mojoAnnotatedClass.getParentClassName() );
+
+        Mojo mojo = mojoAnnotatedClass.getMojo();
+
+        assertEquals( "foo", mojo.name() );
+        assertTrue( mojo.threadSafe() );
+        assertFalse( mojo.aggregator() );
+        assertEquals( LifecyclePhase.COMPILE, mojo.defaultPhase() );
+
+        Execute execute = mojoAnnotatedClass.getExecute();
+
+        assertEquals( "compiler", execute.goal() );
+        assertEquals( "my-lifecycle", execute.lifecycle() );
+        assertEquals( LifecyclePhase.PACKAGE, execute.phase() );
+        assertEquals( "my-phase-id", execute.customPhase() );
+
+        Collection<ComponentAnnotationContent> components = mojoAnnotatedClass.getComponents().values();
+        assertThat( components ).isNotNull().isNotEmpty().hasSize( 1 );
+
+        Collection<ParameterAnnotationContent> parameters = mojoAnnotatedClass.getParameters().values();
+        assertThat( parameters ).isNotNull()
+            .isNotEmpty()
+            .hasSize( 5 )
+            .containsExactlyInAnyOrder(
+                new ParameterAnnotationContent( "bar", null, "thebar", "coolbar", true, false,
+                                                String.class.getName(), Collections.emptyList(), false ),
+                new ParameterAnnotationContent( "beer", null, "thebeer", "coolbeer", false, false,
+                                                String.class.getName(), Collections.emptyList(), false ),
+                new ParameterAnnotationContent( "paramFromSetter", null, "props.paramFromSetter", null,
+                                                false,
+                                                false, String.class.getName(), Collections.emptyList(), true ),
+                new ParameterAnnotationContent( "paramFromAdd", null, "props.paramFromAdd", null,
+                                                false,
+                                                false, String.class.getName(), Collections.emptyList(), true ),
+                new ParameterAnnotationContent( "paramFromSetterDeprecated", null, "props.paramFromSetterDeprecated", null,
+                                                false,
+                                                false, List.class.getName(), Collections.singletonList("java.lang.String"), true )
+            );
+    }
 }