Collect variable tags and improve line collection

This commit is contained in:
naofal.helal
2025-03-24 16:24:10 +03:00
parent 9d67b770da
commit c3c4a1fbcb
7 changed files with 99 additions and 49 deletions

1
.gitignore vendored
View File

@@ -5,6 +5,7 @@
/jdtls-build
.env*
/tags
/third-party/downloads/*
/third-party/**/*.jar

View File

@@ -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));

View File

@@ -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) {

View File

@@ -3,6 +3,7 @@ package xyz.naofal.jtags;
public enum TagKind {
PACKAGE,
CLASS,
RECORD,
INTERFACE,
ANNOTATION,
ENUM,

View File

@@ -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;
}
}

View File

@@ -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);
};
}
}

View File

@@ -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;
}
}