// Copyright 2017 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import 'package:meta/meta.dart'; import 'print.dart'; /// Returns a 5 character long hexadecimal string generated from /// Object.hashCode's 20 least-significant bits. String shortHash(Object object) { return object.hashCode.toUnsigned(20).toRadixString(16).padLeft(5, '0'); } /// Returns a summary of the runtime type and hash code of `object`. String describeIdentity(Object object) => '${object.runtimeType}#${shortHash(object)}'; // This method exists as a workaround for https://github.com/dart-lang/sdk/issues/30021 /// Returns a short description of an enum value. /// /// Strips off the enum class name from the `enumEntry.toString()`. /// /// For example: /// /// ```dart /// enum Day { /// monday, tuesday, wednesday, thursday, friday, saturday, sunday /// } /// /// main() { /// assert(Day.monday.toString() == 'Day.monday'); /// assert(describeEnum(Day.monday) == 'monday'); /// } /// ``` String describeEnum(Object enumEntry) { final String description = enumEntry.toString(); final int indexOfDot = description.indexOf('.'); assert(indexOfDot != -1 && indexOfDot < description.length - 1); return description.substring(indexOfDot + 1); } /// A mixin that helps dump string representations of trees. abstract class TreeDiagnosticsMixin { // This class is intended to be used as a mixin, and should not be // extended directly. factory TreeDiagnosticsMixin._() => null; /// A brief description of this object, usually just the [runtimeType] and the /// [hashCode]. /// /// See also: /// /// * [toStringShallow], for a detailed description of the object. /// * [toStringDeep], for a description of the subtree rooted at this object. @override String toString() => describeIdentity(this); /// Returns a one-line detailed description of the object. /// /// This description includes everything from [debugFillDescription], but does /// not recurse to any children. /// /// The [toStringShallow] method can take an argument, which is the string to /// place between each part obtained from [debugFillDescription]. Passing a /// string such as `'\n '` will result in a multiline string that indents the /// properties of the object below its name (as per [toString]). /// /// See also: /// /// * [toString], for a brief description of the object. /// * [toStringDeep], for a description of the subtree rooted at this object. String toStringShallow([String joiner = '; ']) { final StringBuffer result = new StringBuffer(); result.write(toString()); result.write(joiner); final List<String> description = <String>[]; debugFillDescription(description); result.write(description.join(joiner)); return result.toString(); } /// Returns a string representation of this node and its descendants. /// /// This includes the information from [debugFillDescription], and then /// recurses into the children using [debugDescribeChildren]. /// /// The [toStringDeep] method takes arguments, but those are intended for /// internal use when recursing to the descendants, and so can be ignored. /// /// See also: /// /// * [toString], for a brief description of the object but not its children. /// * [toStringShallow], for a detailed description of the object but not its /// children. String toStringDeep([String prefixLineOne = '', String prefixOtherLines = '']) { String result = '$prefixLineOne$this\n'; final String childrenDescription = debugDescribeChildren(prefixOtherLines); final String descriptionPrefix = childrenDescription != '' ? '$prefixOtherLines \u2502 ' : '$prefixOtherLines '; final List<String> description = <String>[]; debugFillDescription(description); result += description .expand((String description) => debugWordWrap(description, 65, wrapIndent: ' ')) .map<String>((String line) => "$descriptionPrefix$line\n") .join(); if (childrenDescription == '') { final String prefix = prefixOtherLines.trimRight(); if (prefix != '') result += '$prefix\n'; } else { result += childrenDescription; } return result; } /// Add additional information to the given description for use by /// [toStringDeep] and [toStringShallow]. @protected @mustCallSuper void debugFillDescription(List<String> description) { } /// Returns a description of this node's children for use by [toStringDeep]. @protected String debugDescribeChildren(String prefix) => ''; }