Add package and enclosing type fields to tag entries
This commit is contained in:
@@ -324,6 +324,7 @@ public class NoBuild {
|
||||
fileManager.getJavaFileObjects(sourcePaths);
|
||||
|
||||
List<String> compilerOptions = new ArrayList<>();
|
||||
compilerOptions.add("-Xlint:all");
|
||||
compilerOptions.add("-d");
|
||||
compilerOptions.add(classOutputPath);
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ public class Jtags {
|
||||
boolean absolutePaths = false;
|
||||
boolean excludeNonPublic = false;
|
||||
boolean excludeAnonymous = false;
|
||||
boolean excludeStaticField = false;
|
||||
List<Class<? extends TagField>> fields = new ArrayList<>();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
@@ -40,11 +40,6 @@ public class Jtags {
|
||||
options.absolutePaths = true;
|
||||
break;
|
||||
|
||||
case "-no-static":
|
||||
logger.config("Excluding 'file:' field in tags");
|
||||
options.excludeStaticField = true;
|
||||
break;
|
||||
|
||||
case "-no-non-public":
|
||||
logger.config("Excluding non-public elements");
|
||||
options.excludeNonPublic = true;
|
||||
@@ -55,10 +50,47 @@ public class Jtags {
|
||||
options.excludeAnonymous = true;
|
||||
break;
|
||||
|
||||
case "-fields":
|
||||
String fields =
|
||||
switch (arguments.poll()) {
|
||||
case null -> {
|
||||
logger.severe("Expected argument after " + argument);
|
||||
printUsage();
|
||||
System.exit(1);
|
||||
yield null;
|
||||
}
|
||||
case String s -> s;
|
||||
};
|
||||
|
||||
options.fields =
|
||||
fields
|
||||
.chars()
|
||||
.<Class<? extends TagField>>mapToObj(
|
||||
it ->
|
||||
(Class<? extends TagField>)
|
||||
switch (it) {
|
||||
case 's' -> TagField.StaticTag.class;
|
||||
case 'p' -> TagField.Package.class;
|
||||
case 't' -> TagField.EnclosingType.class;
|
||||
default -> {
|
||||
logger.severe("Unknown field: " + it);
|
||||
printUsage();
|
||||
System.exit(1);
|
||||
yield null;
|
||||
}
|
||||
})
|
||||
.toList();
|
||||
|
||||
logger.config(
|
||||
() ->
|
||||
"Including fields: "
|
||||
+ String.join(
|
||||
", ", options.fields.stream().map(it -> it.getSimpleName()).toList()));
|
||||
break;
|
||||
|
||||
case "-lib":
|
||||
logger.config("Third-party library mode");
|
||||
options.absolutePaths = true;
|
||||
options.excludeStaticField = true;
|
||||
options.excludeNonPublic = true;
|
||||
options.excludeAnonymous = true;
|
||||
break;
|
||||
@@ -83,6 +115,12 @@ public class Jtags {
|
||||
}
|
||||
}
|
||||
|
||||
if (options.sources.isEmpty()) {
|
||||
logger.severe("No source files provided");
|
||||
printUsage();
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
System.exit(run(options) ? 0 : 1);
|
||||
}
|
||||
|
||||
@@ -96,16 +134,20 @@ public class Jtags {
|
||||
static void printUsage() {
|
||||
System.err.println(
|
||||
"""
|
||||
Usage: jtags [options] <sources...>
|
||||
Options:
|
||||
-o, -output <file> Write tags to specified <file>
|
||||
-lib Treat sources as third-party libraries
|
||||
(alias for -absolute -no-non-public -no-anonymous)
|
||||
-absolute Use absolute paths for tag locations
|
||||
-no-static Exclude the "file:" field from tags
|
||||
-no-anonymous Exclude anonymous classes
|
||||
-no-anonymous Exclude anonymous classes
|
||||
-h, -help Show this message
|
||||
""");
|
||||
Usage: jtags [options] <sources...>
|
||||
Options:
|
||||
-o, -output <file> Write tags to specified <file>
|
||||
-lib Treat sources as third-party libraries
|
||||
(alias for -absolute -no-non-public -no-anonymous)
|
||||
-no-anonymous Exclude anonymous classes
|
||||
-no-non-public Exclude non-public elements
|
||||
-absolute Use absolute paths for tag locations
|
||||
-fields <fields> Fields to include in tag entries. Default: spt
|
||||
Avaiblable fields are:
|
||||
s static tag
|
||||
p package
|
||||
t enclosing type
|
||||
-h, -help Show this message
|
||||
""");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,13 @@ package xyz.naofal.jtags;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public record Tag(TagKind kind, String name, Path location, String line, boolean isStatic)
|
||||
public record Tag(TagKind kind, String name, Path location, String line, List<TagField> fields)
|
||||
implements Comparable<Tag> {
|
||||
|
||||
public Tag(TagKind kind, String name, Path location, String line) {
|
||||
this(kind, name, location, line, false);
|
||||
this(kind, name, location, line, List.of());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
9
src/main/java/xyz/naofal/jtags/TagField.java
Normal file
9
src/main/java/xyz/naofal/jtags/TagField.java
Normal file
@@ -0,0 +1,9 @@
|
||||
package xyz.naofal.jtags;
|
||||
|
||||
public sealed interface TagField {
|
||||
public record StaticTag() implements TagField {}
|
||||
|
||||
public record Package(String p) implements TagField {}
|
||||
|
||||
public record EnclosingType(String type, TagKind kind) implements TagField {}
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
package xyz.naofal.jtags;
|
||||
|
||||
import static xyz.naofal.jtags.JtagsLogger.logger;
|
||||
import static xyz.naofal.jtags.TagField.EnclosingType;
|
||||
import static xyz.naofal.jtags.TagField.Package;
|
||||
import static xyz.naofal.jtags.TagField.StaticTag;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
@@ -60,8 +63,16 @@ public record TagsWriter(Options options) {
|
||||
case ENUM_CONSTANT -> 'e';
|
||||
case METHOD -> 'm';
|
||||
});
|
||||
if (!options().excludeStaticField && tag.isStatic()) {
|
||||
writer.write("\tfile:");
|
||||
|
||||
for (TagField field : tag.fields()) {
|
||||
writer.write('\t');
|
||||
writer.write(
|
||||
switch (field) {
|
||||
case StaticTag() -> "file:";
|
||||
case Package(var p) -> "package:" + p;
|
||||
case EnclosingType(var t, var k) ->
|
||||
k.name().toLowerCase() + ":" + (t.isEmpty() ? "(Anonymous)" : t);
|
||||
});
|
||||
}
|
||||
|
||||
writer.write('\n');
|
||||
|
||||
@@ -9,7 +9,9 @@ import com.sun.source.tree.PackageTree;
|
||||
import com.sun.source.tree.Tree;
|
||||
import com.sun.source.tree.VariableTree;
|
||||
import com.sun.source.util.TreePathScanner;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.PriorityQueue;
|
||||
import javax.lang.model.element.Modifier;
|
||||
import xyz.naofal.jtags.Jtags.Options;
|
||||
@@ -46,10 +48,11 @@ public class TreeVisitor extends TreePathScanner<Void, TreeVisitorContext> {
|
||||
|
||||
@Override
|
||||
public Void visitClass(ClassTree node, TreeVisitorContext p) {
|
||||
if (options.excludeAnonymous && node.getSimpleName().isEmpty()) {
|
||||
if (options.excludeNonPublic && !node.getModifiers().getFlags().contains(Modifier.PUBLIC)) {
|
||||
return null;
|
||||
}
|
||||
if (options.excludeNonPublic && !node.getModifiers().getFlags().contains(Modifier.PUBLIC)) {
|
||||
|
||||
if (options.excludeAnonymous && node.getSimpleName().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -57,23 +60,40 @@ public class TreeVisitor extends TreePathScanner<Void, TreeVisitorContext> {
|
||||
return scan(node.getMembers(), p);
|
||||
}
|
||||
|
||||
TagKind typeKind = getTypeKind(node);
|
||||
|
||||
List<TagField> fields = new ArrayList<>();
|
||||
|
||||
if (options.fields.contains(TagField.StaticTag.class)
|
||||
&& node.getModifiers().getFlags().contains(Modifier.STATIC)) {
|
||||
fields.add(new TagField.StaticTag());
|
||||
}
|
||||
|
||||
if (options.fields.contains(TagField.Package.class)) {
|
||||
for (var path : getCurrentPath().getParentPath()) {
|
||||
if (path instanceof CompilationUnitTree compilationUnitTree) {
|
||||
fields.add(
|
||||
new TagField.Package(
|
||||
Optional.ofNullable(compilationUnitTree.getPackageName())
|
||||
.map(String::valueOf)
|
||||
.orElse("")));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (options.fields.contains(TagField.EnclosingType.class)) {
|
||||
for (var path : getCurrentPath().getParentPath()) {
|
||||
if (path instanceof ClassTree classTree) {
|
||||
fields.add(new TagField.EnclosingType(classTree.getSimpleName().toString(), typeKind));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Tag tag =
|
||||
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;
|
||||
default -> {
|
||||
logger.warning("Unknown class kind " + node.getKind());
|
||||
yield TagKind.CLASS;
|
||||
}
|
||||
},
|
||||
node.getSimpleName().toString(),
|
||||
p.getLocation(),
|
||||
p.getLine(node),
|
||||
node.getModifiers().getFlags().contains(Modifier.STATIC));
|
||||
typeKind, node.getSimpleName().toString(), p.getLocation(), p.getLine(node), fields);
|
||||
|
||||
logger.finer(() -> "Type: " + tag);
|
||||
|
||||
@@ -88,6 +108,24 @@ public class TreeVisitor extends TreePathScanner<Void, TreeVisitorContext> {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<TagField> fields = new ArrayList<>();
|
||||
|
||||
if (options.fields.contains(TagField.StaticTag.class)
|
||||
&& node.getModifiers().getFlags().contains(Modifier.STATIC)) {
|
||||
fields.add(new TagField.StaticTag());
|
||||
}
|
||||
|
||||
if (options.fields.contains(TagField.EnclosingType.class)) {
|
||||
for (var path : getCurrentPath().getParentPath()) {
|
||||
if (path instanceof ClassTree classTree) {
|
||||
fields.add(
|
||||
new TagField.EnclosingType(
|
||||
classTree.getSimpleName().toString(), getTypeKind(classTree)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Tag tag =
|
||||
new Tag(
|
||||
switch (node.getKind()) {
|
||||
@@ -104,7 +142,7 @@ public class TreeVisitor extends TreePathScanner<Void, TreeVisitorContext> {
|
||||
.toString(),
|
||||
p.getLocation(),
|
||||
p.getLine(node),
|
||||
node.getModifiers().getFlags().contains(Modifier.STATIC));
|
||||
fields);
|
||||
|
||||
logger.finer(() -> "Method: " + tag);
|
||||
|
||||
@@ -125,9 +163,23 @@ public class TreeVisitor extends TreePathScanner<Void, TreeVisitorContext> {
|
||||
return scan(node.getInitializer(), p);
|
||||
}
|
||||
|
||||
TagKind enclosingTypeKind = getTypeKind(enclosingType);
|
||||
|
||||
List<TagField> fields = new ArrayList<>();
|
||||
|
||||
if (options.fields.contains(TagField.StaticTag.class)
|
||||
&& node.getModifiers().getFlags().contains(Modifier.STATIC)) {
|
||||
fields.add(new TagField.StaticTag());
|
||||
}
|
||||
|
||||
if (options.fields.contains(TagField.EnclosingType.class)) {
|
||||
fields.add(
|
||||
new TagField.EnclosingType(enclosingType.getSimpleName().toString(), enclosingTypeKind));
|
||||
}
|
||||
|
||||
Tag tag =
|
||||
new Tag(
|
||||
enclosingType.getKind() == Tree.Kind.ENUM
|
||||
enclosingTypeKind == TagKind.ENUM
|
||||
&& node.getModifiers()
|
||||
.getFlags()
|
||||
.containsAll(List.of(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL))
|
||||
@@ -136,7 +188,7 @@ public class TreeVisitor extends TreePathScanner<Void, TreeVisitorContext> {
|
||||
node.getName().toString(),
|
||||
p.getLocation(),
|
||||
p.getLine(node),
|
||||
node.getModifiers().getFlags().contains(Modifier.STATIC));
|
||||
fields);
|
||||
|
||||
logger.finer(() -> "Variable: " + tag);
|
||||
|
||||
@@ -144,4 +196,18 @@ public class TreeVisitor extends TreePathScanner<Void, TreeVisitorContext> {
|
||||
|
||||
return scan(node.getInitializer(), p);
|
||||
}
|
||||
|
||||
private TagKind getTypeKind(ClassTree classTree) {
|
||||
return switch (classTree.getKind()) {
|
||||
case CLASS -> TagKind.CLASS;
|
||||
case RECORD -> TagKind.RECORD;
|
||||
case INTERFACE -> TagKind.INTERFACE;
|
||||
case ENUM -> TagKind.ENUM;
|
||||
case ANNOTATION_TYPE -> TagKind.ANNOTATION;
|
||||
default -> {
|
||||
logger.warning("Unknown class kind " + classTree.getKind());
|
||||
yield TagKind.CLASS;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user