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/20 16:49:53 UTC

[maven-plugin-tools] 01/01: [MPLUGIN-444] JavadocLinkGenerator.createLink: Support nested binary class names

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

kwin pushed a commit to branch bugfix/binary-name-of-nested-class
in repository https://gitbox.apache.org/repos/asf/maven-plugin-tools.git

commit 2e319b868eac1e173e13678ec261c7845458723e
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Sun Nov 20 17:49:46 2022 +0100

    [MPLUGIN-444] JavadocLinkGenerator.createLink: Support nested binary
    class names
---
 .../converter/JavaClassConverterContextTest.java   |  4 +++
 .../maven/tools/plugin/javadoc/JavadocSite.java    | 31 ++++++++++++++++------
 .../plugin/javadoc/JavadocLinkGeneratorTest.java   | 10 +++++--
 .../maven/tools/plugin/javadoc/JavadocSiteIT.java  |  9 +++++++
 .../tools/plugin/javadoc/JavadocSiteTest.java      | 15 +++++++++++
 5 files changed, 59 insertions(+), 10 deletions(-)

diff --git a/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/converter/JavaClassConverterContextTest.java b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/converter/JavaClassConverterContextTest.java
index c5db83fe..3bfbe026 100644
--- a/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/converter/JavaClassConverterContextTest.java
+++ b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/converter/JavaClassConverterContextTest.java
@@ -101,6 +101,10 @@ class JavaClassConverterContextTest
         assertEquals( new FullyQualifiedJavadocReference( "org.apache.maven.tools.plugin.extractor.annotations.converter.test.other",
                                                           "OtherClassOtherPackage.EmbeddedEnum", false ),
                       context.resolveReference( ( JavadocReference.parse( "OtherClassOtherPackage.EmbeddedEnum" ) ) ) );
+        
+        // nested class from JDK
+        assertEquals( new FullyQualifiedJavadocReference( "java.util", "Map.Entry", true ),
+                context.resolveReference( JavadocReference.parse( "java.util.Map.Entry" ) ) );
     }
 
     @Test
diff --git a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/javadoc/JavadocSite.java b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/javadoc/JavadocSite.java
index 93fddaa8..fce6aeda 100644
--- a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/javadoc/JavadocSite.java
+++ b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/javadoc/JavadocSite.java
@@ -277,6 +277,8 @@ class JavadocSite
         }
     }
 
+    private static final Pattern NESTED_CLASS_PATTERN = Pattern.compile( "([^\\$])(\\$[\\d]*)(.*)" );
+
     /**
      * Splits up a given binary name into package name and class name part.
      * @param binaryName a binary name according to 
@@ -286,25 +288,38 @@ class JavadocSite
      */
     static Map.Entry<String, String> getPackageAndClassName( String binaryName )
     {
-     // assume binary name according to https://docs.oracle.com/javase/specs/jls/se8/html/jls-13.html#jls-13.1
+        // assume binary name according to https://docs.oracle.com/javase/specs/jls/se8/html/jls-13.html#jls-13.1
         int indexOfDollar = binaryName.indexOf( '$' );
+        int indexOfDotBetweenPackageAndClass;
         if ( indexOfDollar >= 0 ) 
         {
-            // emit some warning, as non resolvable: unclear which type of member follows if it is non digit
-            throw new IllegalArgumentException( "Can only resolve binary names of top level classes" );
+            // check following character
+            if ( !Character.isDigit( binaryName.charAt( indexOfDollar + 1 ) ) )
+            {
+                // emit some warning, as non resolvable: unclear which type of member follows if it is non digit
+                throw new IllegalArgumentException( "Can only resolve binary names of (nested) classes, "
+                        + "but not members" );
+            }
+            // nested class
+            indexOfDotBetweenPackageAndClass = binaryName.lastIndexOf( '.', indexOfDollar );
+            // strip digits and replace by dot
+            binaryName = NESTED_CLASS_PATTERN.matcher( binaryName ).replaceAll( "$1.$3" );
+        } 
+        else
+        {
+            indexOfDotBetweenPackageAndClass = binaryName.lastIndexOf( '.' );
         }
-        int indexOfLastDot = binaryName.lastIndexOf( '.' );
-        if ( indexOfLastDot < 0 )
+        if ( indexOfDotBetweenPackageAndClass < 0 )
         {
             throw new IllegalArgumentException( "Resolving primitives is not supported. "
                 + "Binary name must contain at least one dot: " + binaryName );
         }
-        if ( indexOfLastDot == binaryName.length() - 1 )
+        if ( indexOfDotBetweenPackageAndClass == binaryName.length() - 1 )
         {
             throw new IllegalArgumentException( "Invalid binary name ending with a dot: " + binaryName );
         }
-        String packageName = binaryName.substring( 0, indexOfLastDot );
-        String className = binaryName.substring( indexOfLastDot + 1, binaryName.length() );
+        String packageName = binaryName.substring( 0, indexOfDotBetweenPackageAndClass );
+        String className = binaryName.substring( indexOfDotBetweenPackageAndClass + 1, binaryName.length() );
         return new AbstractMap.SimpleEntry<>( packageName, className );
     }
 
