cairo_lang_parser/
colored_printer.rs1use cairo_lang_syntax::node::SyntaxNode;
2use cairo_lang_syntax::node::green::GreenNodeDetails;
3use cairo_lang_syntax::node::kind::SyntaxKind;
4use colored::{ColoredString, Colorize};
5use salsa::Database;
6
7struct ColoredPrinter<'a> {
8 db: &'a dyn Database,
9 verbose: bool,
11 result: String,
12}
13impl ColoredPrinter<'_> {
14 fn print(&mut self, syntax_node: &SyntaxNode<'_>) {
15 let node = syntax_node.green_node(self.db);
16 match &node.details {
17 GreenNodeDetails::Token(text) => {
18 if self.verbose && node.kind == SyntaxKind::TokenMissing {
19 self.result.push_str(&format!("{}", "<m>".red()));
20 } else {
21 self.result.push_str(&set_color(text.long(self.db), node.kind).to_string());
22 }
23 }
24 GreenNodeDetails::Node { .. } => {
25 if self.verbose && node.kind.is_missing() {
26 self.result.push_str(&format!("{}", "<m>".red()));
27 } else if self.verbose && is_empty_kind(node.kind) {
28 self.result.push_str(&format!("{}", "<e>".red()));
29 } else {
30 for child in syntax_node.get_children(self.db).iter() {
31 self.print(child);
32 }
33 }
34 }
35 }
36 }
37}
38
39pub fn is_empty_kind(kind: SyntaxKind) -> bool {
41 matches!(
42 kind,
43 SyntaxKind::OptionStructArgExprEmpty
44 | SyntaxKind::OptionTypeClauseEmpty
45 | SyntaxKind::OptionReturnTypeClauseEmpty
46 | SyntaxKind::OptionTerminalSemicolonEmpty
47 | SyntaxKind::OptionTerminalColonColonEmpty
48 | SyntaxKind::OptionWrappedGenericParamListEmpty
49 )
50}
51
52fn set_color(text: &str, kind: SyntaxKind) -> ColoredString {
53 match kind {
55 SyntaxKind::TokenIdentifier => text.truecolor(255, 255, 100), SyntaxKind::TokenPlus
57 | SyntaxKind::TokenMinus
58 | SyntaxKind::TokenMul
59 | SyntaxKind::TokenDiv
60 | SyntaxKind::TokenMod
61 | SyntaxKind::TokenDot => text.bright_magenta(),
62 SyntaxKind::TokenLiteralNumber
63 | SyntaxKind::TokenFalse
64 | SyntaxKind::TokenTrue
65 | SyntaxKind::TokenShortString
66 | SyntaxKind::TokenString => text.bright_cyan(),
67 SyntaxKind::TokenExtern
68 | SyntaxKind::TokenType
69 | SyntaxKind::TokenFunction
70 | SyntaxKind::TokenModule
71 | SyntaxKind::TokenEnum
72 | SyntaxKind::TokenStruct
73 | SyntaxKind::TokenTrait
74 | SyntaxKind::TokenImpl => text.bright_blue(),
75 SyntaxKind::TokenOf
76 | SyntaxKind::TokenLet
77 | SyntaxKind::TokenReturn
78 | SyntaxKind::TokenMatch
79 | SyntaxKind::TokenIf
80 | SyntaxKind::TokenElse
81 | SyntaxKind::TokenUse
82 | SyntaxKind::TokenImplicits
83 | SyntaxKind::TokenRef
84 | SyntaxKind::TokenMut
85 | SyntaxKind::TokenNoPanic => text.bright_blue(),
86 SyntaxKind::TokenArrow
87 | SyntaxKind::TokenMatchArrow
88 | SyntaxKind::TokenColon
89 | SyntaxKind::TokenColonColon
90 | SyntaxKind::TokenDotDot
91 | SyntaxKind::TokenDotDotEq
92 | SyntaxKind::TokenSemicolon
93 | SyntaxKind::TokenAnd
94 | SyntaxKind::TokenAndAnd
95 | SyntaxKind::TokenOr
96 | SyntaxKind::TokenOrOr
97 | SyntaxKind::TokenXor
98 | SyntaxKind::TokenNot
99 | SyntaxKind::TokenQuestionMark
100 | SyntaxKind::TokenUnderscore
101 | SyntaxKind::TokenHash => text.truecolor(255, 180, 255), SyntaxKind::TokenEq
103 | SyntaxKind::TokenEqEq
104 | SyntaxKind::TokenGE
105 | SyntaxKind::TokenGT
106 | SyntaxKind::TokenLE
107 | SyntaxKind::TokenLT
108 | SyntaxKind::TokenNeq => {
109 text.truecolor(255, 165, 0) }
111 SyntaxKind::TokenLBrace
112 | SyntaxKind::TokenRBrace
113 | SyntaxKind::TokenLBrack
114 | SyntaxKind::TokenRBrack
115 | SyntaxKind::TokenLParen
116 | SyntaxKind::TokenRParen
117 | SyntaxKind::TokenComma => text.clear(),
118 SyntaxKind::TokenEndOfFile => text.clear(),
119 SyntaxKind::TokenBadCharacters => text.red(),
120 SyntaxKind::TokenMissing => text.clear(),
121 SyntaxKind::TokenSkipped => text.on_red(), SyntaxKind::TokenSingleLineComment
123 | SyntaxKind::TokenWhitespace
124 | SyntaxKind::TokenNewline
125 | SyntaxKind::TokenEmpty => text.clear(),
126 _ => panic!("Unexpected syntax kind: {kind:?}"),
128 }
129}
130
131pub fn print_colored(db: &dyn Database, syntax_root: &SyntaxNode<'_>, verbose: bool) -> String {
132 let mut printer = ColoredPrinter { db, verbose, result: Default::default() };
133 printer.print(syntax_root);
134 printer.result
135}