You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2018/12/22 17:19:07 UTC

[groovy] 02/02: Extract javadoc via traversing AST

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

sunlan pushed a commit to branch refine-groovydoc
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit f2a4fc88145d76026281c3ff69e1e46c8d5bbc47
Author: Daniel Sun <su...@apache.org>
AuthorDate: Sun Dec 23 01:18:15 2018 +0800

    Extract javadoc via traversing AST
---
 .../tools/groovydoc/SimpleGroovyClassDoc.java      | 390 ---------------------
 .../groovydoc/SimpleJavaClassDocAssembler.java     | 125 ++++---
 .../SimpleJavaClassDocAssemblerTest.groovy         |   3 +-
 .../SimpleJavaClassDocAssemblerTest1.java          |  45 +++
 4 files changed, 108 insertions(+), 455 deletions(-)

diff --git a/subprojects/groovy-groovydoc/src/main/java/org/apache/groovy/tools/groovydoc/SimpleGroovyClassDoc.java b/subprojects/groovy-groovydoc/src/main/java/org/apache/groovy/tools/groovydoc/SimpleGroovyClassDoc.java
deleted file mode 100644
index 85c5cf6..0000000
--- a/subprojects/groovy-groovydoc/src/main/java/org/apache/groovy/tools/groovydoc/SimpleGroovyClassDoc.java
+++ /dev/null
@@ -1,390 +0,0 @@
-/*
- *  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.groovy.tools.groovydoc;
-
-import org.codehaus.groovy.groovydoc.GroovyAnnotationRef;
-import org.codehaus.groovy.groovydoc.GroovyClassDoc;
-import org.codehaus.groovy.groovydoc.GroovyConstructorDoc;
-import org.codehaus.groovy.groovydoc.GroovyFieldDoc;
-import org.codehaus.groovy.groovydoc.GroovyMethodDoc;
-import org.codehaus.groovy.groovydoc.GroovyPackageDoc;
-import org.codehaus.groovy.groovydoc.GroovyType;
-
-public class SimpleGroovyClassDoc implements GroovyClassDoc {
-    @Override
-    public GroovyConstructorDoc[] constructors() {
-        return new GroovyConstructorDoc[0];
-    }
-
-    @Override
-    public GroovyConstructorDoc[] constructors(boolean filter) {
-        return new GroovyConstructorDoc[0];
-    }
-
-    @Override
-    public boolean definesSerializableFields() {
-        return false;
-    }
-
-    @Override
-    public GroovyFieldDoc[] enumConstants() {
-        return new GroovyFieldDoc[0];
-    }
-
-    @Override
-    public GroovyFieldDoc[] fields() {
-        return new GroovyFieldDoc[0];
-    }
-
-    @Override
-    public GroovyFieldDoc[] properties() {
-        return new GroovyFieldDoc[0];
-    }
-
-    @Override
-    public GroovyFieldDoc[] fields(boolean filter) {
-        return new GroovyFieldDoc[0];
-    }
-
-    @Override
-    public GroovyClassDoc findClass(String className) {
-        return null;
-    }
-
-    @Override
-    public GroovyClassDoc[] importedClasses() {
-        return new GroovyClassDoc[0];
-    }
-
-    @Override
-    public GroovyPackageDoc[] importedPackages() {
-        return new GroovyPackageDoc[0];
-    }
-
-    @Override
-    public GroovyClassDoc[] innerClasses() {
-        return new GroovyClassDoc[0];
-    }
-
-    @Override
-    public GroovyClassDoc[] innerClasses(boolean filter) {
-        return new GroovyClassDoc[0];
-    }
-
-    @Override
-    public GroovyClassDoc[] interfaces() {
-        return new GroovyClassDoc[0];
-    }
-
-    @Override
-    public GroovyType[] interfaceTypes() {
-        return new GroovyType[0];
-    }
-
-    @Override
-    public boolean isAbstract() {
-        return false;
-    }
-
-    @Override
-    public boolean isExternalizable() {
-        return false;
-    }
-
-    @Override
-    public boolean isSerializable() {
-        return false;
-    }
-
-    @Override
-    public GroovyMethodDoc[] methods() {
-        return new GroovyMethodDoc[0];
-    }
-
-    @Override
-    public GroovyMethodDoc[] methods(boolean filter) {
-        return new GroovyMethodDoc[0];
-    }
-
-    @Override
-    public GroovyFieldDoc[] serializableFields() {
-        return new GroovyFieldDoc[0];
-    }
-
-    @Override
-    public GroovyMethodDoc[] serializationMethods() {
-        return new GroovyMethodDoc[0];
-    }
-
-    @Override
-    public boolean subclassOf(GroovyClassDoc gcd) {
-        return false;
-    }
-
-    @Override
-    public GroovyClassDoc superclass() {
-        return null;
-    }
-
-    @Override
-    public GroovyType superclassType() {
-        return null;
-    }
-
-    @Override
-    public String getFullPathName() {
-        return null;
-    }
-
-    @Override
-    public String getRelativeRootPath() {
-        return null;
-    }
-
-    @Override
-    public GroovyAnnotationRef[] annotations() {
-        return new GroovyAnnotationRef[0];
-    }
-
-    @Override
-    public GroovyClassDoc containingClass() {
-        return null;
-    }
-
-    @Override
-    public GroovyPackageDoc containingPackage() {
-        return null;
-    }
-
-    @Override
-    public boolean isFinal() {
-        return false;
-    }
-
-    @Override
-    public boolean isPackagePrivate() {
-        return false;
-    }
-
-    @Override
-    public boolean isPrivate() {
-        return false;
-    }
-
-    @Override
-    public boolean isProtected() {
-        return false;
-    }
-
-    @Override
-    public boolean isPublic() {
-        return false;
-    }
-
-    @Override
-    public boolean isStatic() {
-        return false;
-    }
-
-    @Override
-    public String modifiers() {
-        return null;
-    }
-
-    @Override
-    public int modifierSpecifier() {
-        return 0;
-    }
-
-    @Override
-    public String qualifiedName() {
-        return null;
-    }
-
-    @Override
-    public String commentText() {
-        return null;
-    }
-
-    @Override
-    public String getRawCommentText() {
-        return null;
-    }
-
-    @Override
-    public boolean isAnnotationType() {
-        return false;
-    }
-
-    @Override
-    public boolean isAnnotationTypeElement() {
-        return false;
-    }
-
-    @Override
-    public boolean isClass() {
-        return false;
-    }
-
-    @Override
-    public boolean isConstructor() {
-        return false;
-    }
-
-    @Override
-    public boolean isDeprecated() {
-        return false;
-    }
-
-    @Override
-    public boolean isEnum() {
-        return false;
-    }
-
-    @Override
-    public boolean isEnumConstant() {
-        return false;
-    }
-
-    @Override
-    public boolean isError() {
-        return false;
-    }
-
-    @Override
-    public boolean isException() {
-        return false;
-    }
-
-    @Override
-    public boolean isField() {
-        return false;
-    }
-
-    @Override
-    public boolean isIncluded() {
-        return false;
-    }
-
-    @Override
-    public boolean isInterface() {
-        return false;
-    }
-
-    @Override
-    public boolean isMethod() {
-        return false;
-    }
-
-    @Override
-    public boolean isOrdinaryClass() {
-        return false;
-    }
-
-    @Override
-    public String name() {
-        return null;
-    }
-
-    @Override
-    public void setRawCommentText(String arg0) {
-
-    }
-
-    @Override
-    public String firstSentenceCommentText() {
-        return null;
-    }
-
-    /**
-     * Compares this object with the specified object for order.  Returns a
-     * negative integer, zero, or a positive integer as this object is less
-     * than, equal to, or greater than the specified object.
-     *
-     * <p>The implementor must ensure
-     * {@code sgn(x.compareTo(y)) == -sgn(y.compareTo(x))}
-     * for all {@code x} and {@code y}.  (This
-     * implies that {@code x.compareTo(y)} must throw an exception iff
-     * {@code y.compareTo(x)} throws an exception.)
-     *
-     * <p>The implementor must also ensure that the relation is transitive:
-     * {@code (x.compareTo(y) > 0 && y.compareTo(z) > 0)} implies
-     * {@code x.compareTo(z) > 0}.
-     *
-     * <p>Finally, the implementor must ensure that {@code x.compareTo(y)==0}
-     * implies that {@code sgn(x.compareTo(z)) == sgn(y.compareTo(z))}, for
-     * all {@code z}.
-     *
-     * <p>It is strongly recommended, but <i>not</i> strictly required that
-     * {@code (x.compareTo(y)==0) == (x.equals(y))}.  Generally speaking, any
-     * class that implements the {@code Comparable} interface and violates
-     * this condition should clearly indicate this fact.  The recommended
-     * language is "Note: this class has a natural ordering that is
-     * inconsistent with equals."
-     *
-     * <p>In the foregoing description, the notation
-     * {@code sgn(}<i>expression</i>{@code )} designates the mathematical
-     * <i>signum</i> function, which is defined to return one of {@code -1},
-     * {@code 0}, or {@code 1} according to whether the value of
-     * <i>expression</i> is negative, zero, or positive, respectively.
-     *
-     * @param o the object to be compared.
-     * @return a negative integer, zero, or a positive integer as this object
-     * is less than, equal to, or greater than the specified object.
-     * @throws NullPointerException if the specified object is null
-     * @throws ClassCastException   if the specified object's type prevents it
-     *                              from being compared to this object.
-     */
-    @Override
-    public int compareTo(Object o) {
-        return 0;
-    }
-
-    @Override
-    public boolean isPrimitive() {
-        return false;
-    }
-
-    /**
-     * The qualified name of this type excluding any dimension information.
-     * For example, a two dimensional array of String returns "<code>java.lang.String</code>".
-     */
-    @Override
-    public String qualifiedTypeName() {
-        return null;
-    }
-
-    /**
-     * The unqualified name of this type excluding any dimension or nesting information.
-     * For example, the class <code>Outer.Inner</code> returns "<code>Inner</code>".
-     */
-    @Override
-    public String simpleTypeName() {
-        return null;
-    }
-
-    /**
-     * The unqualified name of this type excluding any dimension information.
-     * For example, a two dimensional array of String returns "<code>String</code>".
-     */
-    @Override
-    public String typeName() {
-        return null;
-    }
-}
diff --git a/subprojects/groovy-groovydoc/src/main/java/org/apache/groovy/tools/groovydoc/SimpleJavaClassDocAssembler.java b/subprojects/groovy-groovydoc/src/main/java/org/apache/groovy/tools/groovydoc/SimpleJavaClassDocAssembler.java
index 1af0066..49579b9 100644
--- a/subprojects/groovy-groovydoc/src/main/java/org/apache/groovy/tools/groovydoc/SimpleJavaClassDocAssembler.java
+++ b/subprojects/groovy-groovydoc/src/main/java/org/apache/groovy/tools/groovydoc/SimpleJavaClassDocAssembler.java
@@ -19,16 +19,17 @@
 package org.apache.groovy.tools.groovydoc;
 
 import com.github.javaparser.JavaParser;
