sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject [sis] branch geoapi-4.0 updated: Repair the Doclet for javadoc generation in JDK 10 environment.
Date Wed, 15 Aug 2018 22:51:05 GMT
This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git


The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
     new e99d131  Repair the Doclet for javadoc generation in JDK 10 environment.
e99d131 is described below

commit e99d131b8b3f1a79063dfb1d5cc52ef128416c4e
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Thu Aug 16 00:42:16 2018 +0200

    Repair the Doclet for javadoc generation in JDK 10 environment.
---
 .../org/apache/sis/internal/doclet/Doclet.java     |  22 ++-
 .../org/apache/sis/internal/doclet/Include.java    |  43 +++--
 .../apache/sis/internal/doclet/InlineTaglet.java   | 158 ----------------
 .../org/apache/sis/internal/doclet/Module.java     |  48 ++---
 .../org/apache/sis/internal/doclet/Preformat.java  |  16 +-
 .../org/apache/sis/internal/doclet/Taglet.java     | 207 +++++++++++++++++++++
 pom.xml                                            |   1 +
 7 files changed, 278 insertions(+), 217 deletions(-)

diff --git a/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Doclet.java
b/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Doclet.java
index 7c3741b..103cd70 100644
--- a/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Doclet.java
+++ b/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Doclet.java
@@ -38,6 +38,7 @@ import jdk.javadoc.doclet.Reporter;
 import jdk.javadoc.doclet.Doclet.Option;
 import jdk.javadoc.doclet.DocletEnvironment;
 import jdk.javadoc.doclet.StandardDoclet;
+import com.sun.source.util.DocTrees;
 
 
 /**
@@ -89,8 +90,25 @@ public final class Doclet extends StandardDoclet {
 
     /**
      * Where to report warnings, or {@code null} if unknown.
+     *
+     * @todo make package-private after {@link #workaround8201817} has been removed.
+     */
+    public Reporter reporter;
+
+    /**
+     * Utility methods for locating the path of elements, or {@code null} if unknown.
+     *
+     * @todo make package-private after {@link #workaround8201817} has been removed.
+     */
+    public DocTrees trees;
+
+    /**
+     * Temporary Workaround for https://bugs.openjdk.java.net/browse/JDK-8201817
+     *
+     * @deprecated to be removed after we upgraded Apache SIS build requirement to JDK 11.
      */
-    Reporter reporter;
+    @Deprecated
+    public static Doclet workaround8201817;
 
     /**
      * Invoked by the Javadoc tools for instantiating the custom doclet.
@@ -108,6 +126,7 @@ public final class Doclet extends StandardDoclet {
     public void init(final Locale locale, final Reporter reporter) {
         super.init(locale, reporter);
         this.reporter = reporter;
+        workaround8201817 = this;
     }
 
     /**
@@ -157,6 +176,7 @@ public final class Doclet extends StandardDoclet {
     @Override
     @SuppressWarnings("CallToPrintStackTrace")
     public boolean run(final DocletEnvironment environment) {
+        trees = environment.getDocTrees();
         final boolean success = super.run(environment);
         if (success && outputDirectory != null) try {
             final File output = new File(outputDirectory);
diff --git a/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Include.java
b/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Include.java
index d444bac..b6a865f 100644
--- a/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Include.java
+++ b/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Include.java
@@ -16,7 +16,10 @@
  */
 package org.apache.sis.internal.doclet;
 
-import java.io.*;
+import java.nio.file.Path;
+import java.nio.file.Files;
+import java.io.BufferedReader;
+import java.io.IOException;
 import com.sun.source.doctree.DocTree;
 
 
@@ -37,7 +40,7 @@ import com.sun.source.doctree.DocTree;
  * @since   0.5
  * @module
  */
