toStringDeep method

String toStringDeep ({String prefixLineOne: '', String prefixOtherLines, TextTreeConfiguration parentConfiguration, DiagnosticLevel minLevel: DiagnosticLevel.debug })

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:

  • toString, for a brief description of the value but not its children.
  • toStringShallow, for a detailed description of the value but not its children.

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();
}