Commit 167c433a authored by Ian Hickson's avatar Ian Hickson

Merge pull request #2520 from Hixie/TextSpan.toString

Fix crash when dumping the app if it uses RichText
parents 3dc22dce 7cf2dbdf
...@@ -46,6 +46,19 @@ class StockSymbolView extends StatelessComponent { ...@@ -46,6 +46,19 @@ class StockSymbolView extends StatelessComponent {
), ),
new Text('Market Cap', style: headings), new Text('Market Cap', style: headings),
new Text('${stock.marketCap}'), new Text('${stock.marketCap}'),
new Container(
height: 8.0
),
new RichText(
text: new TextSpan(
style: DefaultTextStyle.of(context).merge(new TextStyle(fontSize: 8.0)),
text: 'Prices may be delayed by ',
children: <TextSpan>[
new TextSpan(text: 'several', style: new TextStyle(fontStyle: FontStyle.italic)),
new TextSpan(text: ' years.'),
]
)
),
], ],
justifyContent: FlexJustifyContent.collapse justifyContent: FlexJustifyContent.collapse
) )
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
library services; library services;
export 'src/services/activity.dart'; export 'src/services/activity.dart';
export 'src/services/assertions.dart';
export 'src/services/asset_bundle.dart'; export 'src/services/asset_bundle.dart';
export 'src/services/binding.dart'; export 'src/services/binding.dart';
export 'src/services/fetch.dart'; export 'src/services/fetch.dart';
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import 'dart:ui' as ui show Paragraph, ParagraphBuilder, ParagraphStyle, TextBox; import 'dart:ui' as ui show Paragraph, ParagraphBuilder, ParagraphStyle, TextBox;
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:flutter/services.dart';
import 'basic_types.dart'; import 'basic_types.dart';
import 'text_editing.dart'; import 'text_editing.dart';
...@@ -51,6 +52,7 @@ class TextSpan { ...@@ -51,6 +52,7 @@ class TextSpan {
final GestureRecognizer recognizer; final GestureRecognizer recognizer;
void build(ui.ParagraphBuilder builder) { void build(ui.ParagraphBuilder builder) {
assert(debugAssertValid());
final bool hasStyle = style != null; final bool hasStyle = style != null;
if (hasStyle) if (hasStyle)
builder.pushStyle(style.textStyle); builder.pushStyle(style.textStyle);
...@@ -81,6 +83,7 @@ class TextSpan { ...@@ -81,6 +83,7 @@ class TextSpan {
} }
TextSpan getSpanForPosition(TextPosition position) { TextSpan getSpanForPosition(TextPosition position) {
assert(debugAssertValid());
TextAffinity affinity = position.affinity; TextAffinity affinity = position.affinity;
int targetOffset = position.offset; int targetOffset = position.offset;
int offset = 0; int offset = 0;
...@@ -101,6 +104,7 @@ class TextSpan { ...@@ -101,6 +104,7 @@ class TextSpan {
} }
String toPlainText() { String toPlainText() {
assert(debugAssertValid());
StringBuffer buffer = new StringBuffer(); StringBuffer buffer = new StringBuffer();
visitTextSpan((TextSpan span) { visitTextSpan((TextSpan span) {
buffer.write(span.text); buffer.write(span.text);
...@@ -113,15 +117,47 @@ class TextSpan { ...@@ -113,15 +117,47 @@ class TextSpan {
StringBuffer buffer = new StringBuffer(); StringBuffer buffer = new StringBuffer();
buffer.writeln('$prefix$runtimeType:'); buffer.writeln('$prefix$runtimeType:');
String indent = '$prefix '; String indent = '$prefix ';
if (style != null)
buffer.writeln(style.toString(indent)); buffer.writeln(style.toString(indent));
if (text != null) if (text != null)
buffer.writeln('$indent"$text"'); buffer.writeln('$indent"$text"');
if (children != null) if (children != null) {
for (TextSpan child in children) for (TextSpan child in children) {
buffer.writeln(child.toString(indent)); if (child != null) {
buffer.write(child.toString(indent));
} else {
buffer.writeln('$indent<null>');
}
}
}
if (style == null && text == null && children == null)
buffer.writeln('$indent(empty)');
return buffer.toString(); return buffer.toString();
} }
bool debugAssertValid() {
assert(() {
if (!visitTextSpan((TextSpan span) {
if (span.children != null) {
for (TextSpan child in span.children) {
if (child == null)
return false;
}
}
return true;
})) {
throw new FlutterError(
'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'
'${toString(" ")}'
);
}
return true;
});
return true;
}
bool operator ==(dynamic other) { bool operator ==(dynamic other) {
if (identical(this, other)) if (identical(this, other))
return true; return true;
...@@ -149,6 +185,7 @@ class TextPainter { ...@@ -149,6 +185,7 @@ class TextPainter {
/// The (potentially styled) text to paint. /// The (potentially styled) text to paint.
TextSpan get text => _text; TextSpan get text => _text;
void set text(TextSpan value) { void set text(TextSpan value) {
assert(value == null || value.debugAssertValid());
if (_text == value) if (_text == value)
return; return;
_text = value; _text = value;
......
...@@ -15,6 +15,7 @@ class RenderParagraph extends RenderBox { ...@@ -15,6 +15,7 @@ class RenderParagraph extends RenderBox {
TextSpan text TextSpan text
) : _textPainter = new TextPainter(text) { ) : _textPainter = new TextPainter(text) {
assert(text != null); assert(text != null);
assert(text.debugAssertValid());
} }
final TextPainter _textPainter; final TextPainter _textPainter;
...@@ -24,6 +25,7 @@ class RenderParagraph extends RenderBox { ...@@ -24,6 +25,7 @@ class RenderParagraph extends RenderBox {
/// The text to display /// The text to display
TextSpan get text => _textPainter.text; TextSpan get text => _textPainter.text;
void set text(TextSpan value) { void set text(TextSpan value) {
assert(value.debugAssertValid());
if (_textPainter.text == value) if (_textPainter.text == value)
return; return;
_textPainter.text = value; _textPainter.text = value;
......
// Copyright 2016 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.
class FlutterError extends AssertionError {
FlutterError(this.message);
final String message;
String toString() => message;
}
...@@ -27,4 +27,38 @@ void main() { ...@@ -27,4 +27,38 @@ void main() {
expect(b1 == a2, isFalse); expect(b1 == a2, isFalse);
expect(c1 == b2, isFalse); expect(c1 == b2, isFalse);
}); });
test("TextSpan ", () {
final TextSpan test = new TextSpan(
text: 'a',
style: new TextStyle(
fontSize: 10.0
),
children: <TextSpan>[
new TextSpan(
text: 'b',
children: <TextSpan>[
new TextSpan()
]
),
null,
new TextSpan(
text: 'c'
),
]
);
expect(test.toString(), equals(
'TextSpan:\n'
' inherit: true\n'
' size: 10.0\n'
' "a"\n'
' TextSpan:\n'
' "b"\n'
' TextSpan:\n'
' (empty)\n'
' <null>\n'
' TextSpan:\n'
' "c"\n'
));
});
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment