All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.thevpc.commons.md.doc.MdDoclet Maven / Gradle / Ivy

There is a newer version: 1.2.0
Show newest version
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package net.thevpc.commons.md.doc;

//import com.sun.javadoc.ClassDoc;
//import com.sun.javadoc.ConstructorDoc;
//import com.sun.javadoc.Doclet;
//import com.sun.javadoc.ExecutableMemberDoc;
//import com.sun.javadoc.FieldDoc;
//import com.sun.javadoc.MethodDoc;
//import com.sun.javadoc.ParamTag;
//import com.sun.javadoc.Parameter;
//import com.sun.javadoc.RootDoc;
//import com.sun.javadoc.Type;

import net.thevpc.commons.md.MdElement;
import net.thevpc.commons.md.MdFactory;
import net.thevpc.commons.md.MdWriter;
import net.thevpc.commons.md.doc.java.JPRootDoc;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Paths;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;

/**
 * @author vpc
 */
public class MdDoclet /*extends Doclet*/ {

    private static String _GLASSES_ICON = "\uD83D\uDC53";
    private static String _BEETLE_ICON = "\uD83D\uDC1E";
    private static String _CAFE_ICON = "\u2615";
    private static String _DRUM_ICON = "\uD83E\uDD41";
    private static String _PENSIL_ICON = "\u270F";
    private static String _PENSIL2_ICON = "\uD83D\uDD8A";
    private static String _CONTROLS_ICON = "\uD83C\uDF9B";
    private static String _ICECUBE_ICON = "\u2744";
    private static String _PAGE_ICON = "\uD83D\uDCC4";
    private static String _MEMO_ICON = "\uD83D\uDCDD";
    private static String _LOUDSPEAKER_ICON = "\uD83D\uDCE2";

    private static String BUG_ICON = _BEETLE_ICON;
    private static String STATIC_ICON = _LOUDSPEAKER_ICON;
    private static String READONLY_ICON = _PAGE_ICON;
    private static String READWRITE_ICON = _MEMO_ICON;
    private static String WRITEONLY_ICON = _PENSIL_ICON;

    private static String CLASS_ICON = _CAFE_ICON;
    private static String CONSTRUCTOR_ICON = "\uD83E\uDE84";
    private static String METHOD_ICON = "\u2699";
    private static String FIELD_ICON = "\uD83D\uDDD2";
    private static String PROPERTY_ICON = _CONTROLS_ICON;
    private static String STATIC_PROPERTY_ICON = STATIC_ICON + PROPERTY_ICON;
    private static String CONST_ICON = STATIC_ICON + _ICECUBE_ICON;
    private static String STATIC_FIELD_ICON = STATIC_ICON + FIELD_ICON;
    private static String STATIC_METHOD_ICON = STATIC_ICON + METHOD_ICON;
    private static String READ_ICON = _GLASSES_ICON;
    private static String WRITE_ICON = _PENSIL_ICON;

    //    private static String PROPERTY_ICON = "\uD83D\uDC41";
//    private static String STATIC_METHOD_ICON = "\uD83D\uDD27";
//    private static String STATIC_PROPERTY_ICON = "\uD83D\uDC40";
//    private static String STATIC_FIELD_ICON = "\uD83C\uDF8A";
//    private static String STATIC_METHOD_ICON = "\uD83E\uDDF2";
//    private static String CONST_ICON = "\uD83E\uDDCA";
//    public static void main(String[] args) {
//        System.out.println("Hello");
////        com.sun.tools.javadoc.Main.main(new String[]{
////            "-doclet", "net.thevpc.common.docusaurusdoclet.MdDoclet",
//////            "-docletpath", "/data/public/git/docusaurus-docklet/target/docusaurus-docklet-0.1.jar:/usr/java/jdk1.8.0_211-amd64/lib/tools.jar",
////            "-sourcepath","/data/public/git/nuts/nuts/src/main/java",
////            "net.thevpc.nuts"
////        });
//    }
    public static String getCategory(JDClassDoc c) {
        JDDoc jd = c.comments();
        if (jd != null) {
            String t = jd.getTag("category");
            if (t != null) {
                t = t.trim();
                if (!t.isEmpty()) {
                    return t;
                }
            }
        }
        return "Other";
    }