-public final class Include extends InlineTaglet {
+public final class Include extends Taglet {
     /**
      * The beginning and the end of the anchor texts. Must be on the same line.
      */
@@ -66,32 +69,35 @@ public final class Include extends InlineTaglet {
     }
 
     /**
-     * Given the <code>DocTree</code> representation of this custom tag, return
its string representation.
+     * Given the <code>DocTree</code> representation of this custom tag, appends
its string representation.
      *
-     * @param  tag  the tag to format.
-     * @return a string representation of the given tag.
+     * @param  tag     the tag to format.
+     * @param  buffer  the buffer where to format the tag.
      */
     @Override
-    protected String toString(final DocTree tag) {
+    protected void format(final DocTree tag, final StringBuilder buffer) {
         final String reference = text(tag);
         final int sep = reference.indexOf('#');
         if (sep < 0) {
-            printWarning(tag, "@include expected a reference like \"filename#anchor\" but
got \"" + reference + "\".");
-            return reference;
+            printWarning("@include expected a reference like \"filename#anchor\" but got
\"" + reference + "\".");
+            buffer.append(reference);
+            return;
         }
-        File file = file(tag);
-        file = new File(file.getParentFile(), reference.substring(0, sep));
+        final int bs = buffer.length();
+        Path file = getCurrentFile();
+        file = file.getParent().resolve(reference.substring(0, sep));
         final String anchor = reference.substring(sep + 1);
-        final StringBuilder buffer = new StringBuilder();
-        try (BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(file),
"UTF-8"))) {
+        try (BufferedReader in = Files.newBufferedReader(file)) {
             /*
              * Search the anchor.
              */
             String line;
             int start, end;
             do if ((line = in.readLine()) == null) {
-                printWarning(tag, "Header \"" + anchor + "\" not found in file " + file);
-                return reference;
+                printWarning("Header \"" + anchor + "\" not found in file " + file);
+                buffer.setLength(bs);
+                buffer.append(reference);
+                return;
             }
             while ((start = line.indexOf(ANCHOR_START)) < 0 ||
                      (end = line.lastIndexOf(ANCHOR_END)) < start ||
@@ -103,8 +109,10 @@ public final class Include extends InlineTaglet {
             while (true) {
                 line = in.readLine();
                 if (line == null) {
-                    printWarning(tag, "Unexpected end of file in " + file);
-                    return reference;
+                    printWarning("Unexpected end of file in " + file);
+                    buffer.setLength(bs);
+                    buffer.append(reference);
+                    return;
                 }
                 start = line.indexOf(ANCHOR_START);
                 if (start >= 0 && line.lastIndexOf(ANCHOR_END) >= start) {
@@ -116,8 +124,7 @@ public final class Include extends InlineTaglet {
                 buffer.append(line).append('\n');
             }
         } catch (IOException e) {
-            printError(tag, "Error reading " + file + ":\n" + e);
+            printError("Error reading " + file + ":\n" + e);
         }
-        return buffer.toString();
     }
 }
diff --git a/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/InlineTaglet.java
b/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/InlineTaglet.java
deleted file mode 100644
index 3beeebb..0000000
--- a/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/InlineTaglet.java
+++ /dev/null
@@ -1,158 +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.sis.internal.doclet;
-
-import java.io.File;
-import java.util.Set;
-import java.util.EnumSet;
-import java.util.List;
-import javax.tools.Diagnostic;
-import javax.lang.model.element.Element;
-import jdk.javadoc.doclet.Reporter;
-import jdk.javadoc.doclet.Taglet;
-import com.sun.source.doctree.DocTree;
-import com.sun.source.doctree.TextTree;
-import com.sun.source.doctree.UnknownInlineTagTree;
-import com.sun.source.tree.CompilationUnitTree;
-import jdk.javadoc.doclet.DocletEnvironment;
-
-
-/**
- * Base class of inline taglets.
- *
- * @author  Martin Desruisseaux (Geomatys)
- * @version 1.0
- * @since   0.3
- * @module
- */
-abstract class InlineTaglet implements Taglet {
-    /**
-     * Where to report warnings, or {@code null} if unknown.
-     */
-    private Reporter reporter;
-
-    /**
-     * Constructs a default inline taglet.
-     */
-    InlineTaglet() {
-    }
-
-    /**
-     * Initializes this taglet with the given doclet environment and doclet.
-     *
-     * @param env     the environment in which the taglet is running.
-     * @param doclet  the doclet that instantiated this taglet.
-     */
-    @Override
-    public void init(final DocletEnvironment env, final jdk.javadoc.doclet.Doclet doclet)
{
-        reporter = ((Doclet) doclet).reporter;
-    }
-
-    /**
-     * Returns the set of locations in which this taglet may be used.
-     * By default the taglet can be used everywhere.
-     *
-     * @return the set of locations in which this taglet may be used.
-     */
-    @Override
-    public Set<Taglet.Location> getAllowedLocations() {
-        return EnumSet.allOf(Taglet.Location.class);
-    }
-
-    /**
-     * Returns {@code true} since this base class is all about inline tags.
-     *
-     * @return always {@code true}.
-     */
-    @Override
-    public final boolean isInlineTag() {
-        return true;
-    }
-
-    /**
-     * Returns the text contained in the given inline tag.
-     */
-    static String text(final DocTree tag) {
-        for (final DocTree node : ((UnknownInlineTagTree) tag).getContent()) {
-            if (node.getKind() == DocTree.Kind.TEXT) {
-                return ((TextTree) node).getBody().trim();
-            }
-        }
-        return "";
-    }
-
-    /**
-     * Returns the file that contains the given tag.
-     */
-    static File file(final DocTree tag) {
-        return new File(getCompilationUnitTree(tag).getSourceFile().getName());
-    }
-
-    private static CompilationUnitTree getCompilationUnitTree(final DocTree tree) {
-        throw new UnsupportedOperationException("We have not yet found how to get the compilation
unit."); // TODO
-    }
-
-    /**
-     * Given a list of {@code DocTree}s representing this custom tag, returns its string
representation.
-     * This method will be invoked once for each instance of the tag in parsed Javadoc.
-     *
-     * @param  tags     the tags to format.
-     * @param  element  the element to which the enclosing comment belongs.
-     * @return a string representation of the given tags.
-     */
-    @Override
-    public final String toString(final List<? extends DocTree> tags, final Element
element) {
-        final StringBuilder buffer = new StringBuilder(64);
-        for (final DocTree tag : tags) {
-            buffer.append(toString(tag));
-        }
-        return buffer.toString();
-    }
-
-    /**
-     * Given a single {@code DocTree}s representing this custom tag, returns its string representation.
-     * This method will be invoked once for each instance of the tag in parsed Javadoc.
-     *
-     * @param  tag  the tag to format.
-     * @return a string representation of the given tag.
-     */
-    protected abstract String toString(DocTree tag);
-
-    /**
-     * Prints a warning message.
-     */
-    @SuppressWarnings("UseOfSystemOutOrSystemErr")
-    final void printWarning(final DocTree tag, final String message) {
-        if (reporter != null) {
-            reporter.print(Diagnostic.Kind.WARNING, message);
-        } else {
-            System.err.println(message);
-        }
-    }
-
-    /**
-     * Prints an error message.
-     */
-    @SuppressWarnings("UseOfSystemOutOrSystemErr")
-    final void printError(final DocTree tag, final String message) {
-        if (reporter != null) {
-            reporter.print(Diagnostic.Kind.ERROR, message);
-        } else {
-            System.err.println(message);
-        }
-    }
-}
diff --git a/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Module.java
b/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Module.java
index 1ef02df..0959d7a 100644
--- a/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Module.java
+++ b/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Module.java
@@ -16,13 +16,10 @@
  */
 package org.apache.sis.internal.doclet;
 
-import java.io.File;
-import java.util.List;
 import java.util.Set;
 import java.util.EnumSet;
-import jdk.javadoc.doclet.Taglet;
+import java.nio.file.Path;
 import com.sun.source.doctree.DocTree;
-import javax.lang.model.element.Element;
 
 
 /**
@@ -33,17 +30,11 @@ import javax.lang.model.element.Element;
  * @since   0.3
  * @module
  */
-public final class Module implements Taglet {
-    /**
-     * The SIS module in which the <code>@module</code> taglet has been found.
-     */
-    private String module;
-
+public final class Module extends Taglet {
     /**
      * Constructs a <code>@module</code> taglet.
      */
     public Module() {
-        super();
     }
 
     /**
@@ -62,9 +53,8 @@ public final class Module implements Taglet {
      * @return the set of locations in which this taglet may be used.
      */
     @Override
-    public Set<Taglet.Location> getAllowedLocations() {
-        return EnumSet.of(Taglet.Location.PACKAGE,
-                          Taglet.Location.TYPE);
+    public Set<Location> getAllowedLocations() {
+        return EnumSet.of(Location.PACKAGE, Location.TYPE);
     }
 
     /**
@@ -78,27 +68,22 @@ public final class Module implements Taglet {
     }
 
     /**
-     * Given a list of {@code DocTree}s representing this custom tag, returns its string
representation.
+     * Given a {@code DocTree}s representing this custom tag, appends its string representation.
      *
-     * @param  tags     the tags to format.
-     * @param  element  the element to which the enclosing comment belongs.
-     * @return a string representation of the given tags.
+     * @param  tag     the tag to format.
+     * @param  buffer  the buffer where to format the tag.
      */
     @Override
-    public String toString(final List<? extends DocTree> tags, final Element element)
{
-        if (tags == null || tags.isEmpty()) {
-            return "";
-        }
-        final StringBuilder buffer = new StringBuilder(128);
+    protected void format(final DocTree tag, final StringBuilder buffer) {
         buffer.append("\n<p><font size=\"-1\">");
-        for (final DocTree tag : tags) {
-            File file = InlineTaglet.file(tag);
-            module = file.getName();
-            while ((file = file.getParentFile()) != null) {
-                if (file.getName().equals("src")) {
-                    file = file.getParentFile();
+        Path file = getCurrentFile();
+        if (file != null) {
+            String module = file.getFileName().toString();
+            while ((file = file.getParent()) != null) {
+                if (file.getFileName().toString().equals("src")) {
+                    file = file.getParent();
                     if (file != null) {
-                        module = file.getName();
+                        module = file.getFileName().toString();
                     }
                     break;
                 }
@@ -106,8 +91,7 @@ public final class Module implements Taglet {
             /*
              * Appends the module link.
              */
-            buffer.append("Defined in the <code>").append(module).append("</code>
module");
+            buffer.append("Defined in the <code>").append(module).append("</code>
module").append("</font></p>\n");
         }
-        return buffer.append("</font></p>\n").toString();
     }
 }
diff --git a/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Preformat.java
b/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Preformat.java
index b95341f..c67fd18 100644
--- a/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Preformat.java
+++ b/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Preformat.java
@@ -36,7 +36,7 @@ import org.apache.sis.internal.book.CodeColorizer;
  * @since   0.3
  * @module
  */
-public final class Preformat extends InlineTaglet {
+public final class Preformat extends Taglet {
     /**
      * The set of legal words after {@code preformat}. We write them in lower-cases even
if this is not
      * conform to the Java convention for enumeration constants, because we will use {@link
Enum#name()}
@@ -74,13 +74,13 @@ public final class Preformat extends InlineTaglet {
     }
 
     /**
-     * Given the <code>DocTree</code> representation of this custom tag, return
its string representation.
+     * Given the <code>DocTree</code> representation of this custom tag, appends
its string representation.
      *
-     * @param  tag  the tag to format.
-     * @return a string representation of the given tag.
+     * @param  tag     the tag to format.
+     * @param  buffer  the buffer where to format the tag.
      */
     @Override
-    protected String toString(final DocTree tag) {
+    protected void format(final DocTree tag, final StringBuilder buffer) {
         String text = text(tag).replace("\r\n", "\n").replace('\r', '\n');
         String format = "<unspecified>";
         /*
@@ -97,7 +97,7 @@ public final class Preformat extends InlineTaglet {
         try {
             style = Style.valueOf(format);
         } catch (IllegalArgumentException e) {
-            printWarning(tag, "Unknown format: " + format);
+            printWarning("Unknown format: " + format);
             style = Style.text;
         }
         /*
@@ -126,7 +126,7 @@ all:    while (tk.hasMoreTokens()) {
         /*
          * Nows inserts each line.
          */
-        final StringBuilder buffer = new StringBuilder("<blockquote><pre>");
+        buffer.append("<blockquote><pre>");
         tk = new StringTokenizer(text, "\r\n", true);
         while (tk.hasMoreTokens()) {
             String line = tk.nextToken();
@@ -144,7 +144,7 @@ all:    while (tk.hasMoreTokens()) {
             }
             buffer.append(line);
         }
-        return buffer.append("</pre></blockquote>").toString();
+        buffer.append("</pre></blockquote>");
     }
 
     /**
diff --git a/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Taglet.java
b/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Taglet.java
new file mode 100644
index 0000000..b55fafe
--- /dev/null
+++ b/core/sis-build-helper/src/main/java/org/apache/sis/internal/doclet/Taglet.java
@@ -0,0 +1,207 @@
+/*
+ * 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.sis.internal.doclet;
+
+import java.util.Set;
+import java.util.EnumSet;
+import java.util.List;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import javax.tools.Diagnostic;
+import javax.lang.model.element.Element;
+import jdk.javadoc.doclet.DocletEnvironment;
+import jdk.javadoc.doclet.Reporter;
+import com.sun.source.util.DocTrees;
+import com.sun.source.util.TreePath;
+import com.sun.source.doctree.DocTree;
+import com.sun.source.doctree.TextTree;
+import com.sun.source.doctree.UnknownInlineTagTree;
+
+
+/**
+ * Base class of all taglets implemented in this package.
+ * Taglets are assumed inline by default.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.0
+ * @since   0.3
+ * @module
+ */
+abstract class Taglet implements jdk.javadoc.doclet.Taglet {
+    /**
+     * Where to report warnings, or {@code null} if unknown.
+     */
+    private Reporter reporter;
+
+    /**
+     * Utility methods for locating the path of elements, or {@code null} if unknown.
+     */
+    private DocTrees trees;
+
+    /**
+     * The current element, or {@code null} if none.
+     */
+    private Element element;
+
+    /**
+     * Constructs a default inline taglet.
+     */
+    Taglet() {
+    }
+
+    /**
+     * Initializes this taglet with the given doclet environment and doclet.
+     *
+     * @param env     the environment in which the taglet is running.
+     * @param doclet  the doclet that instantiated this taglet.
+     */
+    @Override
+    public void init(final DocletEnvironment env, final jdk.javadoc.doclet.Doclet doclet)
{
+        if (doclet instanceof Doclet) {
+            reporter = ((Doclet) doclet).reporter;
+            trees    = ((Doclet) doclet).trees;
+        } else {
+            // Temporary workaround for https://bugs.openjdk.java.net/browse/JDK-8201817
+            StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE).walk(stream
->
+                stream.filter(frame -> frame.getClassName().equals("org.apache.sis.internal.doclet.Doclet"))
+                      .map(frame -> frame.getDeclaringClass()).findFirst()).ifPresent(docletClass
-> {
+                          try {
+                              Object instance = docletClass.getDeclaredField("workaround8201817").get(null);
+                              reporter = (Reporter) docletClass.getDeclaredField("reporter").get(instance);
+                              trees    = (DocTrees) docletClass.getDeclaredField("trees").get(instance);
+                          } catch (ReflectiveOperationException e) {
+                              printError("Unsupported doclet implementation. Caused by: "
+ e);
+                          }
+                      });
+        }
+    }
+
+    /**
+     * Returns the set of locations in which this taglet may be used.
+     * By default the taglet can be used everywhere.
+     *
+     * @return the set of locations in which this taglet may be used.
+     */
+    @Override
+    public Set<Location> getAllowedLocations() {
+        return EnumSet.allOf(Location.class);
+    }
+
+    /**
+     * Returns {@code true} by default since this base class is about inline tags.
+     *
+     * @return {@code true} if this tagle is an inline taglet.
+     */
+    @Override
+    public boolean isInlineTag() {
+        return true;
+    }
+
+    /**
+     * Returns the text contained in the given inline tag.
+     */
+    static String text(final DocTree tag) {
+        for (final DocTree node : ((UnknownInlineTagTree) tag).getContent()) {
+            if (node.getKind() == DocTree.Kind.TEXT) {
+                return ((TextTree) node).getBody().trim();
+            }
+        }
+        return "";
+    }
+
+    /**
+     * Returns the file that contains the current tag, or {@code null} if the method
+     * can not determine the file.
+     *
+     * @return file containing the current tag, or {@code null}.
+     */
+    protected final Path getCurrentFile() {
+        if (trees != null && element != null) {
+            final TreePath path = trees.getPath(element);
+            if (path != null) {
+                // Following methods do not document 'null' as a possible return value.
+                return Paths.get(path.getCompilationUnit().getSourceFile().toUri());
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Given a list of {@code DocTree}s representing this custom tag, returns its string
representation.
+     * This method will be invoked once for each instance of the tag in parsed Javadoc.
+     *
+     * @param  tags     the tags to format.
+     * @param  element  the element to which the enclosing comment belongs.
+     * @return a string representation of the given tags.
+     */
+    @Override
+    public final String toString(final List<? extends DocTree> tags, final Element
element) {
+        final StringBuilder buffer = new StringBuilder(64);
+        try {
+            this.element = element;
+            for (final DocTree tag : tags) {
+                format(tag, buffer);
+            }
+        } finally {
+            this.element = null;
+        }
+        return buffer.toString();
+    }
+
+    /**
+     * Given a single {@code DocTree}s representing this custom tag, returns its string representation.
+     * This method will be invoked once for each instance of the tag in parsed Javadoc.
+     *
+     * @param  tag       the tag to format.
+     * @param  appendTo  the buffer where to format the tag.
+     */
+    protected abstract void format(DocTree tag, StringBuilder appendTo);
+
+    /**
+     * Prints a warning message for the current tag.
+     *
+     * @param message  the warning message to print.
+     */
+    protected final void printWarning(final String message) {
+        print(Diagnostic.Kind.WARNING, message);
+    }
+
+    /**
+     * Prints an error message for the current tag.
+     *
+     * @param message  the error message to print.
+     */
+    protected final void printError(final String message) {
+        print(Diagnostic.Kind.ERROR, message);
+    }
+
+    /**
+     * Prints an error or warning message.
+     */
+    @SuppressWarnings("UseOfSystemOutOrSystemErr")
+    private void print(final Diagnostic.Kind kind, final String message) {
+        if (reporter != null) {
+            if (element != null) {
+                reporter.print(kind, element, message);
+            } else {
+                reporter.print(kind, message);
+            }
+        } else {
+            System.err.println(message);
+        }
+    }
+}
diff --git a/pom.xml b/pom.xml
index 15e4fd4..88023c8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -565,6 +565,7 @@
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-enforcer-plugin</artifactId>
+        <version>3.0.0-M2</version>
         <executions>
           <execution>
             <id>enforce</id>


Mime
View raw message