OLD | NEW |
| (Empty) |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 /// Internal debugging utilities. | |
6 library dart_style.src.debug; | |
7 | |
8 import 'dart:math' as math; | |
9 | |
10 import 'chunk.dart'; | |
11 import 'line_splitting/rule_set.dart'; | |
12 import 'rule/rule.dart'; | |
13 | |
14 /// Set this to `true` to turn on diagnostic output while building chunks. | |
15 bool traceChunkBuilder = false; | |
16 | |
17 /// Set this to `true` to turn on diagnostic output while writing lines. | |
18 bool traceLineWriter = false; | |
19 | |
20 /// Set this to `true` to turn on diagnostic output while line splitting. | |
21 bool traceSplitter = false; | |
22 | |
23 bool useAnsiColors = false; | |
24 | |
25 const unicodeSection = "\u00a7"; | |
26 const unicodeMidDot = "\u00b7"; | |
27 | |
28 /// The whitespace prefixing each line of output. | |
29 String _indent = ""; | |
30 | |
31 void indent() { | |
32 _indent = " $_indent"; | |
33 } | |
34 | |
35 void unindent() { | |
36 _indent = _indent.substring(2); | |
37 } | |
38 | |
39 /// Constants for ANSI color escape codes. | |
40 final _cyan = _color("\u001b[36m"); | |
41 final _gray = _color("\u001b[1;30m"); | |
42 final _green = _color("\u001b[32m"); | |
43 final _red = _color("\u001b[31m"); | |
44 final _magenta = _color("\u001b[35m"); | |
45 final _none = _color("\u001b[0m"); | |
46 final _noColor = _color("\u001b[39m"); | |
47 final _bold = _color("\u001b[1m"); | |
48 | |
49 /// Prints [message] to stdout with each line correctly indented. | |
50 void log([message]) { | |
51 if (message == null) { | |
52 print(""); | |
53 return; | |
54 } | |
55 | |
56 print(_indent + message.toString().replaceAll("\n", "\n$_indent")); | |
57 } | |
58 | |
59 /// Wraps [message] in gray ANSI escape codes if enabled. | |
60 String gray(message) => "$_gray$message$_none"; | |
61 | |
62 /// Wraps [message] in green ANSI escape codes if enabled. | |
63 String green(message) => "$_green$message$_none"; | |
64 | |
65 /// Wraps [message] in bold ANSI escape codes if enabled. | |
66 String bold(message) => "$_bold$message$_none"; | |
67 | |
68 /// Prints [chunks] to stdout, one chunk per line, with detailed information | |
69 /// about each chunk. | |
70 void dumpChunks(int start, List<Chunk> chunks) { | |
71 if (chunks.isEmpty) return; | |
72 | |
73 // Show the spans as vertical bands over their range. | |
74 var spans = new Set(); | |
75 addSpans(chunks) { | |
76 for (var chunk in chunks) { | |
77 spans.addAll(chunk.spans); | |
78 | |
79 addSpans(chunk.blockChunks); | |
80 } | |
81 } | |
82 | |
83 addSpans(chunks); | |
84 | |
85 spans = spans.toList(); | |
86 | |
87 var rules = chunks | |
88 .map((chunk) => chunk.rule) | |
89 .where((rule) => rule != null && rule is! HardSplitRule) | |
90 .toSet(); | |
91 | |
92 var rows = []; | |
93 | |
94 addChunk(chunk, prefix, index) { | |
95 var row = []; | |
96 row.add("$prefix$index:"); | |
97 | |
98 if (chunk.text.length > 70) { | |
99 row.add(chunk.text.substring(0, 70)); | |
100 } else { | |
101 row.add(chunk.text); | |
102 } | |
103 | |
104 var spanBars = ""; | |
105 for (var span in spans) { | |
106 spanBars += chunk.spans.contains(span) ? "|" : " "; | |
107 } | |
108 row.add(spanBars); | |
109 | |
110 writeIf(predicate, String callback()) { | |
111 if (predicate) { | |
112 row.add(callback()); | |
113 } else { | |
114 row.add(""); | |
115 } | |
116 } | |
117 | |
118 if (chunk.rule != null) { | |
119 row.add(chunk.isHardSplit ? "" : chunk.rule.toString()); | |
120 | |
121 var outerRules = chunk.rule.outerRules.toSet().intersection(rules); | |
122 writeIf(outerRules.isNotEmpty, () => "-> ${outerRules.join(" ")}"); | |
123 } else { | |
124 row.add("(no rule)"); | |
125 | |
126 // Outer rules. | |
127 row.add(""); | |
128 } | |
129 | |
130 writeIf(chunk.indent != null && chunk.indent != 0, | |
131 () => "indent ${chunk.indent}"); | |
132 | |
133 writeIf(chunk.nesting != null && chunk.nesting != 0, | |
134 () => "nest ${chunk.nesting}"); | |
135 | |
136 writeIf(chunk.flushLeft != null && chunk.flushLeft, () => "flush"); | |
137 | |
138 rows.add(row); | |
139 | |
140 for (var j = 0; j < chunk.blockChunks.length; j++) { | |
141 addChunk(chunk.blockChunks[j], "$prefix$index.", j); | |
142 } | |
143 } | |
144 | |
145 var i = start; | |
146 for (var chunk in chunks) { | |
147 addChunk(chunk, "", i); | |
148 i++; | |
149 } | |
150 | |
151 var rowWidths = new List.filled(rows.first.length, 0); | |
152 for (var row in rows) { | |
153 for (var i = 0; i < row.length; i++) { | |
154 rowWidths[i] = math.max(rowWidths[i], row[i].length); | |
155 } | |
156 } | |
157 | |
158 var buffer = new StringBuffer(); | |
159 for (var row in rows) { | |
160 for (var i = 0; i < row.length; i++) { | |
161 var cell = row[i].padRight(rowWidths[i]); | |
162 | |
163 if (i != 1) cell = gray(cell); | |
164 | |
165 buffer.write(cell); | |
166 buffer.write(" "); | |
167 } | |
168 | |
169 buffer.writeln(); | |
170 } | |
171 | |
172 print(buffer.toString()); | |
173 } | |
174 | |
175 /// Convert the line to a [String] representation. | |
176 /// | |
177 /// It will determine how best to split it into multiple lines of output and | |
178 /// return a single string that may contain one or more newline characters. | |
179 void dumpLines(List<Chunk> chunks, int firstLineIndent, SplitSet splits) { | |
180 var buffer = new StringBuffer(); | |
181 | |
182 writeIndent(indent) => buffer.write(gray("| " * (indent ~/ 2))); | |
183 | |
184 writeChunksUnsplit(List<Chunk> chunks) { | |
185 for (var chunk in chunks) { | |
186 buffer.write(chunk.text); | |
187 if (chunk.spaceWhenUnsplit) buffer.write(" "); | |
188 | |
189 // Recurse into the block. | |
190 writeChunksUnsplit(chunk.blockChunks); | |
191 } | |
192 } | |
193 | |
194 writeIndent(firstLineIndent); | |
195 | |
196 for (var i = 0; i < chunks.length - 1; i++) { | |
197 var chunk = chunks[i]; | |
198 buffer.write(chunk.text); | |
199 | |
200 if (splits.shouldSplitAt(i)) { | |
201 for (var j = 0; j < (chunk.isDouble ? 2 : 1); j++) { | |
202 buffer.writeln(); | |
203 writeIndent(splits.getColumn(i)); | |
204 } | |
205 } else { | |
206 writeChunksUnsplit(chunk.blockChunks); | |
207 | |
208 if (chunk.spaceWhenUnsplit) buffer.write(" "); | |
209 } | |
210 } | |
211 | |
212 buffer.write(chunks.last.text); | |
213 log(buffer); | |
214 } | |
215 | |
216 String _color(String ansiEscape) => useAnsiColors ? ansiEscape : ""; | |
OLD | NEW |