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/10 10:46:28 UTC

[isis] 02/02: ISIS-2473: adds support for rendering 'deprecated' from java-doc

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 63aa2d12e45fdb37823b83955567e05844270f77
Author: Andi Huber <ah...@apache.org>
AuthorDate: Thu Dec 10 11:46:10 2020 +0100

    ISIS-2473: adds support for rendering 'deprecated' from java-doc
---
 .../generated/pages/index/FactoryService.adoc      |  24 ++--
 .../modules/generated/pages/index/UserMemento.adoc |  12 +-
 .../modules/generated/pages/index/UserService.adoc |   8 +-
 .../apache/isis/tooling/cli/doclet/Adoclet.java    |   3 +-
 .../isis/tooling/cli/doclet/AdocletContext.java    |  17 ++-
 .../isis/tooling/cli/doclet/HtmlToAsciiDoc.java    | 122 ++++++++++-----------
 .../apache/isis/tooling/cli/doclet/ToAsciiDoc.java |  84 ++++++++++----
 .../apache/isis/tooling/javamodel/Javadocs.java    |   8 ++
 .../isis/tooling/model4adoc/AsciiDocWriter.java    |   5 +-
 9 files changed, 168 insertions(+), 115 deletions(-)

diff --git a/antora/components/system/modules/generated/pages/index/FactoryService.adoc b/antora/components/system/modules/generated/pages/index/FactoryService.adoc
index 781c7d3..4ba272a 100644
--- a/antora/components/system/modules/generated/pages/index/FactoryService.adoc
+++ b/antora/components/system/modules/generated/pages/index/FactoryService.adoc
@@ -4,54 +4,54 @@
 
 
 
-* `*getOrCreate*(Class<T> requiredType)` : `T`
+* `[teal]#*getOrCreate*#<T>(Class<T> requiredType)` : `T`
 +
 General purpose factory method, to automatically get or create an instance of _requiredType_ .
 +
 Maps onto one of the specialized factory methods _#get(Class)_ or _#create(Class)_ based on the type's meta-data.
 
 
-* `*get*(Class<T> requiredType)` : `T`
+* `[teal]#*get*#<T>(Class<T> requiredType)` : `T`
 +
 Gets an instance (possibly shared or independent) of the specified _requiredType_ , with injection points resolved and any life-cycle callback processed.
 
 
-* `*detachedEntity*(Class<T> domainClass)` : `T`
+* `[teal]#*detachedEntity*#<T>(Class<T> domainClass)` : `T`
 +
 Creates a new detached entity instance, with injection points resolved and defaults applied.
 
 
-* `*detachedEntity*(T entity)` : `T`
+* `[teal]#*detachedEntity*#<T>(T entity)` : `T`
 +
 Creates a new detached entity instance, with injection points resolved.
 
 
-* `*mixin*(Class<T> mixinClass, Object mixedIn)` : `T`
+* `[teal]#*mixin*#<T>(Class<T> mixinClass, Object mixedIn)` : `T`
 +
 Creates a new Mixin instance, with injection points resolved.
 
 
-* `*viewModel*(Class<T> viewModelClass, String mementoStr)` : `T`
+* `[teal]#*viewModel*#<T>(Class<T> viewModelClass, String mementoStr)` : `T`
 +
 Creates a new ViewModel instance, with injection points resolved, and initialized according to the given _mementoStr_
 
 
-* `*viewModel*(Class<T> viewModelClass)` : `T`
+* `[teal]#*viewModel*#<T>(Class<T> viewModelClass)` : `T`
 +
 Creates a new ViewModel instance, with injection points resolved and defaults applied.
 
 
-* `*viewModel*(T viewModel)` : `T`
+* `[teal]#*viewModel*#<T>(T viewModel)` : `T`
 +
 Resolves injection points for given ViewModel instance.
 
 
-* `*create*(Class<T> domainClass)` : `T`
+* `[teal]#*create*#<T>(Class<T> domainClass)` : `T`
 +
 Creates a new instance of the specified class, with injection points resolved and defaults applied.
 
 
