/** This code was compiled with Claude Sonnet 4.6
 *  It is meant to show the internal AST for Java source code
 */

import com.sun.source.tree.*;
import com.sun.source.util.*;
import javax.tools.*;
import java.util.*;
import java.io.*;

/**
 * ASTDumper prints the Abstract Syntax Tree (AST) of a Java source file
 * to standard output using the Java Compiler API.
 *
 * <p>Each node in the tree is printed with its {@link Tree.Kind} and a
 * short string representation of the node if it is sufficiently concise.
 * Nodes are indented according to their depth in the tree, giving a
 * visual representation of the parse structure.</p>
 *
 * <p>Usage:</p>
 * <pre>
 *   javac ASTDumper.java
 *   java ASTDumper /path/to/Source.java
 * </pre>
 *
 * <p>Note: This class uses internal {@code com.sun.source} APIs which are
 * part of the JDK but not guaranteed to be stable across versions.</p>
 */
public class ASTDumper {

    /**
     * Entry point for the AST dumper. Parses {@code Expr.java} in the
     * current directory and prints its full AST to standard output.
     *
     * <p>Each line of output represents one AST node and is formatted as:</p>
     * <pre>
     *   [indent] KIND: source_text
     * </pre>
     * <p>where {@code indent} reflects the node's depth in the tree,
     * {@code KIND} is the {@link Tree.Kind} of the node, and
     * {@code source_text} is the node's string representation if it is
     * fewer than 40 characters.</p>
     *
     * @param args command-line arguments (not used)
     * @throws Exception if the source file cannot be found, read, or parsed
     */
    public static void main(String[] args) throws Exception {
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null);
        Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(args[0]);
        JavacTask task = (JavacTask) compiler.getTask(null, fm, null, null, null, files);
        Iterable<? extends CompilationUnitTree> units = task.parse();

        for (CompilationUnitTree unit : units) {
            new TreeScanner<Void, Integer>() {
                @Override
                public Void scan(Tree node, Integer depth) {
                    if (node != null) {
                        System.out.println("  ".repeat(depth) + node.getKind() +
                            (node.toString().length() < 40 ? ": " + node : ""));
                    }
                    return super.scan(node, depth + 1);
                }
            }.scan(unit, 0);
        }
    }
}
