11package org .jetbrains .java .decompiler .main .decompiler ;
22
3+ import org .jetbrains .annotations .NotNull ;
4+ import org .jetbrains .java .decompiler .main .DecompilerContext ;
5+ import org .jetbrains .java .decompiler .main .extern .IFernflowerPreferences ;
36import org .jetbrains .java .decompiler .main .extern .IResultSaver ;
7+ import org .jetbrains .java .decompiler .main .extern .TextTokenVisitor ;
8+ import org .jetbrains .java .decompiler .struct .gen .FieldDescriptor ;
9+ import org .jetbrains .java .decompiler .struct .gen .MethodDescriptor ;
10+ import org .jetbrains .java .decompiler .util .token .TextRange ;
411
512import java .io .File ;
13+ import java .util .Set ;
14+ import java .util .TreeSet ;
615import java .util .jar .Manifest ;
716
817// "Saves" a file to the standard out console
918public final class ConsoleFileSaver implements IResultSaver {
19+ private static class ConsoleTokenVisitor extends TextTokenVisitor {
20+ record Token (TextRange range , Type type ) implements Comparable <Token > {
21+ @ Override
22+ public int compareTo (@ NotNull ConsoleFileSaver .ConsoleTokenVisitor .Token o ) {
23+ return Integer .compare (range .start , o .range .start );
24+ }
25+
26+ enum Type {
27+ CLASS (2 ),
28+ FIELD (3 ),
29+ METHOD (4 ),
30+ PARAMETER (5 ),
31+ LOCAL (6 ),
32+
33+ ;
34+
35+ private final int color ;
36+
37+ Type (int color ) {
38+ this .color = color ;
39+ }
40+
41+ String getEscapeCode () {
42+ return "\u001B [3" + color + "m" ;
43+ }
44+ }
45+ }
46+
47+ private final Set <Token > tokens = new TreeSet <>();
48+ private static final String ESCAPE_RESET = "\u001B [0m" ;
49+
50+ ConsoleTokenVisitor (TextTokenVisitor next ) {
51+ super (next );
52+ }
53+
54+ @ Override
55+ public void visitClass (TextRange range , boolean declaration , String name ) {
56+ tokens .add (new Token (range , Token .Type .CLASS ));
57+ super .visitClass (range , declaration , name );
58+ }
59+
60+ @ Override
61+ public void visitField (TextRange range , boolean declaration , String className , String name , FieldDescriptor descriptor ) {
62+ tokens .add (new Token (range , Token .Type .FIELD ));
63+ super .visitField (range , declaration , className , name , descriptor );
64+ }
65+
66+ @ Override
67+ public void visitMethod (TextRange range , boolean declaration , String className , String name , MethodDescriptor descriptor ) {
68+ tokens .add (new Token (range , Token .Type .METHOD ));
69+ super .visitMethod (range , declaration , className , name , descriptor );
70+ }
71+
72+ @ Override
73+ public void visitParameter (TextRange range , boolean declaration , String className , String methodName , MethodDescriptor methodDescriptor , int index , String name ) {
74+ tokens .add (new Token (range , Token .Type .PARAMETER ));
75+ super .visitParameter (range , declaration , className , methodName , methodDescriptor , index , name );
76+ }
77+
78+ @ Override
79+ public void visitLocal (TextRange range , boolean declaration , String className , String methodName , MethodDescriptor methodDescriptor , int index , String name ) {
80+ tokens .add (new Token (range , Token .Type .LOCAL ));
81+ super .visitLocal (range , declaration , className , methodName , methodDescriptor , index , name );
82+ }
83+
84+ void printClass (String content ) {
85+ var index = 0 ;
86+ for (Token token : tokens ) {
87+ System .out .print (content .substring (index , token .range ().start ));
88+ System .out .print (token .type ().getEscapeCode ());
89+ System .out .print (content .substring (token .range ().start , token .range ().getEnd ()));
90+ System .out .print (ESCAPE_RESET );
91+ index = token .range ().getEnd ();
92+ }
93+ if (index < content .length ()) {
94+ System .out .print (content .substring (index ));
95+ }
96+ System .out .println ();
97+ }
98+ }
1099
11- public ConsoleFileSaver (File unused ) {
12-
100+ private ConsoleTokenVisitor visitor ;
101+
102+ public ConsoleFileSaver (File ignored ) {
103+ ConsoleDecompiler .tokenizerInitializer = () -> {
104+ boolean color = switch (DecompilerContext .getProperty (IFernflowerPreferences .COLORIZE_OUTPUT ).toString ()) {
105+ case "always" -> true ;
106+ case "1" , "auto" -> System .console () != null ;
107+ default -> false ;
108+ };
109+
110+ if (color ) {
111+ TextTokenVisitor .addVisitor (next -> {
112+ visitor = new ConsoleTokenVisitor (next );
113+ return visitor ;
114+ });
115+ }
116+ };
13117 }
118+
14119 @ Override
15120 public void saveFolder (String path ) {
16121
@@ -24,7 +129,11 @@ public void copyFile(String source, String path, String entryName) {
24129 @ Override
25130 public void saveClassFile (String path , String qualifiedName , String entryName , String content , int [] mapping ) {
26131 System .out .println ("==== " + entryName + " ====" );
27- System .out .println (content );
132+ if (visitor != null ) {
133+ visitor .printClass (content );
134+ } else {
135+ System .out .println (content );
136+ }
28137 }
29138
30139 @ Override
@@ -45,7 +154,11 @@ public void copyEntry(String source, String path, String archiveName, String ent
45154 @ Override
46155 public void saveClassEntry (String path , String archiveName , String qualifiedName , String entryName , String content ) {
47156 System .out .println ("==== " + entryName + " ====" );
48- System .out .println (content );
157+ if (visitor != null ) {
158+ visitor .printClass (content );
159+ } else {
160+ System .out .println (content );
161+ }
49162 }
50163
51164 @ Override
0 commit comments