-* `*instantiate*(Class<T> domainClass)` : `T`
+* `[line-through gray]#*instantiate*#<T>(Class<T> domainClass)` : `T`
 +
 Creates a new instance of the specified class, but does not persist it.
 +
@@ -64,3 +64,7 @@ It is recommended that the object be initially instantiated using this method, t
 ** the `created()` callback will not be called.
 +
 The corollary is: if your code never uses `default _Xxx_ ()` supporting methods or the `created()` callback, then you can alternatively just _new()_ up the object rather than call this method.
++
+[red]#_deprecated:_#
++
+with semantic changes since 2.0 previous behavior is no longer guaranteed, instead consider use of @ _#detachedEntity(Class)_ or _#getOrCreate(Class)_ if applicable
diff --git a/antora/components/system/modules/generated/pages/index/UserMemento.adoc b/antora/components/system/modules/generated/pages/index/UserMemento.adoc
index d0bdb89..a7031f8 100644
--- a/antora/components/system/modules/generated/pages/index/UserMemento.adoc
+++ b/antora/components/system/modules/generated/pages/index/UserMemento.adoc
@@ -4,32 +4,32 @@
 
 Immutable serializable value holding details about a user and its roles.
 
-* `*_system_*()` : `xref:system:generated:index/UserMemento.adoc[UserMemento]`
+* `[teal]#*_system_*#()` : `xref:system:generated:index/UserMemento.adoc[UserMemento]`
 +
 The framework's internal user with unrestricted privileges.
 
 
-* `*_ofName_*(String name)` : `xref:system:generated:index/UserMemento.adoc[UserMemento]`
+* `[teal]#*_ofName_*#(String name)` : `xref:system:generated:index/UserMemento.adoc[UserMemento]`
 +
 Creates a new user with the specified name and no roles.
 
 
-* `*_ofNameAndRoles_*(String name, xref:system:generated:index/RoleMemento.adoc[RoleMemento]... roles)` : `xref:system:generated:index/UserMemento.adoc[UserMemento]`
+* `[teal]#*_ofNameAndRoles_*#(String name, xref:system:generated:index/RoleMemento.adoc[RoleMemento]... roles)` : `xref:system:generated:index/UserMemento.adoc[UserMemento]`
 +
 Creates a new user with the specified name and assigned roles.
 
 
-* `*_ofNameAndRoleNames_*(String name, String... roleNames)` : `xref:system:generated:index/UserMemento.adoc[UserMemento]`
+* `[teal]#*_ofNameAndRoleNames_*#(String name, String... roleNames)` : `xref:system:generated:index/UserMemento.adoc[UserMemento]`
 +
 Creates a new user with the specified name and assigned role names.
 
 
-* `*_ofNameAndRoleNames_*(String name, Stream<String> roleNames)` : `xref:system:generated:index/UserMemento.adoc[UserMemento]`
+* `[teal]#*_ofNameAndRoleNames_*#(String name, Stream<String> roleNames)` : `xref:system:generated:index/UserMemento.adoc[UserMemento]`
 +
 Creates a new user with the specified name and assigned role names.
 
 
-* `*isCurrentUser*(String userName)` : `boolean`
+* `[teal]#*isCurrentUser*#(String userName)` : `boolean`
 +
 Determine if the specified name is this user.
 +
diff --git a/antora/components/system/modules/generated/pages/index/UserService.adoc b/antora/components/system/modules/generated/pages/index/UserService.adoc
index b25d4ed..1dff20b 100644
--- a/antora/components/system/modules/generated/pages/index/UserService.adoc
+++ b/antora/components/system/modules/generated/pages/index/UserService.adoc
@@ -5,21 +5,21 @@
 The xref:system:generated:index/UserService.adoc[UserService] allows the domain object to obtain the identity of the user interacting with said object.
 If _SudoService_ has been used to temporarily override the user and/or roles, then this service will report the overridden values instead.
 
