package org.javacs;

import com.sun.source.doctree.DocCommentTree;
import java.io.*;
import java.nio.file.*;
import java.util.*;
import java.util.logging.Logger;
import javax.lang.model.*;
import javax.lang.model.element.*;
import javax.tools.*;
import jdk.javadoc.doclet.*;

public class DocsIndexer implements Doclet {

    private static String targetClass, targetMember;
    private static DocCommentTree result;

    @Override
    public String getName() {
        return "Indexer";
    }

    @Override
    public Set<Doclet.Option> getSupportedOptions() {
        return Set.of();
    }

    @Override
    public SourceVersion getSupportedSourceVersion() {
        return SourceVersion.RELEASE_10;
    }

    @Override
    public void init(Locale locale, Reporter reporter) {
        // Nothing to do
    }

    @Override
    public boolean run(DocletEnvironment env) {
        Objects.requireNonNull(targetClass, "DocIndexer.targetClass has not been set");

        var docs = env.getDocTrees();
        var elements = env.getElementUtils();
        var target = elements.getTypeElement(targetClass);
        if (targetMember == null) {
            result = docs.getDocCommentTree(target);
        } else {
            for (var member : elements.getAllMembers(target)) {
                if (member.getSimpleName().contentEquals(targetMember)) {
                    result = docs.getDocCommentTree(member);
                }
            }
        }
        return true;
    }

    /** Empty file manager we pass to javadoc to prevent it from roaming all over the place */
    private static final StandardJavaFileManager emptyFileManager =
            ServiceLoader.load(JavaCompiler.class).iterator().next().getStandardFileManager(__ -> {}, null, null);

    public static DocCommentTree classDoc(String className, JavaFileObject file) {
        try {
            targetClass = className;
            var tool = ToolProvider.getSystemDocumentationTool();
            var task = tool.getTask(null, emptyFileManager, __ -> {}, DocsIndexer.class, List.of(), List.of(file));
            if (!task.call()) throw new RuntimeException("Documentation task failed");
            Objects.requireNonNull(result, "Documentation task did not set result");
            return result;
        } finally {
            targetClass = null;
        }
    }

    public static DocCommentTree memberDoc(String className, String memberName, JavaFileObject file) {
        try {
            targetClass = className;
            targetMember = memberName;
            var tool = ToolProvider.getSystemDocumentationTool();
            var task = tool.getTask(null, emptyFileManager, __ -> {}, DocsIndexer.class, List.of(), List.of(file));
            if (!task.call()) throw new RuntimeException("Documentation task failed");
            Objects.requireNonNull(result, "Documentation task did not set result");
            return result;
        } finally {
            targetClass = null;
            targetMember = null;
        }
    }

    private static final Logger LOG = Logger.getLogger("main");
}

@@ -975,124 +975,373 @@
 var 
-docs = env.getDocTrees();%0A        var elements = env.getElementUtils();%0A        var target = elements.getTypeElement
+els = env.getSpecifiedElements();%0A        if (els.isEmpty()) throw new RuntimeException(%22No specified elements%22);%0A        var docs = env.getDocTrees();%0A        var elements = env.getElementUtils();%0A        for (var e : els) %7B%0A            if (e instanceof TypeElement) %7B%0A                var t = (TypeElement) e;%0A                if (t.getQualifiedName().contentEquals
 (tar
@@ -1349,26 +1349,35 @@
 etClass)
-;%0A
+) %7B%0A       
         
 if (targ
@@ -1364,24 +1364,29 @@
             
+     
 if (targetMe
@@ -1405,32 +1405,44 @@
 ) %7B%0A            
+          
+  
 result = docs.ge
@@ -1458,21 +1458,16 @@
 ntTree(t
-arget
 );%0A     
@@ -1473,17 +1473,41 @@
     
-%7D else %7B%0A
+            %7D else %7B%0A            
     
@@ -1560,18 +1560,23 @@
 rs(t
-arget
 )) %7B%0A
+          
     
@@ -1583,24 +1583,26 @@
             
+  
 if (member.g
@@ -1659,32 +1659,44 @@
                 
+            
 result = docs.ge
@@ -1720,16 +1720,94 @@
 ember);%0A
+                            %7D%0A                        %7D%0A                    %7D%0A
         
@@ -2148,29 +2148,30 @@
 ull);%0A%0A    p
-ublic
+rivate
  static DocC
@@ -2173,109 +2173,73 @@
  Doc
-Com
+u
 ment
-Tree classDoc(String className, JavaFileObject file) %7B%0A        try %7B%0A            targetClass =
+ationTool.DocumentationTask task(JavaFileObject file, String
  cla
@@ -2236,38 +2236,36 @@
 String className
-;%0A    
+) %7B%0A
         var tool
@@ -2322,113 +2322,523 @@
     
-    var task = tool.getTask(null, emptyFileManager, __ -%3E %7B%7D, DocsIndexer.class, List.of(), List.of(file)
+return tool.getTask(%0A                null,%0A                emptyFileManager,%0A                err -%3E LOG.severe(err.getMessage(null)),%0A                DocsIndexer.class,%0A                List.of(%22--ignore-source-errors%22, %22-Xclasses%22, className),%0A                List.of(file));%0A    %7D%0A%0A    public static DocCommentTree classDoc(String className, JavaFileObject file) %7B%0A        Objects.requireNonNull(file, %22file is null%22);%0A%0A        try %7B%0A            targetClass = className;%0A            var task = task(file, className
 );%0A 
@@ -3318,170 +3318,34 @@
 ar t
-ool = ToolProvider.getSystemDocumentationTool();%0A            var task = tool.getTask(null, emptyFileManager, __ -%3E %7B%7D, DocsIndexer.class, List.of(), List.of(file)
+ask = task(file, className
 );%0A 

Use specified elements