    public boolean start(MdDocletConfig config) {
        JPRootDoc root = new JPRootDoc();
        String[] packages = config.getPackages();
        Predicate packageFilter=packages.length==0?(x->true):x->{
            for (String p : packages) {
                if(p.equals("*")){
                    return true;
                }
                if(p.equals(".*")){
                    String sp = p.substring(0, p.length() - 2);
                    return x.equals(sp) || x.startsWith(sp+".");
                }
                if(p.equals(".**")){
                    String sp = p.substring(0, p.length() - 3);
                    return x.equals(sp) || x.startsWith(sp+".");
                }
                return x.equals(p);
            }
            return false;
        };
        for (String s : config.getSources()) {
            root.parseSrcFolder(Paths.get(s),packageFilter);
        }

        JDClassDoc[] classes = root.classes();
        Arrays.sort(classes, new Comparator() {
            @Override
            public int compare(JDClassDoc o1, JDClassDoc o2) {
                return o1.qualifiedName().compareTo(o2.qualifiedName());
            }
        });
        Map> categories = new HashMap<>();
        for (int i = 0; i < classes.length; ++i) {
            String c = getCategory(classes[i]);
            List li = (List) categories.computeIfAbsent(c, new Function>() {
                @Override
                public List apply(String t) {
                    return new ArrayList();
                }
            });
            li.add(classes[i]);
        }
        for (Map.Entry> entry : categories.entrySet()) {
            String name = entry.getKey();
            String id = "javadoc_" + name.replace(' ', '_');
            File file = new File(config.getTarget(), entry.getKey() + ".md");
            try {
                System.out.println("generating " + file.getCanonicalPath());
            } catch (IOException ex) {
                throw new UncheckedIOException(ex);
            }
            try (MdWriter out = MdFactory.createWriter(config.getBackend(), new FileWriter(file))) {
                out.setHeader("id", id);
                out.setHeader("title", name);
                for (JDClassDoc classDoc : entry.getValue()) {
                    out.write(printClass(classDoc));
                }
            } catch (IOException ex) {
                throw new UncheckedIOException(ex);
            }
        }
        return true;
    }

    static MdElement printClass(JDClassDoc cls) {
        ToClassDoc tcd = new ToClassDoc(cls);
        List seq = new ArrayList<>();
        seq.add(MdFactory.title(2, CLASS_ICON + " " + tcd.getCls().name()));
        seq.add(MdFactory.code("java", tcd.getCls().modifiers() + " " + tcd.getCls().qualifiedName()));
        if (tcd.getCls().comments() != null) {
            seq.add(tcd.getCls().comments().getDescription());
        }
        if (tcd.getConsts().length > 0) {

            seq.add(MdFactory.title(3, CONST_ICON + " Constant Fields"));
            seq.add(printFields(tcd.getConsts()));
        }

        if (tcd.getStaticFields().length > 0) {
            seq.add(MdFactory.title(3, STATIC_FIELD_ICON + " Static Fields"));
            printFields(tcd.getStaticFields());
        }

        if (tcd.getStaticProperties().length > 0) {
            seq.add(MdFactory.title(3, STATIC_PROPERTY_ICON + " Static Properties"));
            seq.add(printProperties(tcd.getStaticProperties()));
        }

        if (tcd.getStaticMethods().length > 0) {
            seq.add(MdFactory.title(3, STATIC_METHOD_ICON + " Static Methods"));
            seq.add(printMembers(tcd.getStaticMethods()));
        }

        if (tcd.getInstanceFields().length > 0) {
            seq.add(MdFactory.title(3, FIELD_ICON + " Instance Fields"));
            seq.add(printFields(tcd.getInstanceFields()));
        }

        if (tcd.getConstructors().length > 0) {
            seq.add(MdFactory.title(3, CONSTRUCTOR_ICON + " Constructors"));
            seq.add(printMembers(tcd.getConstructors()));
        }

        if (tcd.getInstanceProperties().length > 0) {
            seq.add(MdFactory.title(3, PROPERTY_ICON + " Instance Properties"));
            seq.add(printProperties(tcd.getInstanceProperties()));
        }

        if (tcd.getInstanceMethods().length > 0) {
            seq.add(MdFactory.title(3, METHOD_ICON + " Instance Methods"));
            seq.add(printMembers(tcd.getInstanceMethods()));
        }
        return MdFactory.seq(seq);
    }

