@throws expansion; general fixes
This commit is contained in:
parent
cf5a753d1f
commit
20c8adbfd2
@ -7,6 +7,8 @@ import org.springframework.stereotype.Component;
|
||||
* Here is a second line that happens
|
||||
* to span multiple lines.
|
||||
*
|
||||
* Here is a {@link http://inteligr8.com} for testing purposes. And here is another { @link http://inteligr8.com } one.
|
||||
*
|
||||
* @author brian@inteligr8.com
|
||||
* @version 1.0
|
||||
*/
|
||||
@ -81,6 +83,10 @@ public class TestNamedBean {
|
||||
* @param param A parameter comment.
|
||||
* @return A return comment.
|
||||
* @throws java.lang.Exception An exception comment.
|
||||
* @throws org.activiti.engine.delegate.BpmnError http-404
|
||||
* @throws BpmnError http-400 A client error.
|
||||
* @see `test.bean`
|
||||
* @see http://inteligr8.com
|
||||
*/
|
||||
public String apiMethod8(String param) throws Exception {
|
||||
return null;
|
||||
|
@ -54,9 +54,12 @@ class ActivitiApiBeanDoc {
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<ExecutableElement> getMethodElements() {
|
||||
return new ArrayList<>(this.methodElements.values());
|
||||
}
|
||||
|
||||
public List<ExecutableElement> getSortedMethodElements() {
|
||||
List<ExecutableElement> methodElements = new ArrayList<>(this.methodElements.size());
|
||||
methodElements.addAll(this.methodElements.values());
|
||||
List<ExecutableElement> methodElements = this.getMethodElements();
|
||||
Collections.sort(methodElements, new Comparator<ExecutableElement>() {
|
||||
@Override
|
||||
public int compare(ExecutableElement methodElement1, ExecutableElement methodElement2) {
|
||||
|
@ -91,7 +91,6 @@ class ActivitiDocFilter {
|
||||
|
||||
// getAllTypeElements() will get inherited interfaces
|
||||
for (TypeMirror interfaceType : classElement.getInterfaces()) {
|
||||
this.logger.info("{} contains {}", beanId, interfaceType);
|
||||
this.logger.trace("Found interface '{}' on bean '{}'", interfaceType, beanId);
|
||||
|
||||
switch (interfaceType.toString()) {
|
||||
|
95
src/main/java/com/inteligr8/activiti/doclet/FluentMap.java
Normal file
95
src/main/java/com/inteligr8/activiti/doclet/FluentMap.java
Normal file
@ -0,0 +1,95 @@
|
||||
package com.inteligr8.activiti.doclet;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class FluentMap<K, V> implements Map<K, V> {
|
||||
|
||||
private Map<K, V> map;
|
||||
|
||||
public FluentMap(Map<K, V> map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
this.map.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey(Object key) {
|
||||
return this.map.containsKey(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsValue(Object value) {
|
||||
return this.map.containsValue(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Entry<K, V>> entrySet() {
|
||||
return this.map.entrySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return this.map.equals(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public V get(Object key) {
|
||||
return this.map.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.map.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return this.map.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<K> keySet() {
|
||||
return this.map.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public V put(K key, V value) {
|
||||
return this.map.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putAll(Map<? extends K, ? extends V> m) {
|
||||
this.map.putAll(m);
|
||||
}
|
||||
|
||||
@Override
|
||||
public V remove(Object key) {
|
||||
return this.map.remove(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return this.map.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<V> values() {
|
||||
return this.map.values();
|
||||
}
|
||||
|
||||
public FluentMap<K, V> with(K key, V value) {
|
||||
this.map.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public FluentMap<K, V> without(K key) {
|
||||
this.map.remove(key);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
@ -18,11 +18,15 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@ -52,11 +56,25 @@ import jdk.javadoc.doclet.DocletEnvironment;
|
||||
class MarkdownWriter {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
private final Pattern tagPattern = Pattern.compile("@[^ ]+ ?(.*)$");
|
||||
private final Pattern namedTagPattern = Pattern.compile("@[^ ]+ ([^ ]+) ?(.*)$");
|
||||
private final Set<String> bpmnErrorSet = new HashSet<>(Arrays.asList(
|
||||
"BpmnError".toLowerCase(),
|
||||
"org.activiti.engine.delegate.BpmnError".toLowerCase()));
|
||||
|
||||
private final Pattern tagPattern = Pattern.compile("@([^ ]+) ?(.*)$");
|
||||
private final Pattern namedCommentPattern = Pattern.compile("([^ ]+) ?(.*)$");
|
||||
private final Map<Pattern, String> sanitizations = new FluentMap<>(new LinkedHashMap<Pattern, String>())
|
||||
.with(Pattern.compile("^[ ]+", Pattern.MULTILINE), "")
|
||||
.with(Pattern.compile("\r\n", Pattern.MULTILINE), "\n")
|
||||
.with(Pattern.compile("([^\n])\n([^\n])", Pattern.MULTILINE), "$1 $2")
|
||||
.with(Pattern.compile("([^\\.\\?!])[ ]{2}", Pattern.MULTILINE), "$1 ")
|
||||
.with(Pattern.compile("\\{ ?(@[^}]+) \\}"), "{$1}")
|
||||
.with(Pattern.compile("\\{@link ([^}]+)\\}"), "[$1]($1)")
|
||||
.with(Pattern.compile("([A-Za-z0-9\\-\\._]+@[A-Za-z0-9\\-\\._]+)"), "[$1](mailto:$1)");
|
||||
|
||||
private final DocletEnvironment docenv;
|
||||
private final File outputDirectory;
|
||||
private final Configuration fmconfig;
|
||||
|
||||
private String title = "API Documentation";
|
||||
private String apiName;
|
||||
private String flavor;
|
||||
@ -128,9 +146,9 @@ class MarkdownWriter {
|
||||
this.logger.debug("Found documentation for bean: {}", beandoc.getBeanId());
|
||||
|
||||
if (commentTree.getFirstSentence() != null)
|
||||
beanModel.setDocFirstSentence(commentTree.getFirstSentence().toString());
|
||||
beanModel.setDocFirstSentence(this.sanitize(commentTree.getFirstSentence()));
|
||||
if (commentTree.getBody() != null)
|
||||
beanModel.setDocBody(commentTree.getFullBody().toString());
|
||||
beanModel.setDocBody(this.sanitize(commentTree.getFullBody()));
|
||||
for (DocTree tag : commentTree.getBlockTags()) {
|
||||
String tagName = null;
|
||||
if (tag instanceof BlockTagTree) {
|
||||
@ -165,50 +183,57 @@ class MarkdownWriter {
|
||||
}
|
||||
|
||||
Map<String, String> paramComments = new HashMap<>();
|
||||
Map<String, String> throwComments = new HashMap<>();
|
||||
Map<String, String> throwComments = new LinkedHashMap<>();
|
||||
Map<String, String> errorComments = new LinkedHashMap<>();
|
||||
|
||||
MethodSignatureFreemarkerModel sigModel = new MethodSignatureFreemarkerModel();
|
||||
if (methodCommentTree != null) {
|
||||
this.logger.debug("Found documentation for method: {}.{}", beandoc.getBeanId(), methodElement);
|
||||
|
||||
if (methodCommentTree.getFirstSentence() != null) {
|
||||
sigModel.setDocFirstSentence(this.sanitize(methodCommentTree.getFirstSentence()));
|
||||
if (methodModel.getDocFirstSentence() == null)
|
||||
methodModel.setDocFirstSentence(methodCommentTree.getFirstSentence().toString());
|
||||
sigModel.setDocFirstSentence(methodCommentTree.getFirstSentence().toString());
|
||||
methodModel.setDocFirstSentence(sigModel.getDocFirstSentence());
|
||||
}
|
||||
if (methodCommentTree.getBody() != null)
|
||||
sigModel.setDocBody(methodCommentTree.getFullBody().toString());
|
||||
sigModel.setDocBody(this.sanitize(methodCommentTree.getFullBody()));
|
||||
for (DocTree tag : methodCommentTree.getBlockTags()) {
|
||||
String tagName = null;
|
||||
if (tag instanceof BlockTagTree) {
|
||||
tagName = ((BlockTagTree)tag).getTagName();
|
||||
} else if (tag instanceof InlineTagTree) {
|
||||
tagName = ((InlineTagTree)tag).getTagName();
|
||||
} else {
|
||||
this.logger.error("A tag comment is not of an expected type: {}", tag.getClass());
|
||||
Matcher matcher = this.tagPattern.matcher(tag.toString());
|
||||
if (!matcher.find()) {
|
||||
this.logger.warn("A tag for the {} bean and {} method is improperly formatted", beanModel.getBeanId(), methodElement);
|
||||
continue;
|
||||
}
|
||||
|
||||
String tagName = matcher.group(1);
|
||||
String tagComment = matcher.group(2).trim();
|
||||
|
||||
this.logger.trace("Found tag '{}' for method: {}.{}", tagName, beandoc.getBeanId(), methodElement);
|
||||
this.logger.info("Found tag '{}' for method: {}.{}", tagName, beandoc.getBeanId(), methodElement);
|
||||
|
||||
Matcher matcher;
|
||||
switch (tagName) {
|
||||
case "param":
|
||||
matcher = this.namedTagPattern.matcher(tag.toString());
|
||||
matcher = this.namedCommentPattern.matcher(tagComment);
|
||||
if (matcher.find())
|
||||
paramComments.put(matcher.group(1), matcher.group(2).trim());
|
||||
paramComments.put(matcher.group(1), this.sanitize(matcher.group(2).trim()));
|
||||
else this.logger.warn("A @param for the {} bean and {} method is improperly formatted", beanModel.getBeanId(), methodElement);
|
||||
break;
|
||||
case "throws":
|
||||
matcher = this.namedTagPattern.matcher(tag.toString());
|
||||
if (matcher.find())
|
||||
throwComments.put(matcher.group(1), matcher.group(2).trim());
|
||||
matcher = this.namedCommentPattern.matcher(tagComment);
|
||||
if (matcher.find()) {
|
||||
if (this.bpmnErrorSet.contains(matcher.group(1).toLowerCase())) {
|
||||
Matcher ecmatcher = this.namedCommentPattern.matcher(matcher.group(2).trim());
|
||||
if (ecmatcher.find()) {
|
||||
errorComments.put(ecmatcher.group(1), this.sanitize(ecmatcher.group(2).trim()));
|
||||
} else {
|
||||
this.logger.warn("A @throws for the {} bean and {} method is improperly formatted", beanModel.getBeanId(), methodElement);
|
||||
}
|
||||
} else {
|
||||
throwComments.put(matcher.group(1), this.sanitize(matcher.group(2).trim()));
|
||||
}
|
||||
}
|
||||
else this.logger.warn("A @throws for the {} bean and {} method is improperly formatted", beanModel.getBeanId(), methodElement);
|
||||
break;
|
||||
default:
|
||||
matcher = this.tagPattern.matcher(tag.toString());
|
||||
if (matcher.find())
|
||||
this.putAdd(sigModel.getTags(), tagName, matcher.group(1).trim());
|
||||
else this.logger.warn("A '@{}' tag for the {} bean and {} method is improperly formatted", tagName, beanModel.getBeanId(), methodElement);
|
||||
this.putAdd(sigModel.getTags(), tagName, this.sanitize(tagComment));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -221,21 +246,47 @@ class MarkdownWriter {
|
||||
ParamFreemarkerModel paramModel = new ParamFreemarkerModel();
|
||||
paramModel.setName(varElement.getSimpleName().toString());
|
||||
paramModel.setType(varElement.asType().toString());
|
||||
paramModel.setComment(paramComments.get(paramModel.getName()));
|
||||
paramModel.setComment(paramComments.remove(paramModel.getName()));
|
||||
|
||||
sigModel.getParams().put(paramModel.getName(), paramModel);
|
||||
methodSignature.append(varElement.getSimpleName()).append(": ").append(varElement.asType()).append(", ");
|
||||
}
|
||||
|
||||
if (!paramComments.isEmpty())
|
||||
this.logger.warn("The {} bean and {} method has documented parameters that don't exist; ignoring ...", beandoc.getBeanId(), methodElement);
|
||||
|
||||
for (TypeMirror thrownType : methodElement.getThrownTypes()) {
|
||||
this.logger.trace("Found thrown '{}' for method: {}.{}", thrownType, beandoc.getBeanId(), methodElement);
|
||||
|
||||
if ("org.activiti.engine.delegate.BpmnError".equals(thrownType.toString()) && !errorComments.isEmpty())
|
||||
continue;
|
||||
|
||||
ThrowFreemarkerModel throwModel = new ThrowFreemarkerModel();
|
||||
throwModel.setType(thrownType.toString());
|
||||
throwModel.setComment(throwComments.get(throwModel.getType()));
|
||||
throwModel.setComment(throwComments.remove(throwModel.getType()));
|
||||
|
||||
sigModel.getThrowTypes().put(throwModel.getType(), throwModel);
|
||||
}
|
||||
|
||||
for (Entry<String, String> throwComment : throwComments.entrySet()) {
|
||||
this.logger.trace("Found documented but not declared thrown '{}' for method: {}.{}", throwComment.getKey(), beandoc.getBeanId(), methodElement);
|
||||
|
||||
ThrowFreemarkerModel throwModel = new ThrowFreemarkerModel();
|
||||
throwModel.setType(throwComment.getKey());
|
||||
throwModel.setComment(throwComment.getValue());
|
||||
|
||||
sigModel.getThrowTypes().put(throwModel.getType(), throwModel);
|
||||
}
|
||||
|
||||
for (Entry<String, String> errorComment : errorComments.entrySet()) {
|
||||
this.logger.trace("Found BPMN error thrown code '{}' for method: {}.{}", errorComment.getKey(), beandoc.getBeanId(), methodElement);
|
||||
|
||||
ThrowFreemarkerModel errorModel = new ThrowFreemarkerModel();
|
||||
errorModel.setType(errorComment.getKey());
|
||||
errorModel.setComment(errorComment.getValue());
|
||||
|
||||
sigModel.getBpmnErrors().put(errorModel.getType(), errorModel);
|
||||
}
|
||||
|
||||
this.logger.trace("Found return '{}' for method: {}.{}", methodElement.getReturnType(), beandoc.getBeanId(), methodElement);
|
||||
if (!"void".equals(methodElement.getReturnType().toString()))
|
||||
@ -293,6 +344,16 @@ class MarkdownWriter {
|
||||
}
|
||||
}
|
||||
|
||||
private String sanitize(List<? extends DocTree> docs) {
|
||||
return this.sanitize(docs.toString());
|
||||
}
|
||||
|
||||
private String sanitize(String str) {
|
||||
for (Entry<Pattern, String> sanitize : this.sanitizations.entrySet())
|
||||
str = sanitize.getKey().matcher(str).replaceAll(sanitize.getValue());
|
||||
return str;
|
||||
}
|
||||
|
||||
private <T> T putAdd(Map<String, List<T>> map, String key, T value) {
|
||||
List<T> values = map.get(key);
|
||||
if (values == null)
|
||||
|
@ -28,6 +28,8 @@ public class MethodSignatureFreemarkerModel {
|
||||
|
||||
private Map<String, ThrowFreemarkerModel> throwTypes = new LinkedHashMap<>();
|
||||
|
||||
private Map<String, ThrowFreemarkerModel> bpmnErrors = new LinkedHashMap<>();
|
||||
|
||||
private String docFirstSentence;
|
||||
|
||||
private String docBody;
|
||||
@ -65,6 +67,14 @@ public class MethodSignatureFreemarkerModel {
|
||||
public void setThrowTypes(Map<String, ThrowFreemarkerModel> throwTypes) {
|
||||
this.throwTypes = throwTypes;
|
||||
}
|
||||
|
||||
public Map<String, ThrowFreemarkerModel> getBpmnErrors() {
|
||||
return bpmnErrors;
|
||||
}
|
||||
|
||||
public void setBpmnErrors(Map<String, ThrowFreemarkerModel> bpmnErrors) {
|
||||
this.bpmnErrors = bpmnErrors;
|
||||
}
|
||||
|
||||
public String getDocFirstSentence() {
|
||||
return docFirstSentence;
|
||||
|
@ -1,19 +1,22 @@
|
||||
|
||||
# ${title}<#if apiName??>: ${apiName}</#if>: `${beanId}`
|
||||
|
||||
<#if docBody??>${docBody}<#else>No documentation available.</#if>
|
||||
|
||||
<#if (tags.author?? || tags.since?? || tags.see?? || tags.deprecated??)>
|
||||
<#if (tags.author?? || tags.since?? || tags.deprecated??)>
|
||||
<#if tags.author??><#list tags.author as author>
|
||||
*Author*: ${author}
|
||||
</#list></#if>
|
||||
<#if tags.since??>*Since*: ${tags.since[0]}</#if>
|
||||
<#if tags.see??><#list tags.see as see>
|
||||
*See Also*: ${see}
|
||||
</#list></#if>
|
||||
<#if tags.deprecated??>*Deprecated*</#if>
|
||||
|
||||
</#if><#if (delegateRoles?size > 0)>
|
||||
</#if>
|
||||
<#if docBody??>${docBody}<#else>No documentation available.</#if>
|
||||
|
||||
<#if tags.see??><#list tags.see as see>
|
||||
*See Also*: ${see}
|
||||
</#list>
|
||||
|
||||
</#if>
|
||||
<#if (delegateRoles?size > 0)>
|
||||
## Delegate Uses
|
||||
|
||||
This bean may be used in the following entities and their fields in Activiti. In these cases, the value of the "Delegate Expression" field should be as shown in the snippet below.
|
||||
@ -48,38 +51,45 @@ This bean and its methods may be used in any "Expression" field or script in a S
|
||||
<#list method.signatures as sig>
|
||||
**`${beanId}.${sig.methodSignature}`**
|
||||
|
||||
<#if (sig.tags.author?? || sig.tags.since?? || sig.tags.deprecated??)>
|
||||
<#if sig.tags.author??><#list sig.tags.author as author>
|
||||
*Author*: ${author}
|
||||
</#list></#if>
|
||||
<#if sig.tags.since??>*Since*: ${sig.tags.since[0]}</#if>
|
||||
<#if sig.tags.deprecated??>*Deprecated*</#if>
|
||||
|
||||
</#if>
|
||||
<#if sig.docBody??>${sig.docBody}<#else>No documentation available.</#if>
|
||||
|
||||
<#if (sig.params?size > 0)>
|
||||
| Parameter Name | Java Type | Documentation |
|
||||
| ------------------------ | ------------------------------------------------ | ------------------------ |
|
||||
<#list sig.params as paramName, param>
|
||||
| ${("`" + paramName + "`")?right_pad(24)} | ${("`" + param.type + "`")?right_pad(48)} | <#if param.comment??>${param.comment?right_pad(24)}<#else>No documentation available.</#if> |
|
||||
| ${("`" + paramName + "`")?right_pad(24)} | ${("`" + param.type + "`")?right_pad(48)} | <#if (param.comment?? && param.comment?length > 0)>${param.comment?right_pad(24)}<#else>No documentation available.</#if> |
|
||||
</#list>
|
||||
|
||||
</#if>
|
||||
<#if (sig.returnType?? || sig.throwTypes?size > 0)>
|
||||
| Result Type | Java Type | Documentation |
|
||||
| Result Type | Java Type or BPMN Error Code | Documentation |
|
||||
| ------------------------ | ------------------------------------------------ | ------------------------ |
|
||||
<#if sig.returnType??>
|
||||
| Return Value | ${("`" + sig.returnType + "`")?right_pad(48)} | <#if sig.tags.return??>${sig.tags.return[0]?right_pad(24)}<#else>No documentation available.</#if> |
|
||||
| Return Value | ${("`" + sig.returnType + "`")?right_pad(48)} | <#if (sig.tags.return?? && sig.tags.return[0]?length > 0)>${sig.tags.return[0]?right_pad(24)}<#else>No documentation available.</#if> |
|
||||
</#if>
|
||||
<#if (sig.throwTypes?size > 0)>
|
||||
<#list sig.throwTypes as throwType, throw>
|
||||
| Thrown Exception | ${("`" + throwType + "`")?right_pad(48)} | <#if throw.comment??>${throw.comment?right_pad(24)}<#else>No documentation available.</#if> |
|
||||
| Thrown Exception | ${("`" + throwType + "`")?right_pad(48)} | <#if (throw.comment?? && throw.comment?length > 0)>${throw.comment?right_pad(24)}<#else>No documentation available.</#if> |
|
||||
</#list>
|
||||
</#if>
|
||||
<#if (sig.bpmnErrors?size > 0)>
|
||||
<#list sig.bpmnErrors as errorCode, bpmnError>
|
||||
| Thrown BPMN Error | ${("`" + errorCode + "`")?right_pad(48)} | <#if (bpmnError.comment?? && bpmnError.comment?length > 0)>${bpmnError.comment?right_pad(24)}<#else>No documentation available.</#if> |
|
||||
</#list>
|
||||
</#if>
|
||||
|
||||
</#if>
|
||||
<#if (sig.tags.author?? || sig.tags.since?? || sig.tags.see?? || sig.tags.deprecated??)>
|
||||
<#if sig.tags.author??><#list sig.tags.author as author>
|
||||
*Author*: ${author}
|
||||
</#list></#if>
|
||||
<#if sig.tags.since??>*Since*: ${sig.tags.since[0]}</#if>
|
||||
<#if sig.tags.see??><#list sig.tags.see as see>
|
||||
*See Also*: ${see}
|
||||
</#list></#if>
|
||||
<#if sig.tags.deprecated??>*Deprecated*</#if>
|
||||
</#list>
|
||||
|
||||
</#if>
|
||||
</#list>
|
||||
|
Loading…
x
Reference in New Issue
Block a user