-import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.body.AnnotationDeclaration;
+import com.github.javaparser.ast.body.AnnotationMemberDeclaration;
 import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
 import com.github.javaparser.ast.body.ConstructorDeclaration;
 import com.github.javaparser.ast.body.EnumConstantDeclaration;
 import com.github.javaparser.ast.body.EnumDeclaration;
 import com.github.javaparser.ast.body.FieldDeclaration;
 import com.github.javaparser.ast.body.MethodDeclaration;
-import com.github.javaparser.ast.comments.JavadocComment;
-import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
+import com.github.javaparser.ast.nodeTypes.NodeWithJavadoc;
+import com.github.javaparser.ast.visitor.GenericVisitorAdapter;
+import com.github.javaparser.javadoc.Javadoc;
 import org.codehaus.groovy.groovydoc.GroovyClassDoc;
 import org.codehaus.groovy.tools.groovydoc.LinkArgument;
 
@@ -37,9 +38,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Properties;
-import java.util.stream.Collectors;
 
-public class SimpleJavaClassDocAssembler {
+public class SimpleJavaClassDocAssembler extends GenericVisitorAdapter<Object, Object> {
     private final String packagePath;
     private final String javaSourceContent;
     private final String className;
@@ -62,72 +62,69 @@ public class SimpleJavaClassDocAssembler {
         }
     }
 
-    private Map<String, GroovyClassDoc> parse() {
-        new VoidVisitorAdapter<Object>() {
-            @Override
-            public void visit(JavadocComment comment, Object arg) {
-                super.visit(comment, arg);
-
-                System.out.println(collect(comment));
-//
-//                String title = String.format("%s (%s)", comment.getName(), packagePath);
-//                System.out.println(title);
-//                System.out.println(comment.get());
-//                System.out.println("--------------------------");
-//                Javadoc javadoc = comment.get().asJavadocComment().parse();
-//                System.out.println(javadoc.getDescription().toText());
-//                javadoc.getBlockTags().forEach(e -> System.out.println(e.getName() + ":" + e.getContent()));
-//                System.out.println("===========================");
-            }
-        }.visit(JavaParser.parse(javaSourceContent), null);
-
+    public Map<String, GroovyClassDoc> getGroovyClassDocs() {
         return classDocs;
     }
 
-    private static String collect(JavadocComment comment) {
-        Optional<Node> commentedNode = comment.getCommentedNode();
+    public void assemble() {
+        this.visit(JavaParser.parse(javaSourceContent), null);
+    }
 
-        if (!commentedNode.isPresent()) {
-            return null;
-        }
+    @Override
+    public Object visit(final ClassOrInterfaceDeclaration n, final Object arg) {
+        processJavadoc(n);
+        return super.visit(n, arg);
+    }
 
-        Node node = commentedNode.get();
+    @Override
+    public Object visit(final MethodDeclaration n, final Object arg) {
+        processJavadoc(n);
+        return super.visit(n, arg);
+    }
 
-        if (node instanceof MethodDeclaration) {
-            MethodDeclaration methodDeclaration = (MethodDeclaration) node;
-            return "Method " + methodDeclaration.getDeclarationAsString();
-        }
-        if (node instanceof ConstructorDeclaration) {
-            ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) node;
-            return "Constructor " + constructorDeclaration.getDeclarationAsString();
-        }
-        if (node instanceof FieldDeclaration) {
-            FieldDeclaration fieldDeclaration = (FieldDeclaration) node;
-            List<String> varNames = fieldDeclaration.getVariables().stream().map(v -> v.getName().getId()).collect(Collectors.toList());
-            return "Field " + String.join(", ", varNames);
-        }
-        if (node instanceof EnumConstantDeclaration) {
-            EnumConstantDeclaration enumConstantDeclaration = (EnumConstantDeclaration) node;
-            return "Enum Constant" + enumConstantDeclaration.getName();
-        }
-        if (node instanceof ClassOrInterfaceDeclaration) {
-            ClassOrInterfaceDeclaration classOrInterfaceDeclaration = (ClassOrInterfaceDeclaration) node;
-
-            if (classOrInterfaceDeclaration.isInterface()) {
-                return "Interface " + classOrInterfaceDeclaration.getName() + ": " + comment.parse().getDescription().toText();
-            } else {
-                return "Class " + classOrInterfaceDeclaration.getName() + ": " + comment.parse().getDescription().toText();
-            }
-        }
-        if (node instanceof EnumDeclaration) {
-            EnumDeclaration enumDeclaration = (EnumDeclaration) node;
-            return "Enum " + enumDeclaration.getName();
-        }
-        if (node instanceof AnnotationDeclaration) {
-            AnnotationDeclaration annotationDeclaration = (AnnotationDeclaration) node;
-            return "Annotation " + annotationDeclaration.getName();
+    @Override
+    public Object visit(final ConstructorDeclaration n, final Object arg) {
+        processJavadoc(n);
+        return super.visit(n, arg);
+    }
+
+    @Override
+    public Object visit(final FieldDeclaration n, final Object arg) {
+        processJavadoc(n);
+        return super.visit(n, arg);
+    }
+
+    @Override
+    public Object visit(final EnumDeclaration n, final Object arg) {
+        processJavadoc(n);
+        return super.visit(n, arg);
+    }
+
+    @Override
+    public Object visit(final EnumConstantDeclaration n, final Object arg) {
+        processJavadoc(n);
+        return super.visit(n, arg);
+    }
+
+    @Override
+    public Object visit(final AnnotationDeclaration n, final Object arg) {
+        processJavadoc(n);
+        return super.visit(n, arg);
+    }
+
+    @Override
+    public Object visit(final AnnotationMemberDeclaration n, final Object arg) {
+        processJavadoc(n);
+        return super.visit(n, arg);
+    }
+
+    private void processJavadoc(NodeWithJavadoc n) {
+        Optional<Javadoc> optionalJavadoc = n.getJavadoc();
+
+        if (!optionalJavadoc.isPresent()) {
+            return;
         }
 
-        return node.toString();
+        System.out.println(optionalJavadoc.get().getDescription().toText());
     }
 }
\ No newline at end of file
diff --git a/subprojects/groovy-groovydoc/src/test/groovy/org/apache/groovy/tools/groovydoc/SimpleJavaClassDocAssemblerTest.groovy b/subprojects/groovy-groovydoc/src/test/groovy/org/apache/groovy/tools/groovydoc/SimpleJavaClassDocAssemblerTest.groovy
index 677dd4b..9f96175 100644
--- a/subprojects/groovy-groovydoc/src/test/groovy/org/apache/groovy/tools/groovydoc/SimpleJavaClassDocAssemblerTest.groovy
+++ b/subprojects/groovy-groovydoc/src/test/groovy/org/apache/groovy/tools/groovydoc/SimpleJavaClassDocAssemblerTest.groovy
@@ -22,6 +22,7 @@ class SimpleJavaClassDocAssemblerTest extends GroovyTestCase {
     void testClassDoc() {
         def src = SimpleJavaClassDocAssemblerTest.getResourceAsStream('/org/apache/groovy/tools/groovydoc/SimpleJavaClassDocAssemblerTest1.java').text
         def sjcda = new SimpleJavaClassDocAssembler('org/apache/groovy/tools/groovydoc', 'SimpleJavaClassDocAssemblerTest1.java', src, [], new Properties())
-        sjcda.parse()
+        sjcda.assemble()
     }
+
 }
\ No newline at end of file
diff --git a/subprojects/groovy-groovydoc/src/test/resources/org/apache/groovy/tools/groovydoc/SimpleJavaClassDocAssemblerTest1.java b/subprojects/groovy-groovydoc/src/test/resources/org/apache/groovy/tools/groovydoc/SimpleJavaClassDocAssemblerTest1.java
index 87d4668..027991c 100644
--- a/subprojects/groovy-groovydoc/src/test/resources/org/apache/groovy/tools/groovydoc/SimpleJavaClassDocAssemblerTest1.java
+++ b/subprojects/groovy-groovydoc/src/test/resources/org/apache/groovy/tools/groovydoc/SimpleJavaClassDocAssemblerTest1.java
@@ -28,6 +28,37 @@ public class SimpleJavaClassDocAssemblerTest1 {
     public static final String HELLO = "hello";
 
     /**
+     * constructor of SimpleJavaClassDocAssemblerTest1
+     */
+    public SimpleJavaClassDocAssemblerTest1() {
+    }
+
+    /**
+     * This an inner class doc
+     */
+    public static class SomeInnerClass {
+        /**
+         * The greeting word of inner class
+         */
+        public static final String INNER_HELLO = "hello";
+
+        /**
+         * constructor of SomeInnerClass
+         */
+        public SomeInnerClass() {}
+
+        /**
+         * say hello from inner class
+         *
+         * @param name some name
+         * @return the greeting words
+         */
+        public String innerHello(String name) {
+            return HELLO + "," + name;
+        }
+    }
+
+    /**
      * say hello
      *
      * @param name some name
@@ -37,3 +68,17 @@ public class SimpleJavaClassDocAssemblerTest1 {
         return HELLO + "," + name;
     }
 }
+
+/**
+ * some class
+ */
+class SomeClass {
+
+}
+
+/**
+ * some enum
+ */
+enum SomeEnum {
+
+}