mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
a3256e6b2f
Change-Id: Ia36b1bf1127e0b78e0294422cff78338ef19ec26 TEST=this CL updates static analysis settings and address associated warnings Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/204640 Commit-Queue: Devon Carew <devoncarew@google.com> Reviewed-by: Tess Strickland <sstrickl@google.com> Reviewed-by: Slava Egorov <vegorov@google.com>
174 lines
4.7 KiB
Dart
174 lines
4.7 KiB
Dart
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
library vm_snapshot_analysis.ascii_table;
|
|
|
|
import 'dart:math' as math;
|
|
|
|
/// A row in the [AsciiTable].
|
|
abstract class Row {
|
|
String render(List<int> widths, List<AlignmentDirection> alignments);
|
|
|
|
/// Compute the total width of the row given [widths] of individual
|
|
/// columns.
|
|
///
|
|
/// Note: there is a border on the left and right of each column
|
|
/// plus whitespace around it.
|
|
static int totalWidth(List<int> widths) =>
|
|
widths.fold<int>(0, (sum, width) => sum + width + 3) + 1;
|
|
}
|
|
|
|
enum Separator {
|
|
/// Line separator looks like this: `+-------+------+`
|
|
line,
|
|
|
|
/// Wave separator looks like this: `~~~~~~~~~~~~~~~~`.
|
|
wave,
|
|
}
|
|
|
|
/// A separator row in the [AsciiTable].
|
|
class SeparatorRow extends Row {
|
|
final Separator filler;
|
|
SeparatorRow(this.filler);
|
|
|
|
@override
|
|
String render(List<int> widths, List<AlignmentDirection> alignments) {
|
|
final sb = StringBuffer();
|
|
switch (filler) {
|
|
case Separator.line:
|
|
sb.write('+');
|
|
for (var i = 0; i < widths.length; i++) {
|
|
sb.write('-' * (widths[i] + 2));
|
|
sb.write('+');
|
|
}
|
|
break;
|
|
|
|
case Separator.wave:
|
|
sb.write('~' * Row.totalWidth(widths));
|
|
break;
|
|
}
|
|
return sb.toString();
|
|
}
|
|
}
|
|
|
|
/// A separator row in the [AsciiTable].
|
|
class TextSeparatorRow extends Row {
|
|
final Text text;
|
|
TextSeparatorRow(String text)
|
|
: text = Text(value: text, direction: AlignmentDirection.center);
|
|
|
|
@override
|
|
String render(List<int> widths, List<AlignmentDirection> alignments) {
|
|
return text.render(Row.totalWidth(widths));
|
|
}
|
|
}
|
|
|
|
class NormalRow extends Row {
|
|
final List<dynamic> columns;
|
|
NormalRow(this.columns);
|
|
|
|
@override
|
|
String render(List<int> widths, List<AlignmentDirection> alignments) {
|
|
final sb = StringBuffer();
|
|
sb.write('|');
|
|
for (var i = 0; i < widths.length; i++) {
|
|
sb.write(' ');
|
|
final text = columns[i] is Text
|
|
? columns[i]
|
|
: Text(value: columns[i], direction: alignments[i]);
|
|
sb.write(text.render(widths[i]));
|
|
sb.write(' |');
|
|
}
|
|
return sb.toString();
|
|
}
|
|
}
|
|
|
|
enum AlignmentDirection { left, right, center }
|
|
|
|
/// A chunk of text aligned in the given direction within a cell.
|
|
class Text {
|
|
final String value;
|
|
final AlignmentDirection direction;
|
|
|
|
Text({required this.value, required this.direction});
|
|
Text.left(String value)
|
|
: this(value: value, direction: AlignmentDirection.left);
|
|
Text.right(String value)
|
|
: this(value: value, direction: AlignmentDirection.right);
|
|
Text.center(String value)
|
|
: this(value: value, direction: AlignmentDirection.center);
|
|
|
|
String render(int width) {
|
|
if (value.length > width) {
|
|
// Narrowed column.
|
|
return value.substring(0, width - 2) + '..';
|
|
}
|
|
switch (direction) {
|
|
case AlignmentDirection.left:
|
|
return value.padRight(width);
|
|
case AlignmentDirection.right:
|
|
return value.padLeft(width);
|
|
case AlignmentDirection.center:
|
|
final diff = width - value.length;
|
|
return ' ' * (diff ~/ 2) + value + (' ' * (diff - diff ~/ 2));
|
|
}
|
|
}
|
|
|
|
int get length => value.length;
|
|
}
|
|
|
|
class AsciiTable {
|
|
static const int unlimitedWidth = 0;
|
|
|
|
final int maxWidth;
|
|
|
|
final List<Row> rows = <Row>[];
|
|
|
|
AsciiTable({List<dynamic>? header, this.maxWidth = unlimitedWidth}) {
|
|
if (header != null) {
|
|
addSeparator();
|
|
addRow(header);
|
|
addSeparator();
|
|
}
|
|
}
|
|
|
|
void addRow(List<dynamic> columns) => rows.add(NormalRow(columns));
|
|
|
|
void addSeparator([Separator filler = Separator.line]) =>
|
|
rows.add(SeparatorRow(filler));
|
|
|
|
void addTextSeparator(String text) => rows.add(TextSeparatorRow(text));
|
|
|
|
void render() {
|
|
// We assume that the first row gives us alignment directions that
|
|
// subsequent rows would follow.
|
|
List<AlignmentDirection> alignments = rows
|
|
.whereType<NormalRow>()
|
|
.first
|
|
.columns
|
|
.map((v) => v is Text ? v.direction : AlignmentDirection.left)
|
|
.toList();
|
|
List<int> widths =
|
|
List<int>.filled(rows.whereType<NormalRow>().first.columns.length, 0);
|
|
|
|
// Compute max width for each column in the table.
|
|
for (var row in rows.whereType<NormalRow>()) {
|
|
assert(row.columns.length == widths.length);
|
|
for (var i = 0; i < widths.length; i++) {
|
|
widths[i] = math.max(row.columns[i].length, widths[i]);
|
|
}
|
|
}
|
|
|
|
if (maxWidth > 0) {
|
|
for (var i = 0; i < widths.length; i++) {
|
|
widths[i] = math.min(widths[i], maxWidth);
|
|
}
|
|
}
|
|
|
|
for (var row in rows) {
|
|
print(row.render(widths, alignments));
|
|
}
|
|
}
|
|
}
|