toStringDeep method
Returns a string representation of this node and its descendants.
prefixLineOne
will be added to the front of the first line of the
output. prefixOtherLines
will be added to the front of each other line.
If prefixOtherLines
is null, the prefixLineOne
is used for every line.
By default, there is no prefix.
minLevel
specifies the minimum DiagnosticLevel for properties included
in the output.
The toStringDeep method takes other arguments, but those are intended for internal use when recursing to the descendants, and so can be ignored.
See also:
Implementation
String toStringDeep({
String prefixLineOne = '',
String prefixOtherLines,
TextTreeConfiguration parentConfiguration,
DiagnosticLevel minLevel = DiagnosticLevel.debug,
}) {
assert(minLevel != null);
prefixOtherLines ??= prefixLineOne;
final List<DiagnosticsNode> children = getChildren();
final TextTreeConfiguration config = textTreeConfiguration;
if (prefixOtherLines.isEmpty)
prefixOtherLines += config.prefixOtherLinesRootNode;
final _PrefixedStringBuilder builder = _PrefixedStringBuilder(
prefixLineOne,
prefixOtherLines,
);
final String description = toDescription(parentConfiguration: parentConfiguration);
if (description == null || description.isEmpty) {
if (showName && name != null)
builder.write(name);
} else {
if (name != null && name.isNotEmpty && showName) {
builder.write(name);
if (showSeparator)
builder.write(config.afterName);
builder.write(
config.isNameOnOwnLine || description.contains('\n') ? '\n' : ' ');
if (description.contains('\n') && style == DiagnosticsTreeStyle.singleLine)
builder.prefixOtherLines += ' ';
}
builder.prefixOtherLines += children.isEmpty ?
config.propertyPrefixNoChildren : config.propertyPrefixIfChildren;
builder.write(description);
}
final List<DiagnosticsNode> properties = getProperties().where(
(DiagnosticsNode n) => !n.isFiltered(minLevel)
).toList();
if (properties.isNotEmpty || children.isNotEmpty || emptyBodyDescription != null)
builder.write(config.afterDescriptionIfBody);
if (config.lineBreakProperties)
builder.write(config.lineBreak);
if (properties.isNotEmpty)
builder.write(config.beforeProperties);
builder.prefixOtherLines += config.bodyIndent;
if (emptyBodyDescription != null &&
properties.isEmpty &&
children.isEmpty &&
prefixLineOne.isNotEmpty) {
builder.write(emptyBodyDescription);
if (config.lineBreakProperties)
builder.write(config.lineBreak);
}
for (int i = 0; i < properties.length; ++i) {
final DiagnosticsNode property = properties[i];
if (i > 0)
builder.write(config.propertySeparator);
const int kWrapWidth = 65;
if (property.style != DiagnosticsTreeStyle.singleLine) {
final TextTreeConfiguration propertyStyle = property.textTreeConfiguration;
builder.writeRaw(property.toStringDeep(
prefixLineOne: '${builder.prefixOtherLines}${propertyStyle.prefixLineOne}',
prefixOtherLines: '${builder.prefixOtherLines}${propertyStyle.linkCharacter}${propertyStyle.prefixOtherLines}',
parentConfiguration: config,
minLevel: minLevel,
));
continue;
}
assert(property.style == DiagnosticsTreeStyle.singleLine);
final String message = property.toString(parentConfiguration: config, minLevel: minLevel);
if (!config.lineBreakProperties || message.length < kWrapWidth) {
builder.write(message);
} else {
// debugWordWrap doesn't handle line breaks within the text being
// wrapped so we must call it on each line.
final List<String> lines = message.split('\n');
for (int j = 0; j < lines.length; ++j) {
final String line = lines[j];
if (j > 0)
builder.write(config.lineBreak);
builder.write(debugWordWrap(line, kWrapWidth, wrapIndent: ' ').join('\n'));
}
}
if (config.lineBreakProperties)
builder.write(config.lineBreak);
}
if (properties.isNotEmpty)
builder.write(config.afterProperties);
if (!config.lineBreakProperties)
builder.write(config.lineBreak);
final String prefixChildren = '$prefixOtherLines${config.bodyIndent}';
if (children.isEmpty &&
config.addBlankLineIfNoChildren &&
builder.hasMultipleLines) {
final String prefix = prefixChildren.trimRight();
if (prefix.isNotEmpty)
builder.writeRaw('$prefix${config.lineBreak}');
}
if (children.isNotEmpty && config.showChildren) {
if (config.isBlankLineBetweenPropertiesAndChildren &&
properties.isNotEmpty &&
children.first.textTreeConfiguration.isBlankLineBetweenPropertiesAndChildren) {
builder.write(config.lineBreak);
}
for (int i = 0; i < children.length; i++) {
final DiagnosticsNode child = children[i];
assert(child != null);
final TextTreeConfiguration childConfig = _childTextConfiguration(child, config);
if (i == children.length - 1) {
final String lastChildPrefixLineOne = '$prefixChildren${childConfig.prefixLastChildLineOne}';
builder.writeRawLine(child.toStringDeep(
prefixLineOne: lastChildPrefixLineOne,
prefixOtherLines: '$prefixChildren${childConfig.childLinkSpace}${childConfig.prefixOtherLines}',
parentConfiguration: config,
minLevel: minLevel,
));
if (childConfig.footer.isNotEmpty)
builder.writeRaw('$prefixChildren${childConfig.childLinkSpace}${childConfig.footer}');
} else {
final TextTreeConfiguration nextChildStyle = _childTextConfiguration(children[i + 1], config);
final String childPrefixLineOne = '$prefixChildren${childConfig.prefixLineOne}';
final String childPrefixOtherLines ='$prefixChildren${nextChildStyle.linkCharacter}${childConfig.prefixOtherLines}';
builder.writeRawLine(child.toStringDeep(
prefixLineOne: childPrefixLineOne,
prefixOtherLines: childPrefixOtherLines,
parentConfiguration: config,
minLevel: minLevel,
));
if (childConfig.footer.isNotEmpty)
builder.writeRaw('$prefixChildren${nextChildStyle.linkCharacter}${childConfig.footer}');
}
}
}
return builder.toString();
}