diff --git a/.gitignore b/.gitignore index 9be140e..9f2010b 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ /jdtls-build .env* +/tags /third-party/downloads/* /third-party/**/*.jar diff --git a/src/main/java/xyz/naofal/jtags/JtagsLogger.java b/src/main/java/xyz/naofal/jtags/JtagsLogger.java index 7ab4bd3..057acd5 100644 --- a/src/main/java/xyz/naofal/jtags/JtagsLogger.java +++ b/src/main/java/xyz/naofal/jtags/JtagsLogger.java @@ -46,14 +46,14 @@ public class JtagsLogger { @Override public void publish(LogRecord record) { if (record.getMessage() != null && !record.getMessage().isEmpty()) { - // if (System.console().isTerminal()) { - int color = colors.get(record.getLevel()); - System.err.printf( - "\u001b[38;5;%dm[%s]\u001b[0m %s%n", - color, record.getLevel().getName(), record.getMessage()); - // } else { - // System.err.printf("[%s] %s%n", record.getLevel().getName(), record.getMessage()); - // } + if (System.console().isTerminal()) { + int color = colors.get(record.getLevel()); + System.err.printf( + "\u001b[38;5;%dm[%s]\u001b[0m %s%n", + color, record.getLevel().getName(), record.getMessage()); + } else { + System.err.printf("[%s] %s%n", record.getLevel().getName(), record.getMessage()); + } } if (record.getThrown() != null) { System.err.println(record.getThrown().toString().indent(4)); diff --git a/src/main/java/xyz/naofal/jtags/TagCollector.java b/src/main/java/xyz/naofal/jtags/TagCollector.java index af342b9..aef11d5 100644 --- a/src/main/java/xyz/naofal/jtags/TagCollector.java +++ b/src/main/java/xyz/naofal/jtags/TagCollector.java @@ -28,7 +28,7 @@ public class TagCollector { TreeVisitorContext context = new TreeVisitorContext(Trees.instance(task)); TreeVisitor treeVisitor = new TreeVisitor(); for (CompilationUnitTree compilationUnitTree : trees) { - compilationUnitTree.accept(treeVisitor, context); + treeVisitor.scan(compilationUnitTree, context); } } catch (IOException ex) { diff --git a/src/main/java/xyz/naofal/jtags/TagKind.java b/src/main/java/xyz/naofal/jtags/TagKind.java index b2aa63c..86d62c9 100644 --- a/src/main/java/xyz/naofal/jtags/TagKind.java +++ b/src/main/java/xyz/naofal/jtags/TagKind.java @@ -3,6 +3,7 @@ package xyz.naofal.jtags; public enum TagKind { PACKAGE, CLASS, + RECORD, INTERFACE, ANNOTATION, ENUM, diff --git a/src/main/java/xyz/naofal/jtags/TreeVisitor.java b/src/main/java/xyz/naofal/jtags/TreeVisitor.java index 9f121b5..2e9e8dd 100644 --- a/src/main/java/xyz/naofal/jtags/TreeVisitor.java +++ b/src/main/java/xyz/naofal/jtags/TreeVisitor.java @@ -6,26 +6,23 @@ import com.sun.source.tree.ClassTree; import com.sun.source.tree.CompilationUnitTree; import com.sun.source.tree.MethodTree; import com.sun.source.tree.PackageTree; -import com.sun.source.util.SimpleTreeVisitor; +import com.sun.source.tree.Tree; +import com.sun.source.tree.VariableTree; +import com.sun.source.util.TreePathScanner; +import java.util.List; import java.util.PriorityQueue; +import javax.lang.model.element.Modifier; -public class TreeVisitor extends SimpleTreeVisitor { +public class TreeVisitor extends TreePathScanner { public PriorityQueue tags = new PriorityQueue<>(); @Override public Void visitCompilationUnit(CompilationUnitTree node, TreeVisitorContext p) { p.compilationUnitTree = node; - logger.finer("Collecting tags in file: " + p.getLocation()); + logger.fine(() -> "Collecting tags in file: " + p.getLocation()); - PackageTree packageTree = node.getPackage(); - if (packageTree != null) { - packageTree.accept(this, p); - } - - node.getTypeDecls().forEach(it -> it.accept(this, p)); - - return null; + return super.visitCompilationUnit(node, p); } @Override @@ -47,6 +44,7 @@ public class TreeVisitor extends SimpleTreeVisitor { new Tag( switch (node.getKind()) { case CLASS -> TagKind.CLASS; + case RECORD -> TagKind.RECORD; case INTERFACE -> TagKind.INTERFACE; case ENUM -> TagKind.ENUM; case ANNOTATION_TYPE -> TagKind.ANNOTATION; @@ -63,16 +61,40 @@ public class TreeVisitor extends SimpleTreeVisitor { tags.add(tag); - node.getMembers().forEach(it -> it.accept(this, p)); - - return null; + return super.visitClass(node, p); } @Override public Void visitMethod(MethodTree node, TreeVisitorContext p) { Tag tag = new Tag(TagKind.METHOD, node.getName().toString(), p.getLocation(), p.getLine(node)); - logger.fine(() -> "Method: " + tag); + logger.finer(() -> "Method: " + tag); tags.add(tag); + + return super.visitMethod(node, p); + } + + @Override + public Void visitVariable(VariableTree node, TreeVisitorContext p) { + Tree parent = getCurrentPath().getParentPath().getLeaf(); + + if (!(parent instanceof ClassTree enclosingType)) { + return null; + } + + Tag tag = + new Tag( + enclosingType.getKind() == Tree.Kind.ENUM + && node.getModifiers() + .getFlags() + .containsAll(List.of(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)) + ? TagKind.ENUM_CONSTANT + : TagKind.FIELD, + node.getName().toString(), + p.getLocation(), + p.getLine(node)); + logger.finer(() -> "Variable: " + tag); + tags.add(tag); + return null; } } diff --git a/src/main/java/xyz/naofal/jtags/TreeVisitorContext.java b/src/main/java/xyz/naofal/jtags/TreeVisitorContext.java index 82e5473..ae56a17 100644 --- a/src/main/java/xyz/naofal/jtags/TreeVisitorContext.java +++ b/src/main/java/xyz/naofal/jtags/TreeVisitorContext.java @@ -2,17 +2,18 @@ package xyz.naofal.jtags; import static xyz.naofal.jtags.JtagsLogger.logger; +import com.sun.source.tree.ClassTree; import com.sun.source.tree.CompilationUnitTree; +import com.sun.source.tree.MethodTree; +import com.sun.source.tree.ModifiersTree; import com.sun.source.tree.Tree; import com.sun.source.util.SourcePositions; import com.sun.source.util.Trees; import java.io.BufferedReader; -import java.io.IOException; import java.nio.file.Paths; +import java.util.Optional; public class TreeVisitorContext { - private static final int MAX_LINE_LENGTH = 4096; - final Trees trees; final SourcePositions sourcePositions; public CompilationUnitTree compilationUnitTree; @@ -31,27 +32,42 @@ public class TreeVisitorContext { } public String getLine(Tree node) { - assert compilationUnitTree != null; - long offset = sourcePositions.getStartPosition(compilationUnitTree, node); + long offset = getOffsetInSource(compilationUnitTree, node); try (var reader = new BufferedReader(compilationUnitTree.getSourceFile().openReader(true))) { long skipped = 0; - while (skipped <= offset) { - reader.mark(MAX_LINE_LENGTH); + while (true) { String line = reader.readLine(); - if (line == null) break; - int lineLength = line.length(); - if (lineLength >= MAX_LINE_LENGTH) { - logger.severe("Line length exceeded"); - System.exit(1); - } - skipped += lineLength + 1; + if (line == null) throw new RuntimeException("Reached the end of the stream"); + skipped += line.length() + 1; + if (skipped >= offset) return line; } - reader.reset(); - return reader.readLine(); - } catch (IOException e) { + } catch (Exception e) { logger.severe(e.toString()); + logger.finer("Node that caused the exception:\n" + node.toString().indent(4)); System.exit(1); return null; } } + + private long getOffsetInSource(CompilationUnitTree compilationUnitTree, Tree node) { + assert compilationUnitTree != null; + return switch (node) { + case ClassTree t -> { + ModifiersTree modifiers = t.getModifiers(); + if (modifiers == null + || (modifiers.getAnnotations().isEmpty() && modifiers.getFlags().isEmpty())) { + yield sourcePositions.getStartPosition(compilationUnitTree, t); + } else { + yield sourcePositions.getEndPosition(compilationUnitTree, t.getModifiers()); + } + } + case MethodTree t -> + sourcePositions.getEndPosition( + compilationUnitTree, + Optional.ofNullable(t.getReturnType()) + .or(() -> Optional.ofNullable(t.getModifiers())) + .orElse(t)); + default -> sourcePositions.getStartPosition(compilationUnitTree, node); + }; + } } diff --git a/src/main/java/xyz/naofal/jtags/example/Example.java b/src/main/java/xyz/naofal/jtags/example/Example.java index 3d724d1..78a4390 100644 --- a/src/main/java/xyz/naofal/jtags/example/Example.java +++ b/src/main/java/xyz/naofal/jtags/example/Example.java @@ -1,11 +1,21 @@ package xyz.naofal.jtags.example; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; +@interface T { + static int t = 1; +} -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.METHOD) -public @interface Example {} -// +public class Example { + + public static void lorem( + String string1, + String string2, + String string3, + String string4, + String string5, + String string6) {} + + enum T { + A; + int a; + } +}