    static MdElement printFields(JDFieldDoc[] mems) {
        Arrays.sort(mems, new Comparator() {
            @Override
            public int compare(JDFieldDoc o1, JDFieldDoc o2) {
                return o1.qualifiedName().compareTo(o2.qualifiedName());
            }
        });
        List ss = new ArrayList<>();
        for (int i = 0; i < mems.length; ++i) {
            JDFieldDoc mem = mems[i];
            ss.add(printField(mem));
        }
        return MdFactory.seq(ss);
    }

    static MdElement printProperties(PropertyDoc[] mems) {
        List ss = new ArrayList<>();
        for (int i = 0; i < mems.length; ++i) {
            PropertyDoc mem = mems[i];
            ss.add(printProperty(mem));
        }
        return MdFactory.seq(ss);
    }

    static MdElement printMembers(JDExecutableMemberDoc[] mems) {
        Arrays.sort(mems, new Comparator() {
            @Override
            public int compare(JDExecutableMemberDoc o1, JDExecutableMemberDoc o2) {
                return o1.qualifiedName().compareTo(o2.qualifiedName());
            }
        });
        List seq = new ArrayList<>();
        for (int i = 0; i < mems.length; ++i) {
            JDExecutableMemberDoc mem = mems[i];
            seq.add(printMember(mem));
        }
        return MdFactory.seq(seq);
    }

    static MdElement printMember(JDExecutableMemberDoc mem) {
        String icon = null;
        if (mem instanceof JDConstructorDoc) {
            icon = CONSTRUCTOR_ICON;
        } else {
            JDMethodDoc md = (JDMethodDoc) mem;
            if (md.isStatic()) {
                icon = STATIC_METHOD_ICON;
            } else {
                icon = METHOD_ICON;
            }
        }
        JDType returnType = null;
        if (mem instanceof JDMethodDoc) {
            JDMethodDoc dd = (JDMethodDoc) mem;
            returnType = dd.returnType();
        }
        List seq = new ArrayList<>();
        seq.add(MdFactory.title(4, icon + " " + sig(mem)));
        if (mem.commentText() != null) {
            seq.add(mem.commentText().getDescription());
        }
        seq.add(MdFactory.br());
        seq.add(MdFactory.code("java", sig(mem, true, true)));

        JDParameter[] params = mem.parameters();
        for (JDParameter param : params) {
            seq.add(MdFactory.ul(1, MdFactory.seqInline(
                    MdFactory.bold(
                            MdFactory.text(stype(param.type()) + " " + param.name())
                    ),
                    MdFactory.text(" : " + (param.getJavadocContent() == null ? "" : param.getJavadocContent()))
                    ))
            );
        }
        return MdFactory.seq(seq);
    }

    private static String resolveComment(String paramName, JDParamTag[] tags) {
        for (JDParamTag tag : tags) {
            if (tag.parameterName().equals(paramName)) {
                return tag.parameterComment();
            }
        }
        return "";
    }

    static MdElement printField(JDFieldDoc mem) {
        String e = mem.constantValueExpression();
        String icon = FIELD_ICON;
        if (mem.isStatic()) {
            if (mem.isFinal()) {
                icon = CONST_ICON;
            } else {
                icon = STATIC_FIELD_ICON;
            }
        }
        return MdFactory.seq(
                MdFactory.title(4, icon + " " + mem.name()),
                MdFactory.code("java", mem.modifiers() + " " + stype(mem.type()) + " " + mem.name() + (mem.constantValueExpression() == null ? "" : (" = " + mem.constantValueExpression())))
        );
    }