-* `*currentUser*()` : `Optional<xref:system:generated:index/UserMemento.adoc[UserMemento]>`
+* `[teal]#*currentUser*#()` : `Optional<xref:system:generated:index/UserMemento.adoc[UserMemento]>`
 +
 Optionally gets the details about the current user, based on whether an _ExecutionContext_ can be found with the current thread's context.
 
 
-* `*getUser*()` : `xref:system:generated:index/UserMemento.adoc[UserMemento]`
+* `[teal]#*getUser*#()` : `xref:system:generated:index/UserMemento.adoc[UserMemento]`
 +
 Gets the details about the current user.
 
 
-* `*currentUserElseFail*()` : `xref:system:generated:index/UserMemento.adoc[UserMemento]`
+* `[teal]#*currentUserElseFail*#()` : `xref:system:generated:index/UserMemento.adoc[UserMemento]`
 +
 Gets the details about the current user.
 
 
-* `*currentUserName*()` : `Optional<String>`
+* `[teal]#*currentUserName*#()` : `Optional<String>`
 +
 Optionally gets the the current user's name, based on whether an _ExecutionContext_ can be found with the current thread's context.
diff --git a/tooling/cli/src/main/java/org/apache/isis/tooling/cli/doclet/Adoclet.java b/tooling/cli/src/main/java/org/apache/isis/tooling/cli/doclet/Adoclet.java
index 874f472..6326024 100644
--- a/tooling/cli/src/main/java/org/apache/isis/tooling/cli/doclet/Adoclet.java
+++ b/tooling/cli/src/main/java/org/apache/isis/tooling/cli/doclet/Adoclet.java
@@ -19,7 +19,6 @@
 package org.apache.isis.tooling.cli.doclet;
 
 import java.io.File;
-import java.io.IOException;
 import java.util.stream.Stream;
 
 import com.github.javaparser.StaticJavaParser;
@@ -148,7 +147,7 @@ public class Adoclet {
             
             doc.setTitle(title);
             return AsciiDocWriter.toString(doc);
-        } catch (IOException e) {
+        } catch (Exception e) {
             e.printStackTrace();
             return "ERROR: " + e.getMessage();
         }
diff --git a/tooling/cli/src/main/java/org/apache/isis/tooling/cli/doclet/AdocletContext.java b/tooling/cli/src/main/java/org/apache/isis/tooling/cli/doclet/AdocletContext.java
index 684ca93..c77815b 100644
--- a/tooling/cli/src/main/java/org/apache/isis/tooling/cli/doclet/AdocletContext.java
+++ b/tooling/cli/src/main/java/org/apache/isis/tooling/cli/doclet/AdocletContext.java
@@ -44,11 +44,17 @@ public class AdocletContext {
     @Builder.Default
     private final @NonNull String methodFormat = "`%s %s %s(%s)`";
     
-    /**
-     * method-generic-type | return-type | name | param-list
-     */
     @Builder.Default
-    private final @NonNull String staticMethodFormat = "`%s %s _%s_(%s)`"; 
+    private final @NonNull String methodNameFormat = "[teal]#*%s*#";
+    
+    @Builder.Default
+    private final @NonNull String staticMethodNameFormat = "[teal]#*_%s_*#";
+    
+    @Builder.Default
+    private final @NonNull String deprecatedMethodNameFormat = "[line-through gray]#*%s*#";
+    
+    @Builder.Default
+    private final @NonNull String deprecatedStaticMethodNameFormat = "[line-through gray]#*_%s_*#";
     
     /**
      * method | description
@@ -94,8 +100,7 @@ public class AdocletContext {
     
     public static AdocletContextBuilder compactFormat() {
         return AdocletContext.builder()
-                .methodFormat("`*%3$s*%1$s(%4$s)` : `%2$s`") //  method-generic-type | return-type | name | param-list)
-                .staticMethodFormat("`*_%3$s_*%1$s(%4$s)` : `%2$s`") //  method-generic-type | return-type | name | param-list)
+                .methodFormat("`%3$s%1$s(%4$s)` : `%2$s`") //  method-generic-type | return-type | name | param-list)
                 .methodDescriptionFormat("\n* %s\n%s\n") // method | description
                 .includeJavaSource(false)
                 ;        
diff --git a/tooling/cli/src/main/java/org/apache/isis/tooling/cli/doclet/HtmlToAsciiDoc.java b/tooling/cli/src/main/java/org/apache/isis/tooling/cli/doclet/HtmlToAsciiDoc.java
index bed41a7..6c6b903 100644
--- a/tooling/cli/src/main/java/org/apache/isis/tooling/cli/doclet/HtmlToAsciiDoc.java
+++ b/tooling/cli/src/main/java/org/apache/isis/tooling/cli/doclet/HtmlToAsciiDoc.java
@@ -31,72 +31,14 @@ import org.jsoup.select.NodeTraversor;
 import org.jsoup.select.NodeVisitor;
 
 import org.apache.isis.tooling.model4adoc.AsciiDocFactory;
-import org.apache.isis.tooling.model4adoc.AsciiDocWriter;
 
 import lombok.SneakyThrows;
 import lombok.val;
 
 final class HtmlToAsciiDoc {
     
-    private final static class BlockHelper {
-        private final Stack<StructuralNode> stack = new Stack<StructuralNode>();
-        private final Stack<org.asciidoctor.ast.List> listStack = new Stack<org.asciidoctor.ast.List>();
-
-        BlockHelper(Document adoc){
-            stack.push(adoc);
-        }
-        
-        void pop() {
-            stack.pop();
-        }
-        
-        void popList() {
-            stack.pop();
-            listStack.pop();
-        }
-        
-        Block nextBlock() {
-            val block = AsciiDocFactory.block(stack.peek());
-            stack.push(block);
-            return block;
-        }
-        
-        Block getBlock() {
-            return (stack.peek() instanceof Block)
-                    ? (Block) stack.peek()
-                    : nextBlock();
-        }
-        
-        void blockAppend(String source) {
-            val block = getBlock();
-            block.setSource(block.getSource()+source);
-        }
-        
-        org.asciidoctor.ast.List nextList() {
-            val nextList = AsciiDocFactory.list(stack.peek());
-            stack.push(nextList);
-            listStack.push(nextList);
-            return nextList;
-        }
-
-        ListItem nextListItem() {
-            val list = listStack.isEmpty()
-                    ? nextList()
-                    : listStack.peek();
-            
-            // pop until stack top points to list
-            while(!list.equals(stack.peek())) {
-                stack.pop();
-            }
-            val listItem = AsciiDocFactory.listItem(list);
-            stack.push(listItem);
-            return listItem;
-        }
-        
-    }
-
     @SneakyThrows
-    public static String body(Element body, int level) {
+    public static Document body(Element body, int level) {
         
         val adoc = AsciiDocFactory.doc();
         adoc.setLevel(level);
@@ -169,8 +111,66 @@ final class HtmlToAsciiDoc {
             
         }, body);
 
-        return //adoc.toString();
-               AsciiDocWriter.toString(adoc);
+        return adoc;
+    }
+    
+    // -- HELPER
+    
+    private final static class BlockHelper {
+        private final Stack<StructuralNode> stack = new Stack<StructuralNode>();
+        private final Stack<org.asciidoctor.ast.List> listStack = new Stack<org.asciidoctor.ast.List>();
+
+        BlockHelper(Document adoc){
+            stack.push(adoc);
+        }
+        
+        void pop() {
+            stack.pop();
+        }
+        
+        void popList() {
+            stack.pop();
+            listStack.pop();
+        }
+        
+        Block nextBlock() {
+            val block = AsciiDocFactory.block(stack.peek());
+            stack.push(block);
+            return block;
+        }
+        
+        Block getBlock() {
+            return (stack.peek() instanceof Block)
+                    ? (Block) stack.peek()
+                    : nextBlock();
+        }
+        
+        void blockAppend(String source) {
+            val block = getBlock();
+            block.setSource(block.getSource()+source);
+        }
+        
+        org.asciidoctor.ast.List nextList() {
+            val nextList = AsciiDocFactory.list(stack.peek());
+            stack.push(nextList);
+            listStack.push(nextList);
+            return nextList;
+        }
+
+        ListItem nextListItem() {
+            val list = listStack.isEmpty()
+                    ? nextList()
+                    : listStack.peek();
+            
+            // pop until stack top points to list
+            while(!list.equals(stack.peek())) {
+                stack.pop();
+            }
+            val listItem = AsciiDocFactory.listItem(list);
+            stack.push(listItem);
+            return listItem;
+        }
+        
     }
 
 }
diff --git a/tooling/cli/src/main/java/org/apache/isis/tooling/cli/doclet/ToAsciiDoc.java b/tooling/cli/src/main/java/org/apache/isis/tooling/cli/doclet/ToAsciiDoc.java
index 237e909..f8aa58e 100644
--- a/tooling/cli/src/main/java/org/apache/isis/tooling/cli/doclet/ToAsciiDoc.java
+++ b/tooling/cli/src/main/java/org/apache/isis/tooling/cli/doclet/ToAsciiDoc.java
@@ -30,11 +30,17 @@ import com.github.javaparser.ast.type.ClassOrInterfaceType;
 import com.github.javaparser.ast.type.Type;
 import com.github.javaparser.ast.type.TypeParameter;
 import com.github.javaparser.javadoc.Javadoc;
+import com.github.javaparser.javadoc.description.JavadocDescription;
 import com.github.javaparser.javadoc.description.JavadocInlineTag;
 import com.github.javaparser.javadoc.description.JavadocSnippet;
 
+import org.asciidoctor.ast.Document;
 import org.jsoup.Jsoup;
 
+import org.apache.isis.tooling.javamodel.Javadocs;
+import org.apache.isis.tooling.model4adoc.AsciiDocFactory;
+import org.apache.isis.tooling.model4adoc.AsciiDocWriter;
+
 import lombok.NonNull;
 import lombok.Value;
 import lombok.val;
@@ -46,14 +52,24 @@ class ToAsciiDoc {
 
     public String methodDeclaration(final @NonNull MethodDeclaration md) {
         
-        val methodFormat = md.isStatic()
-                ? docletContext.getStaticMethodFormat()
-                : docletContext.getMethodFormat();
+        val isDeprecated = md.getAnnotations().stream()
+                .anyMatch(a->a.getNameAsString().equals("Deprecated"))
+                || md.getJavadoc()
+                    .map(Javadocs::hasDeprecated)
+                    .orElse(false);
+        
+        val methodNameFormat = isDeprecated
+                ? md.isStatic()
+                        ? docletContext.getDeprecatedStaticMethodNameFormat()
+                        : docletContext.getDeprecatedMethodNameFormat()
+                : md.isStatic()
+                    ? docletContext.getStaticMethodNameFormat()
+                    : docletContext.getMethodNameFormat();
         
-        return String.format(methodFormat,
+        return String.format(docletContext.getMethodFormat(),
                 typeParamters(md.getTypeParameters()),
                 type(md.getType()),
-                md.getNameAsString(), 
+                String.format(methodNameFormat, md.getNameAsString()), 
                 md.getParameters()
                     .stream()
                     .map(this::parameterDeclaration)
@@ -105,28 +121,25 @@ class ToAsciiDoc {
                 p.getNameAsString());
     }
     
-    //TODO method java-doc needs further post processing when spanning multiple paragraphs
     public String javadoc(final @NonNull Javadoc javadoc, final int level) {
 
-        val javadocResolved = new StringBuilder();
-
-        javadoc.getDescription().getElements()
-        .forEach(e->{
-
-            if(e instanceof JavadocSnippet) {
-                javadocResolved.append(javadocSnippet((JavadocSnippet)e));
-            } else if(e instanceof JavadocInlineTag) {
-                javadocResolved.append(inlineTag((JavadocInlineTag) e));
-            } else {
-                javadocResolved.append(e.toText());
-            }
-
-        });
-
-        val doc = Jsoup.parse(javadocResolved.toString());
-        return HtmlToAsciiDoc.body(doc.selectFirst("body"), level);
+        val descriptionAdoc = javadocDescription(javadoc.getDescription(), level);
+
+        Javadocs.streamTagContent(javadoc, "deprecated")
+                .findFirst()
+                .map(javadocDescription->javadocDescription(javadocDescription, level))
+                .ifPresent(deprecatedAdoc->{
+                    
+                    val deprecatedBlock = AsciiDocFactory.block(descriptionAdoc);
+                    
+                    deprecatedBlock.setSource("[red]#_deprecated:_#");
+                    
+                    deprecatedBlock.getBlocks().addAll(deprecatedAdoc.getBlocks());
+                });
+        
+        return AsciiDocWriter.toString(descriptionAdoc);
     }
-
+    
     public String inlineTag(final @NonNull JavadocInlineTag inlineTag) {
 
         val inlineContent = inlineTag.getContent().trim();
@@ -157,5 +170,28 @@ class ToAsciiDoc {
     public String javadocSnippet(final @NonNull JavadocSnippet snippet) {
         return snippet.toText();
     }
+    
+    // -- HELPER
+    
+    private Document javadocDescription(final @NonNull JavadocDescription javadocDescription, final int level) {
+        val javadocResolved = new StringBuilder();
+
+        javadocDescription.getElements()
+        .forEach(e->{
+
+            if(e instanceof JavadocSnippet) {
+                javadocResolved.append(javadocSnippet((JavadocSnippet)e));
+            } else if(e instanceof JavadocInlineTag) {
+                javadocResolved.append(inlineTag((JavadocInlineTag) e));
+            } else {
+                javadocResolved.append(e.toText());
+            }
+
+        });
+
+        val descriptionAsHtml = Jsoup.parse(javadocResolved.toString());
+        val adoc = HtmlToAsciiDoc.body(descriptionAsHtml.selectFirst("body"), level);
+        return adoc;
+    }
 
 }
diff --git a/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/Javadocs.java b/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/Javadocs.java
index c591d09..5458d10 100644
--- a/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/Javadocs.java
+++ b/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/Javadocs.java
@@ -53,6 +53,14 @@ public final class Javadocs {
         .orElse(false);
     }
     
+    public static boolean hasDeprecated(
+            final @NonNull Javadoc javadoc) {
+        
+        return streamTagsByName(javadoc, "deprecated") 
+        .findAny()
+        .isPresent();
+    }
+    
     public static boolean hasHidden(
             final @NonNull Javadoc javadoc) {
         
diff --git a/tooling/model4adoc/src/main/java/org/apache/isis/tooling/model4adoc/AsciiDocWriter.java b/tooling/model4adoc/src/main/java/org/apache/isis/tooling/model4adoc/AsciiDocWriter.java
index 6531342..8ae4cbe 100644
--- a/tooling/model4adoc/src/main/java/org/apache/isis/tooling/model4adoc/AsciiDocWriter.java
+++ b/tooling/model4adoc/src/main/java/org/apache/isis/tooling/model4adoc/AsciiDocWriter.java
@@ -35,6 +35,7 @@ import org.asciidoctor.ast.Table;
 import org.apache.isis.commons.internal.base._Strings;
 
 import lombok.RequiredArgsConstructor;
+import lombok.SneakyThrows;
 import lombok.val;
 import lombok.extern.log4j.Log4j2;
 
@@ -55,9 +56,9 @@ public class AsciiDocWriter {
 
     /**
      * the inverse of {@link Asciidoctor#load(String, java.util.Map)}}
-     * @throws IOException 
      */
-    public static String toString(Document doc) throws IOException {
+    @SneakyThrows
+    public static String toString(Document doc) {
         if(doc==null) {
             return "";
         }