You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2020/12/11 13:45:15 UTC

[isis] 02/02: ISIS-2473: j2adoc: adds support for enum types

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

ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git

commit bd39f2bc186c0c5215a6c313a81f73570b417b56
Author: Andi Huber <ah...@apache.org>
AuthorDate: Fri Dec 11 14:44:56 2020 +0100

    ISIS-2473: j2adoc: adds support for enum types
---
 .../apache/isis/tooling/j2adoc/J2AdocContext.java  |   2 +-
 .../org/apache/isis/tooling/j2adoc/J2AdocUnit.java |  46 +++----
 .../tooling/javamodel/ast/AnyTypeDeclaration.java  | 143 +++++++++++++++++++++
 .../ast/ClassOrInterfaceDeclarations.java          |  21 ---
 .../tooling/javamodel/ast/CompilationUnits.java    |  45 ++++++-
 .../isis/tooling/javamodel/test/AnalyzerTest.java  |   9 +-
 6 files changed, 207 insertions(+), 59 deletions(-)

diff --git a/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/J2AdocContext.java b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/J2AdocContext.java
index 031b663..d158ec1 100644
--- a/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/J2AdocContext.java
+++ b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/J2AdocContext.java
@@ -88,7 +88,7 @@ public class J2AdocContext {
         return J2AdocUnit.parse(sourceFile)
         .peek(this::add)
         // ensure the stream is consumed here, 
-        // current implementation does not expect more than 1 result per source file
+        // optimized for 1 result per source file, but can be more
         .collect(Collectors.toCollection(()->new ArrayList<>(1))) 
         .stream();
     }
diff --git a/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/J2AdocUnit.java b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/J2AdocUnit.java
index 3983886..8ccff38 100644
--- a/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/J2AdocUnit.java
+++ b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/J2AdocUnit.java
@@ -23,7 +23,6 @@ import java.util.Optional;
 import java.util.stream.Stream;
 
 import com.github.javaparser.StaticJavaParser;
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
 import com.github.javaparser.ast.body.ConstructorDeclaration;
 import com.github.javaparser.ast.body.MethodDeclaration;
 import com.github.javaparser.javadoc.Javadoc;
@@ -32,10 +31,8 @@ import org.asciidoctor.ast.Document;
 
 import org.apache.isis.commons.collections.Can;
 import org.apache.isis.tooling.j2adoc.util.AsciiDocIncludeTagFilter;
-import org.apache.isis.tooling.javamodel.ast.ClassOrInterfaceDeclarations;
+import org.apache.isis.tooling.javamodel.ast.AnyTypeDeclaration;
 import org.apache.isis.tooling.javamodel.ast.CompilationUnits;
-import org.apache.isis.tooling.javamodel.ast.Javadocs;
-import org.apache.isis.tooling.javamodel.ast.TypeDeclarations;
 
 import lombok.Getter;
 import lombok.NonNull;