diff --git a/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/javadoc/JavadocLinkGeneratorTest.java b/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/javadoc/JavadocLinkGeneratorTest.java
index 620128bf..88a8f41a 100644
--- a/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/javadoc/JavadocLinkGeneratorTest.java
+++ b/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/javadoc/JavadocLinkGeneratorTest.java
@@ -91,14 +91,20 @@ class JavadocLinkGeneratorTest
         throws URISyntaxException
     {
         URI javadocBaseUri = getClass().getResource( "/javadoc/" + jdkName + "/" ).toURI();
+        
         JavadocLinkGenerator linkGenerator = new JavadocLinkGenerator( javadocBaseUri, version );
-        // invalid link for primitives
+        /*// invalid link for primitives
         assertThrows( IllegalArgumentException.class, () -> linkGenerator.createLink( "boolean" ) );
         // link for array
         assertEquals( javadocBaseUri.resolve( new URI( null,
                                                        "java/lang/String.html",
                                                        null ) ),
-                      linkGenerator.createLink( "java.lang.String[]" ) );
+                      linkGenerator.createLink( "java.lang.String[]" ) );*/
+        // link for nested class
+        assertEquals( javadocBaseUri.resolve( new URI( null,
+                                                       "java/util/Map.Entry.html",
+                                                       null ) ),
+                      linkGenerator.createLink( "java.util.Map$123Entry" ) );
 
     }
 
diff --git a/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/javadoc/JavadocSiteIT.java b/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/javadoc/JavadocSiteIT.java
index 24fda84b..f331265f 100644
--- a/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/javadoc/JavadocSiteIT.java
+++ b/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/javadoc/JavadocSiteIT.java
@@ -82,4 +82,13 @@ class JavadocSiteIT
                                                                                              "CASE_INSENSITIVE_ORDER",
                                                                                              MemberType.FIELD, true ) ) );
     }
+    
+    @ParameterizedTest
+    @MethodSource( "javadocBaseUrls" )
+    void testNestedClass( URI javadocBaseUrl )
+            throws IOException
+    {
+        JavadocSite site = new JavadocSite( javadocBaseUrl, null );
+        JavadocSiteTest.assertUrlValid( site.createLink( new FullyQualifiedJavadocReference( "java.util", "Map.Entry", true ) ) );
+    }
 }
diff --git a/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/javadoc/JavadocSiteTest.java b/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/javadoc/JavadocSiteTest.java
index d276507b..6f16d63c 100644
--- a/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/javadoc/JavadocSiteTest.java
+++ b/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/javadoc/JavadocSiteTest.java
@@ -22,15 +22,20 @@ import java.io.BufferedReader;
 import java.io.IOException;
 import java.net.URI;
 import java.net.URISyntaxException;
+import java.util.AbstractMap;
 import java.util.regex.Pattern;
 import java.util.stream.Stream;
 
 import org.apache.maven.tools.plugin.javadoc.FullyQualifiedJavadocReference.MemberType;
+import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.Arguments;
 import org.junit.jupiter.params.provider.MethodSource;
 import org.opentest4j.AssertionFailedError;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
 /**
  * Tests against the locally available javadoc sites. Doesn't require internet connectivity.
  */
@@ -96,6 +101,16 @@ class JavadocSiteTest
         assertUrlValid( site.createLink( new FullyQualifiedJavadocReference( "org.apache.maven.tools.plugin.extractor.annotations.converter.test", "CurrentClass", false ) ) );
     }
 
+    @Test
+    void testGetPackageAndClassName()
+    {
+        assertEquals( new AbstractMap.SimpleEntry<>( "java.util", "Map" ), JavadocSite.getPackageAndClassName( "java.util.Map" ) );
+        assertEquals( new AbstractMap.SimpleEntry<>( "java.util", "Map.Entry" ), JavadocSite.getPackageAndClassName( "java.util.Map$0001Entry" ) );
+        assertThrows( IllegalArgumentException.class, () -> JavadocSite.getPackageAndClassName( "java.util." ) );
+        assertThrows( IllegalArgumentException.class, () -> JavadocSite.getPackageAndClassName( "java.lang.String$chars()" ) );
+        assertThrows( IllegalArgumentException.class, () -> JavadocSite.getPackageAndClassName( "int" ) );
+    }
+
     static JavadocSite getLocalJavadocSite( String name, JavadocLinkGenerator.JavadocToolVersionRange version )
         throws IOException, URISyntaxException
     {