shz.doc.DocHelp Maven / Gradle / Ivy
package shz.doc;
import com.sun.javadoc.*;
import com.sun.tools.javadoc.Main;
import org.slf4j.LoggerFactory;
import shz.core.NullHelp;
import shz.core.ToMap;
import shz.core.tools.compile.CompileHelp;
import java.io.File;
import java.lang.reflect.Method;
import java.util.*;
import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 用法: javadoc [options] [packagenames] [sourcefiles] [@files]
* -overview 从 HTML 文件读取概览文档
* -public 仅显示 public 类和成员
* -protected 显示 protected/public 类和成员 (默认值)
* -package 显示 package/protected/public 类和成员
* -private 显示所有类和成员
* -help 显示命令行选项并退出
* -doclet 通过替代 doclet 生成输出
* -docletpath 指定查找 doclet 类文件的位置
* -sourcepath 指定查找源文件的位置
* -classpath 指定查找用户类文件的位置
* -cp 指定查找用户类文件的位置
* -exclude 指定要排除的程序包列表
* -subpackages 指定要递归加载的子程序包
* -breakiterator 计算带有 BreakIterator 的第一个语句
* -bootclasspath 覆盖由引导类加载器所加载的
* 类文件的位置
* -source 提供与指定发行版的源兼容性
* -extdirs 覆盖所安装扩展的位置
* -verbose 输出有关 Javadoc 正在执行的操作的信息
* -locale 要使用的区域设置, 例如 en_US 或 en_US_WIN
* -encoding 源文件编码名称
* -quiet 不显示状态消息
* -J 直接将 传递到运行时系统
* -X 输出非标准选项的提要
*/
public final class DocHelp {
private static RootDoc rootDoc;
public static boolean start(RootDoc root) {
rootDoc = root;
return true;
}
public static boolean execute(Class> cls, boolean cp, Consumer consumer) {
File file = CompileHelp.findFile(cls);
if (file == null) return false;
List ps = new ArrayList<>();
ps.add("-doclet");
ps.add(DocHelp.class.getName());
ps.add("-encoding");
ps.add("utf-8");
if (cp) {
String lib = CompileHelp.libToCp(file);
if (lib != null) {
ps.add("-cp");
ps.add(lib);
}
}
ps.add(file.getAbsolutePath());
int execute = Main.execute(ps.toArray(new String[0]));
ClassDoc[] classes;
if (execute != 0 || rootDoc == null || NullHelp.isEmpty(classes = rootDoc.classes())) return false;
consumer.accept(classes);
return true;
}
public static boolean execute(Class> cls, boolean cp, Consumer cConsumer, Consumer mConsumer, Consumer fConsumer) {
return execute(cls, cp, classes -> {
for (ClassDoc classDoc : classes) {
if (cConsumer != null) cConsumer.accept(classDoc);
if (mConsumer != null) {
MethodDoc[] methods = classDoc.methods(false);
if (NullHelp.nonEmpty(methods)) for (MethodDoc methodDoc : methods) mConsumer.accept(methodDoc);
}
if (fConsumer != null) {
FieldDoc[] fields = classDoc.fields(false);
if (NullHelp.nonEmpty(fields)) for (FieldDoc fieldDoc : fields) fConsumer.accept(fieldDoc);
}
}
});
}
private static Map, DocDto> DOC_CACHE;
/**
* 不支持并发
*/
public static DocDto execute(Class> cls, boolean cp) {
if (DOC_CACHE == null) DOC_CACHE = new HashMap<>(128);
return DOC_CACHE.computeIfAbsent(cls, k -> {
DocDto docDto = new DocDto();
boolean execute = execute(
cls, cp,
classDoc -> docDto.classDoc = classDoc,
methodDoc -> docDto.methodDocs.put(key(methodDoc), methodDoc),
fieldDoc -> docDto.fieldDocs.put(fieldDoc.name(), fieldDoc)
);
return execute ? docDto : DocDto.NULL;
});
}
public static void clear() {
DOC_CACHE = null;
LoggerFactory.getLogger(DocHelp.class).info("构造 Javadoc 完成!");
}
private static String key(MethodDoc methodDoc) {
StringBuilder sb = new StringBuilder();
sb.append(methodDoc.name());
Parameter[] parameters = methodDoc.parameters();
if (NullHelp.nonEmpty(parameters)) for (Parameter parameter : parameters)
sb.append(":").append(parameter.name());
return sb.toString();
}
public static String key(Method method, String[] parameterNames) {
StringBuilder sb = new StringBuilder();
sb.append(method.getName());
if (NullHelp.nonEmpty(parameterNames)) for (String parameterName : parameterNames)
sb.append(":").append(parameterName);
return sb.toString();
}
public static Map getParams(MethodDoc methodDoc) {
if (methodDoc == null) return Collections.emptyMap();
String rawCommentText = methodDoc.getRawCommentText();
if (NullHelp.isBlank(rawCommentText)) return Collections.emptyMap();
Map result = ToMap.get().build();
Matcher matcher = Pattern.compile("(?<=@param)\\s*(\\w+)\\s*([^@]*)\\s*(?!@)").matcher(rawCommentText);
while (matcher.find()) {
String g2 = matcher.group(2);
if (g2 != null) result.put(matcher.group(1), g2.trim());
}
return result.isEmpty() ? Collections.emptyMap() : result;
}
public static String getReturn(MethodDoc methodDoc) {
if (methodDoc == null) return null;
String rawCommentText = methodDoc.getRawCommentText();
if (NullHelp.isBlank(rawCommentText)) return null;
Matcher matcher = Pattern.compile("(?<=@return)\\s*([^@]*)\\s*").matcher(rawCommentText);
if (matcher.find()) {
String g1 = matcher.group(1);
if (g1 != null) return g1.trim();
}
return null;
}
}