diff --git a/maven-plugin-tools-annotations/pom.xml b/maven-plugin-tools-annotations/pom.xml
index 52e9f3b4d..1830d6698 100644
--- a/maven-plugin-tools-annotations/pom.xml
+++ b/maven-plugin-tools-annotations/pom.xml
@@ -78,6 +78,10 @@
org.ow2.asm
asm
+
+ org.ow2.asm
+ asm-util
+
org.jsoup
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 d37042932..ac7b4ea9d 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
@@ -39,6 +39,7 @@
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
+import java.util.stream.Collectors;
import com.thoughtworks.qdox.JavaProjectBuilder;
import com.thoughtworks.qdox.library.SortedClassLibraryBuilder;
@@ -698,7 +699,13 @@ private List toMojoDescriptors( Map
+ property, null );
}
parameter.setExpression( StringUtils.isEmpty( property ) ? "" : "${" + property + "}" );
- parameter.setType( parameterAnnotationContent.getClassName() );
+ StringBuilder type = new StringBuilder( parameterAnnotationContent.getClassName() );
+ if ( !parameterAnnotationContent.getTypeParameters().isEmpty() )
+ {
+ type.append( parameterAnnotationContent.getTypeParameters().stream()
+ .collect( Collectors.joining( ", ", "<", ">" ) ) );
+ }
+ parameter.setType( type.toString() );
parameter.setSince( parameterAnnotationContent.getSince() );
parameter.setRequired( parameterAnnotationContent.required() );
diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/ParameterAnnotationContent.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/ParameterAnnotationContent.java
index 3d9f8922e..6ac23be50 100644
--- a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/ParameterAnnotationContent.java
+++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/ParameterAnnotationContent.java
@@ -23,6 +23,7 @@
import org.objectweb.asm.Type;
import java.lang.annotation.Annotation;
+import java.util.List;
import java.util.Objects;
/**
@@ -50,16 +51,20 @@ public class ParameterAnnotationContent
private String className;
- public ParameterAnnotationContent( String fieldName, String className )
+ private final List typeParameters;
+
+ public ParameterAnnotationContent( String fieldName, String className, List typeParameters )
{
super( fieldName );
this.className = className;
+ this.typeParameters = typeParameters;
}
public ParameterAnnotationContent( String fieldName, String alias, String property, String defaultValue,
- Class> implementation, boolean required, boolean readonly, String className )
+ Class> implementation, boolean required, boolean readonly, String className,
+ List typeParameters )
{
- this( fieldName, className );
+ this( fieldName, className, typeParameters );
this.alias = alias;
this.property = property;
this.defaultValue = defaultValue;
@@ -177,6 +182,11 @@ public void setClassName( String className )
this.className = className;
}
+ public List getTypeParameters()
+ {
+ return typeParameters;
+ }
+
@Override
public String toString()
{
@@ -185,6 +195,7 @@ public String toString()
sb.append( "ParameterAnnotationContent" );
sb.append( "{fieldName='" ).append( getFieldName() ).append( '\'' );
sb.append( ", className='" ).append( getClassName() ).append( '\'' );
+ sb.append( ", typeParameters='" ).append( getTypeParameters() ).append( '\'' );
sb.append( ", name='" ).append( name ).append( '\'' );
sb.append( ", alias='" ).append( alias ).append( '\'' );
sb.append( ", alias='" ).append( alias ).append( '\'' );
@@ -230,6 +241,10 @@ public boolean equals( Object o )
return false;
}
+ if ( !Objects.equals( typeParameters, that.typeParameters ) )
+ {
+ return false;
+ }
if ( !Objects.equals( alias, that.alias ) )
{
return false;
@@ -253,7 +268,7 @@ public boolean equals( Object o )
@Override
public int hashCode()
{
- return Objects.hash( alias, getFieldName(), property, defaultValue, required, readonly,
- implementationClassName );
+ return Objects.hash( alias, getFieldName(), getClassName(), typeParameters, property, defaultValue, required,
+ readonly, implementationClassName );
}
}
diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScanner.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScanner.java
index 2b441751c..c0e3ed886 100644
--- a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScanner.java
+++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScanner.java
@@ -302,7 +302,8 @@ protected void analyzeVisitors( MojoClassVisitor mojoClassVisitor )
for ( MojoParameterVisitor parameterVisitor : mojoParameterVisitors )
{
ParameterAnnotationContent parameterAnnotationContent =
- new ParameterAnnotationContent( parameterVisitor.getFieldName(), parameterVisitor.getClassName() );
+ new ParameterAnnotationContent( parameterVisitor.getFieldName(), parameterVisitor.getClassName(),
+ parameterVisitor.getTypeParameters() );
Map annotationVisitorMap = parameterVisitor.getAnnotationVisitorMap();
MojoAnnotationVisitor fieldAnnotationVisitor = annotationVisitorMap.get( Parameter.class.getName() );
diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoClassVisitor.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoClassVisitor.java
index 9376564d5..6267d64ff 100644
--- a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoClassVisitor.java
+++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoClassVisitor.java
@@ -20,6 +20,8 @@
*/
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -36,6 +38,8 @@
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
+import org.objectweb.asm.signature.SignatureReader;
+import org.objectweb.asm.util.TraceSignatureVisitor;
/**
* Visitor for Mojo classes.
@@ -117,11 +121,49 @@ public AnnotationVisitor visitAnnotation( String desc, boolean visible )
@Override
public FieldVisitor visitField( int access, String name, String desc, String signature, Object value )
{
- MojoFieldVisitor mojoFieldVisitor = new MojoFieldVisitor( name, Type.getType( desc ).getClassName() );
+ List typeParameters = extractTypeParameters( access, signature, true );
+ MojoFieldVisitor mojoFieldVisitor = new MojoFieldVisitor( name, Type.getType( desc ).getClassName(),
+ typeParameters );
fieldVisitors.add( mojoFieldVisitor );
return mojoFieldVisitor;
}
+ /**
+ * Parses the signature according to
+ * JVMS 4.3.4
+ * and returns the type parameters.
+ * @param access
+ * @param signature
+ * @param isField
+ * @return the list of type parameters (may be empty)
+ */
+ private List extractTypeParameters( int access, String signature, boolean isField )
+ {
+ if ( StringUtils.isEmpty( signature ) )
+ {
+ return Collections.emptyList();
+ }
+ TraceSignatureVisitor traceSignatureVisitor = new TraceSignatureVisitor( access );
+ SignatureReader signatureReader = new SignatureReader( signature );
+ if ( isField )
+ {
+ signatureReader.acceptType( traceSignatureVisitor );
+ }
+ else
+ {
+ signatureReader.accept( traceSignatureVisitor );
+ }
+ String declaration = traceSignatureVisitor.getDeclaration();
+ int startTypeParameters = declaration.indexOf( '<' );
+ if ( startTypeParameters == -1 )
+ {
+ return Collections.emptyList();
+ }
+ String typeParameters = declaration.substring( startTypeParameters + 1,
+ declaration.lastIndexOf( '>' ) );
+ return Arrays.asList( typeParameters.split( ", " ) );
+ }
+
@Override
public MethodVisitor visitMethod( int access, String name, String desc, String signature, String[] exceptions )
{
@@ -142,8 +184,9 @@ public MethodVisitor visitMethod( int access, String name, String desc, String s
{
String fieldName = StringUtils.lowercaseFirstLetter( name.substring( 3 ) );
String className = type.getArgumentTypes()[0].getClassName();
+ List typeParameters = extractTypeParameters( access, signature, false );
- MojoMethodVisitor mojoMethodVisitor = new MojoMethodVisitor( fieldName, className );
+ MojoMethodVisitor mojoMethodVisitor = new MojoMethodVisitor( fieldName, className, typeParameters );
methodVisitors.add( mojoMethodVisitor );
return mojoMethodVisitor;
}
diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoFieldVisitor.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoFieldVisitor.java
index 550bd579d..3e017afc3 100644
--- a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoFieldVisitor.java
+++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoFieldVisitor.java
@@ -20,6 +20,7 @@
*/
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import org.apache.maven.tools.plugin.extractor.annotations.scanner.MojoAnnotationsScanner;
@@ -43,11 +44,14 @@ public class MojoFieldVisitor
private String className;
- MojoFieldVisitor( String fieldName, String className )
+ private final List typeParameters;
+
+ MojoFieldVisitor( String fieldName, String className, List typeParameters )
{
super( Opcodes.ASM9 );
this.fieldName = fieldName;
this.className = className;
+ this.typeParameters = typeParameters;
}
@Override
@@ -62,6 +66,12 @@ public String getFieldName()
return fieldName;
}
+ @Override
+ public List getTypeParameters()
+ {
+ return typeParameters;
+ }
+
@Override
public AnnotationVisitor visitAnnotation( String desc, boolean visible )
{
diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoMethodVisitor.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoMethodVisitor.java
index 448bb7880..dd121f728 100644
--- a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoMethodVisitor.java
+++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoMethodVisitor.java
@@ -20,6 +20,7 @@
*/
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import org.apache.maven.tools.plugin.extractor.annotations.scanner.MojoAnnotationsScanner;
@@ -37,14 +38,15 @@ public class MojoMethodVisitor extends MethodVisitor implements MojoParameterVis
{
private final String className;
private final String fieldName;
-
+ private final List typeParameters;
private Map annotationVisitorMap = new HashMap<>();
- public MojoMethodVisitor( String fieldName, String className )
+ public MojoMethodVisitor( String fieldName, String className, List typeParameters )
{
super( Opcodes.ASM9 );
this.fieldName = fieldName;
this.className = className;
+ this.typeParameters = typeParameters;
}
@Override
@@ -73,6 +75,12 @@ public String getClassName()
return className;
}
+ @Override
+ public List getTypeParameters()
+ {
+ return typeParameters;
+ }
+
@Override
public Map getAnnotationVisitorMap()
{
diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoParameterVisitor.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoParameterVisitor.java
index c95ac05c2..e9ba40570 100644
--- a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoParameterVisitor.java
+++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoParameterVisitor.java
@@ -19,6 +19,7 @@
* under the License.
*/
+import java.util.List;
import java.util.Map;
/**
@@ -32,5 +33,7 @@ public interface MojoParameterVisitor
String getClassName();
+ List getTypeParameters();
+
Map getAnnotationVisitorMap();
}
diff --git a/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/ParametersWithGenericsMojo.java b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/ParametersWithGenericsMojo.java
new file mode 100644
index 000000000..5a1d3a269
--- /dev/null
+++ b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/ParametersWithGenericsMojo.java
@@ -0,0 +1,66 @@
+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.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+
+@Mojo( name = "parameter-with-generics" )
+public class ParametersWithGenericsMojo
+ extends AbstractMojo
+{
+
+ @Parameter
+ private String string;
+
+ @Parameter
+ private Map stringBooleanMap;
+
+ @Parameter
+ private Collection integerCollection;
+
+ @Parameter
+ private Collection> nestedStringCollection;
+
+ @Parameter
+ private Collection integerArrayCollection;
+
+ @Override
+ public void execute() throws MojoExecutionException, MojoFailureException {
+ }
+
+ @Parameter( name="numberList" )
+ public void setNumberList(List numberList) {
+ }
+
+ public static class NestedClass {
+ /**
+ * Some field without type parameter but non-empty signature
+ */
+ protected E filter;
+ }
+}
\ No newline at end of file
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
index 81796881c..dca5896c2 100644
--- 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
@@ -98,25 +98,25 @@ void testReadMojoClass()
.hasSize( 6 )
.containsExactlyInAnyOrder(
new ParameterAnnotationContent( "bar", null, "thebar", "coolbar", null, true, false,
- String.class.getName() ),
+ String.class.getName(), Collections.emptyList() ),
new ParameterAnnotationContent( "beer", null, "thebeer", "coolbeer", null, false, false,
- String.class.getName() ),
+ String.class.getName(), Collections.emptyList() ),
new ParameterAnnotationContent( "fooInterface", null, "fooInterface", null,
FooInterfaceImpl.class,
false,
- false, FooInterface.class.getName() ),
+ false, FooInterface.class.getName(), Collections.emptyList() ),
new ParameterAnnotationContent( "paramFromSetter", null, "props.paramFromSetter", null,
null,
false,
- false, String.class.getName() ),
+ false, String.class.getName(), Collections.emptyList() ),
new ParameterAnnotationContent( "paramFromAdd", null, "props.paramFromAdd", null,
null,
false,
- false, String.class.getName() ),
+ false, String.class.getName(), Collections.emptyList() ),
new ParameterAnnotationContent( "paramFromSetterDeprecated", null, "props.paramFromSetterDeprecated", null,
null,
false,
- false, List.class.getName() )
+ false, List.class.getName(), Collections.singletonList("java.lang.String") )
);
}
}
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 87dfc4e50..9c8f0b8d7 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
@@ -26,10 +26,14 @@
import org.apache.maven.tools.plugin.extractor.ExtractionException;
import org.apache.maven.tools.plugin.extractor.annotations.DeprecatedMojo;
+import org.apache.maven.tools.plugin.extractor.annotations.ParametersWithGenericsMojo;
+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.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.Mockito.mock;
class DefaultMojoAnnotationsScannerTest
@@ -76,4 +80,48 @@ void scanDeprecatedMojoAnnotatins() throws ExtractionException, IOException
.isEqualTo( "property.anotherNotDeprecated" );
}
+ @Test
+ void scanParametersWithGenerics() throws ExtractionException, IOException
+ {
+ File directoryToScan = new File( ParametersWithGenericsMojo.class.getResource( "" ).getFile() );
+
+ scanner.enableLogging( mock( Logger.class ) );
+ Map result = scanner.scanDirectory(
+ directoryToScan, Collections.singletonList( "ParametersWithGenericsMojo**.class" ), null, false );
+
+ assertThat( result ).hasSize( 2 ); // mojo and nested class
+
+ MojoAnnotatedClass annotatedClass = result.get( ParametersWithGenericsMojo.class.getName() );
+ assertThat( annotatedClass.getClassName() ).isEqualTo( ParametersWithGenericsMojo.class.getName() );
+
+ ParameterAnnotationContent parameter = annotatedClass.getParameters().get( "string" );
+ assertNotNull( parameter );
+ assertEquals( "java.lang.String", parameter.getClassName() );
+ assertThat( parameter.getTypeParameters() ).isEmpty();
+
+ parameter = annotatedClass.getParameters().get( "stringBooleanMap" );
+ assertNotNull( parameter );
+ assertEquals( "java.util.Map", parameter.getClassName() );
+ assertThat( parameter.getTypeParameters() ).containsExactly( "java.lang.String", "java.lang.Boolean" );
+
+ parameter = annotatedClass.getParameters().get( "integerCollection" );
+ assertNotNull( parameter );
+ assertEquals( "java.util.Collection", parameter.getClassName() );
+ assertThat( parameter.getTypeParameters() ).containsExactly( "java.lang.Integer" );
+
+ parameter = annotatedClass.getParameters().get( "nestedStringCollection" );
+ assertNotNull( parameter );
+ assertEquals( "java.util.Collection", parameter.getClassName() );
+ assertThat( parameter.getTypeParameters() ).containsExactly( "java.util.Collection" );
+
+ parameter = annotatedClass.getParameters().get( "integerArrayCollection" );
+ assertNotNull( parameter );
+ assertEquals( "java.util.Collection", parameter.getClassName() );
+ assertThat( parameter.getTypeParameters() ).containsExactly( "java.lang.Integer[]" );
+
+ parameter = annotatedClass.getParameters().get( "numberList" );
+ assertNotNull( parameter );
+ assertEquals( "java.util.List", parameter.getClassName() );
+ assertThat( parameter.getTypeParameters() ).containsExactly( "java.lang.Number" );
+ }
}
diff --git a/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorFilesGenerator.java b/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorFilesGenerator.java
index 1f0f00c8a..a21a4e443 100644
--- a/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorFilesGenerator.java
+++ b/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorFilesGenerator.java
@@ -511,31 +511,8 @@ else if ( type != DescriptorType.LIMITED_FOR_HELP_MOJO || parameter.isEditable()
GeneratorUtils.element( w, "alias", parameter.getAlias() );
}
- GeneratorUtils.element( w, "type", parameter.getType() );
+ writeParameterType( w, type, javadocLinkGenerator, parameter, mojoDescriptor.getGoal() );
- if ( type == DescriptorType.XHTML && javadocLinkGenerator != null )
- {
- // skip primitives which never has javadoc
- if ( parameter.getType().indexOf( '.' ) == -1 )
- {
- LOG.debug( "Javadoc URLs are not available for primitive types like {}",
- parameter.getType() );
- }
- else
- {
- try
- {
- URI uri = javadocLinkGenerator.createLink( parameter.getType() );
- GeneratorUtils.element( w, "typeJavadocUrl", uri.toString() );
- }
- catch ( IllegalArgumentException e )
- {
- LOG.warn( "Could not get javadoc URL for type {} of parameter {} from goal {}: {}",
- parameter.getType(), parameter.getName(), mojoDescriptor.getGoal(),
- e.getMessage() );
- }
- }
- }
if ( parameter.getSince() != null )
{
w.startElement( "since" );
@@ -665,6 +642,83 @@ else if ( type != DescriptorType.LIMITED_FOR_HELP_MOJO || parameter.isEditable()
w.endElement();
}
+ /**
+ * Writes parameter type information and potentially also the related javadoc URL.
+ * @param w
+ * @param type
+ * @param javadocLinkGenerator
+ * @param parameter
+ * @param goal
+ */
+ protected void writeParameterType( XMLWriter w, DescriptorType type, JavadocLinkGenerator javadocLinkGenerator,
+ Parameter parameter, String goal )
+ {
+ String parameterType = parameter.getType();
+
+ if ( type == DescriptorType.STANDARD )
+ {
+ // strip type by parameter type (generics) information for standard plugin descriptor
+ parameterType = StringUtils.chomp( parameterType, "<" );
+ }
+ GeneratorUtils.element( w, "type", parameterType );
+
+ if ( type == DescriptorType.XHTML && javadocLinkGenerator != null )
+ {
+ // skip primitives which never has javadoc
+ if ( parameter.getType().indexOf( '.' ) == -1 )
+ {
+ LOG.debug( "Javadoc URLs are not available for primitive types like {}",
+ parameter.getType() );
+ }
+ else
+ {
+ try
+ {
+ URI javadocUrl = getJavadocUrlForType( javadocLinkGenerator, parameterType );
+ GeneratorUtils.element( w, "typeJavadocUrl", javadocUrl.toString() );
+ }
+ catch ( IllegalArgumentException e )
+ {
+ LOG.warn( "Could not get javadoc URL for type {} of parameter {} from goal {}: {}",
+ parameter.getType(), parameter.getName(), goal,
+ e.getMessage() );
+ }
+ }
+ }
+ }
+
+ static URI getJavadocUrlForType( JavadocLinkGenerator javadocLinkGenerator, String type )
+ {
+ final String binaryName;
+ int startOfParameterType = type.indexOf( "<" );
+ if ( startOfParameterType != -1 )
+ {
+ // parse parameter type
+ String mainType = type.substring( 0, startOfParameterType );
+
+ // some heuristics here
+ String[] parameterTypes = type.substring( startOfParameterType + 1, type.lastIndexOf( ">" ) )
+ .split( ",\\s*" );
+ switch ( parameterTypes.length )
+ {
+ case 1: // if only one parameter type, assume collection, first parameter type is most interesting
+ binaryName = parameterTypes[0];
+ break;
+ case 2: // if two parameter types assume map, second parameter type is most interesting
+ binaryName = parameterTypes[1];
+ break;
+ default:
+ // all other cases link to main type
+ binaryName = mainType;
+ }
+ }
+ else
+ {
+ binaryName = type;
+ }
+ return javadocLinkGenerator.createLink( binaryName );
+ }
+
/**
* Get the expression value, eventually surrounding it with ${ }
.
*
diff --git a/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginXdocGenerator.java b/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginXdocGenerator.java
index 9344cae85..c13a17908 100644
--- a/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginXdocGenerator.java
+++ b/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginXdocGenerator.java
@@ -546,13 +546,63 @@ private void writeParameterDetails( List parameterList, XMLWriter w )
w.endElement();
}
+ static String getShortType( String type )
+ {
+ // split into type arguments and main type
+ int startTypeArguments = type.indexOf( '<' );
+ if ( startTypeArguments == -1 )
+ {
+ return getShortTypeOfSimpleType( type );
+ }
+ else
+ {
+ StringBuilder shortType = new StringBuilder();
+ shortType.append( getShortTypeOfSimpleType( type.substring( 0, startTypeArguments ) ) );
+ shortType.append( "<" )
+ .append( getShortTypeOfTypeArgument(
+ type.substring( startTypeArguments + 1, type.lastIndexOf( ">" ) ) ) )
+ .append( ">" );
+ return shortType.toString();
+ }
+
+ }
+
+ private static String getShortTypeOfTypeArgument( String type )
+ {
+ String[] typeArguments = type.split( ",\\s*" );
+ StringBuilder shortType = new StringBuilder();
+ for ( int i = 0; i < typeArguments.length; i++ )
+ {
+ String typeArgument = typeArguments[i];
+ if ( typeArgument.contains( "<" ) )
+ {
+ // nested type arguments lead to ellipsis
+ return "...";
+ }
+ else
+ {
+ shortType.append( getShortTypeOfSimpleType( typeArgument ) );
+ if ( i < typeArguments.length - 1 )
+ {
+ shortType.append( "," );
+ }
+ }
+ }
+ return shortType.toString();
+ }
+
+ private static String getShortTypeOfSimpleType( String type )
+ {
+ int index = type.lastIndexOf( '.' );
+ return type.substring( index + 1 );
+ }
+
private String getLinkedType( Parameter parameter, boolean isShortType )
{
final String typeValue;
if ( isShortType )
{
- int index = parameter.getType().lastIndexOf( '.' );
- typeValue = parameter.getType().substring( index + 1 );
+ typeValue = getShortType( parameter.getType() );
}
else
{
@@ -568,12 +618,12 @@ private String getLinkedType( Parameter parameter, boolean isShortType )
if ( javadocUrl.isAbsolute()
|| JavadocLinkGenerator.isLinkValid( javadocUrl, reportOutputDirectory.toPath() ) )
{
- return format( "pluginxdoc.mojodescriptor.parameter.type_link",
- new Object[] { typeValue, enhancedParameter.getTypeJavadocUrl() } );
+ return format( "pluginxdoc.mojodescriptor.parameter.type_link",
+ new Object[] { escapeXml( typeValue ), enhancedParameter.getTypeJavadocUrl() } );
}
}
}
- return typeValue;
+ return escapeXml( typeValue );
}
private boolean addUl( XMLWriter w, boolean addedUl, String content )
diff --git a/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/PluginDescriptorFilesGeneratorTest.java b/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/PluginDescriptorFilesGeneratorTest.java
index 0187af033..3e8decd8e 100644
--- a/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/PluginDescriptorFilesGeneratorTest.java
+++ b/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/PluginDescriptorFilesGeneratorTest.java
@@ -19,22 +19,26 @@
* under the License.
*/
-import org.apache.maven.plugin.descriptor.MojoDescriptor;
-import org.apache.maven.plugin.descriptor.Parameter;
-import org.apache.maven.plugin.descriptor.PluginDescriptor;
-import org.apache.maven.plugin.descriptor.PluginDescriptorBuilder;
-import org.codehaus.plexus.component.repository.ComponentDependency;
-import org.codehaus.plexus.testing.PlexusTest;
-import org.codehaus.plexus.util.ReaderFactory;
-
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
+import java.net.URI;
+import java.net.URISyntaxException;
import java.util.List;
+import org.apache.maven.plugin.descriptor.MojoDescriptor;
+import org.apache.maven.plugin.descriptor.Parameter;
+import org.apache.maven.plugin.descriptor.PluginDescriptor;
+import org.apache.maven.plugin.descriptor.PluginDescriptorBuilder;
+import org.apache.maven.tools.plugin.javadoc.JavadocLinkGenerator;
+import org.codehaus.plexus.component.repository.ComponentDependency;
+import org.codehaus.plexus.testing.PlexusTest;
+import org.codehaus.plexus.util.ReaderFactory;
+import org.junit.jupiter.api.Test;
+
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -131,4 +135,19 @@ private void checkDependency( String groupId, String artifactId, String version,
assertEquals( version, dependency.getVersion() );
}
+
+ @Test
+ void testGetJavadocUrlForType() throws URISyntaxException
+ {
+ URI javadocBaseUri = new URI( "http://localhost/apidocs/" );
+ JavadocLinkGenerator linkGenerator = new JavadocLinkGenerator( javadocBaseUri, "1.8" );
+ assertEquals( javadocBaseUri.resolve("java/lang/String.html"),
+ PluginDescriptorFilesGenerator.getJavadocUrlForType( linkGenerator, "java.lang.String" ) );
+ assertEquals( javadocBaseUri.resolve("java/lang/String.html"),
+ PluginDescriptorFilesGenerator.getJavadocUrlForType( linkGenerator, "java.lang.Collection" ) );
+ assertEquals( javadocBaseUri.resolve("java/lang/Integer.html"),
+ PluginDescriptorFilesGenerator.getJavadocUrlForType( linkGenerator, "java.lang.Map" ) );
+ assertEquals( javadocBaseUri.resolve("java/util/function/BiFunction.html"),
+ PluginDescriptorFilesGenerator.getJavadocUrlForType( linkGenerator, "java.util.function.BiFunction" ) );
+ }
}
\ No newline at end of file
diff --git a/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/PluginXdocGeneratorTest.java b/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/PluginXdocGeneratorTest.java
index d4c983dc2..05903058b 100644
--- a/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/PluginXdocGeneratorTest.java
+++ b/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/PluginXdocGeneratorTest.java
@@ -26,6 +26,9 @@
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* @author Jason van Zyl
@@ -52,4 +55,12 @@ protected void validate( File destinationDirectory )
}
+ @Test
+ void testGetShortType()
+ {
+ assertEquals("String", PluginXdocGenerator.getShortType( "java.lang.String" ) );
+ assertEquals("List", PluginXdocGenerator.getShortType( "java.util.List" ) );
+ assertEquals("Map", PluginXdocGenerator.getShortType( "java.util.Map" ) );
+ assertEquals("List<...>", PluginXdocGenerator.getShortType( "java.util.List>" ) );
+ }
}
diff --git a/pom.xml b/pom.xml
index 07e914a9d..de7fa1e13 100644
--- a/pom.xml
+++ b/pom.xml
@@ -246,7 +246,11 @@
asm-commons
${asmVersion}
-
+
+ org.ow2.asm
+ asm-util
+ ${asmVersion}
+
org.apache.maven.plugin-testing