Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
*/
@Documented
@Retention( RetentionPolicy.CLASS )
@Target( { ElementType.FIELD } )
@Target( { ElementType.FIELD, ElementType.METHOD } )
@Inherited
public @interface Parameter
{
Expand Down
1 change: 1 addition & 0 deletions maven-plugin-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@
<settingsFile>src/it/settings.xml</settingsFile>
<debug>true</debug>
<streamLogsOnFailures>true</streamLogsOnFailures>
<showErrors>true</showErrors>
<filterProperties>
<sitePluginVersion>3.12.1</sitePluginVersion>
<projectInfoReportsPlugin>3.4.1</projectInfoReportsPlugin>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ assert mojo.requirements.requirement[1].role.text() == 'org.apache.maven.project
assert mojo.requirements.requirement[1].'role-hint'.text() == ''
assert mojo.requirements.requirement[1].'field-name'.text() == 'projectHelper'

assert mojo.parameters.parameter.size() == 4
assert mojo.parameters.parameter.size() == 7

def parameter = mojo.parameters.parameter.findAll{ it.name.text() == "aliasedParam"}[0]

Expand Down Expand Up @@ -107,4 +107,37 @@ assert parameter.required.text() == 'false'
assert parameter.editable.text() == 'true'
assert parameter.description.text() == 'Interface type as parameter.'

parameter = mojo.parameters.parameter.findAll{ it.name.text() == "paramFromSetter"}[0]

assert parameter.name.text() == 'paramFromSetter'
assert parameter.alias.isEmpty()
assert parameter.type.text() == 'java.lang.String'
assert parameter.implementation.isEmpty()
assert parameter.deprecated.isEmpty()
assert parameter.required.text() == 'false'
assert parameter.editable.text() == 'true'
assert parameter.description.text() == 'setter as parameter.'

parameter = mojo.parameters.parameter.findAll{ it.name.text() == "paramFromAdd"}[0]

assert parameter.name.text() == 'paramFromAdd'
assert parameter.alias.isEmpty()
assert parameter.type.text() == 'java.lang.String'
assert parameter.implementation.isEmpty()
assert parameter.deprecated.isEmpty()
assert parameter.required.text() == 'false'
assert parameter.editable.text() == 'true'
assert parameter.description.text() == 'add method as parameter.'

parameter = mojo.parameters.parameter.findAll{ it.name.text() == "paramFromSetterDeprecated"}[0]

assert parameter.name.text() == 'paramFromSetterDeprecated'
assert parameter.alias.isEmpty()
assert parameter.type.text() == 'java.util.List'
assert parameter.implementation.isEmpty()
assert parameter.deprecated.text() == 'reason of deprecation'
assert parameter.required.text() == 'false'
assert parameter.editable.text() == 'true'
assert parameter.description.text() == 'deprecated setter as parameter.'

return true;
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,22 @@ Using Plugin Tools Java Annotations

Information for plugin descriptor generation is specified using 4 annotations:

* 2 class-level annotations:
* 2 class level annotations:

* <<<@Mojo>>>: This annotation will mark your class as a Mojo,

* <<<@Execute>>>: Used if your Mojo needs to fork a lifecycle,

[]

* 2 field-level annotations:
* 1 field or method level annotations:

* <<<@Parameter>>>: Used to configure your Mojo parameters,

[]

* 1 field level annotations:

* <<<@Component>>>: Used to configure injection of Plexus components or Maven context components.

[]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@
import com.thoughtworks.qdox.model.JavaAnnotatedElement;
import com.thoughtworks.qdox.model.JavaClass;
import com.thoughtworks.qdox.model.JavaField;
import com.thoughtworks.qdox.model.JavaMember;
import com.thoughtworks.qdox.model.JavaMethod;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.resolver.ArtifactResolutionRequest;
import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
Expand All @@ -63,8 +65,8 @@
import org.apache.maven.tools.plugin.extractor.GroupKey;
import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor;
import org.apache.maven.tools.plugin.extractor.annotations.converter.ConverterContext;
import org.apache.maven.tools.plugin.extractor.annotations.converter.JavadocBlockTagsToXhtmlConverter;
import org.apache.maven.tools.plugin.extractor.annotations.converter.JavaClassConverterContext;
import org.apache.maven.tools.plugin.extractor.annotations.converter.JavadocBlockTagsToXhtmlConverter;
import org.apache.maven.tools.plugin.extractor.annotations.converter.JavadocInlineTagsToXhtmlConverter;
import org.apache.maven.tools.plugin.extractor.annotations.datamodel.ComponentAnnotationContent;
import org.apache.maven.tools.plugin.extractor.annotations.datamodel.ExecuteAnnotationContent;
Expand Down Expand Up @@ -141,7 +143,7 @@ public List<MojoDescriptor> execute( PluginToolsRequest request )
JavaProjectBuilder builder = scanJavadoc( request, mojoAnnotatedClasses.values() );
Map<String, JavaClass> javaClassesMap = discoverClasses( builder );


JavadocLinkGenerator linkGenerator = new JavadocLinkGenerator( request.getInternalJavadocBaseUrl(),
request.getInternalJavadocVersion(),
request.getExternalJavadocBaseUrls(),
Expand Down Expand Up @@ -176,11 +178,11 @@ private JavaProjectBuilder scanJavadoc( PluginToolsRequest request,

// if we need to scan sources from external artifacts
Set<Artifact> externalArtifacts = new HashSet<>();

JavaProjectBuilder builder = new JavaProjectBuilder( new SortedClassLibraryBuilder( ) );
builder.setEncoding( request.getEncoding() );
extendJavaProjectBuilder( builder, request.getProject() );

for ( MojoAnnotatedClass mojoAnnotatedClass : mojoAnnotatedClasses )
{
if ( Objects.equals( mojoAnnotatedClass.getArtifact().getArtifactId(),
Expand Down Expand Up @@ -244,7 +246,7 @@ protected void populateDataFromJavadoc( JavaProjectBuilder javaProjectBuilder,
Map<String, JavaClass> javaClassesMap,
JavadocLinkGenerator linkGenerator )
{

for ( Map.Entry<String, MojoAnnotatedClass> entry : mojoAnnotatedClasses.entrySet() )
{
JavaClass javaClass = javaClassesMap.get( entry.getKey() );
Expand All @@ -256,11 +258,11 @@ protected void populateDataFromJavadoc( JavaProjectBuilder javaProjectBuilder,
MojoAnnotationContent mojoAnnotationContent = entry.getValue().getMojo();
if ( mojoAnnotationContent != null )
{
JavaClassConverterContext context =
JavaClassConverterContext context =
new JavaClassConverterContext( javaClass, javaProjectBuilder,
mojoAnnotatedClasses, linkGenerator,
mojoAnnotatedClasses, linkGenerator,
javaClass.getLineNumber() );
mojoAnnotationContent.setDescription(
mojoAnnotationContent.setDescription(
getDescriptionFromElement( javaClass, context ) );

DocletTag since = findInClassHierarchy( javaClass, "since" );
Expand All @@ -276,35 +278,35 @@ protected void populateDataFromJavadoc( JavaProjectBuilder javaProjectBuilder,
}
}

Map<String, JavaField> fieldsMap = extractFieldParameterTags( javaClass, javaClassesMap );
Map<String, JavaAnnotatedElement> elementMap = extractParameterAnnotations( javaClass, javaClassesMap );

// populate parameters
Map<String, ParameterAnnotationContent> parameters =
getParametersParentHierarchy( entry.getValue(), mojoAnnotatedClasses );
parameters = new TreeMap<>( parameters );
for ( Map.Entry<String, ParameterAnnotationContent> parameter : parameters.entrySet() )
{
JavaField javaField = fieldsMap.get( parameter.getKey() );
if ( javaField == null )
JavaAnnotatedElement element = elementMap.get( parameter.getKey() );
if ( element == null )
{
continue;
}

JavaClassConverterContext context =
new JavaClassConverterContext( javaClass, javaField.getDeclaringClass(),
javaProjectBuilder, mojoAnnotatedClasses,
linkGenerator, javaField.getLineNumber() );
JavaClassConverterContext context =
new JavaClassConverterContext( javaClass, ( (JavaMember) element ).getDeclaringClass(),
javaProjectBuilder, mojoAnnotatedClasses,
linkGenerator, element.getLineNumber() );
ParameterAnnotationContent parameterAnnotationContent = parameter.getValue();
parameterAnnotationContent.setDescription(
getDescriptionFromElement( javaField, context ) );
parameterAnnotationContent.setDescription(
getDescriptionFromElement( element, context ) );

DocletTag deprecated = javaField.getTagByName( "deprecated" );
DocletTag deprecated = element.getTagByName( "deprecated" );
if ( deprecated != null )
{
parameterAnnotationContent.setDeprecated( getRawValueFromTaglet ( deprecated, context ) );
}

DocletTag since = javaField.getTagByName( "since" );
DocletTag since = element.getTagByName( "since" );
if ( since != null )
{
parameterAnnotationContent.setSince( getRawValueFromTaglet ( since, context ) );
Expand All @@ -315,27 +317,27 @@ protected void populateDataFromJavadoc( JavaProjectBuilder javaProjectBuilder,
Map<String, ComponentAnnotationContent> components = entry.getValue().getComponents();
for ( Map.Entry<String, ComponentAnnotationContent> component : components.entrySet() )
{
JavaField javaField = fieldsMap.get( component.getKey() );
if ( javaField == null )
JavaAnnotatedElement element = elementMap.get( component.getKey() );
if ( element == null )
{
continue;
}

JavaClassConverterContext context =
new JavaClassConverterContext( javaClass, javaField.getDeclaringClass(),
javaProjectBuilder, mojoAnnotatedClasses,
linkGenerator, javaClass.getLineNumber() );
JavaClassConverterContext context =
new JavaClassConverterContext( javaClass, ( (JavaMember) element ).getDeclaringClass(),
javaProjectBuilder, mojoAnnotatedClasses,
linkGenerator, javaClass.getLineNumber() );
ComponentAnnotationContent componentAnnotationContent = component.getValue();
componentAnnotationContent.setDescription(
getDescriptionFromElement( javaField, context ) );
componentAnnotationContent.setDescription(
getDescriptionFromElement( element, context ) );

DocletTag deprecated = javaField.getTagByName( "deprecated" );
DocletTag deprecated = element.getTagByName( "deprecated" );
if ( deprecated != null )
{
componentAnnotationContent.setDeprecated( getRawValueFromTaglet ( deprecated, context ) );
}

DocletTag since = javaField.getTagByName( "since" );
DocletTag since = element.getTagByName( "since" );
if ( since != null )
{
componentAnnotationContent.setSince( getRawValueFromTaglet ( since, context ) );
Expand All @@ -355,7 +357,7 @@ protected void populateDataFromJavadoc( JavaProjectBuilder javaProjectBuilder,
*/
String getDescriptionFromElement( JavaAnnotatedElement element, JavaClassConverterContext context )
{

String comment = element.getComment();
if ( comment == null )
{
Expand Down Expand Up @@ -411,32 +413,33 @@ private DocletTag findInClassHierarchy( JavaClass javaClass, String tagName )

/**
* extract fields that are either parameters or components.
* Also extract methods that are parameters
*
* @param javaClass not null
* @return map with Mojo parameters names as keys
*/
private Map<String, JavaField> extractFieldParameterTags( JavaClass javaClass,
Map<String, JavaClass> javaClassesMap )
private Map<String, JavaAnnotatedElement> extractParameterAnnotations( JavaClass javaClass,
Map<String, JavaClass> javaClassesMap )
{
try
{
Map<String, JavaField> rawParams = new TreeMap<>();
Map<String, JavaAnnotatedElement> rawParams = new TreeMap<>();

// we have to add the parent fields first, so that they will be overwritten by the local fields if
// that actually happens...
JavaClass superClass = javaClass.getSuperJavaClass();

if ( superClass != null )
{
if ( superClass.getFields().size() > 0 )
if ( !superClass.getFields().isEmpty() || !superClass.getMethods().isEmpty() )
{
rawParams = extractFieldParameterTags( superClass, javaClassesMap );
rawParams = extractParameterAnnotations( superClass, javaClassesMap );
}
// maybe sources comes from scan of sources artifact
superClass = javaClassesMap.get( superClass.getFullyQualifiedName() );
if ( superClass != null )
if ( superClass != null && ( !superClass.getFields().isEmpty() || !superClass.getMethods().isEmpty() ) )
{
rawParams = extractFieldParameterTags( superClass, javaClassesMap );
rawParams = extractParameterAnnotations( superClass, javaClassesMap );
}
}
else
Expand All @@ -450,6 +453,15 @@ private Map<String, JavaField> extractFieldParameterTags( JavaClass javaClass,
rawParams.put( field.getName(), field );
}

for ( JavaMethod method : javaClass.getMethods() )
{
if ( isPublicSetterMethod( method ) )
{
rawParams.put(
StringUtils.lowercaseFirstLetter( method.getName().substring( 3 ) ), method );
}
}

return rawParams;
}
catch ( NoClassDefFoundError e )
Expand All @@ -459,6 +471,16 @@ private Map<String, JavaField> extractFieldParameterTags( JavaClass javaClass,
}
}

private boolean isPublicSetterMethod( JavaMethod method )
{
return method.isPublic()
Comment thread
slawekjaranowski marked this conversation as resolved.
&& !method.isStatic()
&& method.getName().length() > 3
&& ( method.getName().startsWith( "add" ) || method.getName().startsWith( "set" ) )
&& "void".equals( method.getReturnType().getValue() )
&& method.getParameters().size() == 1;
}

protected Map<String, JavaClass> discoverClasses( JavaProjectBuilder builder )
{
Collection<JavaClass> javaClasses = builder.getClasses();
Expand All @@ -477,7 +499,7 @@ protected Map<String, JavaClass> discoverClasses( JavaProjectBuilder builder )

return javaClassMap;
}

protected void extendJavaProjectBuilderWithSourcesJar( JavaProjectBuilder builder,
Artifact artifact, PluginToolsRequest request,
String classifier )
Expand All @@ -488,7 +510,7 @@ protected void extendJavaProjectBuilderWithSourcesJar( JavaProjectBuilder builde
Artifact sourcesArtifact =
repositorySystem.createArtifactWithClassifier( artifact.getGroupId(), artifact.getArtifactId(),
artifact.getVersion(), artifact.getType(), classifier );

ArtifactResolutionRequest req = new ArtifactResolutionRequest();
req.setArtifact( sourcesArtifact );
req.setLocalRepository( request.getLocal() );
Expand All @@ -501,25 +523,25 @@ protected void extendJavaProjectBuilderWithSourcesJar( JavaProjectBuilder builde
+ artifact.getVersion() + ". Some javadoc tags (@since, @deprecated and comments) won't be used" );
return;
}

if ( sourcesArtifact.getFile() == null || !sourcesArtifact.getFile().exists() )
{
// could not get artifact sources
return;
}

// extract sources to target/maven-plugin-plugin-sources/${groupId}/${artifact}/sources
File extractDirectory = new File( request.getProject().getBuild().getDirectory(),
"maven-plugin-plugin-sources/" + sourcesArtifact.getGroupId() + "/"
+ sourcesArtifact.getArtifactId() + "/" + sourcesArtifact.getVersion()
+ "/" + sourcesArtifact.getClassifier() );
extractDirectory.mkdirs();

UnArchiver unArchiver = archiverManager.getUnArchiver( "jar" );
unArchiver.setSourceFile( sourcesArtifact.getFile() );
unArchiver.setDestDirectory( extractDirectory );
unArchiver.extract();

extendJavaProjectBuilder( builder,
Arrays.asList( extractDirectory ),
request.getDependencies() );
Expand All @@ -530,7 +552,7 @@ protected void extendJavaProjectBuilderWithSourcesJar( JavaProjectBuilder builde
}
}

private void extendJavaProjectBuilder( JavaProjectBuilder builder,
private void extendJavaProjectBuilder( JavaProjectBuilder builder,
final MavenProject project )
{
List<File> sources = new ArrayList<>();
Expand Down
Loading