mirror of
https://github.com/flutter/flutter
synced 2024-10-13 11:42:54 +00:00
Refactor SemanticsData and SemanticsNode to use Diagnosticable. (#11957)
* Refactor SemanticsData and SemanticsNode to use Diagnosticable. * Switch toStringDeep to take named parameters.
This commit is contained in:
parent
ff90ba5b3a
commit
0229711ba1
|
@ -679,7 +679,7 @@ abstract class DiagnosticsNode {
|
|||
String toString({ TextTreeConfiguration parentConfiguration }) {
|
||||
assert(style != null);
|
||||
if (style == DiagnosticsTreeStyle.singleLine)
|
||||
return toStringDeep('', '', parentConfiguration);
|
||||
return toStringDeep(parentConfiguration: parentConfiguration);
|
||||
|
||||
final String description = toDescription(parentConfiguration: parentConfiguration);
|
||||
|
||||
|
@ -736,7 +736,11 @@ abstract class DiagnosticsNode {
|
|||
/// * [toString], for a brief description of the [value] but not its children.
|
||||
/// * [toStringShallow], for a detailed description of the [value] but not its
|
||||
/// children.
|
||||
String toStringDeep([String prefixLineOne = '', String prefixOtherLines, TextTreeConfiguration parentConfiguration]) {
|
||||
String toStringDeep({
|
||||
String prefixLineOne: '',
|
||||
String prefixOtherLines,
|
||||
TextTreeConfiguration parentConfiguration,
|
||||
}) {
|
||||
prefixOtherLines ??= prefixLineOne;
|
||||
|
||||
final List<DiagnosticsNode> children = getChildren();
|
||||
|
@ -796,9 +800,9 @@ abstract class DiagnosticsNode {
|
|||
if (property.style != DiagnosticsTreeStyle.singleLine) {
|
||||
final TextTreeConfiguration propertyStyle = property.textTreeConfiguration;
|
||||
builder.writeRaw(property.toStringDeep(
|
||||
'${builder.prefixOtherLines}${propertyStyle.prefixLineOne}',
|
||||
'${builder.prefixOtherLines}${propertyStyle.linkCharacter}${propertyStyle.prefixOtherLines}',
|
||||
config,
|
||||
prefixLineOne: '${builder.prefixOtherLines}${propertyStyle.prefixLineOne}',
|
||||
prefixOtherLines: '${builder.prefixOtherLines}${propertyStyle.linkCharacter}${propertyStyle.prefixOtherLines}',
|
||||
parentConfiguration: config,
|
||||
));
|
||||
continue;
|
||||
}
|
||||
|
@ -850,9 +854,9 @@ abstract class DiagnosticsNode {
|
|||
if (i == children.length - 1) {
|
||||
final String lastChildPrefixLineOne = '$prefixChildren${childConfig.prefixLastChildLineOne}';
|
||||
builder.writeRawLine(child.toStringDeep(
|
||||
lastChildPrefixLineOne,
|
||||
'$prefixChildren${childConfig.childLinkSpace}${childConfig.prefixOtherLines}',
|
||||
config,
|
||||
prefixLineOne: lastChildPrefixLineOne,
|
||||
prefixOtherLines: '$prefixChildren${childConfig.childLinkSpace}${childConfig.prefixOtherLines}',
|
||||
parentConfiguration: config,
|
||||
));
|
||||
if (childConfig.footer.isNotEmpty)
|
||||
builder.writeRaw('$prefixChildren${childConfig.childLinkSpace}${childConfig.footer}');
|
||||
|
@ -860,7 +864,7 @@ abstract class DiagnosticsNode {
|
|||
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(childPrefixLineOne, childPrefixOtherLines));
|
||||
builder.writeRawLine(child.toStringDeep(prefixLineOne: childPrefixLineOne, prefixOtherLines: childPrefixOtherLines));
|
||||
if (childConfig.footer.isNotEmpty)
|
||||
builder.writeRaw('$prefixChildren${nextChildStyle.linkCharacter}${childConfig.footer}');
|
||||
}
|
||||
|
@ -1249,16 +1253,18 @@ class IterableProperty<T> extends DiagnosticsProperty<Iterable<T>> {
|
|||
/// value with 0 elements would, confusingly, be displayed as the empty
|
||||
/// string. It defaults to the string `[]`.
|
||||
///
|
||||
/// The [style] and [hidden] arguments must also not be null.
|
||||
/// The [style], [hidden], and [showName] arguments must also not be null.
|
||||
IterableProperty(String name, Iterable<T> value, {
|
||||
Object defaultValue: kNoDefaultValue,
|
||||
String ifNull,
|
||||
String ifEmpty: '[]',
|
||||
DiagnosticsTreeStyle style: DiagnosticsTreeStyle.singleLine,
|
||||
bool hidden: false,
|
||||
bool showName: true,
|
||||
}) : assert(ifEmpty != null),
|
||||
assert(style != null),
|
||||
assert(hidden != null),
|
||||
assert(showName != null),
|
||||
super(
|
||||
name,
|
||||
value,
|
||||
|
@ -1267,6 +1273,7 @@ class IterableProperty<T> extends DiagnosticsProperty<Iterable<T>> {
|
|||
ifEmpty: ifEmpty,
|
||||
style: style,
|
||||
hidden: hidden,
|
||||
showName: showName,
|
||||
);
|
||||
|
||||
@override
|
||||
|
@ -1634,14 +1641,19 @@ class DiagnosticsProperty<T> extends DiagnosticsNode {
|
|||
List<DiagnosticsNode> getChildren() => <DiagnosticsNode>[];
|
||||
}
|
||||
|
||||
/// [DiagnosticsNode] for an instance of [Diagnosticable].
|
||||
class _DiagnosticableNode<T extends Diagnosticable> extends DiagnosticsNode {
|
||||
_DiagnosticableNode({
|
||||
/// [DiagnosticsNode] that lazily calls the associated [Diagnosticable] [value]
|
||||
/// to implement [getChildren] and [getProperties].
|
||||
class DiagnosticableNode<T extends Diagnosticable> extends DiagnosticsNode {
|
||||
/// Create a diagnostics describing a [Diagnosticable] value.
|
||||
///
|
||||
/// The [value] argument must not be null.
|
||||
DiagnosticableNode({
|
||||
String name,
|
||||
@required this.value,
|
||||
@required DiagnosticsTreeStyle style,
|
||||
String emptyBodyDescription,
|
||||
}) : super(
|
||||
}) : assert(value != null),
|
||||
super(
|
||||
name: name,
|
||||
style: style,
|
||||
);
|
||||
|
@ -1683,7 +1695,7 @@ class _DiagnosticableNode<T extends Diagnosticable> extends DiagnosticsNode {
|
|||
}
|
||||
|
||||
/// [DiagnosticsNode] for an instance of [DiagnosticableTree].
|
||||
class _DiagnosticableTreeNode extends _DiagnosticableNode<DiagnosticableTree> {
|
||||
class _DiagnosticableTreeNode extends DiagnosticableNode<DiagnosticableTree> {
|
||||
_DiagnosticableTreeNode({
|
||||
String name,
|
||||
@required DiagnosticableTree value,
|
||||
|
@ -1841,7 +1853,7 @@ abstract class Diagnosticable {
|
|||
/// relationship between the parent and the node. For example, pass
|
||||
/// [DiagnosticsTreeStyle.offstage] to indicate that a node is offstage.
|
||||
DiagnosticsNode toDiagnosticsNode({ String name, DiagnosticsTreeStyle style }) {
|
||||
return new _DiagnosticableNode<Diagnosticable>(
|
||||
return new DiagnosticableNode<Diagnosticable>(
|
||||
name: name,
|
||||
value: this,
|
||||
style: style,
|
||||
|
@ -2110,8 +2122,8 @@ abstract class DiagnosticableTree extends Diagnosticable {
|
|||
/// * [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]) {
|
||||
return toDiagnosticsNode().toStringDeep(prefixLineOne, prefixOtherLines);
|
||||
String toStringDeep({ String prefixLineOne: '', String prefixOtherLines }) {
|
||||
return toDiagnosticsNode().toStringDeep(prefixLineOne: prefixLineOne, prefixOtherLines: prefixOtherLines);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -2176,8 +2188,8 @@ abstract class DiagnosticableTreeMixin implements DiagnosticableTree {
|
|||
}
|
||||
|
||||
@override
|
||||
String toStringDeep([String prefixLineOne = '', String prefixOtherLines]) {
|
||||
return toDiagnosticsNode().toStringDeep(prefixLineOne, prefixOtherLines);
|
||||
String toStringDeep({ String prefixLineOne: '', String prefixOtherLines }) {
|
||||
return toDiagnosticsNode().toStringDeep(prefixLineOne: prefixLineOne, prefixOtherLines: prefixOtherLines);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -271,7 +271,7 @@ class TextSpan extends DiagnosticableTree {
|
|||
'TextSpan contains a null child.\n'
|
||||
'A TextSpan object with a non-null child list should not have any nulls in its child list.\n'
|
||||
'The full text in question was:\n'
|
||||
'${toStringDeep(' ')}'
|
||||
'${toStringDeep(prefixLineOne: ' ')}'
|
||||
);
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -329,7 +329,7 @@ void debugDumpLayerTree() {
|
|||
/// The order in which the children of a [SemanticsNode] will be printed is
|
||||
/// controlled by the [childOrder] parameter.
|
||||
void debugDumpSemanticsTree(DebugSemanticsDumpOrder childOrder) {
|
||||
debugPrint(RendererBinding.instance?.renderView?.debugSemantics?.toStringDeep(childOrder) ?? 'Semantics not collected.');
|
||||
debugPrint(RendererBinding.instance?.renderView?.debugSemantics?.toStringDeep(childOrder: childOrder) ?? 'Semantics not collected.');
|
||||
}
|
||||
|
||||
/// A concrete binding for applications that use the Rendering framework
|
||||
|
|
|
@ -145,11 +145,15 @@ List<String> debugDescribeTransform(Matrix4 transform) {
|
|||
/// Property which handles [Matrix4] that represent transforms.
|
||||
class TransformProperty extends DiagnosticsProperty<Matrix4> {
|
||||
/// Create a diagnostics property for [Matrix4] objects.
|
||||
///
|
||||
/// The [showName] argument must not be null.
|
||||
TransformProperty(String name, Matrix4 value, {
|
||||
bool showName: true,
|
||||
Object defaultValue: kNoDefaultValue,
|
||||
}) : super(
|
||||
}) : assert(showName != null), super(
|
||||
name,
|
||||
value,
|
||||
showName: showName,
|
||||
defaultValue: defaultValue,
|
||||
);
|
||||
|
||||
|
|
|
@ -2839,11 +2839,11 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
|
|||
/// If the prefix argument is provided, then every line in the output
|
||||
/// will be prefixed by that string.
|
||||
@override
|
||||
String toStringDeep([String prefixLineOne = '', String prefixOtherLines = '']) {
|
||||
String toStringDeep({ String prefixLineOne: '', String prefixOtherLines: '' }) {
|
||||
final RenderObject debugPreviousActiveLayout = _debugActiveLayout;
|
||||
_debugActiveLayout = null;
|
||||
|
||||
final String result = super.toStringDeep(prefixLineOne, prefixOtherLines);
|
||||
final String result = super.toStringDeep(prefixLineOne: prefixLineOne, prefixOtherLines: prefixOtherLines);
|
||||
|
||||
_debugActiveLayout = debugPreviousActiveLayout;
|
||||
return result;
|
||||
|
|
|
@ -91,7 +91,7 @@ class SemanticsTag {
|
|||
///
|
||||
/// Typically obtained from [SemanticsNode.getSemanticsData].
|
||||
@immutable
|
||||
class SemanticsData {
|
||||
class SemanticsData extends Diagnosticable {
|
||||
/// Creates a semantics data object.
|
||||
///
|
||||
/// The [flags], [actions], [label], and [Rect] arguments must not be null.
|
||||
|
@ -146,25 +146,28 @@ class SemanticsData {
|
|||
bool hasAction(SemanticsAction action) => (actions & action.index) != 0;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
final StringBuffer buffer = new StringBuffer();
|
||||
buffer.write('$runtimeType($rect');
|
||||
if (transform != null)
|
||||
buffer.write('; $transform');
|
||||
String toStringShort() => '$runtimeType';
|
||||
|
||||
@override
|
||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
super.debugFillProperties(properties);
|
||||
properties.add(new DiagnosticsProperty<Rect>('rect', rect, showName: false));
|
||||
properties.add(new TransformProperty('transform', transform, showName: false, defaultValue: null));
|
||||
final List<String> actionSummary = <String>[];
|
||||
for (SemanticsAction action in SemanticsAction.values.values) {
|
||||
if ((actions & action.index) != 0)
|
||||
buffer.write('; $action');
|
||||
actionSummary.add(describeEnum(action));
|
||||
}
|
||||
properties.add(new IterableProperty<String>('actions', actionSummary, hidden: actionSummary.isEmpty));
|
||||
|
||||
final List<String> flagSummary = <String>[];
|
||||
for (SemanticsFlags flag in SemanticsFlags.values.values) {
|
||||
if ((flags & flag.index) != 0)
|
||||
buffer.write('; $flag');
|
||||
flagSummary.add(describeEnum(flag));
|
||||
}
|
||||
if (label.isNotEmpty)
|
||||
buffer.write('; "$label"');
|
||||
if (textDirection != null)
|
||||
buffer.write('; $textDirection');
|
||||
buffer.write(')');
|
||||
return buffer.toString();
|
||||
properties.add(new IterableProperty<String>('flags', flagSummary, hidden: flagSummary.isEmpty));
|
||||
properties.add(new StringProperty('label', label, defaultValue: ''));
|
||||
properties.add(new EnumProperty<TextDirection>('textDirection', textDirection, defaultValue: null));
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -185,13 +188,36 @@ class SemanticsData {
|
|||
int get hashCode => hashValues(flags, actions, label, textDirection, rect, tags, transform);
|
||||
}
|
||||
|
||||
class _SemanticsDiagnosticableNode extends DiagnosticableNode<SemanticsNode> {
|
||||
_SemanticsDiagnosticableNode({
|
||||
String name,
|
||||
@required SemanticsNode value,
|
||||
@required DiagnosticsTreeStyle style,
|
||||
@required this.childOrder,
|
||||
}) : super(
|
||||
name: name,
|
||||
value: value,
|
||||
style: style,
|
||||
);
|
||||
|
||||
final DebugSemanticsDumpOrder childOrder;
|
||||
|
||||
@override
|
||||
List<DiagnosticsNode> getChildren() {
|
||||
if (value != null)
|
||||
return value.debugDescribeChildren(childOrder: childOrder);
|
||||
|
||||
return const <DiagnosticsNode>[];
|
||||
}
|
||||
}
|
||||
|
||||
/// A node that represents some semantic data.
|
||||
///
|
||||
/// The semantics tree is maintained during the semantics phase of the pipeline
|
||||
/// (i.e., during [PipelineOwner.flushSemantics]), which happens after
|
||||
/// compositing. The semantics tree is then uploaded into the engine for use
|
||||
/// by assistive technology.
|
||||
class SemanticsNode extends AbstractNode {
|
||||
class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin {
|
||||
/// Creates a semantic node.
|
||||
///
|
||||
/// Each semantic node has a unique identifier that is assigned when the node
|
||||
|
@ -211,7 +237,7 @@ class SemanticsNode extends AbstractNode {
|
|||
VoidCallback showOnScreen,
|
||||
SemanticsOwner owner,
|
||||
}) : id = 0,
|
||||
_showOnScreen = showOnScreen,
|
||||
_showOnScreen = showOnScreen,
|
||||
_actionHandler = handler {
|
||||
attach(owner);
|
||||
}
|
||||
|
@ -722,77 +748,87 @@ class SemanticsNode extends AbstractNode {
|
|||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
final StringBuffer buffer = new StringBuffer();
|
||||
buffer.write('$runtimeType($id');
|
||||
if (_dirty)
|
||||
buffer.write(' (${ owner != null && owner._dirtyNodes.contains(this) ? "dirty" : "STALE; owner=$owner" })');
|
||||
if (_shouldMergeAllDescendantsIntoThisNode)
|
||||
buffer.write(' (leaf merge)');
|
||||
String toStringShort() => '$runtimeType#$id';
|
||||
|
||||
@override
|
||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
bool hideOwner = true;
|
||||
if (_dirty) {
|
||||
final bool inDirtyNodes = owner != null && owner._dirtyNodes.contains(this);
|
||||
properties.add(new FlagProperty('inDirtyNodes', value: inDirtyNodes, ifTrue: 'dirty', ifFalse: 'STALE'));
|
||||
hideOwner = inDirtyNodes;
|
||||
}
|
||||
properties.add(new DiagnosticsProperty<SemanticsOwner>('owner', owner, hidden: hideOwner));
|
||||
properties.add(new FlagProperty('shouldMergeAllDescendantsIntoThisNode', value: _shouldMergeAllDescendantsIntoThisNode, ifTrue: 'leaf merge'));
|
||||
final Offset offset = transform != null ? MatrixUtils.getAsTranslation(transform) : null;
|
||||
if (offset != null) {
|
||||
buffer.write('; ${rect.shift(offset)}');
|
||||
properties.add(new DiagnosticsProperty<Rect>('rect', rect.shift(offset), showName: false));
|
||||
} else {
|
||||
final double scale = transform != null ? MatrixUtils.getAsScale(transform) : null;
|
||||
String description;
|
||||
if (scale != null) {
|
||||
buffer.write('; $rect scaled by ${scale.toStringAsFixed(1)}x');
|
||||
description = '$rect scaled by ${scale.toStringAsFixed(1)}x';
|
||||
} else if (transform != null && !MatrixUtils.isIdentity(transform)) {
|
||||
final String matrix = transform.toString().split('\n').take(4).map((String line) => line.substring(4)).join('; ');
|
||||
buffer.write('; $rect with transform [$matrix]');
|
||||
} else {
|
||||
buffer.write('; $rect');
|
||||
description = '$rect with transform [$matrix]';
|
||||
}
|
||||
properties.add(new DiagnosticsProperty<Rect>('rect', rect, description: description, showName: false));
|
||||
}
|
||||
if (wasAffectedByClip)
|
||||
buffer.write(' (clipped)');
|
||||
properties.add(new FlagProperty('wasAffectedByClip', value: wasAffectedByClip, ifTrue: 'clipped'));
|
||||
final List<String> actions = <String>[];
|
||||
for (SemanticsAction action in SemanticsAction.values.values) {
|
||||
if ((_actions & action.index) != 0)
|
||||
buffer.write('; $action');
|
||||
actions.add(describeEnum(action));
|
||||
}
|
||||
for (SemanticsTag tag in _tags)
|
||||
buffer.write('; $tag');
|
||||
if (hasCheckedState) {
|
||||
if (isChecked)
|
||||
buffer.write('; checked');
|
||||
else
|
||||
buffer.write('; unchecked');
|
||||
}
|
||||
if (isSelected)
|
||||
buffer.write('; selected');
|
||||
if (label.isNotEmpty)
|
||||
buffer.write('; "$label"');
|
||||
if (textDirection != null)
|
||||
buffer.write('; $textDirection');
|
||||
buffer.write(')');
|
||||
return buffer.toString();
|
||||
properties.add(new IterableProperty<String>('actions', actions, hidden: actions.isEmpty));
|
||||
properties.add(new IterableProperty<SemanticsTag>('tags', _tags, hidden: _tags.isEmpty));
|
||||
if (hasCheckedState)
|
||||
properties.add(new FlagProperty('isChecked', value: isChecked, ifTrue: 'checked', ifFalse: 'unchecked'));
|
||||
properties.add(new FlagProperty('isSelected', value: isSelected, ifTrue: 'selected'));
|
||||
properties.add(new StringProperty('label', label, defaultValue: ''));
|
||||
properties.add(new EnumProperty<TextDirection>('textDirection', textDirection, defaultValue: null));
|
||||
}
|
||||
|
||||
/// Returns a string representation of this node and its descendants.
|
||||
///
|
||||
/// The order in which the children of the [SemanticsNode] will be printed is
|
||||
/// controlled by the [childOrder] parameter.
|
||||
String toStringDeep(DebugSemanticsDumpOrder childOrder, [
|
||||
String prefixLineOne = '',
|
||||
String prefixOtherLines = ''
|
||||
]) {
|
||||
@override
|
||||
String toStringDeep({
|
||||
String prefixLineOne: '',
|
||||
String prefixOtherLines,
|
||||
DebugSemanticsDumpOrder childOrder: DebugSemanticsDumpOrder.traversal,
|
||||
}) {
|
||||
assert(childOrder != null);
|
||||
final StringBuffer result = new StringBuffer()
|
||||
..write(prefixLineOne)
|
||||
..write(this)
|
||||
..write('\n');
|
||||
if (_children != null && _children.isNotEmpty) {
|
||||
final List<SemanticsNode> childrenInOrder = _getChildrenInOrder(childOrder);
|
||||
for (int index = 0; index < childrenInOrder.length - 1; index += 1) {
|
||||
final SemanticsNode child = childrenInOrder[index];
|
||||
result.write(child.toStringDeep(childOrder, "$prefixOtherLines \u251C", "$prefixOtherLines \u2502"));
|
||||
}
|
||||
result.write(childrenInOrder.last.toStringDeep(childOrder, "$prefixOtherLines \u2514", "$prefixOtherLines "));
|
||||
}
|
||||
return result.toString();
|
||||
return toDiagnosticsNode(childOrder: childOrder).toStringDeep(prefixLineOne: prefixLineOne, prefixOtherLines: prefixOtherLines);
|
||||
}
|
||||
|
||||
@override
|
||||
DiagnosticsNode toDiagnosticsNode({
|
||||
String name,
|
||||
DiagnosticsTreeStyle style: DiagnosticsTreeStyle.dense,
|
||||
DebugSemanticsDumpOrder childOrder: DebugSemanticsDumpOrder.traversal,
|
||||
}) {
|
||||
return new _SemanticsDiagnosticableNode(
|
||||
name: name,
|
||||
value: this,
|
||||
style: style,
|
||||
childOrder: childOrder,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
List<DiagnosticsNode> debugDescribeChildren({ DebugSemanticsDumpOrder childOrder: DebugSemanticsDumpOrder.inverseHitTest }) {
|
||||
return _getChildrenInOrder(childOrder)
|
||||
.map<DiagnosticsNode>((SemanticsNode node) => node.toDiagnosticsNode(childOrder: childOrder))
|
||||
.toList();
|
||||
}
|
||||
|
||||
Iterable<SemanticsNode> _getChildrenInOrder(DebugSemanticsDumpOrder childOrder) {
|
||||
assert(childOrder != null);
|
||||
if (_children == null)
|
||||
return const <SemanticsNode>[];
|
||||
|
||||
switch(childOrder) {
|
||||
case DebugSemanticsDumpOrder.traversal:
|
||||
return new List<SemanticsNode>.from(_children)..sort(_geometryComparator);
|
||||
|
|
|
@ -456,6 +456,6 @@ class FocusManager {
|
|||
final String indent = ' ';
|
||||
return '${describeIdentity(this)}$status\n'
|
||||
'${indent}currentFocus: $_currentFocus\n'
|
||||
'${rootScope.toStringDeep(indent, indent)}';
|
||||
'${rootScope.toStringDeep(prefixLineOne: indent, prefixOtherLines: indent)}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
|
||||
import 'rendering_tester.dart';
|
||||
|
||||
|
@ -94,8 +95,8 @@ void main() {
|
|||
});
|
||||
|
||||
test('toStringDeep() does not throw with transform == null', () {
|
||||
final SemanticsNode child2 = new SemanticsNode();
|
||||
final SemanticsNode child1 = new SemanticsNode();
|
||||
final SemanticsNode child2 = new SemanticsNode();
|
||||
final SemanticsNode root = new SemanticsNode();
|
||||
root.addChildren(<SemanticsNode>[child1, child2]);
|
||||
root.finalizeChildren();
|
||||
|
@ -104,10 +105,106 @@ void main() {
|
|||
expect(child1.transform, isNull);
|
||||
expect(child2.transform, isNull);
|
||||
|
||||
expect(root.toStringDeep(DebugSemanticsDumpOrder.traversal),
|
||||
'SemanticsNode(8 (STALE; owner=null); Rect.fromLTRB(0.0, 0.0, 0.0, 0.0))\n'
|
||||
' ├SemanticsNode(7; Rect.fromLTRB(0.0, 0.0, 0.0, 0.0))\n'
|
||||
' └SemanticsNode(6; Rect.fromLTRB(0.0, 0.0, 0.0, 0.0))\n'
|
||||
expect(
|
||||
root.toStringDeep(childOrder: DebugSemanticsDumpOrder.traversal),
|
||||
'SemanticsNode#8(STALE, owner: null, Rect.fromLTRB(0.0, 0.0, 0.0, 0.0))\n'
|
||||
'├SemanticsNode#6(Rect.fromLTRB(0.0, 0.0, 0.0, 0.0))\n'
|
||||
'└SemanticsNode#7(Rect.fromLTRB(0.0, 0.0, 0.0, 0.0))\n',
|
||||
);
|
||||
});
|
||||
|
||||
test('toStringDeep respects childOrder parameter', () {
|
||||
final SemanticsNode child1 = new SemanticsNode()
|
||||
..rect = new Rect.fromLTRB(20.0, 20.0, 20.0, 20.0);
|
||||
final SemanticsNode child2 = new SemanticsNode()
|
||||
..rect = new Rect.fromLTRB(10.0, 10.0, 10.0, 10.0);
|
||||
final SemanticsNode root = new SemanticsNode();
|
||||
root.addChildren(<SemanticsNode>[child1, child2]);
|
||||
root.finalizeChildren();
|
||||
expect(
|
||||
root.toStringDeep(childOrder: DebugSemanticsDumpOrder.traversal),
|
||||
'SemanticsNode#11(STALE, owner: null, Rect.fromLTRB(0.0, 0.0, 0.0, 0.0))\n'
|
||||
'├SemanticsNode#10(STALE, owner: null, Rect.fromLTRB(10.0, 10.0, 10.0, 10.0))\n'
|
||||
'└SemanticsNode#9(STALE, owner: null, Rect.fromLTRB(20.0, 20.0, 20.0, 20.0))\n',
|
||||
);
|
||||
|
||||
expect(
|
||||
root.toStringDeep(childOrder: DebugSemanticsDumpOrder.inverseHitTest),
|
||||
'SemanticsNode#11(STALE, owner: null, Rect.fromLTRB(0.0, 0.0, 0.0, 0.0))\n'
|
||||
'├SemanticsNode#9(STALE, owner: null, Rect.fromLTRB(20.0, 20.0, 20.0, 20.0))\n'
|
||||
'└SemanticsNode#10(STALE, owner: null, Rect.fromLTRB(10.0, 10.0, 10.0, 10.0))\n',
|
||||
);
|
||||
|
||||
final SemanticsNode child3 = new SemanticsNode()
|
||||
..rect = new Rect.fromLTRB(0.0, 0.0, 0.0, 0.0);
|
||||
child3.addChildren(<SemanticsNode>[
|
||||
new SemanticsNode()..rect = new Rect.fromLTRB(20.0, 0.0, 20.0, 0.0),
|
||||
new SemanticsNode(),
|
||||
]);
|
||||
child3.finalizeChildren();
|
||||
|
||||
final SemanticsNode rootComplex = new SemanticsNode();
|
||||
rootComplex.addChildren(<SemanticsNode>[child1, child2, child3]);
|
||||
rootComplex.finalizeChildren();
|
||||
|
||||
expect(
|
||||
rootComplex.toStringDeep(childOrder: DebugSemanticsDumpOrder.traversal),
|
||||
'SemanticsNode#15(STALE, owner: null, Rect.fromLTRB(0.0, 0.0, 0.0, 0.0))\n'
|
||||
'├SemanticsNode#12(STALE, owner: null, Rect.fromLTRB(0.0, 0.0, 0.0, 0.0))\n'
|
||||
'│├SemanticsNode#14(Rect.fromLTRB(0.0, 0.0, 0.0, 0.0))\n'
|
||||
'│└SemanticsNode#13(STALE, owner: null, Rect.fromLTRB(20.0, 0.0, 20.0, 0.0))\n'
|
||||
'├SemanticsNode#10(STALE, owner: null, Rect.fromLTRB(10.0, 10.0, 10.0, 10.0))\n'
|
||||
'└SemanticsNode#9(STALE, owner: null, Rect.fromLTRB(20.0, 20.0, 20.0, 20.0))\n',
|
||||
);
|
||||
|
||||
expect(
|
||||
rootComplex.toStringDeep(childOrder: DebugSemanticsDumpOrder.inverseHitTest),
|
||||
'SemanticsNode#15(STALE, owner: null, Rect.fromLTRB(0.0, 0.0, 0.0, 0.0))\n'
|
||||
'├SemanticsNode#9(STALE, owner: null, Rect.fromLTRB(20.0, 20.0, 20.0, 20.0))\n'
|
||||
'├SemanticsNode#10(STALE, owner: null, Rect.fromLTRB(10.0, 10.0, 10.0, 10.0))\n'
|
||||
'└SemanticsNode#12(STALE, owner: null, Rect.fromLTRB(0.0, 0.0, 0.0, 0.0))\n'
|
||||
' ├SemanticsNode#13(STALE, owner: null, Rect.fromLTRB(20.0, 0.0, 20.0, 0.0))\n'
|
||||
' └SemanticsNode#14(Rect.fromLTRB(0.0, 0.0, 0.0, 0.0))\n',
|
||||
);
|
||||
});
|
||||
|
||||
test('debug properties', () {
|
||||
expect(
|
||||
new SemanticsNode().toStringDeep(),
|
||||
'SemanticsNode#16(Rect.fromLTRB(0.0, 0.0, 0.0, 0.0))\n',
|
||||
);
|
||||
|
||||
final SemanticsNode allProperties = new SemanticsNode()
|
||||
..rect = new Rect.fromLTWH(50.0, 10.0, 20.0, 30.0)
|
||||
..mergeAllDescendantsIntoThisNode = true
|
||||
..transform = new Matrix4.translation(new Vector3(10.0, 10.0, 0.0))
|
||||
..wasAffectedByClip = true
|
||||
..addAction(SemanticsAction.scrollUp)
|
||||
..addAction(SemanticsAction.longPress)
|
||||
..addAction(SemanticsAction.showOnScreen)
|
||||
..isChecked = false
|
||||
..isSelected = true
|
||||
..label = "Use all the properties"
|
||||
..textDirection = TextDirection.rtl;
|
||||
expect(
|
||||
allProperties.toStringDeep(),
|
||||
'SemanticsNode#17(STALE, owner: null, leaf merge, Rect.fromLTRB(60.0, 20.0, 80.0, 50.0), clipped, actions: [longPress, scrollUp, showOnScreen], selected, label: "Use all the properties", textDirection: rtl)\n',
|
||||
);
|
||||
expect(
|
||||
allProperties.getSemanticsData().toString(),
|
||||
'SemanticsData(Rect.fromLTRB(50.0, 10.0, 70.0, 40.0), [1.0,0.0,0.0,10.0; 0.0,1.0,0.0,10.0; 0.0,0.0,1.0,0.0; 0.0,0.0,0.0,1.0], actions: [longPress, scrollUp, showOnScreen], flags: [isSelected], label: "Use all the properties", textDirection: rtl)',
|
||||
);
|
||||
|
||||
final SemanticsNode scaled = new SemanticsNode()
|
||||
..rect = new Rect.fromLTWH(50.0, 10.0, 20.0, 30.0)
|
||||
..transform = new Matrix4.diagonal3(new Vector3(10.0, 10.0, 1.0));
|
||||
expect(
|
||||
scaled.toStringDeep(),
|
||||
'SemanticsNode#18(STALE, owner: null, Rect.fromLTRB(50.0, 10.0, 70.0, 40.0) scaled by 10.0x)\n',
|
||||
);
|
||||
expect(
|
||||
scaled.getSemanticsData().toString(),
|
||||
'SemanticsData(Rect.fromLTRB(50.0, 10.0, 70.0, 40.0), [10.0,0.0,0.0,0.0; 0.0,10.0,0.0,0.0; 0.0,0.0,1.0,0.0; 0.0,0.0,0.0,1.0])',
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -507,7 +507,7 @@ class _HasGoodToStringDeep extends Matcher {
|
|||
final String prefixOtherLines = 'PREFIX_OTHER_LINES_';
|
||||
final List<String> prefixIssues = <String>[];
|
||||
String descriptionWithPrefixes =
|
||||
object.toStringDeep(prefixLineOne, prefixOtherLines);
|
||||
object.toStringDeep(prefixLineOne: prefixLineOne, prefixOtherLines: prefixOtherLines);
|
||||
if (descriptionWithPrefixes.endsWith('\n')) {
|
||||
// Trim off trailing \n as the remaining calculations assume
|
||||
// the description does not end with a trailing \n.
|
||||
|
@ -532,7 +532,7 @@ class _HasGoodToStringDeep extends Matcher {
|
|||
|
||||
if (prefixIssues.isNotEmpty) {
|
||||
errorDescription.writeln(
|
||||
'Bad toStringDeep("$prefixLineOne", "$prefixOtherLines"):');
|
||||
'Bad toStringDeep(prefixLineOne: "$prefixLineOne", prefixOtherLines: "$prefixOtherLines"):');
|
||||
errorDescription.writeln(descriptionWithPrefixes);
|
||||
errorDescription.writeAll(prefixIssues, '\n');
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ class _MockToStringDeep {
|
|||
/// line break.
|
||||
List<String> _lines;
|
||||
|
||||
String toStringDeep([String prefixLineOne="", String prefixOtherLines=""]) {
|
||||
String toStringDeep({ String prefixLineOne: "", String prefixOtherLines: "" }) {
|
||||
final StringBuffer sb = new StringBuffer();
|
||||
if (_lines.isNotEmpty)
|
||||
sb.write('$prefixLineOne${_lines.first}');
|
||||
|
|
Loading…
Reference in a new issue