Just use SemanticAnnotator instead of Iterable<SemanticAnnotator> (#4813)

diff --git a/packages/flutter/lib/src/material/slider.dart b/packages/flutter/lib/src/material/slider.dart
index 4e4119a..6966ed4 100644
--- a/packages/flutter/lib/src/material/slider.dart
+++ b/packages/flutter/lib/src/material/slider.dart
@@ -423,14 +423,14 @@
   }
 
   @override
-  bool get hasSemantics => isInteractive;
+  bool get isSemanticBoundary => isInteractive;
 
   @override
-  Iterable<SemanticAnnotator> getSemanticAnnotators() sync* {
-    yield (SemanticsNode semantics) {
-      if (isInteractive)
-        semantics.addAdjustmentActions();
-    };
+  SemanticAnnotator get semanticAnnotator => _annotate;
+
+  void _annotate(SemanticsNode semantics) {
+    if (isInteractive)
+      semantics.addAdjustmentActions();
   }
 
   @override
diff --git a/packages/flutter/lib/src/material/toggleable.dart b/packages/flutter/lib/src/material/toggleable.dart
index 0fd7594..0c8c4d4 100644
--- a/packages/flutter/lib/src/material/toggleable.dart
+++ b/packages/flutter/lib/src/material/toggleable.dart
@@ -263,17 +263,17 @@
   }
 
   @override
-  bool get hasSemantics => isInteractive;
+  bool get isSemanticBoundary => isInteractive;
 
   @override
