| 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 |