@@ -47,7 +44,7 @@ import lombok.extern.log4j.Log4j2;
 @Log4j2
 public final class J2AdocUnit {
 
-    private final ClassOrInterfaceDeclaration td;
+    private final AnyTypeDeclaration atd;
     
     public static Stream<J2AdocUnit> parse(final @NonNull File sourceFile) {
 
@@ -65,8 +62,8 @@ public final class J2AdocUnit {
             val cu = StaticJavaParser.parse(source);
             
             return Stream.of(cu)
-            .flatMap(CompilationUnits::streamPublicTypeDeclarations)
-            .filter(TypeDeclarations::hasIndexDirective)
+            .flatMap(CompilationUnits::streamTypeDeclarations)
+            .filter(AnyTypeDeclaration::hasIndexDirective)
             .map(J2AdocUnit::new);
 
         } catch (Exception e) {
@@ -80,31 +77,28 @@ public final class J2AdocUnit {
      * Returns the recursively resolved (nested) type name. 
      * Same as {@link #getSimpleName()} if type is not nested. 
      */
-    @Getter(lazy = true)
-    private final String name = ClassOrInterfaceDeclarations.name(td);
+    public String getName() {
+        return atd.getName();
+    }
     
-    @Getter(lazy = true)
-    private final String simpleName = td.getNameAsString();
+    public String getSimpleName() {
+        return atd.getSimpleName();
+    }
     
-    @Getter(lazy = true)
-    private final String declarationKeyword = td.isInterface()
-            ? "interface"
-            : "class";
+    public String getDeclarationKeyword() {
+        return atd.getKind().name().toLowerCase();
+    }
     
-    @Getter(lazy = true)
-    private final Can<ConstructorDeclaration> publicConstructorDeclarations =
-        ClassOrInterfaceDeclarations.streamPublicConstructorDeclarations(td)
-                .filter(Javadocs::presentAndNotHidden)
-                .collect(Can.toCan());
+    public Can<ConstructorDeclaration> getPublicConstructorDeclarations() {
+        return atd.getPublicConstructorDeclarations();
+    }
     
-    @Getter(lazy = true)
-    private final Can<MethodDeclaration> publicMethodDeclarations =
-        ClassOrInterfaceDeclarations.streamPublicMethodDeclarations(td)
-                .filter(Javadocs::presentAndNotHidden)
-                .collect(Can.toCan());
+    public Can<MethodDeclaration> getPublicMethodDeclarations() {
+        return atd.getPublicMethodDeclarations();
+    }
     
     @Getter(lazy = true)
-    private final Optional<Javadoc> javadoc = td.getJavadoc();
+    private final Optional<Javadoc> javadoc = atd.getJavadoc();
     
     public String getAsciiDocXref(
             final @NonNull J2AdocContext j2aContext) {
diff --git a/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/AnyTypeDeclaration.java b/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/AnyTypeDeclaration.java
new file mode 100644
index 0000000..1c8b190
--- /dev/null
+++ b/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/AnyTypeDeclaration.java
@@ -0,0 +1,143 @@
+/*
+ *  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.isis.tooling.javamodel.ast;
+
+import java.util.Optional;
+import java.util.stream.Stream;
+
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.ConstructorDeclaration;
+import com.github.javaparser.ast.body.EnumDeclaration;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.ast.body.TypeDeclaration;
+import com.github.javaparser.ast.nodeTypes.NodeWithSimpleName;
+import com.github.javaparser.javadoc.Javadoc;
+
+import org.apache.isis.commons.collections.Can;
+import org.apache.isis.commons.internal.exceptions._Exceptions;
+
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
+
+@Getter
+@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+public class AnyTypeDeclaration {
+
+    public static enum Kind {
+        CLASS,
+        ENUM,
+        INTERFACE
+        ;
+        public boolean isClass() { return this == CLASS; }
+        public boolean isEnum() { return this == ENUM; }
+        public boolean isInterface() { return this == INTERFACE; }
+    }
+    
+    private final @NonNull Kind kind;
+    private final TypeDeclaration<?> td;
+    private final ClassOrInterfaceDeclaration classOrInterfaceDeclaration; 
+    private final EnumDeclaration enumDeclaration;
+    
+    private final Can<ConstructorDeclaration> publicConstructorDeclarations;
+    private final Can<MethodDeclaration> publicMethodDeclarations;
+    
+    // -- FACTORIES
+    
+    public static AnyTypeDeclaration of(
+            final @NonNull ClassOrInterfaceDeclaration classOrInterfaceDeclaration) {
+        return new AnyTypeDeclaration(
+                classOrInterfaceDeclaration.isInterface() ? Kind.INTERFACE : Kind.CLASS, 
+                classOrInterfaceDeclaration,
+                classOrInterfaceDeclaration,
+                null,
+                ClassOrInterfaceDeclarations.streamPublicConstructorDeclarations(classOrInterfaceDeclaration)
+                    .filter(Javadocs::presentAndNotHidden)
+                    .collect(Can.toCan()),
+                ClassOrInterfaceDeclarations.streamPublicMethodDeclarations(classOrInterfaceDeclaration)
+                    .filter(Javadocs::presentAndNotHidden)
+                    .collect(Can.toCan())
+                );
+    }
+    
+    public static AnyTypeDeclaration of(
+            final @NonNull EnumDeclaration enumDeclaration) {
+        return new AnyTypeDeclaration(
+                Kind.ENUM, 
+                enumDeclaration, 
+                null, 
+                enumDeclaration,
+                Can.empty(),
+                Can.empty());
+    }
+    
+    public static AnyTypeDeclaration auto(
+            final @NonNull TypeDeclaration<?> td) {
+        
+        if(td instanceof ClassOrInterfaceDeclaration) {
+            return of((ClassOrInterfaceDeclaration)td);
+        }
+        if(td instanceof EnumDeclaration) {
+            return of((EnumDeclaration)td);
+        }
+        throw _Exceptions.unsupportedOperation("unsupported TypeDeclaration %s", td.getClass());
+    }
+    
+    // -- UTILITY
+    
+    public Stream<MethodDeclaration> streamMethodDeclarations() {
+        return td.getMethods().stream();
+    }
+
+    public Optional<Javadoc> getJavadoc() {
+        return td.getJavadoc();
+    }
+    
+    public boolean hasIndexDirective() {
+        return TypeDeclarations.hasIndexDirective(td);
+    }
+    
+    /**
+     * Returns the recursively resolved (nested) type name. 
+     * Same as {@link #getSimpleName()} if type is not nested. 
+     */
+    @Getter(lazy = true)
+    private final String name = createName();
+    
+    public String getSimpleName() {
+        return td.getNameAsString();
+    }
+    
+    // -- HELPER 
+    
+    private String createName() {
+        String name = td.getNameAsString(); 
+        Node walker = td; 
+        while(walker.getParentNode().isPresent()) {
+            walker = walker.getParentNode().get();
+            if(walker instanceof NodeWithSimpleName) {
+                name = ((NodeWithSimpleName<?>)walker).getNameAsString() + "." + name;
+            } else break;
+        }
+        return name;
+    }
+    
+}
diff --git a/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/ClassOrInterfaceDeclarations.java b/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/ClassOrInterfaceDeclarations.java
index 980448f..42c49e0 100644
--- a/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/ClassOrInterfaceDeclarations.java
+++ b/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/ClassOrInterfaceDeclarations.java
@@ -20,11 +20,9 @@ package org.apache.isis.tooling.javamodel.ast;
 
 import java.util.stream.Stream;
 
-import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
 import com.github.javaparser.ast.body.ConstructorDeclaration;
 import com.github.javaparser.ast.body.MethodDeclaration;
-import com.github.javaparser.ast.nodeTypes.NodeWithSimpleName;
 
 import lombok.NonNull;
 
@@ -51,24 +49,5 @@ public final class ClassOrInterfaceDeclarations {
         return streamMethodDeclarations(typeDeclaration)
                 .filter(md->MethodDeclarations.isEffectivePublic(md, typeDeclaration));
     }
-
-    /**
-     * Returns the recursively resolved (nested) type name. 
-     * Same as {@link #getSimpleName()} if type is not nested. 
-     */
-    public static String name(
-            final @NonNull ClassOrInterfaceDeclaration td) {
-        String name = td.getNameAsString(); 
-        Node walker = td; 
-        while(walker.getParentNode().isPresent()) {
-            walker = walker.getParentNode().get();
-            if(walker instanceof NodeWithSimpleName) {
-                name = ((NodeWithSimpleName<?>)walker).getNameAsString() + "." + name;
-            } else break;
-        }
-        return name;
-    }
-    
-
     
 }
diff --git a/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/CompilationUnits.java b/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/CompilationUnits.java
index 7eb846d..2447106 100644
--- a/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/CompilationUnits.java
+++ b/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/CompilationUnits.java
@@ -19,12 +19,15 @@
 package org.apache.isis.tooling.javamodel.ast;
 
 import java.io.File;
+import java.util.Optional;
 import java.util.function.Predicate;
 import java.util.stream.Stream;
 
 import com.github.javaparser.StaticJavaParser;
 import com.github.javaparser.ast.CompilationUnit;
 import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.EnumDeclaration;
+import com.github.javaparser.ast.body.TypeDeclaration;
 
 import lombok.NonNull;
 import lombok.SneakyThrows;
@@ -43,7 +46,40 @@ public final class CompilationUnits {
         .orElse(false);
     }
     
-    public static <T> Stream<ClassOrInterfaceDeclaration> streamPublicTypeDeclarations(
+    public static <T> Stream<AnyTypeDeclaration> streamTypeDeclarations(
+            final @NonNull CompilationUnit compilationUnit) {
+        
+        return getPrimaryType(compilationUnit)
+        .map(type->type
+                .findAll(TypeDeclaration.class)
+                .stream()
+                .map(AnyTypeDeclaration::auto))
+        .orElseGet(Stream::empty);
+    }
+    
+    public static <T> Stream<ClassOrInterfaceDeclaration> streamClassOrInterfaceDeclarations(
+            final @NonNull CompilationUnit compilationUnit) {
+        
+        return getPrimaryType(compilationUnit)
+        .map(type->type
+                .findAll(ClassOrInterfaceDeclaration.class)
+                .stream())
+        .orElseGet(Stream::empty);
+    }
+    
+    public static <T> Stream<EnumDeclaration> streamEnumDeclarations(
+            final @NonNull CompilationUnit compilationUnit) {
+        
+        return getPrimaryType(compilationUnit)
+        .map(type->type
+                .findAll(EnumDeclaration.class)
+                .stream())
+        .orElseGet(Stream::empty);
+    }
+    
+    // -- HELPER
+    
+    private static Optional<TypeDeclaration<?>> getPrimaryType(
             final @NonNull CompilationUnit compilationUnit) {
         
         val type = compilationUnit.getPrimaryType()
@@ -55,13 +91,10 @@ public final class CompilationUnits {
         if(type==null) {
             System.err.println("could not find any type in CompilationUnit ...\n" + 
                     compilationUnit);
-            return Stream.empty();
+            return Optional.empty();
         }
         
-        //TODO not processing enums yet
-        return type.findAll(ClassOrInterfaceDeclaration.class)
-                .stream();
-
+        return Optional.of(type);        
     }
 
     
diff --git a/tooling/javamodel/src/test/java/org/apache/isis/tooling/javamodel/test/AnalyzerTest.java b/tooling/javamodel/src/test/java/org/apache/isis/tooling/javamodel/test/AnalyzerTest.java
index aca1d2f..5077b4f 100644
--- a/tooling/javamodel/src/test/java/org/apache/isis/tooling/javamodel/test/AnalyzerTest.java
+++ b/tooling/javamodel/src/test/java/org/apache/isis/tooling/javamodel/test/AnalyzerTest.java
@@ -26,7 +26,7 @@ import org.junit.jupiter.api.Test;
 
 import org.apache.isis.commons.internal.base._Files;
 import org.apache.isis.tooling.javamodel.AnalyzerConfigFactory;
-import org.apache.isis.tooling.javamodel.ast.ClassOrInterfaceDeclarations;
+import org.apache.isis.tooling.javamodel.ast.AnyTypeDeclaration;
 import org.apache.isis.tooling.javamodel.ast.CompilationUnits;
 
 import lombok.val;
@@ -65,11 +65,10 @@ class AnalyzerTest {
         .filter(source->source.toString().contains("UserService"))
         .peek(source->System.out.println("parsing source: " + source))
         .map(CompilationUnits::parse)
-        .flatMap(CompilationUnits::streamPublicTypeDeclarations)
+        .flatMap(CompilationUnits::streamTypeDeclarations)
         .peek(td->{
             
-            td.getJavadocComment().ifPresent(javadocComment->{
-                val javadoc = javadocComment.parse();
+            td.getJavadoc().ifPresent(javadoc->{
             
                 javadoc.getBlockTags().stream()
                 .filter(tag->tag.getTagName().equals("since"))
@@ -78,7 +77,7 @@ class AnalyzerTest {
             });
             
         })
-        .flatMap(ClassOrInterfaceDeclarations::streamMethodDeclarations)
+        .flatMap(AnyTypeDeclaration::streamMethodDeclarations)
         .forEach(md->{
             
             System.out.println("javadoc: " + md.getJavadocComment());