-  Iterable<SemanticAnnotator> getSemanticAnnotators() sync* {
-    yield (SemanticsNode semantics) {
-      semantics
-        ..hasCheckedState = true
-        ..isChecked = _value;
-      if (isInteractive)
-        semantics.addAction(SemanticAction.tap);
-    };
+  SemanticAnnotator get semanticAnnotator => _annotate;
+
+  void _annotate(SemanticsNode semantics) {
+    semantics
+      ..hasCheckedState = true
+      ..isChecked = _value;
+    if (isInteractive)
+      semantics.addAction(SemanticAction.tap);
   }
 
   @override
diff --git a/packages/flutter/lib/src/rendering/object.dart b/packages/flutter/lib/src/rendering/object.dart
index 089780a..603117b 100644
--- a/packages/flutter/lib/src/rendering/object.dart
+++ b/packages/flutter/lib/src/rendering/object.dart
@@ -508,13 +508,11 @@
 abstract class _SemanticsFragment {
   _SemanticsFragment({
     RenderObject renderObjectOwner,
-    Iterable<SemanticAnnotator> annotators,
+    this.annotator,
     List<_SemanticsFragment> children
   }) {
     assert(renderObjectOwner != null);
     _ancestorChain = <RenderObject>[renderObjectOwner];
-    if (annotators != null)
-      addAnnotators(annotators);
     assert(() {
       if (children == null)
         return true;
@@ -526,6 +524,8 @@
     _children = children ?? const <_SemanticsFragment>[];
   }
 
+  final SemanticAnnotator annotator;
+
   List<RenderObject> _ancestorChain;
   void addAncestor(RenderObject ancestor) {
     _ancestorChain.add(ancestor);
@@ -533,14 +533,6 @@
 
   RenderObject get renderObjectOwner => _ancestorChain.first;
 
-  List<SemanticAnnotator> _annotators;
-  void addAnnotators(Iterable<SemanticAnnotator> moreAnnotators) {
-    if (_annotators == null)
-      _annotators = moreAnnotators is List<SemanticAnnotator> ? moreAnnotators : moreAnnotators.toList();
-    else
-      _annotators.addAll(moreAnnotators);
-  }
-
   List<_SemanticsFragment> _children;
 
   bool _debugCompiled = false;
@@ -579,9 +571,9 @@
 abstract class _InterestingSemanticsFragment extends _SemanticsFragment {
   _InterestingSemanticsFragment({
     RenderObject renderObjectOwner,
-    Iterable<SemanticAnnotator> annotators,
+    SemanticAnnotator annotator,
     Iterable<_SemanticsFragment> children
-  }) : super(renderObjectOwner: renderObjectOwner, annotators: annotators, children: children);
+  }) : super(renderObjectOwner: renderObjectOwner, annotator: annotator, children: children);
 
   bool get haveConcreteNode => true;
 
@@ -590,7 +582,7 @@
     assert(!_debugCompiled);
     assert(() { _debugCompiled = true; return true; });
     SemanticsNode node = establishSemanticsNode(geometry, currentSemantics, parentSemantics);
-    for (SemanticAnnotator annotator in _annotators)
+    if (annotator != null)
       annotator(node);
     for (_SemanticsFragment child in _children) {
       assert(child._ancestorChain.last == renderObjectOwner);
@@ -613,9 +605,9 @@
 class _RootSemanticsFragment extends _InterestingSemanticsFragment {
   _RootSemanticsFragment({
     RenderObject renderObjectOwner,
-    Iterable<SemanticAnnotator> annotators,
+    SemanticAnnotator annotator,
     Iterable<_SemanticsFragment> children
-  }) : super(renderObjectOwner: renderObjectOwner, annotators: annotators, children: children);
+  }) : super(renderObjectOwner: renderObjectOwner, annotator: annotator, children: children);
 
   @override
   SemanticsNode establishSemanticsNode(_SemanticsGeometry geometry, SemanticsNode currentSemantics, SemanticsNode parentSemantics) {
@@ -643,9 +635,9 @@
 class _ConcreteSemanticsFragment extends _InterestingSemanticsFragment {
   _ConcreteSemanticsFragment({
     RenderObject renderObjectOwner,
-    Iterable<SemanticAnnotator> annotators,
+    SemanticAnnotator annotator,
     Iterable<_SemanticsFragment> children
-  }) : super(renderObjectOwner: renderObjectOwner, annotators: annotators, children: children);
+  }) : super(renderObjectOwner: renderObjectOwner, annotator: annotator, children: children);
 
   @override
   SemanticsNode establishSemanticsNode(_SemanticsGeometry geometry, SemanticsNode currentSemantics, SemanticsNode parentSemantics) {
@@ -671,9 +663,9 @@
 class _ImplicitSemanticsFragment extends _InterestingSemanticsFragment {
   _ImplicitSemanticsFragment({
     RenderObject renderObjectOwner,
-    Iterable<SemanticAnnotator> annotators,
+    SemanticAnnotator annotator,
     Iterable<_SemanticsFragment> children
-  }) : super(renderObjectOwner: renderObjectOwner, annotators: annotators, children: children);
+  }) : super(renderObjectOwner: renderObjectOwner, annotator: annotator, children: children);
 
   @override
   bool get haveConcreteNode => _haveConcreteNode;
@@ -683,7 +675,7 @@
   SemanticsNode establishSemanticsNode(_SemanticsGeometry geometry, SemanticsNode currentSemantics, SemanticsNode parentSemantics) {
     SemanticsNode node;
     assert(_haveConcreteNode == null);
-    _haveConcreteNode = currentSemantics == null && _annotators.isNotEmpty;
+    _haveConcreteNode = currentSemantics == null && annotator != null;
     if (haveConcreteNode) {
       renderObjectOwner._semantics ??= new SemanticsNode(
         handler: renderObjectOwner is SemanticActionHandler ? renderObjectOwner as dynamic : null
@@ -758,10 +750,9 @@
 /// 3. [flushPaint] visites any render objects that need to paint. During this
 ///    phase, render objects get a chance to record painting commands into
 ///    [PictureLayer]s and construct other composited [Layer]s.
-/// 4. Finally, if [SemanticsNode.hasListeners] is true, [flushSemantics] will
-///    compile the semantics for the render objects. This semantic information
-///    is used by assistive technology to improve the accessibility of the
-///    render tree.
+/// 4. Finally, if semantics are enabled, [flushSemantics] will compile the
+///    semantics for the render objects. This semantic information is used by
+///    assistive technology to improve the accessibility of the render tree.
 ///
 /// The [RendererBinding] holds the pipeline owner for the render objects that
 /// are visible on screen. You can create other pipeline owners to manage
@@ -1197,7 +1188,7 @@
       _needsPaint = false;
       markNeedsPaint();
     }
-    if (_needsSemanticsUpdate && hasSemantics) {
+    if (_needsSemanticsUpdate && isSemanticBoundary) {
       // Don't enter this block if we've never updated semantics at all;
       // scheduleInitialSemantics() will handle it
       _needsSemanticsUpdate = false;
@@ -1900,7 +1891,7 @@
   }
 
   /// Whether this RenderObject introduces a new box for accessibility purposes.
-  bool get hasSemantics => false;
+  bool get isSemanticBoundary => false;
 
   /// The bounding box, in the local coordinate system, of this
   /// object, for accessibility purposes.
@@ -2024,7 +2015,7 @@
 
   _SemanticsFragment _getSemanticsFragment() {
     // early-exit if we're not dirty and have our own semantics
-    if (!_needsSemanticsUpdate && hasSemantics) {
+    if (!_needsSemanticsUpdate && isSemanticBoundary) {
       assert(_semantics != null);
       return new _CleanSemanticsFragment(renderObjectOwner: this);
     }
@@ -2047,13 +2038,13 @@
     });
     _needsSemanticsUpdate = false;
     _needsSemanticsGeometryUpdate = false;
-    Iterable<SemanticAnnotator> annotators = getSemanticAnnotators();
+    SemanticAnnotator annotator = semanticAnnotator;
     if (parent is! RenderObject)
-      return new _RootSemanticsFragment(renderObjectOwner: this, annotators: annotators, children: children);
-    if (hasSemantics)
-      return new _ConcreteSemanticsFragment(renderObjectOwner: this, annotators: annotators, children: children);
-    if (annotators.isNotEmpty)
-      return new _ImplicitSemanticsFragment(renderObjectOwner: this, annotators: annotators, children: children);
+      return new _RootSemanticsFragment(renderObjectOwner: this, annotator: annotator, children: children);
+    if (isSemanticBoundary)
+      return new _ConcreteSemanticsFragment(renderObjectOwner: this, annotator: annotator, children: children);
+    if (annotator != null)
+      return new _ImplicitSemanticsFragment(renderObjectOwner: this, annotator: annotator, children: children);
     _semantics = null;
     if (children == null)
       return null;
@@ -2098,7 +2089,7 @@
   /// non-zero, and hasSemantics isn't true, then the associated call
   /// to markNeedsSemanticsUpdate() must not have 'onlyChanges' set, as
   /// it is possible that the node should be entirely removed.
-  Iterable<SemanticAnnotator> getSemanticAnnotators() sync* { }
+  SemanticAnnotator get semanticAnnotator => null;
 
 
   // EVENTS
diff --git a/packages/flutter/lib/src/rendering/paragraph.dart b/packages/flutter/lib/src/rendering/paragraph.dart
index ce933bb..265268b 100644
--- a/packages/flutter/lib/src/rendering/paragraph.dart
+++ b/packages/flutter/lib/src/rendering/paragraph.dart
@@ -231,10 +231,10 @@
   }
 
   @override
-  Iterable<SemanticAnnotator> getSemanticAnnotators() sync* {
-    yield (SemanticsNode node) {
-      node.label = text.toPlainText();
-    };
+  SemanticAnnotator get semanticAnnotator => _annotate;
+
+  void _annotate(SemanticsNode node) {
+    node.label = text.toPlainText();
   }
 
   @override
diff --git a/packages/flutter/lib/src/rendering/proxy_box.dart b/packages/flutter/lib/src/rendering/proxy_box.dart
index 4578c50..7ab769d 100644
--- a/packages/flutter/lib/src/rendering/proxy_box.dart
+++ b/packages/flutter/lib/src/rendering/proxy_box.dart
@@ -2054,11 +2054,11 @@
   set onTap(GestureTapCallback value) {
     if (_onTap == value)
       return;
-    bool didHaveSemantics = hasSemantics;
+    bool wasSemanticBoundary = isSemanticBoundary;
     bool hadHandler = _onTap != null;
     _onTap = value;
     if ((value != null) != hadHandler)
-      markNeedsSemanticsUpdate(onlyChanges: hasSemantics == didHaveSemantics);
+      markNeedsSemanticsUpdate(onlyChanges: isSemanticBoundary == wasSemanticBoundary);
   }
 
   /// Called when the user presses on the render object for a long period of time.
@@ -2067,11 +2067,11 @@
   set onLongPress(GestureLongPressCallback value) {
     if (_onLongPress == value)
       return;
-    bool didHaveSemantics = hasSemantics;
+    bool wasSemanticBoundary = isSemanticBoundary;
     bool hadHandler = _onLongPress != null;
     _onLongPress = value;
     if ((value != null) != hadHandler)
-      markNeedsSemanticsUpdate(onlyChanges: hasSemantics == didHaveSemantics);
+      markNeedsSemanticsUpdate(onlyChanges: isSemanticBoundary == wasSemanticBoundary);
   }
 
   /// Called when the user scrolls to the left or to the right.
@@ -2080,11 +2080,11 @@
   set onHorizontalDragUpdate(GestureDragUpdateCallback value) {
     if (_onHorizontalDragUpdate == value)
       return;
-    bool didHaveSemantics = hasSemantics;
+    bool wasSemanticBoundary = isSemanticBoundary;
     bool hadHandler = _onHorizontalDragUpdate != null;
     _onHorizontalDragUpdate = value;
     if ((value != null) != hadHandler)
-      markNeedsSemanticsUpdate(onlyChanges: hasSemantics == didHaveSemantics);
+      markNeedsSemanticsUpdate(onlyChanges: isSemanticBoundary == wasSemanticBoundary);
   }
 
   /// Called when the user scrolls up or down.
@@ -2093,11 +2093,11 @@
   set onVerticalDragUpdate(GestureDragUpdateCallback value) {
     if (_onVerticalDragUpdate == value)
       return;
-    bool didHaveSemantics = hasSemantics;
+    bool wasSemanticBoundary = isSemanticBoundary;
     bool hadHandler = _onVerticalDragUpdate != null;
     _onVerticalDragUpdate = value;
     if ((value != null) != hadHandler)
-      markNeedsSemanticsUpdate(onlyChanges: hasSemantics == didHaveSemantics);
+      markNeedsSemanticsUpdate(onlyChanges: isSemanticBoundary == wasSemanticBoundary);
   }
 
   /// The fraction of the dimension of this render box to use when
@@ -2108,7 +2108,7 @@
   double scrollFactor;
 
   @override
-  bool get hasSemantics {
+  bool get isSemanticBoundary {
     return onTap != null
         || onLongPress != null
         || onHorizontalDragUpdate != null
@@ -2116,19 +2116,17 @@
   }
 
   @override
-  Iterable<SemanticAnnotator> getSemanticAnnotators() sync* {
-    if (hasSemantics) {
-      yield (SemanticsNode semantics) {
-        if (onTap != null)
-          semantics.addAction(SemanticAction.tap);
-        if (onLongPress != null)
-          semantics.addAction(SemanticAction.longPress);
-        if (onHorizontalDragUpdate != null)
-          semantics.addHorizontalScrollingActions();
-        if (onVerticalDragUpdate != null)
-          semantics.addVerticalScrollingActions();
-      };
-    }
+  SemanticAnnotator get semanticAnnotator => isSemanticBoundary ? _annotate : null;
+
+  void _annotate(SemanticsNode node) {
+    if (onTap != null)
+      node.addAction(SemanticAction.tap);
+    if (onLongPress != null)
+      node.addAction(SemanticAction.longPress);
+    if (onHorizontalDragUpdate != null)
+      node.addHorizontalScrollingActions();
+    if (onVerticalDragUpdate != null)
+      node.addVerticalScrollingActions();
   }
 
   @override
@@ -2243,21 +2241,19 @@
   }
 
   @override
-  bool get hasSemantics => container;
+  bool get isSemanticBoundary => container;
 
   @override
-  Iterable<SemanticAnnotator> getSemanticAnnotators() sync* {
+  SemanticAnnotator get semanticAnnotator => checked != null || label != null ? _annotate : null;
+
+  void _annotate(SemanticsNode node) {
     if (checked != null) {
-      yield (SemanticsNode semantics) {
-        semantics.hasCheckedState = true;
-        semantics.isChecked = checked;
-      };
+      node
+        ..hasCheckedState = true
+        ..isChecked = checked;
     }
-    if (label != null) {
-      yield (SemanticsNode semantics) {
-        semantics.label = label;
-      };
-    }
+    if (label != null)
+      node.label = label;
   }
 }
 
@@ -2273,8 +2269,10 @@
   RenderMergeSemantics({ RenderBox child }) : super(child);
 
   @override
-  Iterable<SemanticAnnotator> getSemanticAnnotators() sync* {
-    yield (SemanticsNode node) { node.mergeAllDescendantsIntoThisNode = true; };
+  SemanticAnnotator get semanticAnnotator => _annotate;
+
+  void _annotate(SemanticsNode node) {
+    node.mergeAllDescendantsIntoThisNode = true;
   }
 }