Revert "Reland "Text inline widgets, TextSpan rework" (#33946)" (#34002)

This reverts commit 14414f350ac040f9626f1aa0b3071f42cc9136a6.
diff --git a/dev/benchmarks/complex_layout/lib/main.dart b/dev/benchmarks/complex_layout/lib/main.dart
index 634be45..2d349ae 100644
--- a/dev/benchmarks/complex_layout/lib/main.dart
+++ b/dev/benchmarks/complex_layout/lib/main.dart
@@ -438,8 +438,8 @@
                       borderRadius: BorderRadius.circular(2.0),
                     ),
                     padding: const EdgeInsets.all(4.0),
-                    child: RichText(
-                      text: const TextSpan(
+                    child: const RichText(
+                      text: TextSpan(
                         style: TextStyle(color: Colors.white),
                         children: <TextSpan>[
                           TextSpan(
diff --git a/dev/manual_tests/lib/text.dart b/dev/manual_tests/lib/text.dart
index 3d5f482..6382fb3 100644
--- a/dev/manual_tests/lib/text.dart
+++ b/dev/manual_tests/lib/text.dart
@@ -145,7 +145,7 @@
     return TextSpan(
       text: _fiddleWithText(node.text),
       style: _fiddleWithStyle(node.style),
-      children: _fiddleWithChildren(node.children?.map((InlineSpan child) => _fiddleWith(child))?.toList() ?? <InlineSpan>[]),
+      children: _fiddleWithChildren(node.children?.map((TextSpan child) => _fiddleWith(child))?.toList() ?? <TextSpan>[]),
     );
   }
 
diff --git a/packages/flutter/lib/painting.dart b/packages/flutter/lib/painting.dart
index a22d5bf..fe432cb 100644
--- a/packages/flutter/lib/painting.dart
+++ b/packages/flutter/lib/painting.dart
@@ -17,7 +17,7 @@
 ///    painting boxes.
 library painting;
 
-export 'dart:ui' show Shadow, PlaceholderAlignment;
+export 'dart:ui' show Shadow;
 
 export 'src/painting/alignment.dart';
 export 'src/painting/basic_types.dart';
@@ -46,11 +46,9 @@
 export 'src/painting/image_provider.dart';
 export 'src/painting/image_resolution.dart';
 export 'src/painting/image_stream.dart';
-export 'src/painting/inline_span.dart';
 export 'src/painting/matrix_utils.dart';
 export 'src/painting/notched_shapes.dart';
 export 'src/painting/paint_utilities.dart';
-export 'src/painting/placeholder_span.dart';
 export 'src/painting/rounded_rectangle_border.dart';
 export 'src/painting/shader_warm_up.dart';
 export 'src/painting/shape_decoration.dart';
diff --git a/packages/flutter/lib/src/material/time_picker.dart b/packages/flutter/lib/src/material/time_picker.dart
index 8eb322b..9d720aa 100644
--- a/packages/flutter/lib/src/material/time_picker.dart
+++ b/packages/flutter/lib/src/material/time_picker.dart
@@ -993,7 +993,6 @@
         final double width = labelPainter.width * _semanticNodeSizeScale;
         final double height = labelPainter.height * _semanticNodeSizeScale;
         final Offset nodeOffset = getOffsetForTheta(labelTheta, ring) + Offset(-width / 2.0, -height / 2.0);
-        final TextSpan textSpan = labelPainter.text;
         final CustomPainterSemantics node = CustomPainterSemantics(
           rect: Rect.fromLTRB(
             nodeOffset.dx - 24.0 + width / 2,
@@ -1004,7 +1003,7 @@
           properties: SemanticsProperties(
             sortKey: OrdinalSortKey(i.toDouble() + ordinalOffset),
             selected: label.value == selectedValue,
-            value: textSpan?.text,
+            value: labelPainter.text.text,
             textDirection: textDirection,
             onTap: label.onTap,
           ),
diff --git a/packages/flutter/lib/src/painting/inline_span.dart b/packages/flutter/lib/src/painting/inline_span.dart
deleted file mode 100644
index ac09ded..0000000
--- a/packages/flutter/lib/src/painting/inline_span.dart
+++ /dev/null
@@ -1,249 +0,0 @@
-// Copyright 2015 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 'dart:ui' as ui show ParagraphBuilder;
-
-import 'package:flutter/foundation.dart';
-
-import 'basic_types.dart';
-import 'text_painter.dart';
-import 'text_style.dart';
-
-/// Mutable wrapper of an integer that can be passed by reference to track a
-/// value across a recursive stack.
-class Accumulator {
-  /// [Accumulator] may be initialized with a specified value, otherwise, it will
-  /// initialize to zero.
-  Accumulator([this._value = 0]);
-
-  /// The integer stored in this [Accumulator].
-  int get value => _value;
-  int _value;
-
-  /// Increases the [value] by the `addend`.
-  void increment(int addend) {
-    assert(addend >= 0);
-    _value += addend;
-  }
-}
-/// Called on each span as [InlineSpan.visitChildren] walks the [InlineSpan] tree.
-///
-/// Returns true when the walk should continue, and false to stop visiting further
-/// [InlineSpan]s.
-typedef InlineSpanVisitor = bool Function(InlineSpan span);
-
-/// An immutable span of inline content which forms part of a paragraph.
-///
-///  * The subclass [TextSpan] specifies text and may contain child [InlineSpan]s.
-///  * The subclass [PlaceholderSpan] represents a placeholder that may be
-///    filled with non-text content. [PlaceholderSpan] itself defines a
-///    [ui.PlaceholderAlignemnt] and a [TextBaseline]. To be useful,
-///    [PlaceholderSpan] must be extended to define content. An instance of
-///    this is the [WidgetSpan] class in the widgets library.
-///  * The subclass [WidgetSpan] specifies embedded inline widgets.
-///
-/// {@tool sample}
-///
-/// This example shows a tree of [InlineSpan]s that make a query asking for a
-/// name with a [TextField] embedded inline.
-///
-/// ```dart
-/// Text.rich(
-///   TextSpan(
-///     text: 'My name is ',
-///     style: TextStyle(color: Colors.black),
-///     children: <InlineSpan>[
-///       WidgetSpan(
-///         alignment: PlaceholderAlignment.baseline,
-///         baseline: TextBaseline.alphabetic,
-///         child: ConstrainedBox(
-///           constraints: BoxConstraints(maxWidth: 100),
-///           child: TextField(),
-///         )
-///       ),
-///       TextSpan(
-///         text: '.',
-///       ),
-///     ],
-///   ),
-/// )
-/// ```
-/// {@end-tool}
-///
-/// See also:
-///
-///  * [Text], a widget for showing uniformly-styled text.
-///  * [RichText], a widget for finer control of text rendering.
-///  * [TextPainter], a class for painting [InlineSpan] objects on a [Canvas].
-@immutable
-abstract class InlineSpan extends DiagnosticableTree {
-  /// Creates an [InlineSpan] with the given values.
-  const InlineSpan({
-    this.style,
-  });
-
-  /// The [TextStyle] to apply to this span.
-  ///
-  /// The [style] is also applied to any child spans when this is an instance
-  /// of [TextSpan].
-  final TextStyle style;
-
-  /// Apply the properties of this object to the given [ParagraphBuilder], from
-  /// which a [Paragraph] can be obtained.
-  ///
-  /// The `textScaleFactor` parameter specifies a scale that the text and
-  /// placeholders will be scaled by. The scaling is performed before layout,
-  /// so the text will be laid out with the scaled glyphs and placeholders.
-  ///
-  /// The `dimensions` parameter specifies the sizes of the placeholders.
-  /// Each [PlaceholderSpan] must be paired with a [PlaceholderDimensions]
-  /// in the same order as defined in the [InlineSpan] tree.
-  ///
-  /// [Paragraph] objects can be drawn on [Canvas] objects.
-  void build(ui.ParagraphBuilder builder, { double textScaleFactor = 1.0, List<PlaceholderDimensions> dimensions });
-
-  /// Walks this [InlineSpan] and any descendants in pre-order and calls `visitor`
-  /// for each span that has content.
-  ///
-  /// When `visitor` returns true, the walk will continue. When `visitor` returns
-  /// false, then the walk will end.
-  bool visitChildren(InlineSpanVisitor visitor);
-
-  /// Returns the text span that contains the given position in the text.
-  InlineSpan getSpanForPosition(TextPosition position) {
-    assert(debugAssertIsValid());
-    final Accumulator offset = Accumulator();
-    InlineSpan result;
-    visitChildren((InlineSpan span) {
-      result = span.getSpanForPositionVisitor(position, offset);
-      return result == null;
-    });
-    return result;
-  }
-
-  /// Performs the check at each [InlineSpan] for if the `position` falls within the range
-  /// of the span and returns the span if it does.
-  ///
-  /// The `offset` parameter tracks the current index offset in the text buffer formed
-  /// if the contents of the [InlineSpan] tree were concatenated together starting
-  /// from the root [InlineSpan].
-  ///
-  /// This method should not be directly called. Use [getSpanForPosition] instead.
-  @protected
-  InlineSpan getSpanForPositionVisitor(TextPosition position, Accumulator offset);
-
-  /// Flattens the [InlineSpan] tree into a single string.
-  ///
-  /// Styles are not honored in this process. If `includeSemanticsLabels` is
-  /// true, then the text returned will include the [TextSpan.semanticsLabel]s
-  /// instead of the text contents for [TextSpan]s.
-  ///
-  /// When `includePlaceholders` is true, [PlaceholderSpan]s in the tree will be
-  /// represented as a 0xFFFC 'object replacement character'.
-  String toPlainText({bool includeSemanticsLabels = true, bool includePlaceholders = true}) {
-    final StringBuffer buffer = StringBuffer();
-    computeToPlainText(buffer, includeSemanticsLabels: includeSemanticsLabels, includePlaceholders: includePlaceholders);
-    return buffer.toString();
-  }
-
-  /// Walks the [InlineSpan] tree and writes the plain text representation to `buffer`.
-  ///
-  /// This method should not be directly called. Use [toPlainText] instead.
-  ///
-  /// Styles are not honored in this process. If `includeSemanticsLabels` is
-  /// true, then the text returned will include the [TextSpan.semanticsLabel]s
-  /// instead of the text contents for [TextSpan]s.
-  ///
-  /// When `includePlaceholders` is true, [PlaceholderSpan]s in the tree will be
-  /// represented as a 0xFFFC 'object replacement character'.
-  ///
-  /// The plain-text representation of this [InlineSpan] is written into the `buffer`.
-  /// This method will then recursively call [computeToPlainText] on its childen
-  /// [InlineSpan]s if available.
-  @protected
-  void computeToPlainText(StringBuffer buffer, {bool includeSemanticsLabels = true, bool includePlaceholders = true});
-
-  /// Returns the UTF-16 code unit at the given `index` in the flattened string.
-  ///
-  /// This only accounts for the [TextSpan.text] values and ignores [PlaceholderSpans].
-  ///
-  /// Returns null if the `index` is out of bounds.
-  int codeUnitAt(int index) {
-    if (index < 0)
-      return null;
-    final Accumulator offset = Accumulator();
-    int result;
-    visitChildren((InlineSpan span) {
-      result = span.codeUnitAtVisitor(index, offset);
-      return result == null;
-    });
-    return result;
-  }
-
-  /// Performs the check at each [InlineSpan] for if the `index` falls within the range
-  /// of the span and returns the corresponding code unit. Returns null otherwise.
-  ///
-  /// The `offset` parameter tracks the current index offset in the text buffer formed
-  /// if the contents of the [InlineSpan] tree were concatenated together starting
-  /// from the root [InlineSpan].
-  ///
-  /// This method should not be directly called. Use [codeUnitAt] instead.
-  @protected
-  int codeUnitAtVisitor(int index, Accumulator offset);
-
-  /// Populates the `semanticsOffsets` and `semanticsElements` with the appropriate data
-  /// to be able to construct a [SemanticsNode].
-  ///
-  /// If applicable, the beginning and end text offset are added to [semanticsOffsets].
-  /// [PlaceholderSpan]s have a text length of 1, which corresponds to the object
-  /// replacement character (0xFFFC) that is inserted to represent it.
-  ///
-  /// Any [GestureRecognizer]s are added to `semanticsElements`. Null is added to
-  /// `semanticsElements` for [PlaceholderSpan]s.
-  void describeSemantics(Accumulator offset, List<int> semanticsOffsets, List<dynamic> semanticsElements);
-
-  /// In checked mode, throws an exception if the object is not in a
-  /// valid configuration. Otherwise, returns true.
-  ///
-  /// This is intended to be used as follows:
-  ///
-  /// ```dart
-  /// assert(myInlineSpan.debugAssertIsValid());
-  /// ```
-  bool debugAssertIsValid() => true;
-
-  /// Describe the difference between this span and another, in terms of
-  /// how much damage it will make to the rendering. The comparison is deep.
-  ///
-  /// Comparing [InlineSpan] objects of different types, for example, comparing
-  /// a [TextSpan] to a [WidgetSpan], always results in [RenderComparison.layout].
-  ///
-  /// See also:
-  ///
-  ///  * [TextStyle.compareTo], which does the same thing for [TextStyle]s.
-  RenderComparison compareTo(InlineSpan other);
-
-  @override
-  bool operator ==(dynamic other) {
-    if (identical(this, other))
-      return true;
-    if (other.runtimeType != runtimeType)
-      return false;
-    final InlineSpan typedOther = other;
-    return typedOther.style == style;
-  }
-
-  @override
-  int get hashCode => style.hashCode;
-
-  @override
-  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
-    super.debugFillProperties(properties);
-    properties.defaultDiagnosticsTreeStyle = DiagnosticsTreeStyle.whitespace;
-
-    if (style != null) {
-      style.debugFillProperties(properties);
-    }
-  }
-}
diff --git a/packages/flutter/lib/src/painting/placeholder_span.dart b/packages/flutter/lib/src/painting/placeholder_span.dart
deleted file mode 100644
index e052ea6..0000000
--- a/packages/flutter/lib/src/painting/placeholder_span.dart
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2015 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 'dart:ui' as ui show PlaceholderAlignment;
-
-import 'package:flutter/foundation.dart';
-
-import 'basic_types.dart';
-import 'inline_span.dart';
-import 'text_painter.dart';
-import 'text_span.dart';
-import 'text_style.dart';
-
-/// An immutable placeholder that is embedded inline within text.
-///
-/// [PlaceholderSpan] represents a placeholder that acts as a stand-in for other
-/// content. A [PlaceholderSpan] by itself does not contain useful
-/// information to change a [TextSpan]. Instead, this class must be extended
-/// to define contents.
-///
-/// [WidgetSpan] from the widgets library extends [PlaceholderSpan] and may be
-/// used instead to specify a widget as the contents of the placeholder.
-///
-/// See also:
-///
-///  * [WidgetSpan], a leaf node that represents an embedded inline widget.
-///  * [TextSpan], a node that represents text in a [TextSpan] tree.
-///  * [Text], a widget for showing uniformly-styled text.
-///  * [RichText], a widget for finer control of text rendering.
-///  * [TextPainter], a class for painting [TextSpan] objects on a [Canvas].
-abstract class PlaceholderSpan extends InlineSpan {
-  /// Creates a [PlaceholderSpan] with the given values.
-  ///
-  /// A [TextStyle] may be provided with the [style] property, but only the
-  /// decoration, foreground, background, and spacing options will be used.
-  const PlaceholderSpan({
-    this.alignment = ui.PlaceholderAlignment.bottom,
-    this.baseline,
-    TextStyle style,
-  }) : super(style: style,);
-
-  /// How the placeholder aligns vertically with the text.
-  ///
-  /// See [ui.PlaceholderAlignment] for details on each mode.
-  final ui.PlaceholderAlignment alignment;
-
-  /// The [TextBaseline] to align against when using [ui.PlaceholderAlignment.baseline],
-  /// [ui.PlaceholderAlignment.aboveBaseline], and [ui.PlaceholderAlignment.belowBaseline].
-  ///
-  /// This is ignored when using other alignment modes.
-  final TextBaseline baseline;
-
-  /// [PlaceholderSpan]s are flattened to a `0xFFFC` object replacement character in the
-  /// plain text representation when `includePlaceholders` is true.
-  @override
-  void computeToPlainText(StringBuffer buffer, {bool includeSemanticsLabels = true, bool includePlaceholders = true}) {
-    if (includePlaceholders) {
-      buffer.write('\uFFFC');
-    }
-  }
-
-  /// Populates the `semanticsOffsets` and `semanticsElements` with the appropriate data
-  /// to be able to construct a [SemanticsNode].
-  ///
-  /// [PlaceholderSpan]s have a text length of 1, which corresponds to the object
-  /// replacement character (0xFFFC) that is inserted to represent it.
-  ///
-  /// Null is added to `semanticsElements` for [PlaceholderSpan]s.
-  @override
-  void describeSemantics(Accumulator offset, List<int> semanticsOffsets, List<dynamic> semanticsElements) {
-    semanticsOffsets.add(offset.value);
-    semanticsOffsets.add(offset.value + 1);
-    semanticsElements.add(null); // null indicates this is a placeholder.
-    offset.increment(1);
-  }
-
-  @override
-  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
-    super.debugFillProperties(properties);
-
-    properties.add(EnumProperty<ui.PlaceholderAlignment>('alignment', alignment, defaultValue: null));
-    properties.add(EnumProperty<TextBaseline>('baseline', baseline, defaultValue: null));
-  }
-}
diff --git a/packages/flutter/lib/src/painting/text_painter.dart b/packages/flutter/lib/src/painting/text_painter.dart
index 0c61959..b4f20cb 100644
--- a/packages/flutter/lib/src/painting/text_painter.dart
+++ b/packages/flutter/lib/src/painting/text_painter.dart
@@ -3,82 +3,18 @@
 // found in the LICENSE file.
 
 import 'dart:math' show min, max;
-import 'dart:ui' as ui show Paragraph, ParagraphBuilder, ParagraphConstraints, ParagraphStyle, PlaceholderAlignment;
+import 'dart:ui' as ui show Paragraph, ParagraphBuilder, ParagraphConstraints, ParagraphStyle;
 
 import 'package:flutter/foundation.dart';
 import 'package:flutter/gestures.dart';
 import 'package:flutter/services.dart';
 
 import 'basic_types.dart';
-import 'inline_span.dart';
-import 'placeholder_span.dart';
 import 'strut_style.dart';
 import 'text_span.dart';
 
 export 'package:flutter/services.dart' show TextRange, TextSelection;
 
-/// Holds the [Size] and baseline required to represent the dimensions of
-/// a placeholder in text.
-///
-/// Placeholders specify an empty space in the text layout, which is used
-/// to later render arbitrary inline widgets into defined by a [WidgetSpan].
-///
-/// The [size] and [alignment] properties are required and cannot be null.
-///
-/// See also:
-///
-///  * [WidgetSpan], a subclass of [InlineSpan] and [PlaceholderSpan] that
-///    represents an inline widget embedded within text. The space this
-///    widget takes is indicated by a placeholder.
-///  * [RichText], a text widget that supports text inline widgets.
-@immutable
-class PlaceholderDimensions {
-  /// Constructs a [PlaceholderDimensions] with the specified parameters.
-  ///
-  /// The `size` and `alignment` are required as a placeholder's dimensions
-  /// require at least `size` and `alignment` to be fully defined.
-  const PlaceholderDimensions({
-    @required this.size,
-    @required this.alignment,
-    this.baseline,
-    this.baselineOffset,
-  }) : assert(size != null),
-       assert(alignment != null);
-
-  /// Width and height dimensions of the placeholder.
-  final Size size;
-
-  /// How to align the placeholder with the text.
-  ///
-  /// See also:
-  ///
-  ///  * [baseline], the baseline to align to when using
-  ///    [ui.PlaceholderAlignment.baseline],
-  ///    [ui.PlaceholderAlignment.aboveBaseline],
-  ///    or [ui.PlaceholderAlignment.underBaseline].
-  ///  * [baselineOffset], the distance of the alphabetic baseline from the upper
-  ///    edge of the placeholder.
-  final ui.PlaceholderAlignment alignment;
-
-  /// Distance of the [baseline] from the upper edge of the placeholder.
-  ///
-  /// Only used when [alignment] is [ui.PlaceholderAlignment.baseline].
-  final double baselineOffset;
-
-  /// The [TextBaseline] to align to. Used with:
-  ///
-  ///  * [ui.PlaceholderAlignment.baseline]
-  ///  * [ui.PlaceholderAlignment.aboveBaseline]
-  ///  * [ui.PlaceholderAlignment.underBaseline]
-  ///  * [ui.PlaceholderAlignment.middle]
-  final TextBaseline baseline;
-
-  @override
-  String toString() {
-    return 'PlaceholderDimensions($size, $baseline)';
-  }
-}
-
 /// The different ways of considering the width of one or more lines of text.
 ///
 /// See [Text.widthType].
@@ -94,9 +30,6 @@
   longestLine,
 }
 
-/// This is used to cache and pass the computed metrics regarding the
-/// caret's size and position. This is preferred due to the expensive
-/// nature of the calculation.
 class _CaretMetrics {
   const _CaretMetrics({this.offset, this.fullHeight});
   /// The offset of the top left corner of the caret from the top left
@@ -134,7 +67,7 @@
   ///
   /// The [maxLines] property, if non-null, must be greater than zero.
   TextPainter({
-    InlineSpan text,
+    TextSpan text,
     TextAlign textAlign = TextAlign.start,
     TextDirection textDirection,
     double textScaleFactor = 1.0,
@@ -166,9 +99,9 @@
   /// After this is set, you must call [layout] before the next call to [paint].
   ///
   /// This and [textDirection] must be non-null before you call [layout].
-  InlineSpan get text => _text;
-  InlineSpan _text;
-  set text(InlineSpan value) {
+  TextSpan get text => _text;
+  TextSpan _text;
+  set text(TextSpan value) {
     assert(value == null || value.debugAssertIsValid());
     if (_text == value)
       return;
@@ -333,53 +266,6 @@
 
   ui.Paragraph _layoutTemplate;
 
-  /// An ordered list of [TextBox]es that bound the positions of the placeholders
-  /// in the paragraph.
-  ///
-  /// Each box corresponds to a [PlaceholderSpan] in the order they were defined
-  /// in the [InlineSpan] tree.
-  List<TextBox> get inlinePlaceholderBoxes => _inlinePlaceholderBoxes;
-  List<TextBox> _inlinePlaceholderBoxes;
-
-  /// An ordered list of scales for each placeholder in the paragraph.
-  ///
-  /// The scale is used as a multiplier on the height, width and baselineOffset of
-  /// the placeholder. Scale is primarily used to handle accessibility scaling.
-  ///
-  /// Each scale corresponds to a [PlaceholderSpan] in the order they were defined
-  /// in the [InlineSpan] tree.
-  List<double> get inlinePlaceholderScales => _inlinePlaceholderScales;
-  List<double> _inlinePlaceholderScales;
-
-  /// Sets the dimensions of each placeholder in [text].
-  ///
-  /// The number of [PlaceholderDimensions] provided should be the same as the
-  /// number of [PlaceholderSpan]s in text. Passing in an empty or null `value`
-  /// will do nothing.
-  ///
-  /// If [layout] is attempted without setting the placeholder dimensions, the
-  /// placeholders will be ignored in the text layout and no valid
-  /// [inlinePlaceholderBoxes] will be returned.
-  void setPlaceholderDimensions(List<PlaceholderDimensions> value) {
-    if (value == null || value.isEmpty || listEquals(value, _placeholderDimensions)) {
-      return;
-    }
-    assert(() {
-      int placeholderCount = 0;
-      text.visitChildren((InlineSpan span) {
-        if (span is PlaceholderSpan) {
-          placeholderCount += 1;
-        }
-        return true;
-      });
-      return placeholderCount;
-    }() == value.length);
-    _placeholderDimensions = value;
-    _needsLayout = true;
-    _paragraph = null;
-  }
-  List<PlaceholderDimensions> _placeholderDimensions;
-
   ui.ParagraphStyle _createParagraphStyle([ TextDirection defaultTextDirection ]) {
     // The defaultTextDirection argument is used for preferredLineHeight in case
     // textDirection hasn't yet been set.
@@ -533,8 +419,7 @@
     _needsLayout = false;
     if (_paragraph == null) {
       final ui.ParagraphBuilder builder = ui.ParagraphBuilder(_createParagraphStyle());
-      _text.build(builder, textScaleFactor: textScaleFactor, dimensions: _placeholderDimensions);
-      _inlinePlaceholderScales = builder.placeholderScales;
+      _text.build(builder, textScaleFactor: textScaleFactor);
       _paragraph = builder.build();
     }
     _lastMinWidth = minWidth;
@@ -542,11 +427,9 @@
     _paragraph.layout(ui.ParagraphConstraints(width: maxWidth));
     if (minWidth != maxWidth) {
       final double newWidth = maxIntrinsicWidth.clamp(minWidth, maxWidth);
-      if (newWidth != width) {
+      if (newWidth != width)
         _paragraph.layout(ui.ParagraphConstraints(width: newWidth));
-      }
     }
-    _inlinePlaceholderBoxes = _paragraph.getBoxesForPlaceholders();
   }
 
   /// Paints the text onto the given canvas at the given offset.
@@ -608,7 +491,7 @@
   // TODO(garyq): Use actual extended grapheme cluster length instead of
   // an increasing cluster length amount to achieve deterministic performance.
   Rect _getRectFromUpstream(int offset, Rect caretPrototype) {
-    final String flattenedText = _text.toPlainText(includePlaceholders: false);
+    final String flattenedText = _text.toPlainText();
     final int prevCodeUnit = _text.codeUnitAt(max(0, offset - 1));
     if (prevCodeUnit == null)
       return null;
@@ -624,12 +507,10 @@
       if (boxes.isEmpty) {
         // When we are at the beginning of the line, a non-surrogate position will
         // return empty boxes. We break and try from downstream instead.
-        if (!needsSearch) {
+        if (!needsSearch)
           break; // Only perform one iteration if no search is required.
-        }
-        if (prevRuneOffset < -flattenedText.length) {
+        if (prevRuneOffset < -flattenedText.length)
           break; // Stop iterating when beyond the max length of the text.
-        }
         // Multiply by two to log(n) time cover the entire text span. This allows
         // faster discovery of very long clusters and reduces the possibility
         // of certain large clusters taking much longer than others, which can
@@ -657,7 +538,7 @@
   // TODO(garyq): Use actual extended grapheme cluster length instead of
   // an increasing cluster length amount to achieve deterministic performance.
   Rect _getRectFromDownstream(int offset, Rect caretPrototype) {
-    final String flattenedText = _text.toPlainText(includePlaceholders: false);
+    final String flattenedText = _text.toPlainText();
     // We cap the offset at the final index of the _text.
     final int nextCodeUnit = _text.codeUnitAt(min(offset, flattenedText == null ? 0 : flattenedText.length - 1));
     if (nextCodeUnit == null)
@@ -673,12 +554,10 @@
       if (boxes.isEmpty) {
         // When we are at the end of the line, a non-surrogate position will
         // return empty boxes. We break and try from upstream instead.
-        if (!needsSearch) {
+        if (!needsSearch)
           break; // Only perform one iteration if no search is required.
-        }
-        if (nextRuneOffset >= flattenedText.length << 1) {
+        if (nextRuneOffset >= flattenedText.length << 1)
           break; // Stop iterating when beyond the max length of the text.
-        }
         // Multiply by two to log(n) time cover the entire text span. This allows
         // faster discovery of very long clusters and reduces the possibility
         // of certain large clusters taking much longer than others, which can
diff --git a/packages/flutter/lib/src/painting/text_span.dart b/packages/flutter/lib/src/painting/text_span.dart
index 31baf09..bba61a7 100644
--- a/packages/flutter/lib/src/painting/text_span.dart
+++ b/packages/flutter/lib/src/painting/text_span.dart
@@ -9,8 +9,6 @@
 import 'package:flutter/services.dart';
 
 import 'basic_types.dart';
-import 'inline_span.dart';
-import 'text_painter.dart';
 import 'text_style.dart';
 
 /// An immutable span of text.
@@ -23,9 +21,7 @@
 /// only partially) override the [style] of this object. If a
 /// [TextSpan] has both [text] and [children], then the [text] is
 /// treated as if it was an unstyled [TextSpan] at the start of the
-/// [children] list. Leaving the [TextSpan.text] field null results
-/// in the [TextSpan] acting as an empty node in the [InlineSpan]
-/// tree with a list of children.
+/// [children] list.
 ///
 /// To paint a [TextSpan] on a [Canvas], use a [TextPainter]. To display a text
 /// span in a widget, use a [RichText]. For text with a single style, consider
@@ -46,33 +42,27 @@
 /// _There is some more detailed sample code in the documentation for the
 /// [recognizer] property._
 ///
-/// The [TextSpan.text] will be used as the semantics label unless overriden
-/// by the [TextSpan.semanticsLabel] property. Any [PlaceholderSpan]s in the
-/// [TextSpan.children] list will separate the text before and after it into
-/// two semantics nodes.
-///
 /// See also:
 ///
-///  * [WidgetSpan], a leaf node that represents an embedded inline widget
-///    in an [InlineSpan] tree. Specify a widget within the [children]
-///    list by wrapping the widget with a [WidgetSpan]. The widget will be
-///    laid out inline within the paragraph.
 ///  * [Text], a widget for showing uniformly-styled text.
 ///  * [RichText], a widget for finer control of text rendering.
 ///  * [TextPainter], a class for painting [TextSpan] objects on a [Canvas].
 @immutable
-class TextSpan extends InlineSpan {
+class TextSpan extends DiagnosticableTree {
   /// Creates a [TextSpan] with the given values.
   ///
   /// For the object to be useful, at least one of [text] or
   /// [children] should be set.
   const TextSpan({
+    this.style,
     this.text,
     this.children,
-    TextStyle style,
     this.recognizer,
     this.semanticsLabel,
-  }) : super(style: style,);
+  });
+
+  /// The style to apply to the [text] and the [children].
+  final TextStyle style;
 
   /// The text contained in the span.
   ///
@@ -89,26 +79,26 @@
   /// supported and may have unexpected results.
   ///
   /// The list must not contain any nulls.
-  final List<InlineSpan> children;
+  final List<TextSpan> children;
 
-  /// A gesture recognizer that will receive events that hit this span.
+  /// A gesture recognizer that will receive events that hit this text span.
   ///
-  /// [InlineSpan] itself does not implement hit testing or event dispatch. The
-  /// object that manages the [InlineSpan] painting is also responsible for
+  /// [TextSpan] itself does not implement hit testing or event dispatch. The
+  /// object that manages the [TextSpan] painting is also responsible for
   /// dispatching events. In the rendering library, that is the
   /// [RenderParagraph] object, which corresponds to the [RichText] widget in
-  /// the widgets layer; these objects do not bubble events in [InlineSpan]s, so a
+  /// the widgets layer; these objects do not bubble events in [TextSpan]s, so a
   /// [recognizer] is only effective for events that directly hit the [text] of
-  /// that [InlineSpan], not any of its [children].
+  /// that [TextSpan], not any of its [children].
   ///
-  /// [InlineSpan] also does not manage the lifetime of the gesture recognizer.
+  /// [TextSpan] also does not manage the lifetime of the gesture recognizer.
   /// The code that owns the [GestureRecognizer] object must call
-  /// [GestureRecognizer.dispose] when the [InlineSpan] object is no longer used.
+  /// [GestureRecognizer.dispose] when the [TextSpan] object is no longer used.
   ///
   /// {@tool sample}
   ///
   /// This example shows how to manage the lifetime of a gesture recognizer
-  /// provided to an [InlineSpan] object. It defines a `BuzzingText` widget which
+  /// provided to a [TextSpan] object. It defines a `BuzzingText` widget which
   /// uses the [HapticFeedback] class to vibrate the device when the user
   /// long-presses the "find the" span, which is underlined in wavy green. The
   /// hit-testing is handled by the [RichText] widget.
@@ -141,11 +131,11 @@
   ///
   ///   @override
   ///   Widget build(BuildContext context) {
-  ///     return Text.rich(
-  ///       TextSpan(
+  ///     return RichText(
+  ///       text: TextSpan(
   ///         text: 'Can you ',
   ///         style: TextStyle(color: Colors.black),
-  ///         children: <InlineSpan>[
+  ///         children: <TextSpan>[
   ///           TextSpan(
   ///             text: 'find the',
   ///             style: TextStyle(
@@ -167,7 +157,7 @@
   /// {@end-tool}
   final GestureRecognizer recognizer;
 
-  /// An alternative semantics label for this [TextSpan].
+  /// An alternative semantics label for this text.
   ///
   /// If present, the semantics of this span will contain this value instead
   /// of the actual text.
@@ -187,8 +177,7 @@
   /// Rather than using this directly, it's simpler to use the
   /// [TextPainter] class to paint [TextSpan] objects onto [Canvas]
   /// objects.
-  @override
-  void build(ui.ParagraphBuilder builder, { double textScaleFactor = 1.0, List<PlaceholderDimensions> dimensions }) {
+  void build(ui.ParagraphBuilder builder, { double textScaleFactor = 1.0 }) {
     assert(debugAssertIsValid());
     final bool hasStyle = style != null;
     if (hasStyle)
@@ -196,9 +185,9 @@
     if (text != null)
       builder.addText(text);
     if (children != null) {
-      for (InlineSpan child in children) {
+      for (TextSpan child in children) {
         assert(child != null);
-        child.build(builder, textScaleFactor: textScaleFactor, dimensions: dimensions);
+        child.build(builder, textScaleFactor: textScaleFactor);
       }
     }
     if (hasStyle)
@@ -207,15 +196,14 @@
 
   /// Walks this text span and its descendants in pre-order and calls [visitor]
   /// for each span that has text.
-  @override
-  bool visitChildren(InlineSpanVisitor visitor) {
+  bool visitTextSpan(bool visitor(TextSpan span)) {
     if (text != null) {
       if (!visitor(this))
         return false;
     }
     if (children != null) {
-      for (InlineSpan child in children) {
-        if (!child.visitChildren(visitor))
+      for (TextSpan child in children) {
+        if (!child.visitTextSpan(visitor))
           return false;
       }
     }
@@ -223,62 +211,63 @@
   }
 
   /// Returns the text span that contains the given position in the text.
-  @override
-  InlineSpan getSpanForPositionVisitor(TextPosition position, Accumulator offset) {
-    if (text == null) {
-      return null;
-    }
+  TextSpan getSpanForPosition(TextPosition position) {
+    assert(debugAssertIsValid());
     final TextAffinity affinity = position.affinity;
     final int targetOffset = position.offset;
-    final int endOffset = offset.value + text.length;
-    if (offset.value == targetOffset && affinity == TextAffinity.downstream ||
-        offset.value < targetOffset && targetOffset < endOffset ||
-        endOffset == targetOffset && affinity == TextAffinity.upstream) {
-      return this;
-    }
-    offset.increment(text.length);
-    return null;
-  }
-
-  @override
-  void computeToPlainText(StringBuffer buffer, {bool includeSemanticsLabels = true, bool includePlaceholders = true}) {
-    assert(debugAssertIsValid());
-    if (semanticsLabel != null && includeSemanticsLabels) {
-      buffer.write(semanticsLabel);
-    } else if (text != null) {
-      buffer.write(text);
-    }
-    if (children != null) {
-      for (InlineSpan child in children) {
-        child.computeToPlainText(buffer,
-          includeSemanticsLabels: includeSemanticsLabels,
-          includePlaceholders: includePlaceholders,
-        );
+    int offset = 0;
+    TextSpan result;
+    visitTextSpan((TextSpan span) {
+      assert(result == null);
+      final int endOffset = offset + span.text.length;
+      if (targetOffset == offset && affinity == TextAffinity.downstream ||
+          targetOffset > offset && targetOffset < endOffset ||
+          targetOffset == endOffset && affinity == TextAffinity.upstream) {
+        result = span;
+        return false;
       }
-    }
+      offset = endOffset;
+      return true;
+    });
+    return result;
   }
 
-  @override
-  int codeUnitAtVisitor(int index, Accumulator offset) {
-    if (text == null) {
+  /// Flattens the [TextSpan] tree into a single string.
+  ///
+  /// Styles are not honored in this process. If `includeSemanticsLabels` is
+  /// true, then the text returned will include the [semanticsLabel]s instead of
+  /// the text contents when they are present.
+  String toPlainText({bool includeSemanticsLabels = true}) {
+    assert(debugAssertIsValid());
+    final StringBuffer buffer = StringBuffer();
+    visitTextSpan((TextSpan span) {
+      if (span.semanticsLabel != null && includeSemanticsLabels) {
+        buffer.write(span.semanticsLabel);
+      } else {
+        buffer.write(span.text);
+      }
+      return true;
+    });
+    return buffer.toString();
+  }
+
+  /// Returns the UTF-16 code unit at the given index in the flattened string.
+  ///
+  /// Returns null if the index is out of bounds.
+  int codeUnitAt(int index) {
+    if (index < 0)
       return null;
-    }
-    if (index - offset.value < text.length) {
-      return text.codeUnitAt(index - offset.value);
-    }
-    offset.increment(text.length);
-    return null;
-  }
-
-  @override
-  void describeSemantics(Accumulator offset, List<int> semanticsOffsets, List<dynamic> semanticsElements) {
-    if (recognizer != null && (recognizer is TapGestureRecognizer || recognizer is LongPressGestureRecognizer)) {
-      final int length = semanticsLabel?.length ?? text.length;
-      semanticsOffsets.add(offset.value);
-      semanticsOffsets.add(offset.value + length);
-      semanticsElements.add(recognizer);
-    }
-    offset.increment(text != null ? text.length : 0);
+    int offset = 0;
+    int result;
+    visitTextSpan((TextSpan span) {
+      if (index - offset < span.text.length) {
+        result = span.text.codeUnitAt(index - offset);
+        return false;
+      }
+      offset += span.text.length;
+      return true;
+    });
+    return result;
   }
 
   /// In checked mode, throws an exception if the object is not in a
@@ -289,39 +278,45 @@
   /// ```dart
   /// assert(myTextSpan.debugAssertIsValid());
   /// ```
-  @override
   bool debugAssertIsValid() {
     assert(() {
-      if (children != null) {
-        for (InlineSpan child in children) {
-          assert(child != null,
-            '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(prefixLineOne: '  ')}'
-          );
-          assert(child.debugAssertIsValid());
+      if (!visitTextSpan((TextSpan span) {
+        if (span.children != null) {
+          for (TextSpan child in span.children) {
+            if (child == null)
+              return false;
+          }
         }
+        return true;
+      })) {
+        throw 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'
+          '${toStringDeep(prefixLineOne: '  ')}'
+        );
       }
       return true;
     }());
-    return super.debugAssertIsValid();
+    return true;
   }
 
-  @override
-  RenderComparison compareTo(InlineSpan other) {
+  /// Describe the difference between this text span and another, in terms of
+  /// how much damage it will make to the rendering. The comparison is deep.
+  ///
+  /// See also:
+  ///
+  ///  * [TextStyle.compareTo], which does the same thing for [TextStyle]s.
+  RenderComparison compareTo(TextSpan other) {
     if (identical(this, other))
       return RenderComparison.identical;
-    if (other.runtimeType != runtimeType)
+    if (other.text != text ||
+        children?.length != other.children?.length ||
+        (style == null) != (other.style == null))
       return RenderComparison.layout;
-    final TextSpan textSpan = other;
-    if (textSpan.text != text ||
-        children?.length != textSpan.children?.length ||
-        (style == null) != (textSpan.style == null))
-      return RenderComparison.layout;
-    RenderComparison result = recognizer == textSpan.recognizer ? RenderComparison.identical : RenderComparison.metadata;
+    RenderComparison result = recognizer == other.recognizer ? RenderComparison.identical : RenderComparison.metadata;
     if (style != null) {
-      final RenderComparison candidate = style.compareTo(textSpan.style);
+      final RenderComparison candidate = style.compareTo(other.style);
       if (candidate.index > result.index)
         result = candidate;
       if (result == RenderComparison.layout)
@@ -329,7 +324,7 @@
     }
     if (children != null) {
       for (int index = 0; index < children.length; index += 1) {
-        final RenderComparison candidate = children[index].compareTo(textSpan.children[index]);
+        final RenderComparison candidate = children[index].compareTo(other.children[index]);
         if (candidate.index > result.index)
           result = candidate;
         if (result == RenderComparison.layout)
@@ -345,17 +340,16 @@
       return true;
     if (other.runtimeType != runtimeType)
       return false;
-    if (super != other)
-      return false;
     final TextSpan typedOther = other;
     return typedOther.text == text
+        && typedOther.style == style
         && typedOther.recognizer == recognizer
         && typedOther.semanticsLabel == semanticsLabel
-        && listEquals<InlineSpan>(typedOther.children, children);
+        && listEquals<TextSpan>(typedOther.children, children);
   }
 
   @override
-  int get hashCode => hashValues(super.hashCode, text, recognizer, semanticsLabel, hashList(children));
+  int get hashCode => hashValues(style, text, recognizer, semanticsLabel, hashList(children));
 
   @override
   String toStringShort() => '$runtimeType';
@@ -363,10 +357,11 @@
   @override
   void debugFillProperties(DiagnosticPropertiesBuilder properties) {
     super.debugFillProperties(properties);
-
-    properties.add(StringProperty('text', text, showName: false, defaultValue: null));
-    if (style == null && text == null && children == null)
-      properties.add(DiagnosticsNode.message('(empty)'));
+    properties.defaultDiagnosticsTreeStyle = DiagnosticsTreeStyle.whitespace;
+    // Properties on style are added as if they were properties directly on
+    // this TextSpan.
+    if (style != null)
+      style.debugFillProperties(properties);
 
     properties.add(DiagnosticsProperty<GestureRecognizer>(
       'recognizer', recognizer,
@@ -374,16 +369,22 @@
       defaultValue: null,
     ));
 
+
     if (semanticsLabel != null) {
       properties.add(StringProperty('semanticsLabel', semanticsLabel));
     }
+
+
+    properties.add(StringProperty('text', text, showName: false, defaultValue: null));
+    if (style == null && text == null && children == null)
+      properties.add(DiagnosticsNode.message('(empty)'));
   }
 
   @override
   List<DiagnosticsNode> debugDescribeChildren() {
     if (children == null)
       return const <DiagnosticsNode>[];
-    return children.map<DiagnosticsNode>((InlineSpan child) {
+    return children.map<DiagnosticsNode>((TextSpan child) {
       if (child != null) {
         return child.toDiagnosticsNode();
       } else {
diff --git a/packages/flutter/lib/src/rendering/box.dart b/packages/flutter/lib/src/rendering/box.dart
index bcff74c..0b82947 100644
--- a/packages/flutter/lib/src/rendering/box.dart
+++ b/packages/flutter/lib/src/rendering/box.dart
@@ -1728,10 +1728,7 @@
       return true;
     }());
     _size = value;
-    assert(() {
-      debugAssertDoesMeetConstraints();
-      return true;
-    }());
+    assert(() { debugAssertDoesMeetConstraints(); return true; }());
   }
 
   /// Claims ownership of the given [Size].
diff --git a/packages/flutter/lib/src/rendering/debug_overflow_indicator.dart b/packages/flutter/lib/src/rendering/debug_overflow_indicator.dart
index be8790a..d7a0d6d 100644
--- a/packages/flutter/lib/src/rendering/debug_overflow_indicator.dart
+++ b/packages/flutter/lib/src/rendering/debug_overflow_indicator.dart
@@ -284,8 +284,8 @@
     final List<_OverflowRegionData> overflowRegions = _calculateOverflowRegions(overflow, containerRect);
     for (_OverflowRegionData region in overflowRegions) {
       context.canvas.drawRect(region.rect.shift(offset), _indicatorPaint);
-      final TextSpan textSpan = _indicatorLabel[region.side.index].text;
-      if (textSpan?.text != region.label) {
+
+      if (_indicatorLabel[region.side.index].text?.text != region.label) {
         _indicatorLabel[region.side.index].text = TextSpan(
           text: region.label,
           style: _indicatorTextStyle,
diff --git a/packages/flutter/lib/src/rendering/paragraph.dart b/packages/flutter/lib/src/rendering/paragraph.dart
index b0f44bb..151f0adf 100644
--- a/packages/flutter/lib/src/rendering/paragraph.dart
+++ b/packages/flutter/lib/src/rendering/paragraph.dart
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'dart:ui' as ui show Gradient, Shader, TextBox, PlaceholderAlignment;
+import 'dart:ui' as ui show Gradient, Shader, TextBox;
 
 import 'package:flutter/foundation.dart';
 import 'package:flutter/gestures.dart';
@@ -10,7 +10,6 @@
 import 'package:flutter/semantics.dart';
 import 'package:flutter/services.dart';
 
-import 'package:vector_math/vector_math_64.dart';
 
 import 'box.dart';
 import 'debug.dart';
@@ -36,27 +35,8 @@
 
 const String _kEllipsis = '\u2026';
 
-/// Parent data for use with [RenderParagraph].
-class TextParentData extends ContainerBoxParentData<RenderBox> {
-  /// The scaling of the text.
-  double scale;
-
-  @override
-  String toString() {
-    final List<String> values = <String>[];
-    if (offset != null)
-      values.add('offset=$offset');
-    if (scale != null)
-      values.add('scale=$scale');
-    values.add(super.toString());
-    return values.join('; ');
-  }
-}
-
-/// A render object that displays a paragraph of text.
-class RenderParagraph extends RenderBox
-    with ContainerRenderObjectMixin<RenderBox, TextParentData>,
-             RenderBoxContainerDefaultsMixin<RenderBox, TextParentData> {
+/// A render object that displays a paragraph of text
+class RenderParagraph extends RenderBox {
   /// Creates a paragraph render object.
   ///
   /// The [text], [textAlign], [textDirection], [overflow], [softWrap], and
@@ -64,7 +44,8 @@
   ///
   /// The [maxLines] property may be null (and indeed defaults to null), but if
   /// it is not null, it must be greater than zero.
-  RenderParagraph(InlineSpan text, {
+  RenderParagraph(
+    TextSpan text, {
     TextAlign textAlign = TextAlign.start,
     @required TextDirection textDirection,
     bool softWrap = true,
@@ -74,7 +55,6 @@
     TextWidthBasis textWidthBasis = TextWidthBasis.parent,
     Locale locale,
     StrutStyle strutStyle,
-    List<RenderBox> children,
   }) : assert(text != null),
        assert(text.debugAssertIsValid()),
        assert(textAlign != null),
@@ -96,22 +76,13 @@
          locale: locale,
          strutStyle: strutStyle,
          textWidthBasis: textWidthBasis,
-       ) {
-    addAll(children);
-    _extractPlaceholderSpans(text);
-  }
-
-  @override
-  void setupParentData(RenderBox child) {
-    if (child.parentData is! TextParentData)
-      child.parentData = TextParentData();
-  }
+       );
 
   final TextPainter _textPainter;
 
   /// The text to display
-  InlineSpan get text => _textPainter.text;
-  set text(InlineSpan value) {
+  TextSpan get text => _textPainter.text;
+  set text(TextSpan value) {
     assert(value != null);
     switch (_textPainter.text.compareTo(value)) {
       case RenderComparison.identical:
@@ -119,31 +90,17 @@
         return;
       case RenderComparison.paint:
         _textPainter.text = value;
-        _extractPlaceholderSpans(value);
         markNeedsPaint();
         markNeedsSemanticsUpdate();
         break;
       case RenderComparison.layout:
         _textPainter.text = value;
         _overflowShader = null;
-        _extractPlaceholderSpans(value);
         markNeedsLayout();
         break;
     }
   }
 
-  List<PlaceholderSpan> _placeholderSpans;
-  void _extractPlaceholderSpans(InlineSpan span) {
-    _placeholderSpans = <PlaceholderSpan>[];
-    span.visitChildren((InlineSpan span) {
-      if (span is PlaceholderSpan) {
-        final PlaceholderSpan placeholderSpan = span;
-        _placeholderSpans.add(placeholderSpan);
-      }
-      return true;
-    });
-  }
-
   /// How the text should be aligned horizontally.
   TextAlign get textAlign => _textPainter.textAlign;
   set textAlign(TextAlign value) {
@@ -272,31 +229,28 @@
     markNeedsLayout();
   }
 
+  void _layoutText({ double minWidth = 0.0, double maxWidth = double.infinity }) {
+    final bool widthMatters = softWrap || overflow == TextOverflow.ellipsis;
+    _textPainter.layout(minWidth: minWidth, maxWidth: widthMatters ? maxWidth : double.infinity);
+  }
+
+  void _layoutTextWithConstraints(BoxConstraints constraints) {
+    _layoutText(minWidth: constraints.minWidth, maxWidth: constraints.maxWidth);
+  }
+
   @override
   double computeMinIntrinsicWidth(double height) {
-    if (!_canComputeIntrinsics()) {
-      return 0.0;
-    }
-    _computeChildrenWidthWithMinIntrinsics(height);
-    _layoutText(); // layout with infinite width.
+    _layoutText();
     return _textPainter.minIntrinsicWidth;
   }
 
   @override
   double computeMaxIntrinsicWidth(double height) {
-    if (!_canComputeIntrinsics()) {
-      return 0.0;
-    }
-    _computeChildrenWidthWithMaxIntrinsics(height);
-    _layoutText(); // layout with infinite width.
+    _layoutText();
     return _textPainter.maxIntrinsicWidth;
   }
 
   double _computeIntrinsicHeight(double width) {
-    if (!_canComputeIntrinsics()) {
-      return 0.0;
-    }
-    _computeChildrenHeightWithMinIntrinsics(width);
     _layoutText(minWidth: width, maxWidth: width);
     return _textPainter.height;
   }
@@ -320,115 +274,10 @@
     return _textPainter.computeDistanceToActualBaseline(baseline);
   }
 
-  // Intrinsics cannot be calculated without a full layout for
-  // alignments that require the baseline (baseline, aboveBaseline,
-  // belowBaseline).
-  bool _canComputeIntrinsics() {
-    for (PlaceholderSpan span in _placeholderSpans) {
-      switch (span.alignment) {
-        case ui.PlaceholderAlignment.baseline:
-        case ui.PlaceholderAlignment.aboveBaseline:
-        case ui.PlaceholderAlignment.belowBaseline: {
-          assert(RenderObject.debugCheckingIntrinsics,
-            'Intrinsics are not available for PlaceholderAlignment.baseline, '
-            'PlaceholderAlignment.aboveBaseline, or PlaceholderAlignment.belowBaseline,');
-          return false;
-        }
-        case ui.PlaceholderAlignment.top:
-        case ui.PlaceholderAlignment.middle:
-        case ui.PlaceholderAlignment.bottom: {
-          continue;
-        }
-      }
-    }
-    return true;
-  }
-
-  void _computeChildrenWidthWithMaxIntrinsics(double height) {
-    RenderBox child = firstChild;
-    final List<PlaceholderDimensions> placeholderDimensions = List<PlaceholderDimensions>(childCount);
-    int childIndex = 0;
-    while (child != null) {
-      // Height and baseline is irrelevant as all text will be laid
-      // out in a single line.
-      placeholderDimensions[childIndex] = PlaceholderDimensions(
-        size: Size(child.getMaxIntrinsicWidth(height), height),
-        alignment: _placeholderSpans[childIndex].alignment,
-        baseline: _placeholderSpans[childIndex].baseline,
-      );
-      child = childAfter(child);
-      childIndex += 1;
-    }
-    _textPainter.setPlaceholderDimensions(placeholderDimensions);
-  }
-
-  void _computeChildrenWidthWithMinIntrinsics(double height) {
-    RenderBox child = firstChild;
-    final List<PlaceholderDimensions> placeholderDimensions = List<PlaceholderDimensions>(childCount);
-    int childIndex = 0;
-    while (child != null) {
-      final double intrinsicWidth = child.getMinIntrinsicWidth(height);
-      final double intrinsicHeight = child.getMinIntrinsicHeight(intrinsicWidth);
-      placeholderDimensions[childIndex] = PlaceholderDimensions(
-        size: Size(intrinsicWidth, intrinsicHeight),
-        alignment: _placeholderSpans[childIndex].alignment,
-        baseline: _placeholderSpans[childIndex].baseline,
-      );
-      child = childAfter(child);
-      childIndex += 1;
-    }
-    _textPainter.setPlaceholderDimensions(placeholderDimensions);
-  }
-
-  void _computeChildrenHeightWithMinIntrinsics(double width) {
-    RenderBox child = firstChild;
-    final List<PlaceholderDimensions> placeholderDimensions = List<PlaceholderDimensions>(childCount);
-    int childIndex = 0;
-    while (child != null) {
-      final double intrinsicHeight = child.getMinIntrinsicHeight(width);
-      final double intrinsicWidth = child.getMinIntrinsicWidth(intrinsicHeight);
-      placeholderDimensions[childIndex] = PlaceholderDimensions(
-        size: Size(intrinsicWidth, intrinsicHeight),
-        alignment: _placeholderSpans[childIndex].alignment,
-        baseline: _placeholderSpans[childIndex].baseline,
-      );
-      child = childAfter(child);
-      childIndex += 1;
-    }
-    _textPainter.setPlaceholderDimensions(placeholderDimensions);
-  }
-
   @override
   bool hitTestSelf(Offset position) => true;
 
   @override
-  bool hitTestChildren(BoxHitTestResult result, { Offset position }) {
-    RenderBox child = firstChild;
-    while (child != null) {
-      final TextParentData textParentData = child.parentData;
-      final Matrix4 transform = Matrix4.translationValues(textParentData.offset.dx, textParentData.offset.dy, 0.0)
-        ..scale(textParentData.scale, textParentData.scale, textParentData.scale);
-      final bool isHit = result.addWithPaintTransform(
-        transform: transform,
-        position: position,
-        hitTest: (BoxHitTestResult result, Offset transformed) {
-          assert(() {
-            final Offset manualPosition = (position - textParentData.offset) / textParentData.scale;
-            return (transformed.dx - manualPosition.dx).abs() < precisionErrorTolerance
-              && (transformed.dy - manualPosition.dy).abs() < precisionErrorTolerance;
-          }());
-          return child.hitTest(result, position: transformed);
-        },
-      );
-      if (isHit) {
-        return true;
-      }
-      child = childAfter(child);
-    }
-    return false;
-  }
-
-  @override
   void handleEvent(PointerEvent event, BoxHitTestEntry entry) {
     assert(debugHandleEvent(event, entry));
     if (event is! PointerDownEvent)
@@ -450,81 +299,9 @@
   @visibleForTesting
   bool get debugHasOverflowShader => _overflowShader != null;
 
-  void _layoutText({ double minWidth = 0.0, double maxWidth = double.infinity }) {
-    final bool widthMatters = softWrap || overflow == TextOverflow.ellipsis;
-    _textPainter.layout(minWidth: minWidth, maxWidth: widthMatters ? maxWidth : double.infinity);
-  }
-
-  void _layoutTextWithConstraints(BoxConstraints constraints) {
-    _layoutText(minWidth: constraints.minWidth, maxWidth: constraints.maxWidth);
-  }
-
-  // Layout the child inline widgets. We then pass the dimensions of the
-  // children to _textPainter so that appropriate placeholders can be inserted
-  // into the LibTxt layout. This does not do anything if no inline widgets were
-  // specified.
-  void _layoutChildren(BoxConstraints constraints) {
-    if (childCount == 0) {
-      return;
-    }
-    RenderBox child = firstChild;
-    final List<PlaceholderDimensions> placeholderDimensions = List<PlaceholderDimensions>(childCount);
-    int childIndex = 0;
-    while (child != null) {
-      // Only constrain the width to the maximum width of the paragraph.
-      // Leave height unconstrained, which will overflow if expanded past.
-      child.layout(
-        BoxConstraints(
-          maxWidth: constraints.maxWidth,
-        ),
-        parentUsesSize: true
-      );
-      double baselineOffset;
-      switch (_placeholderSpans[childIndex].alignment) {
-        case ui.PlaceholderAlignment.baseline: {
-          baselineOffset = child.getDistanceToBaseline(_placeholderSpans[childIndex].baseline);
-          break;
-        }
-        default: {
-          baselineOffset = null;
-          break;
-        }
-      }
-      placeholderDimensions[childIndex] = PlaceholderDimensions(
-        size: child.size,
-        alignment: _placeholderSpans[childIndex].alignment,
-        baseline: _placeholderSpans[childIndex].baseline,
-        baselineOffset: baselineOffset,
-      );
-      child = childAfter(child);
-      childIndex += 1;
-    }
-    _textPainter.setPlaceholderDimensions(placeholderDimensions);
-  }
-
-  // Iterate through the laid-out children and set the parentData offsets based
-  // off of the placeholders inserted for each child.
-  void _setParentData() {
-    RenderBox child = firstChild;
-    int childIndex = 0;
-    while (child != null) {
-      final TextParentData textParentData = child.parentData;
-      textParentData.offset = Offset(
-        _textPainter.inlinePlaceholderBoxes[childIndex].left,
-        _textPainter.inlinePlaceholderBoxes[childIndex].top
-      );
-      textParentData.scale = _textPainter.inlinePlaceholderScales[childIndex];
-      child = childAfter(child);
-      childIndex += 1;
-    }
-  }
-
   @override
   void performLayout() {
-    _layoutChildren(constraints);
     _layoutTextWithConstraints(constraints);
-    _setParentData();
-
     // We grab _textPainter.size and _textPainter.didExceedMaxLines here because
     // assigning to `size` will trigger us to validate our intrinsic sizes,
     // which will change _textPainter's layout because the intrinsic size
@@ -609,12 +386,13 @@
     // If you remove this call, make sure that changing the textAlign still
     // works properly.
     _layoutTextWithConstraints(constraints);
+    final Canvas canvas = context.canvas;
 
     assert(() {
       if (debugRepaintTextRainbowEnabled) {
         final Paint paint = Paint()
           ..color = debugCurrentRepaintColor.toColor();
-        context.canvas.drawRect(offset & size, paint);
+        canvas.drawRect(offset & size, paint);
       }
       return true;
     }());
@@ -624,44 +402,22 @@
       if (_overflowShader != null) {
         // This layer limits what the shader below blends with to be just the text
         // (as opposed to the text and its background).
-        context.canvas.saveLayer(bounds, Paint());
+        canvas.saveLayer(bounds, Paint());
       } else {
-        context.canvas.save();
+        canvas.save();
       }
-      context.canvas.clipRect(bounds);
+      canvas.clipRect(bounds);
     }
-    _textPainter.paint(context.canvas, offset);
-
-    RenderBox child = firstChild;
-    int childIndex = 0;
-    while (child != null) {
-      assert(childIndex < _textPainter.inlinePlaceholderBoxes.length);
-      final TextParentData textParentData = child.parentData;
-
-      final double scale = textParentData.scale;
-      context.pushTransform(
-        needsCompositing,
-        offset + textParentData.offset,
-        Matrix4.diagonal3Values(scale, scale, scale),
-        (PaintingContext context, Offset offset) {
-          context.paintChild(
-            child,
-            offset,
-          );
-        },
-      );
-      child = childAfter(child);
-      childIndex += 1;
-    }
+    _textPainter.paint(canvas, offset);
     if (_needsClipping) {
       if (_overflowShader != null) {
-        context.canvas.translate(offset.dx, offset.dy);
+        canvas.translate(offset.dx, offset.dy);
         final Paint paint = Paint()
           ..blendMode = BlendMode.modulate
           ..shader = _overflowShader;
-        context.canvas.drawRect(Offset.zero & size, paint);
+        canvas.drawRect(Offset.zero & size, paint);
       }
-      context.canvas.restore();
+      canvas.restore();
     }
   }
 
@@ -725,23 +481,26 @@
     return _textPainter.size;
   }
 
-  // The offsets for each span that requires custom semantics.
-  final List<int> _inlineSemanticsOffsets = <int>[];
-  // Holds either [GestureRecognizer] or null (for placeholders) to generate
-  // proper semnatics configurations.
-  final List<dynamic> _inlineSemanticsElements = <dynamic>[];
+  final List<int> _recognizerOffsets = <int>[];
+  final List<GestureRecognizer> _recognizers = <GestureRecognizer>[];
 
   @override
   void describeSemanticsConfiguration(SemanticsConfiguration config) {
     super.describeSemanticsConfiguration(config);
-    _inlineSemanticsOffsets.clear();
-    _inlineSemanticsElements.clear();
-    final Accumulator offset = Accumulator();
-    text.visitChildren((InlineSpan span) {
-      span.describeSemantics(offset, _inlineSemanticsOffsets, _inlineSemanticsElements);
+    _recognizerOffsets.clear();
+    _recognizers.clear();
+    int offset = 0;
+    text.visitTextSpan((TextSpan span) {
+      if (span.recognizer != null && (span.recognizer is TapGestureRecognizer || span.recognizer is LongPressGestureRecognizer)) {
+        final int length = span.semanticsLabel?.length ?? span.text.length;
+        _recognizerOffsets.add(offset);
+        _recognizerOffsets.add(offset + length);
+        _recognizers.add(span.recognizer);
+      }
+      offset += span.text.length;
       return true;
     });
-    if (_inlineSemanticsOffsets.isNotEmpty) {
+    if (_recognizerOffsets.isNotEmpty) {
       config.explicitChildNodes = true;
       config.isSemanticBoundary = true;
     } else {
@@ -752,9 +511,10 @@
 
   @override
   void assembleSemanticsNode(SemanticsNode node, SemanticsConfiguration config, Iterable<SemanticsNode> children) {
-    assert(_inlineSemanticsOffsets.isNotEmpty);
-    assert(_inlineSemanticsOffsets.length.isEven);
-    assert(_inlineSemanticsElements.isNotEmpty);
+    assert(_recognizerOffsets.isNotEmpty);
+    assert(_recognizerOffsets.length.isEven);
+    assert(_recognizers.isNotEmpty);
+    assert(children.isEmpty);
     final List<SemanticsNode> newChildren = <SemanticsNode>[];
     final String rawLabel = text.toPlainText();
     int current = 0;
@@ -762,7 +522,7 @@
     TextDirection currentDirection = textDirection;
     Rect currentRect;
 
-    SemanticsConfiguration buildSemanticsConfig(int start, int end, { bool includeText = true }) {
+    SemanticsConfiguration buildSemanticsConfig(int start, int end) {
       final TextDirection initialDirection = currentDirection;
       final TextSelection selection = TextSelection(baseOffset: start, extentOffset: end);
       final List<ui.TextBox> rects = getBoxesForSelection(selection);
@@ -782,21 +542,15 @@
         rect.bottom.ceilToDouble() + 4.0,
       );
       order += 1;
-      final SemanticsConfiguration configuration = SemanticsConfiguration()
+      return SemanticsConfiguration()
         ..sortKey = OrdinalSortKey(order)
-        ..textDirection = initialDirection;
-      if (includeText) {
-        configuration.label = rawLabel.substring(start, end);
-      }
-      return configuration;
+        ..textDirection = initialDirection
+        ..label = rawLabel.substring(start, end);
     }
 
-    int childIndex = 0;
-    RenderBox child = firstChild;
-    for (int i = 0, j = 0; i < _inlineSemanticsOffsets.length; i += 2, j++) {
-      final int start = _inlineSemanticsOffsets[i];
-      final int end = _inlineSemanticsOffsets[i + 1];
-      // Add semantics for any text between the previous recognizer/widget and this one.
+    for (int i = 0, j = 0; i < _recognizerOffsets.length; i += 2, j++) {
+      final int start = _recognizerOffsets[i];
+      final int end = _recognizerOffsets[i + 1];
       if (current != start) {
         final SemanticsNode node = SemanticsNode();
         final SemanticsConfiguration configuration = buildSemanticsConfig(current, start);
@@ -804,38 +558,19 @@
         node.rect = currentRect;
         newChildren.add(node);
       }
-      final dynamic inlineElement = _inlineSemanticsElements[j];
-      final SemanticsConfiguration configuration = buildSemanticsConfig(start, end, includeText: false);
-      if (inlineElement != null) {
-        // Add semantics for this recognizer.
-        final SemanticsNode node = SemanticsNode();
-        if (inlineElement is TapGestureRecognizer) {
-          final TapGestureRecognizer recognizer = inlineElement;
-          configuration.onTap = recognizer.onTap;
-        } else if (inlineElement is LongPressGestureRecognizer) {
-          final LongPressGestureRecognizer recognizer = inlineElement;
-          configuration.onLongPress = recognizer.onLongPress;
-        } else {
-          assert(false);
-        }
-        node.updateWith(config: configuration);
-        node.rect = currentRect;
-        newChildren.add(node);
-      } else if (childIndex < children.length) {
-        // Add semantics for this placeholder. Semantics are precomputed in the children
-        // argument.
-        final SemanticsNode childNode = children.elementAt(childIndex);
-        final TextParentData parentData = child.parentData;
-        childNode.rect = Rect.fromLTWH(
-          childNode.rect.left,
-          childNode.rect.top,
-          childNode.rect.width * parentData.scale,
-          childNode.rect.height * parentData.scale,
-        );
-        newChildren.add(children.elementAt(childIndex));
-        childIndex += 1;
-        child = childAfter(child);
+      final SemanticsNode node = SemanticsNode();
+      final SemanticsConfiguration configuration = buildSemanticsConfig(start, end);
+      final GestureRecognizer recognizer = _recognizers[j];
+      if (recognizer is TapGestureRecognizer) {
+        configuration.onTap = recognizer.onTap;
+      } else if (recognizer is LongPressGestureRecognizer) {
+        configuration.onLongPress = recognizer.onLongPress;
+      } else {
+        assert(false);
       }
+      node.updateWith(config: configuration);
+      node.rect = currentRect;
+      newChildren.add(node);
       current = end;
     }
     if (current < rawLabel.length) {
diff --git a/packages/flutter/lib/src/widgets/basic.dart b/packages/flutter/lib/src/widgets/basic.dart
index 596b883..e627b3e 100644
--- a/packages/flutter/lib/src/widgets/basic.dart
+++ b/packages/flutter/lib/src/widgets/basic.dart
@@ -12,7 +12,6 @@
 import 'debug.dart';
 import 'framework.dart';
 import 'localizations.dart';
-import 'widget_span.dart';
 
 export 'package:flutter/animation.dart';
 export 'package:flutter/foundation.dart' show
@@ -4914,9 +4913,7 @@
 ///  * [TextSpan], which is used to describe the text in a paragraph.
 ///  * [Text], which automatically applies the ambient styles described by a
 ///    [DefaultTextStyle] to a single string.
-///  * [Text.rich], a const text widget that provides similar functionality
-///    as [RichText]. [Text.rich] will inherit [TextStyle] from [DefaultTextStyle].
-class RichText extends MultiChildRenderObjectWidget {
+class RichText extends LeafRenderObjectWidget {
   /// Creates a paragraph of rich text.
   ///
   /// The [text], [textAlign], [softWrap], [overflow], and [textScaleFactor]
@@ -4927,7 +4924,7 @@
   ///
   /// The [textDirection], if null, defaults to the ambient [Directionality],
   /// which in that case must not be null.
-  RichText({
+  const RichText({
     Key key,
     @required this.text,
     this.textAlign = TextAlign.start,
@@ -4946,23 +4943,10 @@
        assert(textScaleFactor != null),
        assert(maxLines == null || maxLines > 0),
        assert(textWidthBasis != null),
-       super(key: key, children: _extractChildren(text));
-
-  // Traverses the InlineSpan tree and depth-first collects the list of
-  // child widgets that are created in WidgetSpans.
-  static List<Widget> _extractChildren(InlineSpan span) {
-    final List<Widget> result = <Widget>[];
-    span.visitChildren((InlineSpan span) {
-      if (span is WidgetSpan) {
-        result.add(span.child);
-      }
-      return true;
-    });
-    return result;
-  }
+       super(key: key);
 
   /// The text to display in this widget.
-  final InlineSpan text;
+  final TextSpan text;
 
   /// How the text should be aligned horizontally.
   final TextAlign textAlign;
diff --git a/packages/flutter/lib/src/widgets/text.dart b/packages/flutter/lib/src/widgets/text.dart
index 18637dd..ee3233f 100644
--- a/packages/flutter/lib/src/widgets/text.dart
+++ b/packages/flutter/lib/src/widgets/text.dart
@@ -256,16 +256,9 @@
        textSpan = null,
        super(key: key);
 
-  /// Creates a text widget with a [InlineSpan].
-  ///
-  /// The following subclasses of [InlineSpan] may be used to build rich text:
-  ///
-  /// * [TextSpan]s define text and children [InlineSpan]s.
-  /// * [WidgetSpan]s define embedded inline widgets.
+  /// Creates a text widget with a [TextSpan].
   ///
   /// The [textSpan] parameter must not be null.
-  ///
-  /// See [RichText] which provides a lower-level way to draw text.
   const Text.rich(
     this.textSpan, {
     Key key,
@@ -292,10 +285,10 @@
   /// This will be null if a [textSpan] is provided instead.
   final String data;
 
-  /// The text to display as a [InlineSpan].
+  /// The text to display as a [TextSpan].
   ///
   /// This will be null if [data] is provided instead.
-  final InlineSpan textSpan;
+  final TextSpan textSpan;
 
   /// If non-null, the style to use for this text.
   ///
diff --git a/packages/flutter/lib/src/widgets/widget_inspector.dart b/packages/flutter/lib/src/widgets/widget_inspector.dart
index ab9a1be..ab178a0 100644
--- a/packages/flutter/lib/src/widgets/widget_inspector.dart
+++ b/packages/flutter/lib/src/widgets/widget_inspector.dart
@@ -2752,8 +2752,7 @@
   ) {
     canvas.save();
     final double maxWidth = size.width - 2 * (_kScreenEdgeMargin + _kTooltipPadding);
-    final TextSpan textSpan = _textPainter?.text;
-    if (_textPainter == null || textSpan.text != message || _textPainterMaxWidth != maxWidth) {
+    if (_textPainter == null || _textPainter.text.text != message || _textPainterMaxWidth != maxWidth) {
       _textPainterMaxWidth = maxWidth;
       _textPainter = TextPainter()
         ..maxLines = _kMaxTooltipLines
diff --git a/packages/flutter/lib/src/widgets/widget_span.dart b/packages/flutter/lib/src/widgets/widget_span.dart
deleted file mode 100644
index a24c04a..0000000
--- a/packages/flutter/lib/src/widgets/widget_span.dart
+++ /dev/null
@@ -1,198 +0,0 @@
-// Copyright 2015 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 'dart:ui' as ui show ParagraphBuilder, PlaceholderAlignment;
-
-import 'package:flutter/painting.dart';
-
-import 'framework.dart';
-
-/// An immutable widget that is embedded inline within text.
-///
-/// The [child] property is the widget that will be embedded. Children are
-/// constrained by the width of the paragraph.
-///
-/// The [child] property may contain its own [Widget] children (if applicable),
-/// including [Text] and [RichText] widgets which may include additional
-/// [WidgetSpan]s. Child [Text] and [RichText] widgets will be laid out
-/// independently and occupy a rectangular space in the parent text layout.
-///
-/// [WidgetSpan]s will be ignored when passed into a [TextPainter] directly.
-/// To properly layout and paint the [child] widget, [WidgetSpan] should be
-/// passed into a [Text.rich] widget.
-///
-/// {@tool sample}
-///
-/// A card with `Hello World!` embedded inline within a TextSpan tree.
-///
-/// ```dart
-/// Text.rich(
-///   TextSpan(
-///     children: <InlineSpan>[
-///       TextSpan(text: 'Flutter is'),
-///       WidgetSpan(
-///         child: SizedBox(
-///           width: 120,
-///           height: 50,
-///           child: Card(
-///             child: Center(
-///               child: Text('Hello World!')
-///             )
-///           ),
-///         )
-///       ),
-///       TextSpan(text: 'the best!'),
-///     ],
-///   )
-/// )
-/// ```
-/// {@end-tool}
-///
-/// [WidgetSpan] contributes the semantics of the [WidgetSpan.child] to the
-/// semantics tree.
-///
-/// See also:
-///
-///  * [TextSpan], a node that represents text in an [InlineSpan] tree.
-///  * [Text], a widget for showing uniformly-styled text.
-///  * [RichText], a widget for finer control of text rendering.
-///  * [TextPainter], a class for painting [InlineSpan] objects on a [Canvas].
-@immutable
-class WidgetSpan extends PlaceholderSpan {
-  /// Creates a [WidgetSpan] with the given values.
-  ///
-  /// The [child] property must be non-null. [WidgetSpan] is a leaf node in
-  /// the [InlineSpan] tree. Child widgets are constrained by the width of the
-  /// paragraph they occupy. Child widget heights are unconstrained, and may
-  /// cause the text to overflow and be ellipsized/truncated.
-  ///
-  /// A [TextStyle] may be provided with the [style] property, but only the
-  /// decoration, foreground, background, and spacing options will be used.
-  const WidgetSpan({
-    @required this.child,
-    ui.PlaceholderAlignment alignment = ui.PlaceholderAlignment.bottom,
-    TextBaseline baseline,
-    TextStyle style,
-  }) : assert(child != null),
-       assert((identical(alignment, ui.PlaceholderAlignment.aboveBaseline) ||
-              identical(alignment, ui.PlaceholderAlignment.belowBaseline) ||
-              identical(alignment, ui.PlaceholderAlignment.baseline)) ? baseline != null : true),
-       super(
-         alignment: alignment,
-         baseline: baseline,
-         style: style,
-       );
-
-  /// The widget to embed inline within text.
-  final Widget child;
-
-  /// Adds a placeholder box to the paragraph builder if a size has been
-  /// calculated for the widget.
-  ///
-  /// Sizes are provided through `dimensions`, which should contain a 1:1
-  /// in-order mapping of widget to laid-out dimensions. If no such dimension
-  /// is provided, the widget will be skipped.
-  ///
-  /// The `textScaleFactor` will be applied to the laid-out size of the widget.
-  @override
-  void build(ui.ParagraphBuilder builder, { double textScaleFactor = 1.0, @required List<PlaceholderDimensions> dimensions }) {
-    assert(debugAssertIsValid());
-    assert(dimensions != null);
-    final bool hasStyle = style != null;
-    if (hasStyle) {
-      builder.pushStyle(style.getTextStyle(textScaleFactor: textScaleFactor));
-    }
-    assert(builder.placeholderCount < dimensions.length);
-    final PlaceholderDimensions currentDimensions = dimensions[builder.placeholderCount];
-    builder.addPlaceholder(
-      currentDimensions.size.width,
-      currentDimensions.size.height,
-      alignment,
-      scale: textScaleFactor,
-      baseline: currentDimensions.baseline,
-      baselineOffset: currentDimensions.baselineOffset,
-    );
-    if (hasStyle) {
-      builder.pop();
-    }
-  }
-
-  /// Calls `visitor` on this [WidgetSpan]. There are no children spans to walk.
-  @override
-  bool visitChildren(InlineSpanVisitor visitor) {
-    return visitor(this);
-  }
-
-  @override
-  InlineSpan getSpanForPositionVisitor(TextPosition position, Accumulator offset) {
-    return null;
-  }
-
-  @override
-  int codeUnitAtVisitor(int index, Accumulator offset) {
-    return null;
-  }
-
-  @override
-  RenderComparison compareTo(InlineSpan other) {
-    if (identical(this, other))
-      return RenderComparison.identical;
-    if (other.runtimeType != runtimeType)
-      return RenderComparison.layout;
-    if ((style == null) != (other.style == null))
-      return RenderComparison.layout;
-    final WidgetSpan typedOther = other;
-    if (child != typedOther.child || alignment != typedOther.alignment) {
-      return RenderComparison.layout;
-    }
-    RenderComparison result = RenderComparison.identical;
-    if (style != null) {
-      final RenderComparison candidate = style.compareTo(other.style);
-      if (candidate.index > result.index)
-        result = candidate;
-      if (result == RenderComparison.layout)
-        return result;
-    }
-    return result;
-  }
-
-  @override
-  bool operator ==(dynamic other) {
-    if (identical(this, other))
-      return true;
-    if (other.runtimeType != runtimeType)
-      return false;
-    if (super != other)
-      return false;
-    final WidgetSpan typedOther = other;
-    return typedOther.child == child
-        && typedOther.alignment == alignment
-        && typedOther.baseline == baseline;
-  }
-
-  @override
-  int get hashCode => hashValues(super.hashCode, child, alignment, baseline);
-
-  /// Returns the text span that contains the given position in the text.
-  @override
-  InlineSpan getSpanForPosition(TextPosition position) {
-    assert(debugAssertIsValid());
-    return null;
-  }
-
-  /// In debug mode, throws an exception if the object is not in a
-  /// valid configuration. Otherwise, returns true.
-  ///
-  /// This is intended to be used as follows:
-  ///
-  /// ```dart
-  /// assert(myWidgetSpan.debugAssertIsValid());
-  /// ```
-  @override
-  bool debugAssertIsValid() {
-    // WidgetSpans are always valid as asserts prevent invalid WidgetSpans
-    // from being constructed.
-    return true;
-  }
-}
diff --git a/packages/flutter/lib/widgets.dart b/packages/flutter/lib/widgets.dart
index d0871cf..744a3fb 100644
--- a/packages/flutter/lib/widgets.dart
+++ b/packages/flutter/lib/widgets.dart
@@ -108,5 +108,4 @@
 export 'src/widgets/viewport.dart';
 export 'src/widgets/visibility.dart';
 export 'src/widgets/widget_inspector.dart';
-export 'src/widgets/widget_span.dart';
 export 'src/widgets/will_pop_scope.dart';
diff --git a/packages/flutter/test/painting/text_painter_rtl_test.dart b/packages/flutter/test/painting/text_painter_rtl_test.dart
index e44cfe0..5f3f02b 100644
--- a/packages/flutter/test/painting/text_painter_rtl_test.dart
+++ b/packages/flutter/test/painting/text_painter_rtl_test.dart
@@ -43,8 +43,7 @@
            //      0       12345678      9      101234567       18     90123456       27
       style: TextStyle(fontFamily: 'Ahem', fontSize: 10.0),
     );
-    TextSpan textSpan = painter.text;
-    expect(textSpan.text.length, 28);
+    expect(painter.text.text.length, 28);
     painter.layout();
 
     // The skips here are because the old rendering code considers the bidi formatting characters
@@ -128,8 +127,7 @@
     );
 
     final List<List<TextBox>> list = <List<TextBox>>[];
-    textSpan = painter.text;
-    for (int index = 0; index < textSpan.text.length; index += 1)
+    for (int index = 0; index < painter.text.text.length; index += 1)
       list.add(painter.getBoxesForSelection(TextSelection(baseOffset: index, extentOffset: index + 1)));
     expect(list, const <List<TextBox>>[
       <TextBox>[], // U+202E, non-printing Unicode bidi formatting character
@@ -174,8 +172,7 @@
            //      0       12345678      9      101234567       18     90123456       27
       style: TextStyle(fontFamily: 'Ahem', fontSize: 10.0),
     );
-    final TextSpan textSpan = painter.text;
-    expect(textSpan.text.length, 28);
+    expect(painter.text.text.length, 28);
     painter.layout();
 
     final TextRange hebrew1 = painter.getWordBoundary(const TextPosition(offset: 4, affinity: TextAffinity.downstream));
@@ -264,8 +261,7 @@
       text: 'A\u05D0', // A, Alef
       style: TextStyle(fontFamily: 'Ahem', fontSize: 10.0),
     );
-    final TextSpan textSpan = painter.text;
-    expect(textSpan.text.length, 2);
+    expect(painter.text.text.length, 2);
     painter.layout(maxWidth: 10.0);
 
     for (int index = 0; index <= 2; index += 1) {
diff --git a/packages/flutter/test/painting/text_painter_test.dart b/packages/flutter/test/painting/text_painter_test.dart
index cfa5f56..80d0c22 100644
--- a/packages/flutter/test/painting/text_painter_test.dart
+++ b/packages/flutter/test/painting/text_painter_test.dart
@@ -5,7 +5,6 @@
 import 'dart:ui' as ui;
 
 import 'package:flutter/painting.dart';
-import 'package:flutter/widgets.dart';
 import 'package:flutter_test/flutter_test.dart';
 
 void main() {
@@ -635,98 +634,4 @@
     expect(caretOffset.dx, closeTo(0.0, 0.0001));
     expect(caretOffset.dy, closeTo(0.0, 0.0001));
   });
-
-  test('TextPainter widget span', () {
-    final TextPainter painter = TextPainter()
-      ..textDirection = TextDirection.ltr;
-
-    const String text = 'test';
-    painter.text = const TextSpan(
-      text: text,
-      children: <InlineSpan>[
-        WidgetSpan(child: SizedBox(width: 50, height: 30)),
-        TextSpan(text: text),
-        WidgetSpan(child: SizedBox(width: 50, height: 30)),
-        WidgetSpan(child: SizedBox(width: 50, height: 30)),
-        TextSpan(text: text),
-        WidgetSpan(child: SizedBox(width: 50, height: 30)),
-        WidgetSpan(child: SizedBox(width: 50, height: 30)),
-        WidgetSpan(child: SizedBox(width: 50, height: 30)),
-        WidgetSpan(child: SizedBox(width: 50, height: 30)),
-        WidgetSpan(child: SizedBox(width: 50, height: 30)),
-        WidgetSpan(child: SizedBox(width: 50, height: 30)),
-        WidgetSpan(child: SizedBox(width: 50, height: 30)),
-        WidgetSpan(child: SizedBox(width: 50, height: 30)),
-        WidgetSpan(child: SizedBox(width: 50, height: 30)),
-        WidgetSpan(child: SizedBox(width: 50, height: 30)),
-        WidgetSpan(child: SizedBox(width: 50, height: 30)),
-      ]
-    );
-
-    // We provide dimensions for the widgets
-    painter.setPlaceholderDimensions(const <PlaceholderDimensions>[
-      PlaceholderDimensions(size: Size(50, 30), baselineOffset: 25, alignment: ui.PlaceholderAlignment.bottom),
-      PlaceholderDimensions(size: Size(50, 30), baselineOffset: 25, alignment: ui.PlaceholderAlignment.bottom),
-      PlaceholderDimensions(size: Size(50, 30), baselineOffset: 25, alignment: ui.PlaceholderAlignment.bottom),
-      PlaceholderDimensions(size: Size(50, 30), baselineOffset: 25, alignment: ui.PlaceholderAlignment.bottom),
-      PlaceholderDimensions(size: Size(50, 30), baselineOffset: 25, alignment: ui.PlaceholderAlignment.bottom),
-      PlaceholderDimensions(size: Size(50, 30), baselineOffset: 25, alignment: ui.PlaceholderAlignment.bottom),
-      PlaceholderDimensions(size: Size(50, 30), baselineOffset: 25, alignment: ui.PlaceholderAlignment.bottom),
-      PlaceholderDimensions(size: Size(50, 30), baselineOffset: 25, alignment: ui.PlaceholderAlignment.bottom),
-      PlaceholderDimensions(size: Size(50, 30), baselineOffset: 25, alignment: ui.PlaceholderAlignment.bottom),
-      PlaceholderDimensions(size: Size(50, 30), baselineOffset: 25, alignment: ui.PlaceholderAlignment.bottom),
-      PlaceholderDimensions(size: Size(50, 30), baselineOffset: 25, alignment: ui.PlaceholderAlignment.bottom),
-      PlaceholderDimensions(size: Size(50, 30), baselineOffset: 25, alignment: ui.PlaceholderAlignment.bottom),
-      PlaceholderDimensions(size: Size(51, 30), baselineOffset: 25, alignment: ui.PlaceholderAlignment.bottom),
-      PlaceholderDimensions(size: Size(50, 30), baselineOffset: 25, alignment: ui.PlaceholderAlignment.bottom),
-    ]);
-
-    painter.layout(maxWidth: 500);
-
-    // Now, each of the WidgetSpans will have their own placeholder 'hole'.
-    Offset caretOffset = painter.getOffsetForCaret(const ui.TextPosition(offset: 1), ui.Rect.zero);
-    expect(caretOffset.dx, 14);
-    caretOffset = painter.getOffsetForCaret(const ui.TextPosition(offset: 4), ui.Rect.zero);
-    expect(caretOffset.dx, 56);
-    caretOffset = painter.getOffsetForCaret(const ui.TextPosition(offset: 5), ui.Rect.zero);
-    expect(caretOffset.dx, 106);
-    caretOffset = painter.getOffsetForCaret(const ui.TextPosition(offset: 6), ui.Rect.zero);
-    expect(caretOffset.dx, 120);
-    caretOffset = painter.getOffsetForCaret(const ui.TextPosition(offset: 10), ui.Rect.zero);
-    expect(caretOffset.dx, 212);
-    caretOffset = painter.getOffsetForCaret(const ui.TextPosition(offset: 11), ui.Rect.zero);
-    expect(caretOffset.dx, 262);
-    caretOffset = painter.getOffsetForCaret(const ui.TextPosition(offset: 12), ui.Rect.zero);
-    expect(caretOffset.dx, 276);
-    caretOffset = painter.getOffsetForCaret(const ui.TextPosition(offset: 13), ui.Rect.zero);
-    expect(caretOffset.dx, 290);
-    caretOffset = painter.getOffsetForCaret(const ui.TextPosition(offset: 14), ui.Rect.zero);
-    expect(caretOffset.dx, 304);
-    caretOffset = painter.getOffsetForCaret(const ui.TextPosition(offset: 15), ui.Rect.zero);
-    expect(caretOffset.dx, 318);
-    caretOffset = painter.getOffsetForCaret(const ui.TextPosition(offset: 16), ui.Rect.zero);
-    expect(caretOffset.dx, 368);
-    caretOffset = painter.getOffsetForCaret(const ui.TextPosition(offset: 17), ui.Rect.zero);
-    expect(caretOffset.dx, 418);
-    caretOffset = painter.getOffsetForCaret(const ui.TextPosition(offset: 18), ui.Rect.zero);
-    expect(caretOffset.dx, 0);
-    caretOffset = painter.getOffsetForCaret(const ui.TextPosition(offset: 19), ui.Rect.zero);
-    expect(caretOffset.dx, 50);
-    caretOffset = painter.getOffsetForCaret(const ui.TextPosition(offset: 23), ui.Rect.zero);
-    expect(caretOffset.dx, 250);
-
-    expect(painter.inlinePlaceholderBoxes.length, 14);
-    expect(painter.inlinePlaceholderBoxes[0], const TextBox.fromLTRBD(56, 0, 106, 30, TextDirection.ltr));
-    expect(painter.inlinePlaceholderBoxes[2], const TextBox.fromLTRBD(212, 0, 262, 30, TextDirection.ltr));
-    expect(painter.inlinePlaceholderBoxes[3], const TextBox.fromLTRBD(318, 0, 368, 30, TextDirection.ltr));
-    expect(painter.inlinePlaceholderBoxes[4], const TextBox.fromLTRBD(368, 0, 418, 30, TextDirection.ltr));
-    expect(painter.inlinePlaceholderBoxes[5], const TextBox.fromLTRBD(418, 0, 468, 30, TextDirection.ltr));
-    // line should break here
-    expect(painter.inlinePlaceholderBoxes[6], const TextBox.fromLTRBD(0, 30, 50, 60, TextDirection.ltr));
-    expect(painter.inlinePlaceholderBoxes[7], const TextBox.fromLTRBD(50, 30, 100, 60, TextDirection.ltr));
-    expect(painter.inlinePlaceholderBoxes[10], const TextBox.fromLTRBD(200, 30, 250, 60, TextDirection.ltr));
-    expect(painter.inlinePlaceholderBoxes[11], const TextBox.fromLTRBD(250, 30, 300, 60, TextDirection.ltr));
-    expect(painter.inlinePlaceholderBoxes[12], const TextBox.fromLTRBD(300, 30, 351, 60, TextDirection.ltr));
-    expect(painter.inlinePlaceholderBoxes[13], const TextBox.fromLTRBD(351, 30, 401, 60, TextDirection.ltr));
-  });
 }
diff --git a/packages/flutter/test/painting/text_span_test.dart b/packages/flutter/test/painting/text_span_test.dart
index 2f7e975..072ea5f 100644
--- a/packages/flutter/test/painting/text_span_test.dart
+++ b/packages/flutter/test/painting/text_span_test.dart
@@ -3,17 +3,17 @@
 // found in the LICENSE file.
 
 import 'package:flutter/painting.dart';
-import 'package:flutter/widgets.dart';
+import 'package:flutter_test/flutter_test.dart' show nonconst;
 import '../flutter_test_alternative.dart';
 
 void main() {
   test('TextSpan equals', () {
-    const TextSpan a1 = TextSpan(text: 'a');
-    const TextSpan a2 = TextSpan(text: 'a');
-    const TextSpan b1 = TextSpan(children: <TextSpan>[ a1 ]);
-    const TextSpan b2 = TextSpan(children: <TextSpan>[ a2 ]);
-    const TextSpan c1 = TextSpan(text: null);
-    const TextSpan c2 = TextSpan(text: null);
+    final TextSpan a1 = TextSpan(text: nonconst('a'));
+    final TextSpan a2 = TextSpan(text: nonconst('a'));
+    final TextSpan b1 = TextSpan(children: <TextSpan>[ a1 ]);
+    final TextSpan b2 = TextSpan(children: <TextSpan>[ a2 ]);
+    final TextSpan c1 = TextSpan(text: nonconst(null));
+    final TextSpan c2 = TextSpan(text: nonconst(null));
 
     expect(a1 == a2, isTrue);
     expect(b1 == b2, isTrue);
@@ -73,18 +73,6 @@
     expect(textSpan.toPlainText(), 'abc');
   });
 
-  test('WidgetSpan toPlainText', () {
-    const TextSpan textSpan = TextSpan(
-      text: 'a',
-      children: <InlineSpan>[
-        TextSpan(text: 'b'),
-        WidgetSpan(child: SizedBox(width: 10, height: 10)),
-        TextSpan(text: 'c'),
-      ],
-    );
-    expect(textSpan.toPlainText(), 'ab\uFFFCc');
-  });
-
   test('TextSpan toPlainText with semanticsLabel', () {
     const TextSpan textSpan = TextSpan(
       text: 'a',
@@ -96,117 +84,4 @@
     expect(textSpan.toPlainText(), 'afooc');
     expect(textSpan.toPlainText(includeSemanticsLabels: false), 'abc');
   });
-
-  test('TextSpan widget change test', () {
-    const TextSpan textSpan1 = TextSpan(
-      text: 'a',
-      children: <InlineSpan>[
-        TextSpan(text: 'b'),
-        WidgetSpan(child: SizedBox(width: 10, height: 10)),
-        TextSpan(text: 'c'),
-      ],
-    );
-
-    const TextSpan textSpan2 = TextSpan(
-      text: 'a',
-      children: <InlineSpan>[
-        TextSpan(text: 'b'),
-        WidgetSpan(child: SizedBox(width: 10, height: 10)),
-        TextSpan(text: 'c'),
-      ],
-    );
-
-    const TextSpan textSpan3 = TextSpan(
-      text: 'a',
-      children: <InlineSpan>[
-        TextSpan(text: 'b'),
-        WidgetSpan(child: SizedBox(width: 11, height: 10)),
-        TextSpan(text: 'c'),
-      ],
-    );
-
-    const TextSpan textSpan4 = TextSpan(
-      text: 'a',
-      children: <InlineSpan>[
-        TextSpan(text: 'b'),
-        WidgetSpan(child: Text('test')),
-        TextSpan(text: 'c'),
-      ],
-    );
-
-    const TextSpan textSpan5 = TextSpan(
-      text: 'a',
-      children: <InlineSpan>[
-        TextSpan(text: 'b'),
-        WidgetSpan(child: Text('different!')),
-        TextSpan(text: 'c'),
-      ],
-    );
-
-    const TextSpan textSpan6 = TextSpan(
-      text: 'a',
-      children: <InlineSpan>[
-        TextSpan(text: 'b'),
-        WidgetSpan(
-          child: SizedBox(width: 10, height: 10),
-          alignment: PlaceholderAlignment.top,
-        ),
-        TextSpan(text: 'c'),
-      ],
-    );
-
-    expect(textSpan1.compareTo(textSpan3), RenderComparison.layout);
-    expect(textSpan1.compareTo(textSpan4), RenderComparison.layout);
-    expect(textSpan1.compareTo(textSpan1), RenderComparison.identical);
-    expect(textSpan2.compareTo(textSpan2), RenderComparison.identical);
-    expect(textSpan3.compareTo(textSpan3), RenderComparison.identical);
-    expect(textSpan2.compareTo(textSpan3), RenderComparison.layout);
-    expect(textSpan4.compareTo(textSpan5), RenderComparison.layout);
-    expect(textSpan3.compareTo(textSpan5), RenderComparison.layout);
-    expect(textSpan2.compareTo(textSpan5), RenderComparison.layout);
-    expect(textSpan1.compareTo(textSpan5), RenderComparison.layout);
-    expect(textSpan1.compareTo(textSpan6), RenderComparison.layout);
-  });
-
-  test('TextSpan nested widget change test', () {
-    const TextSpan textSpan1 = TextSpan(
-      text: 'a',
-      children: <InlineSpan>[
-        TextSpan(text: 'b'),
-        WidgetSpan(
-          child: Text.rich(
-            TextSpan(
-              children: <InlineSpan>[
-                WidgetSpan(child: SizedBox(width: 10, height: 10)),
-                TextSpan(text: 'The sky is falling :)')
-              ],
-            )
-          ),
-        ),
-        TextSpan(text: 'c'),
-      ],
-    );
-
-    const TextSpan textSpan2 = TextSpan(
-      text: 'a',
-      children: <InlineSpan>[
-        TextSpan(text: 'b'),
-        WidgetSpan(
-          child: Text.rich(
-            TextSpan(
-              children: <InlineSpan>[
-                WidgetSpan(child: SizedBox(width: 10, height: 11)),
-                TextSpan(text: 'The sky is falling :)')
-              ],
-            )
-          ),
-        ),
-        TextSpan(text: 'c'),
-      ],
-    );
-
-    expect(textSpan1.compareTo(textSpan2), RenderComparison.layout);
-    expect(textSpan1.compareTo(textSpan1), RenderComparison.identical);
-    expect(textSpan2.compareTo(textSpan2), RenderComparison.identical);
-  });
 }
diff --git a/packages/flutter/test/rendering/paragraph_test.dart b/packages/flutter/test/rendering/paragraph_test.dart
index 356b6d8..c998d4e 100644
--- a/packages/flutter/test/rendering/paragraph_test.dart
+++ b/packages/flutter/test/rendering/paragraph_test.dart
@@ -5,7 +5,6 @@
 import 'dart:ui' as ui show TextBox;
 
 import 'package:flutter/rendering.dart';
-import 'package:flutter/widgets.dart';
 import 'package:flutter/services.dart';
 import 'package:flutter_test/flutter_test.dart';
 
@@ -325,93 +324,4 @@
     expect(paragraph.locale, const Locale('ja', 'JP'));
   });
 
-  test('inline widgets test', () {
-    const TextSpan text = TextSpan(
-      text: 'a',
-      style: TextStyle(fontSize: 10.0),
-      children: <InlineSpan>[
-        WidgetSpan(child: SizedBox(width: 21, height: 21)),
-        WidgetSpan(child: SizedBox(width: 21, height: 21)),
-        TextSpan(text: 'a'),
-        WidgetSpan(child: SizedBox(width: 21, height: 21)),
-      ],
-    );
-    // Fake the render boxes that correspond to the WidgetSpans. We use
-    // RenderParagraph to reduce dependencies this test has.
-    final List<RenderBox> renderBoxes = <RenderBox>[];
-    renderBoxes.add(RenderParagraph(const TextSpan(text: 'b'), textDirection: TextDirection.ltr));
-    renderBoxes.add(RenderParagraph(const TextSpan(text: 'b'), textDirection: TextDirection.ltr));
-    renderBoxes.add(RenderParagraph(const TextSpan(text: 'b'), textDirection: TextDirection.ltr));
-
-    final RenderParagraph paragraph = RenderParagraph(
-      text,
-      textDirection: TextDirection.ltr,
-      children: renderBoxes,
-    );
-    layout(paragraph, constraints: const BoxConstraints(maxWidth: 100.0));
-
-    final List<ui.TextBox> boxes = paragraph.getBoxesForSelection(
-        const TextSelection(baseOffset: 0, extentOffset: 8)
-    );
-
-    expect(boxes.length, equals(5));
-    expect(boxes[0], const TextBox.fromLTRBD(0.0, 4.0, 10.0, 14.0, TextDirection.ltr));
-    expect(boxes[1], const TextBox.fromLTRBD(10.0, 0.0, 24.0, 14.0, TextDirection.ltr));
-    expect(boxes[2], const TextBox.fromLTRBD(24.0, 0.0, 38.0, 14.0, TextDirection.ltr));
-    expect(boxes[3], const TextBox.fromLTRBD(38.0, 4.0, 48.0, 14.0, TextDirection.ltr));
-    expect(boxes[4], const TextBox.fromLTRBD(48.0, 0.0, 62.0, 14.0, TextDirection.ltr));
-  // Ahem-based tests don't yet quite work on Windows or some MacOS environments
-  }, skip: isWindows || isMacOS);
-
-  test('inline widgets multiline test', () {
-    const TextSpan text = TextSpan(
-      text: 'a',
-      style: TextStyle(fontSize: 10.0),
-      children: <InlineSpan>[
-        WidgetSpan(child: SizedBox(width: 21, height: 21)),
-        WidgetSpan(child: SizedBox(width: 21, height: 21)),
-        TextSpan(text: 'a'),
-        WidgetSpan(child: SizedBox(width: 21, height: 21)),
-        WidgetSpan(child: SizedBox(width: 21, height: 21)),
-        WidgetSpan(child: SizedBox(width: 21, height: 21)),
-        WidgetSpan(child: SizedBox(width: 21, height: 21)),
-        WidgetSpan(child: SizedBox(width: 21, height: 21)),
-      ],
-    );
-    // Fake the render boxes that correspond to the WidgetSpans. We use
-    // RenderParagraph to reduce dependencies this test has.
-    final List<RenderBox> renderBoxes = <RenderBox>[];
-    renderBoxes.add(RenderParagraph(const TextSpan(text: 'b'), textDirection: TextDirection.ltr));
-    renderBoxes.add(RenderParagraph(const TextSpan(text: 'b'), textDirection: TextDirection.ltr));
-    renderBoxes.add(RenderParagraph(const TextSpan(text: 'b'), textDirection: TextDirection.ltr));
-    renderBoxes.add(RenderParagraph(const TextSpan(text: 'b'), textDirection: TextDirection.ltr));
-    renderBoxes.add(RenderParagraph(const TextSpan(text: 'b'), textDirection: TextDirection.ltr));
-    renderBoxes.add(RenderParagraph(const TextSpan(text: 'b'), textDirection: TextDirection.ltr));
-    renderBoxes.add(RenderParagraph(const TextSpan(text: 'b'), textDirection: TextDirection.ltr));
-
-    final RenderParagraph paragraph = RenderParagraph(
-      text,
-      textDirection: TextDirection.ltr,
-      children: renderBoxes,
-    );
-    layout(paragraph, constraints: const BoxConstraints(maxWidth: 50.0));
-
-    final List<ui.TextBox> boxes = paragraph.getBoxesForSelection(
-        const TextSelection(baseOffset: 0, extentOffset: 12)
-    );
-
-    expect(boxes.length, equals(9));
-    expect(boxes[0], const TextBox.fromLTRBD(0.0, 4.0, 10.0, 14.0, TextDirection.ltr));
-    expect(boxes[1], const TextBox.fromLTRBD(10.0, 0.0, 24.0, 14.0, TextDirection.ltr));
-    expect(boxes[2], const TextBox.fromLTRBD(24.0, 0.0, 38.0, 14.0, TextDirection.ltr));
-    expect(boxes[3], const TextBox.fromLTRBD(38.0, 4.0, 48.0, 14.0, TextDirection.ltr));
-    // Wraps
-    expect(boxes[4], const TextBox.fromLTRBD(0.0, 14.0, 14.0, 28.0 , TextDirection.ltr));
-    expect(boxes[5], const TextBox.fromLTRBD(14.0, 14.0, 28.0, 28.0, TextDirection.ltr));
-    expect(boxes[6], const TextBox.fromLTRBD(28.0, 14.0, 42.0, 28.0, TextDirection.ltr));
-    // Wraps
-    expect(boxes[7], const TextBox.fromLTRBD(0.0, 28.0, 14.0, 42.0, TextDirection.ltr));
-    expect(boxes[8], const TextBox.fromLTRBD(14.0, 28.0, 28.0, 42.0 , TextDirection.ltr));
-  // Ahem-based tests don't yet quite work on Windows or some MacOS environments
-  }, skip: isWindows || isMacOS);
 }
diff --git a/packages/flutter/test/widgets/backdrop_filter_test.dart b/packages/flutter/test/widgets/backdrop_filter_test.dart
index aa27ee3..c0cff73 100644
--- a/packages/flutter/test/widgets/backdrop_filter_test.dart
+++ b/packages/flutter/test/widgets/backdrop_filter_test.dart
@@ -10,7 +10,6 @@
 
 void main() {
   testWidgets('BackdropFilter\'s cull rect does not shrink', (WidgetTester tester) async {
-    tester.binding.addTime(const Duration(seconds: 15));
     await tester.pumpWidget(
       MaterialApp(
         home: Scaffold(
diff --git a/packages/flutter/test/widgets/basic_test.dart b/packages/flutter/test/widgets/basic_test.dart
index 15c6996..41e218c 100644
--- a/packages/flutter/test/widgets/basic_test.dart
+++ b/packages/flutter/test/widgets/basic_test.dart
@@ -8,6 +8,7 @@
 import 'package:flutter/widgets.dart';
 import 'package:flutter/rendering.dart';
 
+
 void main() {
   group('PhysicalShape', () {
     testWidgets('properties', (WidgetTester tester) async {
diff --git a/packages/flutter/test/widgets/editable_text_test.dart b/packages/flutter/test/widgets/editable_text_test.dart
index 015795c..ec9748b 100644
--- a/packages/flutter/test/widgets/editable_text_test.dart
+++ b/packages/flutter/test/widgets/editable_text_test.dart
@@ -1870,9 +1870,8 @@
     final RenderEditable renderEditable = findRenderEditable(tester);
     // The actual text span is split into 3 parts with the middle part underlined.
     expect(renderEditable.text.children.length, 3);
-    final TextSpan textSpan = renderEditable.text.children[1];
-    expect(textSpan.text, 'composing');
-    expect(textSpan.style.decoration, TextDecoration.underline);
+    expect(renderEditable.text.children[1].text, 'composing');
+    expect(renderEditable.text.children[1].style.decoration, TextDecoration.underline);
 
     focusNode.unfocus();
     await tester.pump();
diff --git a/packages/flutter/test/widgets/text_golden_test.dart b/packages/flutter/test/widgets/text_golden_test.dart
index bdc0294..5627dcf 100644
--- a/packages/flutter/test/widgets/text_golden_test.dart
+++ b/packages/flutter/test/widgets/text_golden_test.dart
@@ -151,15 +151,16 @@
             decoration: const BoxDecoration(
               color: Colors.green,
             ),
-            child: Text.rich(
-              TextSpan(
+            child: RichText(
+              textDirection: TextDirection.ltr,
+              text: TextSpan(
                 text: 'text1 ',
                 style: TextStyle(
                   color: translucentGreen,
                   background: Paint()
                     ..color = red.withOpacity(0.5),
                 ),
-                children: <InlineSpan>[
+                children: <TextSpan>[
                   TextSpan(
                     text: 'text2',
                     style: TextStyle(
@@ -170,7 +171,6 @@
                   ),
                 ],
               ),
-              textDirection: TextDirection.ltr,
             ),
           ),
         ),
@@ -242,7 +242,7 @@
       find.byType(Container),
       matchesGoldenFile('text_golden.StrutDefault.png'),
     );
-  }, skip: true); // Should only be on linux (skip: !isLinux).
+  }, skip: true); // Should only be on linux (skip: !Platform.isLinux).
                   // Disabled for now until font inconsistency is resolved.
 
   testWidgets('Strut text 1', (WidgetTester tester) async {
@@ -270,7 +270,7 @@
       find.byType(Container),
       matchesGoldenFile('text_golden.Strut.1.1.png'),
     );
-  }, skip: true); // Should only be on linux (skip: !isLinux).
+  }, skip: true); // Should only be on linux (skip: !Platform.isLinux).
                   // Disabled for now until font inconsistency is resolved.
 
   testWidgets('Strut text 2', (WidgetTester tester) async {
@@ -299,7 +299,7 @@
       find.byType(Container),
       matchesGoldenFile('text_golden.Strut.2.1.png'),
     );
-  }, skip: true); // Should only be on linux (skip: !isLinux).
+  }, skip: true); // Should only be on linux (skip: !Platform.isLinux).
                   // Disabled for now until font inconsistency is resolved.
 
   testWidgets('Strut text rich', (WidgetTester tester) async {
@@ -319,7 +319,7 @@
                   color: Colors.red,
                   fontSize: 30,
                 ),
-                children: <InlineSpan>[
+                children: <TextSpan>[
                   TextSpan(
                     text: 'Second line!\n',
                     style: TextStyle(
@@ -351,7 +351,7 @@
       find.byType(Container),
       matchesGoldenFile('text_golden.Strut.3.1.png'),
     );
-  }, skip: true); // Should only be on linux (skip: !isLinux).
+  }, skip: true); // Should only be on linux (skip: !Platform.isLinux).
                   // Disabled for now until font inconsistency is resolved.
 
   testWidgets('Strut text font fallback', (WidgetTester tester) async {
@@ -387,7 +387,7 @@
       find.byType(Container),
       matchesGoldenFile('text_golden.Strut.4.1.png'),
     );
-  }, skip: true); // Should only be on linux (skip: !isLinux).
+  }, skip: true); // Should only be on linux (skip: !Platform.isLinux).
                   // Disabled for now until font inconsistency is resolved.
 
   testWidgets('Strut text rich forceStrutHeight', (WidgetTester tester) async {
@@ -407,7 +407,7 @@
                   color: Colors.red,
                   fontSize: 30,
                 ),
-                children: <InlineSpan>[
+                children: <TextSpan>[
                   TextSpan(
                     text: 'Second line!\n',
                     style: TextStyle(
@@ -439,7 +439,7 @@
       find.byType(Container),
       matchesGoldenFile('text_golden.StrutForce.1.1.png'),
     );
-  }, skip: true); // Should only be on linux (skip: !isLinux).
+  }, skip: true); // Should only be on linux (skip: !Platform.isLinux).
                   // Disabled for now until font inconsistency is resolved.
 
   testWidgets('Decoration thickness', (WidgetTester tester) async {
@@ -518,807 +518,4 @@
       matchesGoldenFile('text_golden.DecorationThickness.1.0.png'),
     );
   }, skip: !isLinux); // Coretext uses different thicknesses for decoration
-
-  testWidgets('Text Inline widget', (WidgetTester tester) async {
-    await tester.pumpWidget(
-      Center(
-        child: RepaintBoundary(
-          child: Material(
-            child: Directionality(
-              textDirection: TextDirection.ltr,
-              child: Container(
-                width: 400.0,
-                height: 200.0,
-                decoration: const BoxDecoration(
-                  color: Color(0xff00ff00),
-                ),
-                child: ConstrainedBox(
-                  constraints: const BoxConstraints(minWidth: 0, maxWidth: 200, minHeight: 0, maxHeight: 100),
-                  child: const Text.rich(
-                    TextSpan(
-                      text: 'C ',
-                      style: TextStyle(
-                        fontSize: 16,
-                      ),
-                      children: <InlineSpan>[
-                        WidgetSpan(
-                          child: Checkbox(value: true, onChanged: null),
-                        ),
-                        WidgetSpan(
-                          child: Checkbox(value: false, onChanged: null),
-                        ),
-                        TextSpan(text: 'He ', style: TextStyle(fontSize: 20)),
-                        WidgetSpan(
-                          child: SizedBox(
-                            width: 50.0,
-                            height: 55.0,
-                            child: DecoratedBox(
-                              decoration: BoxDecoration(
-                                color: Color(0xffffff00),
-                              ),
-                              child: Center(
-                                child:SizedBox(
-                                  width: 10.0,
-                                  height: 15.0,
-                                  child: DecoratedBox(
-                                    decoration: BoxDecoration(
-                                      color: Color(0xffff0000),
-                                    ),
-                                  )
-                                ),
-                              ),
-                            )
-                          ),
-                        ),
-                        TextSpan(text: 'hello world! sieze the day!'),
-                        WidgetSpan(
-                          child: Checkbox(value: false, onChanged: null),
-                        ),
-                        WidgetSpan(
-                          child: SizedBox(
-                            width: 20,
-                            height: 20,
-                            child: Checkbox(value: true, onChanged: null),
-                          )
-                        ),
-                        WidgetSpan(
-                          child: Checkbox(value: false, onChanged: null),
-                          alignment: PlaceholderAlignment.baseline,
-                          baseline: TextBaseline.alphabetic
-                        ),
-                        WidgetSpan(
-                          child: SizedBox(
-                            width: 20,
-                            height: 20,
-                            child: Checkbox(value: true, onChanged: null),
-                          )
-                        ),
-                        WidgetSpan(
-                          child: Text('embedded'),
-                        ),
-                      ],
-                    ),
-                    textDirection: TextDirection.ltr,
-                  ),
-                ),
-              ),
-            ),
-          ),
-        ),
-      ),
-    );
-    await expectLater(
-      find.byType(Container),
-      matchesGoldenFile('text_golden.TextInlineWidget.1.1.png'),
-    );
-  }, skip: !isLinux); // Coretext uses different thicknesses for decoration
-
-  testWidgets('Text Inline widget textfield', (WidgetTester tester) async {
-    await tester.pumpWidget(
-      Center(
-        child: MaterialApp(
-          home: RepaintBoundary(
-            child: Material(
-              child: Container(
-                width: 400.0,
-                height: 200.0,
-                decoration: const BoxDecoration(
-                  color: Color(0xff00ff00),
-                ),
-                child: ConstrainedBox(
-                  constraints: const BoxConstraints(minWidth: 0, maxWidth: 200, minHeight: 0, maxHeight: 100),
-                  child: const Text.rich(
-                    TextSpan(
-                      text: 'My name is: ',
-                      style: TextStyle(
-                        fontSize: 20,
-                      ),
-                      children: <InlineSpan>[
-                        WidgetSpan(
-                          child: SizedBox(width: 70, height: 25, child: TextField()),
-                        ),
-                        TextSpan(text: ', and my favorite city is: ', style: TextStyle(fontSize: 20)),
-                        WidgetSpan(
-                          child: SizedBox(width: 70, height: 25, child: TextField()),
-                        ),
-                      ],
-                    ),
-                    textDirection: TextDirection.ltr,
-                  ),
-                ),
-              ),
-            ),
-          ),
-        ),
-      ),
-    );
-    await expectLater(
-      find.byType(Container),
-      matchesGoldenFile('text_golden.TextInlineWidget.2.2.png'),
-    );
-  }, skip: !isLinux); // Coretext uses different thicknesses for decoration
-
-  // This tests if multiple Text.rich widgets are able to inline nest within each other.
-  testWidgets('Text Inline widget nesting', (WidgetTester tester) async {
-    await tester.pumpWidget(
-      Center(
-        child: MaterialApp(
-          home: RepaintBoundary(
-            child: Material(
-              child: Container(
-                width: 400.0,
-                height: 200.0,
-                decoration: const BoxDecoration(
-                  color: Color(0xff00ff00),
-                ),
-                child: ConstrainedBox(
-                  constraints: const BoxConstraints(minWidth: 0, maxWidth: 200, minHeight: 0, maxHeight: 100),
-                  child: const Text.rich(
-                    TextSpan(
-                      text: 'outer',
-                      style: TextStyle(
-                        fontSize: 20,
-                      ),
-                      children: <InlineSpan>[
-                        WidgetSpan(
-                          child: Text.rich(
-                            TextSpan(
-                              text: 'inner',
-                              style: TextStyle(color: Color(0xff402f4ff)),
-                              children: <InlineSpan>[
-                                WidgetSpan(
-                                  child: Text.rich(
-                                    TextSpan(
-                                      text: 'inner2',
-                                      style: TextStyle(color: Color(0xff003ffff)),
-                                      children: <InlineSpan>[
-                                        WidgetSpan(
-                                          child: SizedBox(
-                                            width: 50.0,
-                                            height: 55.0,
-                                            child: DecoratedBox(
-                                              decoration: BoxDecoration(
-                                                color: Color(0xffffff30),
-                                              ),
-                                              child: Center(
-                                                child:SizedBox(
-                                                  width: 10.0,
-                                                  height: 15.0,
-                                                  child: DecoratedBox(
-                                                    decoration: BoxDecoration(
-                                                      color: Color(0xff5f00f0),
-                                                    ),
-                                                  )
-                                                ),
-                                              ),
-                                            )
-                                          ),
-                                        ),
-                                      ],
-                                    ),
-                                  ),
-                                ),
-                                WidgetSpan(
-                                  child: SizedBox(
-                                    width: 50.0,
-                                    height: 55.0,
-                                    child: DecoratedBox(
-                                      decoration: BoxDecoration(
-                                        color: Color(0xff5fff00),
-                                      ),
-                                      child: Center(
-                                        child:SizedBox(
-                                          width: 10.0,
-                                          height: 15.0,
-                                          child: DecoratedBox(
-                                            decoration: BoxDecoration(
-                                              color: Color(0xff5f0000),
-                                            ),
-                                          )
-                                        ),
-                                      ),
-                                    )
-                                  ),
-                                ),
-                              ],
-                            ),
-                          ),
-                        ),
-                        TextSpan(text: 'outer', style: TextStyle(fontSize: 20)),
-                        WidgetSpan(
-                          child: SizedBox(width: 70, height: 25, child: TextField()),
-                        ),
-                        WidgetSpan(
-                          child: SizedBox(
-                            width: 50.0,
-                            height: 55.0,
-                            child: DecoratedBox(
-                              decoration: BoxDecoration(
-                                color: Color(0xffff00ff),
-                              ),
-                              child: Center(
-                                child:SizedBox(
-                                  width: 10.0,
-                                  height: 15.0,
-                                  child: DecoratedBox(
-                                    decoration: BoxDecoration(
-                                      color: Color(0xff0000ff),
-                                    ),
-                                  )
-                                ),
-                              ),
-                            )
-                          ),
-                        ),
-                      ],
-                    ),
-                    textDirection: TextDirection.ltr,
-                  ),
-                ),
-              ),
-            ),
-          ),
-        ),
-      ),
-    );
-    await expectLater(
-      find.byType(Container),
-      matchesGoldenFile('text_golden.TextInlineWidgetNest.1.2.png'),
-    );
-  }, skip: !isLinux); // Coretext uses different thicknesses for decoration
-
-  testWidgets('Text Inline widget baseline', (WidgetTester tester) async {
-    await tester.pumpWidget(
-      Center(
-        child: RepaintBoundary(
-          child: Material(
-            child: Directionality(
-              textDirection: TextDirection.ltr,
-              child: Container(
-                width: 400.0,
-                height: 200.0,
-                decoration: const BoxDecoration(
-                  color: Color(0xff00ff00),
-                ),
-                child: ConstrainedBox(
-                  constraints: const BoxConstraints(minWidth: 0, maxWidth: 200, minHeight: 0, maxHeight: 100),
-                  child: const Text.rich(
-                    TextSpan(
-                      text: 'C ',
-                      style: TextStyle(
-                        fontSize: 16,
-                      ),
-                      children: <InlineSpan>[
-                        WidgetSpan(
-                          alignment: PlaceholderAlignment.baseline,
-                          baseline: TextBaseline.alphabetic,
-                          child: Checkbox(value: true, onChanged: null),
-                        ),
-                        WidgetSpan(
-                          child: Checkbox(value: false, onChanged: null),
-                        ),
-                        TextSpan(text: 'He ', style: TextStyle(fontSize: 20)),
-                        WidgetSpan(
-                          alignment: PlaceholderAlignment.baseline,
-                          baseline: TextBaseline.alphabetic,
-                          child: SizedBox(
-                            width: 50.0,
-                            height: 55.0,
-                            child: DecoratedBox(
-                              decoration: BoxDecoration(
-                                color: Color(0xffffff00),
-                              ),
-                              child: Center(
-                                child:SizedBox(
-                                  width: 10.0,
-                                  height: 15.0,
-                                  child: DecoratedBox(
-                                    decoration: BoxDecoration(
-                                      color: Color(0xffff0000),
-                                    ),
-                                  )
-                                ),
-                              ),
-                            )
-                          ),
-                        ),
-                        TextSpan(text: 'hello world! sieze the day!'),
-                        WidgetSpan(
-                          alignment: PlaceholderAlignment.baseline,
-                          baseline: TextBaseline.alphabetic,
-                          child: Checkbox(value: false, onChanged: null),
-                        ),
-                        WidgetSpan(
-                          alignment: PlaceholderAlignment.baseline,
-                          baseline: TextBaseline.alphabetic,
-                          child: SizedBox(
-                            width: 20,
-                            height: 20,
-                            child: Checkbox(value: true, onChanged: null),
-                          )
-                        ),
-                        WidgetSpan(
-                          alignment: PlaceholderAlignment.baseline,
-                          baseline: TextBaseline.alphabetic,
-                          child: Checkbox(value: false, onChanged: null),
-                        ),
-                        WidgetSpan(
-                          alignment: PlaceholderAlignment.baseline,
-                          baseline: TextBaseline.alphabetic,
-                          child: SizedBox(
-                            width: 20,
-                            height: 20,
-                            child: Checkbox(value: true, onChanged: null),
-                          )
-                        ),
-                        WidgetSpan(
-                          alignment: PlaceholderAlignment.baseline,
-                          baseline: TextBaseline.alphabetic,
-                          child: Text('embedded'),
-                        ),
-                        TextSpan(text: 'ref'),
-                      ],
-                    ),
-                    textDirection: TextDirection.ltr,
-                  ),
-                ),
-              ),
-            ),
-          ),
-        ),
-      ),
-    );
-    await expectLater(
-      find.byType(Container),
-      matchesGoldenFile('text_golden.TextInlineWidgetBaseline.1.1.png'),
-    );
-  }, skip: !isLinux); // Coretext uses different thicknesses for decoration
-
-  testWidgets('Text Inline widget aboveBaseline', (WidgetTester tester) async {
-    await tester.pumpWidget(
-      Center(
-        child: RepaintBoundary(
-          child: Material(
-            child: Directionality(
-              textDirection: TextDirection.ltr,
-              child: Container(
-                width: 400.0,
-                height: 200.0,
-                decoration: const BoxDecoration(
-                  color: Color(0xff00ff00),
-                ),
-                child: ConstrainedBox(
-                  constraints: const BoxConstraints(minWidth: 0, maxWidth: 200, minHeight: 0, maxHeight: 100),
-                  child: const Text.rich(
-                    TextSpan(
-                      text: 'C ',
-                      style: TextStyle(
-                        fontSize: 16,
-                      ),
-                      children: <InlineSpan>[
-                        WidgetSpan(
-                          alignment: PlaceholderAlignment.aboveBaseline,
-                          baseline: TextBaseline.alphabetic,
-                          child: Checkbox(value: true, onChanged: null),
-                        ),
-                        WidgetSpan(
-                          child: Checkbox(value: false, onChanged: null),
-                        ),
-                        TextSpan(text: 'He ', style: TextStyle(fontSize: 20)),
-                        WidgetSpan(
-                          alignment: PlaceholderAlignment.aboveBaseline,
-                          baseline: TextBaseline.alphabetic,
-                          child: SizedBox(
-                            width: 50.0,
-                            height: 55.0,
-                            child: DecoratedBox(
-                              decoration: BoxDecoration(
-                                color: Color(0xffffff00),
-                              ),
-                              child: Center(
-                                child:SizedBox(
-                                  width: 10.0,
-                                  height: 15.0,
-                                  child: DecoratedBox(
-                                    decoration: BoxDecoration(
-                                      color: Color(0xffff0000),
-                                    ),
-                                  )
-                                ),
-                              ),
-                            )
-                          ),
-                        ),
-                        TextSpan(text: 'hello world! sieze the day!'),
-                        WidgetSpan(
-                          alignment: PlaceholderAlignment.aboveBaseline,
-                          baseline: TextBaseline.alphabetic,
-                          child: Checkbox(value: false, onChanged: null),
-                        ),
-                        WidgetSpan(
-                          alignment: PlaceholderAlignment.aboveBaseline,
-                          baseline: TextBaseline.alphabetic,
-                          child: SizedBox(
-                            width: 20,
-                            height: 20,
-                            child: Checkbox(value: true, onChanged: null),
-                          )
-                        ),
-                        WidgetSpan(
-                          alignment: PlaceholderAlignment.aboveBaseline,
-                          baseline: TextBaseline.alphabetic,
-                          child: Checkbox(value: false, onChanged: null),
-                        ),
-                        WidgetSpan(
-                          alignment: PlaceholderAlignment.aboveBaseline,
-                          baseline: TextBaseline.alphabetic,
-                          child: SizedBox(
-                            width: 20,
-                            height: 20,
-                            child: Checkbox(value: true, onChanged: null),
-                          )
-                        ),
-                        WidgetSpan(
-                          alignment: PlaceholderAlignment.aboveBaseline,
-                          baseline: TextBaseline.alphabetic,
-                          child: Text('embedded'),
-                        ),
-                        TextSpan(text: 'ref'),
-                      ],
-                    ),
-                    textDirection: TextDirection.ltr,
-                  ),
-                ),
-              ),
-            ),
-          ),
-        ),
-      ),
-    );
-    await expectLater(
-      find.byType(Container),
-      matchesGoldenFile('text_golden.TextInlineWidgetAboveBaseline.1.1.png'),
-    );
-  }, skip: !isLinux); // Coretext uses different thicknesses for decoration
-
-  testWidgets('Text Inline widget belowBaseline', (WidgetTester tester) async {
-    await tester.pumpWidget(
-      Center(
-        child: RepaintBoundary(
-          child: Material(
-            child: Directionality(
-              textDirection: TextDirection.ltr,
-              child: Container(
-                width: 400.0,
-                height: 200.0,
-                decoration: const BoxDecoration(
-                  color: Color(0xff00ff00),
-                ),
-                child: ConstrainedBox(
-                  constraints: const BoxConstraints(minWidth: 0, maxWidth: 200, minHeight: 0, maxHeight: 100),
-                  child: const Text.rich(
-                    TextSpan(
-                      text: 'C ',
-                      style: TextStyle(
-                        fontSize: 16,
-                      ),
-                      children: <InlineSpan>[
-                        WidgetSpan(
-                          alignment: PlaceholderAlignment.belowBaseline,
-                          baseline: TextBaseline.alphabetic,
-                          child: Checkbox(value: true, onChanged: null),
-                        ),
-                        WidgetSpan(
-                          child: Checkbox(value: false, onChanged: null),
-                        ),
-                        TextSpan(text: 'He ', style: TextStyle(fontSize: 20)),
-                        WidgetSpan(
-                          alignment: PlaceholderAlignment.belowBaseline,
-                          baseline: TextBaseline.alphabetic,
-                          child: SizedBox(
-                            width: 50.0,
-                            height: 55.0,
-                            child: DecoratedBox(
-                              decoration: BoxDecoration(
-                                color: Color(0xffffff00),
-                              ),
-                              child: Center(
-                                child:SizedBox(
-                                  width: 10.0,
-                                  height: 15.0,
-                                  child: DecoratedBox(
-                                    decoration: BoxDecoration(
-                                      color: Color(0xffff0000),
-                                    ),
-                                  )
-                                ),
-                              ),
-                            )
-                          ),
-                        ),
-                        TextSpan(text: 'hello world! sieze the day!'),
-                        WidgetSpan(
-                          alignment: PlaceholderAlignment.belowBaseline,
-                          baseline: TextBaseline.alphabetic,
-                          child: Checkbox(value: false, onChanged: null),
-                        ),
-                        WidgetSpan(
-                          alignment: PlaceholderAlignment.belowBaseline,
-                          baseline: TextBaseline.alphabetic,
-                          child: SizedBox(
-                            width: 20,
-                            height: 20,
-                            child: Checkbox(value: true, onChanged: null),
-                          )
-                        ),
-                        WidgetSpan(
-                          alignment: PlaceholderAlignment.belowBaseline,
-                          baseline: TextBaseline.alphabetic,
-                          child: Checkbox(value: false, onChanged: null),
-                        ),
-                        WidgetSpan(
-                          alignment: PlaceholderAlignment.belowBaseline,
-                          baseline: TextBaseline.alphabetic,
-                          child: SizedBox(
-                            width: 20,
-                            height: 20,
-                            child: Checkbox(value: true, onChanged: null),
-                          )
-                        ),
-                        WidgetSpan(
-                          alignment: PlaceholderAlignment.belowBaseline,
-                          baseline: TextBaseline.alphabetic,
-                          child: Text('embedded'),
-                        ),
-                        TextSpan(text: 'ref'),
-                      ],
-                    ),
-                    textDirection: TextDirection.ltr,
-                  ),
-                ),
-              ),
-            ),
-          ),
-        ),
-      ),
-    );
-    await expectLater(
-      find.byType(Container),
-      matchesGoldenFile('text_golden.TextInlineWidgetBelowBaseline.1.1.png'),
-    );
-  }, skip: !isLinux); // Coretext uses different thicknesses for decoration
-
-  testWidgets('Text Inline widget top', (WidgetTester tester) async {
-    await tester.pumpWidget(
-      Center(
-        child: RepaintBoundary(
-          child: Material(
-            child: Directionality(
-              textDirection: TextDirection.ltr,
-              child: Container(
-                width: 400.0,
-                height: 200.0,
-                decoration: const BoxDecoration(
-                  color: Color(0xff00ff00),
-                ),
-                child: ConstrainedBox(
-                  constraints: const BoxConstraints(minWidth: 0, maxWidth: 200, minHeight: 0, maxHeight: 100),
-                  child: const Text.rich(
-                    TextSpan(
-                      text: 'C ',
-                      style: TextStyle(
-                        fontSize: 16,
-                      ),
-                      children: <InlineSpan>[
-                        WidgetSpan(
-                          alignment: PlaceholderAlignment.top,
-                          baseline: TextBaseline.alphabetic,
-                          child: Checkbox(value: true, onChanged: null),
-                        ),
-                        WidgetSpan(
-                          child: Checkbox(value: false, onChanged: null),
-                        ),
-                        TextSpan(text: 'He ', style: TextStyle(fontSize: 20)),
-                        WidgetSpan(
-                          alignment: PlaceholderAlignment.top,
-                          baseline: TextBaseline.alphabetic,
-                          child: SizedBox(
-                            width: 50.0,
-                            height: 55.0,
-                            child: DecoratedBox(
-                              decoration: BoxDecoration(
-                                color: Color(0xffffff00),
-                              ),
-                              child: Center(
-                                child:SizedBox(
-                                  width: 10.0,
-                                  height: 15.0,
-                                  child: DecoratedBox(
-                                    decoration: BoxDecoration(
-                                      color: Color(0xffff0000),
-                                    ),
-                                  )
-                                ),
-                              ),
-                            )
-                          ),
-                        ),
-                        TextSpan(text: 'hello world! sieze the day!'),
-                        WidgetSpan(
-                          alignment: PlaceholderAlignment.top,
-                          baseline: TextBaseline.alphabetic,
-                          child: Checkbox(value: false, onChanged: null),
-                        ),
-                        WidgetSpan(
-                          alignment: PlaceholderAlignment.top,
-                          baseline: TextBaseline.alphabetic,
-                          child: SizedBox(
-                            width: 20,
-                            height: 20,
-                            child: Checkbox(value: true, onChanged: null),
-                          )
-                        ),
-                        WidgetSpan(
-                          alignment: PlaceholderAlignment.top,
-                          baseline: TextBaseline.alphabetic,
-                          child: Checkbox(value: false, onChanged: null),
-                        ),
-                        WidgetSpan(
-                          alignment: PlaceholderAlignment.top,
-                          baseline: TextBaseline.alphabetic,
-                          child: SizedBox(
-                            width: 20,
-                            height: 20,
-                            child: Checkbox(value: true, onChanged: null),
-                          )
-                        ),
-                        WidgetSpan(
-                          alignment: PlaceholderAlignment.top,
-                          baseline: TextBaseline.alphabetic,
-                          child: Text('embedded'),
-                        ),
-                        TextSpan(text: 'ref'),
-                      ],
-                    ),
-                    textDirection: TextDirection.ltr,
-                  ),
-                ),
-              ),
-            ),
-          ),
-        ),
-      ),
-    );
-    await expectLater(
-      find.byType(Container),
-      matchesGoldenFile('text_golden.TextInlineWidgetTop.1.1.png'),
-    );
-  }, skip: !isLinux); // Coretext uses different thicknesses for decoration
-
-  testWidgets('Text Inline widget middle', (WidgetTester tester) async {
-    await tester.pumpWidget(
-      Center(
-        child: RepaintBoundary(
-          child: Material(
-            child: Directionality(
-              textDirection: TextDirection.ltr,
-              child: Container(
-                width: 400.0,
-                height: 200.0,
-                decoration: const BoxDecoration(
-                  color: Color(0xff00ff00),
-                ),
-                child: ConstrainedBox(
-                  constraints: const BoxConstraints(minWidth: 0, maxWidth: 200, minHeight: 0, maxHeight: 100),
-                  child: const Text.rich(
-                    TextSpan(
-                      text: 'C ',
-                      style: TextStyle(
-                        fontSize: 16,
-                      ),
-                      children: <InlineSpan>[
-                        WidgetSpan(
-                          alignment: PlaceholderAlignment.middle,
-                          baseline: TextBaseline.alphabetic,
-                          child: Checkbox(value: true, onChanged: null),
-                        ),
-                        WidgetSpan(
-                          child: Checkbox(value: false, onChanged: null),
-                        ),
-                        TextSpan(text: 'He ', style: TextStyle(fontSize: 20)),
-                        WidgetSpan(
-                          alignment: PlaceholderAlignment.middle,
-                          baseline: TextBaseline.alphabetic,
-                          child: SizedBox(
-                            width: 50.0,
-                            height: 55.0,
-                            child: DecoratedBox(
-                              decoration: BoxDecoration(
-                                color: Color(0xffffff00),
-                              ),
-                              child: Center(
-                                child:SizedBox(
-                                  width: 10.0,
-                                  height: 15.0,
-                                  child: DecoratedBox(
-                                    decoration: BoxDecoration(
-                                      color: Color(0xffff0000),
-                                    ),
-                                  )
-                                ),
-                              ),
-                            )
-                          ),
-                        ),
-                        TextSpan(text: 'hello world! sieze the day!'),
-                        WidgetSpan(
-                          alignment: PlaceholderAlignment.middle,
-                          baseline: TextBaseline.alphabetic,
-                          child: Checkbox(value: false, onChanged: null),
-                        ),
-                        WidgetSpan(
-                          alignment: PlaceholderAlignment.middle,
-                          baseline: TextBaseline.alphabetic,
-                          child: SizedBox(
-                            width: 20,
-                            height: 20,
-                            child: Checkbox(value: true, onChanged: null),
-                          )
-                        ),
-                        WidgetSpan(
-                          alignment: PlaceholderAlignment.middle,
-                          baseline: TextBaseline.alphabetic,
-                          child: Checkbox(value: false, onChanged: null),
-                        ),
-                        WidgetSpan(
-                          alignment: PlaceholderAlignment.middle,
-                          baseline: TextBaseline.alphabetic,
-                          child: SizedBox(
-                            width: 20,
-                            height: 20,
-                            child: Checkbox(value: true, onChanged: null),
-                          )
-                        ),
-                        WidgetSpan(
-                          alignment: PlaceholderAlignment.middle,
-                          baseline: TextBaseline.alphabetic,
-                          child: Text('embedded'),
-                        ),
-                        TextSpan(text: 'ref'),
-                      ],
-                    ),
-                    textDirection: TextDirection.ltr,
-                  ),
-                ),
-              ),
-            ),
-          ),
-        ),
-      ),
-    );
-    await expectLater(
-      find.byType(Container),
-      matchesGoldenFile('text_golden.TextInlineWidgetMiddle.1.1.png'),
-    );
-  }, skip: !isLinux); // Coretext uses different thicknesses for decoration
 }
diff --git a/packages/flutter/test/widgets/text_test.dart b/packages/flutter/test/widgets/text_test.dart
index 269263b..48a89ba 100644
--- a/packages/flutter/test/widgets/text_test.dart
+++ b/packages/flutter/test/widgets/text_test.dart
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'package:flutter_test/flutter_test.dart';
-import 'package:flutter/foundation.dart';
 import 'package:flutter/gestures.dart';
-import 'package:flutter/material.dart';
+import 'package:flutter_test/flutter_test.dart';
 import 'package:flutter/widgets.dart';
+import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
 
 import '../rendering/mock_canvas.dart';
 import 'semantics_tester.dart';
@@ -294,140 +294,6 @@
     semantics.dispose();
   }, skip: true); // TODO(jonahwilliams): correct once https://github.com/flutter/flutter/issues/20891 is resolved.
 
-  testWidgets('inline widgets generate semantic nodes', (WidgetTester tester) async {
-    final SemanticsTester semantics = SemanticsTester(tester);
-    const TextStyle textStyle = TextStyle(fontFamily: 'Ahem');
-    await tester.pumpWidget(
-      Text.rich(
-        TextSpan(
-          children: <InlineSpan>[
-            const TextSpan(text: 'a '),
-            TextSpan(text: 'pebble', recognizer: TapGestureRecognizer()..onTap = () { }),
-            const TextSpan(text: ' in the '),
-            WidgetSpan(
-              child: SizedBox(
-                width: 20,
-                height: 40,
-                child: Card(
-                  child: RichText(
-                    text: const TextSpan(text: 'INTERRUPTION'),
-                    textDirection: TextDirection.rtl,
-                  ),
-                ),
-              ),
-            ),
-            const TextSpan(text: 'sky'),
-          ],
-          style: textStyle,
-        ),
-        textDirection: TextDirection.ltr,
-      ),
-    );
-    final TestSemantics expectedSemantics = TestSemantics.root(
-      children: <TestSemantics>[
-        TestSemantics.rootChild(
-          children: <TestSemantics>[
-            TestSemantics(
-              label: 'a ',
-              textDirection: TextDirection.ltr,
-            ),
-            TestSemantics(
-              label: 'pebble',
-              textDirection: TextDirection.ltr,
-              actions: <SemanticsAction>[
-                SemanticsAction.tap,
-              ],
-            ),
-            TestSemantics(
-              label: ' in the ',
-              textDirection: TextDirection.ltr,
-            ),
-            TestSemantics(
-              label: 'INTERRUPTION',
-              textDirection: TextDirection.rtl,
-            ),
-            TestSemantics(
-              label: 'sky',
-              textDirection: TextDirection.ltr,
-            ),
-          ],
-        ),
-      ],
-    );
-    expect(semantics, hasSemantics(expectedSemantics, ignoreTransform: true, ignoreId: true, ignoreRect: true));
-    semantics.dispose();
-  });
-
-  testWidgets('inline widgets semantic nodes scale', (WidgetTester tester) async {
-    final SemanticsTester semantics = SemanticsTester(tester);
-    const TextStyle textStyle = TextStyle(fontFamily: 'Ahem');
-    await tester.pumpWidget(
-      Text.rich(
-        TextSpan(
-          children: <InlineSpan>[
-            const TextSpan(text: 'a '),
-            TextSpan(text: 'pebble', recognizer: TapGestureRecognizer()..onTap = () { }),
-            const TextSpan(text: ' in the '),
-            WidgetSpan(
-              child: SizedBox(
-                width: 20,
-                height: 40,
-                child: Card(
-                  child: RichText(
-                    text: const TextSpan(text: 'INTERRUPTION'),
-                    textDirection: TextDirection.rtl,
-                  ),
-                ),
-              ),
-            ),
-            const TextSpan(text: 'sky'),
-          ],
-          style: textStyle,
-        ),
-        textDirection: TextDirection.ltr,
-        textScaleFactor: 2,
-      ),
-    );
-    final TestSemantics expectedSemantics = TestSemantics.root(
-      children: <TestSemantics>[
-        TestSemantics.rootChild(
-          rect: const Rect.fromLTRB(0.0, 0.0, 800.0, 600.0),
-          children: <TestSemantics>[
-            TestSemantics(
-              label: 'a ',
-              textDirection: TextDirection.ltr,
-              rect: const Rect.fromLTRB(-4.0, 48.0, 60.0, 84.0),
-            ),
-            TestSemantics(
-              label: 'pebble',
-              textDirection: TextDirection.ltr,
-              actions: <SemanticsAction>[
-                SemanticsAction.tap,
-              ],
-              rect: const Rect.fromLTRB(52.0, 48.0, 228.0, 84.0),
-            ),
-            TestSemantics(
-              label: ' in the ',
-              textDirection: TextDirection.ltr,
-              rect: const Rect.fromLTRB(220.0, 48.0, 452.0, 84.0),
-            ),
-            TestSemantics(
-              label: 'INTERRUPTION',
-              textDirection: TextDirection.rtl,
-              rect: const Rect.fromLTRB(448.0, 0.0, 488.0, 80.0),
-            ),
-            TestSemantics(
-              label: 'sky',
-              textDirection: TextDirection.ltr,
-              rect: const Rect.fromLTRB(484.0, 48.0, 576.0, 84.0),
-            ),
-          ],
-        ),
-      ],
-    );
-    expect(semantics, hasSemantics(expectedSemantics, ignoreTransform: true, ignoreId: true,));
-    semantics.dispose();
-  });
 
   testWidgets('Overflow is clipping correctly - short text with overflow: clip', (WidgetTester tester) async {
     await _pumpTextWidget(
diff --git a/packages/flutter/test/widgets/widget_inspector_test.dart b/packages/flutter/test/widgets/widget_inspector_test.dart
index 8db54de..046528a 100644
--- a/packages/flutter/test/widgets/widget_inspector_test.dart
+++ b/packages/flutter/test/widgets/widget_inspector_test.dart
@@ -329,10 +329,7 @@
       }
       // State type is private, hence using dynamic.
       dynamic getInspectorState() => inspectorKey.currentState;
-      String paragraphText(RenderParagraph paragraph) {
-        final TextSpan textSpan = paragraph.text;
-        return textSpan.text;
-      }
+      String paragraphText(RenderParagraph paragraph) => paragraph.text.text;
 
       await tester.pumpWidget(
         Directionality(