    static MdElement printProperty(PropertyDoc mem) {
        String icon = PROPERTY_ICON;
        if (mem.isStatic()) {
            icon = STATIC_PROPERTY_ICON;
        }
        if (mem.isRW()) {
            icon = READWRITE_ICON + icon;
        } else if (mem.isRO()) {
            icon = READONLY_ICON + icon;
        } else if (mem.isWO()) {
            icon = WRITEONLY_ICON + icon;
        }
        List seq = new ArrayList<>();
        seq.add(MdFactory.title(4, icon + " " + mem.name));
        if (mem.commentText() != null) {
            seq.add(mem.commentText().getDescription());
        }
        StringBuilder code = new StringBuilder();
        if (mem.isRW()) {
            code.append("[read-write] " + stype(mem.type()) + " " + mem.setter.modifiers() + " " + mem.name).append("\n");
            if (mem.field != null) {
                code.append(mem.field.modifiers() + " " + stype(mem.field.type()) + " " + mem.field.name() + (mem.field.constantValueExpression() == null ? "" : (" = " + mem.field.constantValueExpression()))).append("\n");
            }
            if (mem.getter != null) {
                code.append(mem.getter.modifiers() + " " + sig2(mem.getter)).append("\n");
            }
            if (mem.setter != null) {
                code.append(mem.setter.modifiers() + " " + sig2(mem.setter)).append("\n");
            }

        } else if (mem.isWO()) {
            code.append("[write-only] " + stype(mem.type()) + " " + mem.setter.modifiers() + " " + mem.name).append("\n");
            if (mem.field != null) {
                code.append(mem.field.modifiers() + " " + stype(mem.field.type()) + " " + mem.field.name() + (mem.field.constantValueExpression() == null ? "" : (" = " + mem.field.constantValueExpression()))).append("\n");
            }
            if (mem.getter != null) {
                code.append(mem.getter.modifiers() + " " + sig2(mem.getter)).append("\n");
            }
            if (mem.setter != null) {
                code.append(mem.setter.modifiers() + " " + sig2(mem.setter)).append("\n");
            }

        } else if (mem.isRO()) {
            code.append("[read-only] " + mem.getter.modifiers() + " " + stype(mem.type()) + " " + mem.name).append("\n");
            if (mem.field != null) {
                code.append(mem.field.modifiers() + " " + stype(mem.field.type()) + " " + mem.field.name() + (mem.field.constantValueExpression() == null ? "" : (" = " + mem.field.constantValueExpression()))).append("\n");
            }
            if (mem.getter != null) {
                code.append(mem.getter.modifiers() + " " + sig2(mem.getter)).append("\n");
            }
            if (mem.setter != null) {
                code.append(mem.setter.modifiers() + " " + sig2(mem.setter)).append("\n");
            }

        } else {
            throw new IllegalArgumentException("Should never happen");
        }
        seq.add(MdFactory.code("java", code.toString()));
        return MdFactory.seq(seq);
    }

    static String stype(JDType mem) {
        if (mem == null) {
            return "?";
        }
        if (mem.isPrimitive()) {
            return mem.toString();
        }
        String tn = mem.toString();
        if (tn.indexOf('.') > 0) {
            if (tn.indexOf('<') < 0) {
                return escape(tn.substring(tn.lastIndexOf('.') + 1));
            }
        }
        return escape(mem.toString());
    }

    static String sig2(JDExecutableMemberDoc mem) {
        String s = sig(mem);
        if (mem instanceof JDMethodDoc) {
            JDMethodDoc md = (JDMethodDoc) mem;
            if (md.returnType() != null) {
                return stype(md.returnType()) + " " + s;
            }
            return stype(md.returnType()) + " " + s;
        }
        return s;
    }

    static String sig(JDExecutableMemberDoc mem) {
        StringBuilder sb = new StringBuilder();
        sb.append(mem.name());
        sb.append("(");
        for (int i = 0; i < mem.parameters().length; i++) {
            JDParameter parameter = mem.parameters()[i];
            if (i > 0) {
                sb.append(", ");
            }
            sb.append(parameter.name());
        }
        sb.append(")");
        return sb.toString();
    }

    static String sig(JDExecutableMemberDoc mem, boolean includeReturn, boolean includeTypes) {
        StringBuilder sb = new StringBuilder();
        if (includeReturn) {
            if (mem instanceof JDMethodDoc) {
                JDMethodDoc md = (JDMethodDoc) mem;
                if (md.returnType() != null) {
                    sb.append(stype(md.returnType()));
                    sb.append(" ");
                }
            }
        }
        sb.append(mem.name());
        sb.append("(");
        for (int i = 0; i < mem.parameters().length; i++) {
            JDParameter parameter = mem.parameters()[i];
            if (i > 0) {
                sb.append(", ");
            }
            if (includeTypes) {
                sb.append(stype(parameter.type()));
                sb.append(" ");
            }
            sb.append(parameter.name());
        }
        sb.append(")");
        return sb.toString();
    }

    static String escape(String s) {
        if (s == null) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        for (char c : s.toCharArray()) {
            switch (c) {
                case '<':
                case '>':
                case '\'':
                case '{':
                case '}':
                case '@':
                case '\\': {
                    sb.append('\\').append(c);
                    break;
                }
                default: {
                    sb.append(c);
                }
            }
        }
        return sb.toString();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy