Collect variable tags and improve line collection
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -5,6 +5,7 @@
|
||||
/jdtls-build
|
||||
|
||||
.env*
|
||||
/tags
|
||||
|
||||
/third-party/downloads/*
|
||||
/third-party/**/*.jar
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -3,6 +3,7 @@ package xyz.naofal.jtags;
|
||||
public enum TagKind {
|
||||
PACKAGE,
|
||||
CLASS,
|
||||
RECORD,
|
||||
INTERFACE,
|
||||
ANNOTATION,
|
||||
ENUM,
|
||||
|
||||
@@ -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<Void, TreeVisitorContext> {
|
||||
public class TreeVisitor extends TreePathScanner<Void, TreeVisitorContext> {
|
||||
public PriorityQueue<Tag> 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<Void, TreeVisitorContext> {
|
||||
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<Void, TreeVisitorContext> {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.<Tree>ofNullable(t.getReturnType())
|
||||
.or(() -> Optional.ofNullable(t.getModifiers()))
|
||||
.orElse(t));
|
||||
default -> sourcePositions.getStartPosition(compilationUnitTree, node);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user