Complete docs for RenderObject (#4266)
diff --git a/packages/flutter/lib/src/rendering/object.dart b/packages/flutter/lib/src/rendering/object.dart
index 3d28ab3..bdf161e 100644
--- a/packages/flutter/lib/src/rendering/object.dart
+++ b/packages/flutter/lib/src/rendering/object.dart
@@ -734,18 +734,72 @@
   }
 }
 
+/// The pipeline owner manages the rendering pipeline.
+///
+/// The pipeline owner provides an interface for driving the rendering pipeline
+/// and stores the state about which render objects have requested to be visited
+/// in each stage of the pipeline. To flush the pipeline, call the following
+/// functions in order:
+///
+/// 1. [flushLayout] updates any render objects that need to compute their
+///    layout. During this phase, the size and position of each render
+///    object is calculated. Render objects might dirty their painting or
+///    compositing state during this phase.
+/// 2. [flushCompositingBits] updates any render objects that have dirty
+///    compositing bits. During this phase, each render object learns whether
+///    any of its children require compositing. This information is used during
+///    the painting phase when selecting how to implement visual effects such as
+///    clipping. If a render object has a composited child, its needs to use a
+///    [Layer] to create the clip in order for the clip to apply to the
+///    composited child (which will be painted into its own [Layer]).
+/// 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.
+///
+/// The [RendererBinding] holds the pipeline owner for the render objects that
+/// are visible on screen. You can create other pipeline owners to manage
+/// off-screen objects, which can flush their pipelines independently of the
+/// on-screen render objects.
 class PipelineOwner {
+  /// Creates a pipeline owner.
+  ///
+  /// Typically created by the binding (e.g., [RendererBinding]), but can be
+  /// created separately from the binding to drive off-screen render objects
+  /// through the rendering pipeline.
   PipelineOwner({ this.onNeedVisualUpdate });
+
+  /// Called when a render object associated with this pipeline owner wishes to
+  /// update its visual appearance.
+  ///
+  /// Typical implementations of this function will schedule a task to flush the
+  /// various stages of the pipeline. This function might be called multiple
+  /// times in quick succession. Implementations should take care to discard
+  /// duplicate calls quickly.
   final VoidCallback onNeedVisualUpdate;
 
+  /// Calls [onNeedVisualUpdate] if [onNeedVisualUpdate] is not null.
+  ///
+  /// Used to notify the pipeline owner that an associated render object wishes
+  /// to update its visual appearance.
   void requestVisualUpdate() {
     if (onNeedVisualUpdate != null)
       onNeedVisualUpdate();
   }
 
   List<RenderObject> _nodesNeedingLayout = <RenderObject>[];
-  bool _debugDoingLayout = false;
+
+  /// Whether this pipeline is currently in the layout phase.
+  ///
+  /// Specifically, whether [flushLayout] is currently running.
+  ///
+  /// Only valid when asserts are enabled.
   bool get debugDoingLayout => _debugDoingLayout;
+  bool _debugDoingLayout = false;
+
   /// Update the layout information for all dirty render objects.
   ///
   /// This function is one of the core stages of the rendering pipeline. Layout
@@ -789,8 +843,15 @@
   }
 
   List<RenderObject> _nodesNeedingPaint = <RenderObject>[];
-  bool _debugDoingPaint = false;
+
+  /// Whether this pipeline is currently in the paint phase.
+  ///
+  /// Specifically, whether [flushPaint] is currently running.
+  ///
+  /// Only valid when asserts are enabled.
   bool get debugDoingPaint => _debugDoingPaint;
+  bool _debugDoingPaint = false;
+
   /// Update the display lists for all render objects.
   ///
   /// This function is one of the core stages of the rendering pipeline.
@@ -820,6 +881,13 @@
   bool _debugDoingSemantics = false;
   List<RenderObject> _nodesNeedingSemantics = <RenderObject>[];
 
+  /// Update the semantics for all render objects.
+  ///
+  /// This function is one of the core stages of the rendering pipeline. The
+  /// semantics are compiled after painting and only after
+  /// [RenderObject.scheduleInitialSemantics] has been called.
+  ///
+  /// See [FlutterBinding] for an example of how this function is used.
   void flushSemantics() {
     Timeline.startSync('Semantics');
     assert(_semanticsEnabled);
@@ -878,7 +946,7 @@
 /// The [RenderBox] subclass introduces the opinion that the layout
 /// system uses cartesian coordinates.
 abstract class RenderObject extends AbstractNode implements HitTestTarget {
-
+  /// Initializes internal fields for subclasses.
   RenderObject() {
     _needsCompositing = isRepaintBoundary || alwaysNeedsCompositing;
     _performLayout = performLayout;
@@ -919,7 +987,7 @@
   /// You can call this function to set up the parent data for child before the
   /// child is added to the parent's child list.
   void setupParentData(RenderObject child) {
-    assert(debugCanPerformMutations);
+    assert(_debugCanPerformMutations);
     if (child.parentData is! ParentData)
       child.parentData = new ParentData();
   }
@@ -930,7 +998,7 @@
   /// in other cases will lead to an inconsistent tree and probably cause crashes.
   @override
   void adoptChild(RenderObject child) {
-    assert(debugCanPerformMutations);
+    assert(_debugCanPerformMutations);
     assert(child != null);
     setupParentData(child);
     super.adoptChild(child);
@@ -944,7 +1012,7 @@
   /// in other cases will lead to an inconsistent tree and probably cause crashes.
   @override
   void dropChild(RenderObject child) {
-    assert(debugCanPerformMutations);
+    assert(_debugCanPerformMutations);
     assert(child != null);
     assert(child.parentData != null);
     child._cleanRelayoutSubtreeRoot();
@@ -1005,26 +1073,65 @@
     ));
   }
 
-  bool _debugDoingThisResize = false;
+  /// Whether [performResize] for this render object is currently running.
+  ///
+  /// Only valid when asserts are enabled. In release builds, always returns
+  /// false.
   bool get debugDoingThisResize => _debugDoingThisResize;
-  bool _debugDoingThisLayout = false;
+  bool _debugDoingThisResize = false;
+
+  /// Whether [performLayout] for this render object is currently running.
+  ///
+  /// Only valid when asserts are enabled. In release builds, always returns
+  /// false.
   bool get debugDoingThisLayout => _debugDoingThisLayout;
-  static RenderObject _debugActiveLayout;
+  bool _debugDoingThisLayout = false;
+
+  /// The render object that is actively computing layout.
+  ///
+  /// Only valid when asserts are enabled. In release builds, always returns
+  /// null.
   static RenderObject get debugActiveLayout => _debugActiveLayout;
-  bool _debugMutationsLocked = false;
-  bool _debugCanParentUseSize;
+  static RenderObject _debugActiveLayout;
+
+  /// Whether the parent render object is permitted to use this render object's
+  /// size.
+  ///
+  /// Determined by the `parentUsesSize` parameter to [layout].
+  ///
+  /// Only valid when asserts are enabled. In release builds, always returns
+  /// null.
   bool get debugCanParentUseSize => _debugCanParentUseSize;
-  bool get debugCanPerformMutations {
-    RenderObject node = this;
-    while (true) {
-      if (node._doingThisLayoutWithCallback)
-        return true;
-      if (node._debugMutationsLocked)
-        return false;
-      if (node.parent is! RenderObject)
-        return true;
-      node = node.parent;
-    }
+  bool _debugCanParentUseSize;
+
+  bool _debugMutationsLocked = false;
+
+  /// Whether tree mutations are currently permitted.
+  ///
+  /// Only valid when asserts are enabled. In release builds, always returns
+  /// null.
+  bool get _debugCanPerformMutations {
+    bool result;
+    assert(() {
+      RenderObject node = this;
+      while (true) {
+        if (node._doingThisLayoutWithCallback) {
+          result = true;
+          break;
+        }
+        if (node._debugMutationsLocked) {
+          result = false;
+          break;
+        }
+        if (node.parent is! RenderObject) {
+          result = true;
+          break;
+        }
+        node = node.parent;
+      }
+      return true;
+    });
+    return result;
   }
 
   @override
@@ -1085,7 +1192,7 @@
   /// debugAssertDoesMeetConstraints(), and should not be checked in
   /// release mode (where it will always be false).
   static bool debugCheckingIntrinsics = false;
-  bool debugAncestorsAlreadyMarkedNeedsLayout() {
+  bool _debugAncestorsAlreadyMarkedNeedsLayout() {
     if (_relayoutSubtreeRoot == null)
       return true; // we haven't yet done layout even once, so there's nothing for us to do
     RenderObject node = this;
@@ -1115,9 +1222,9 @@
   /// computing its layout information, this function will also mark the parent
   /// as needing layout.
   void markNeedsLayout() {
-    assert(debugCanPerformMutations);
+    assert(_debugCanPerformMutations);
     if (_needsLayout) {
-      assert(debugAncestorsAlreadyMarkedNeedsLayout());
+      assert(_debugAncestorsAlreadyMarkedNeedsLayout());
       return;
     }
     _needsLayout = true;
@@ -1414,10 +1521,19 @@
 
   // PAINTING
 
-  bool _debugDoingThisPaint = false;
+  /// Whether [paint] for this render object is currently running.
+  ///
+  /// Only valid when asserts are enabled. In release builds, always returns
+  /// false.
   bool get debugDoingThisPaint => _debugDoingThisPaint;
-  static RenderObject _debugActivePaint;
+  bool _debugDoingThisPaint = false;
+
+  /// The render object that is actively painting.
+  ///
+  /// Only valid when asserts are enabled. In release builds, always returns
+  /// null.
   static RenderObject get debugActivePaint => _debugActivePaint;
+  static RenderObject _debugActivePaint;
 
   /// Whether this render object repaints separately from its parent.
   ///
@@ -1711,7 +1827,15 @@
   bool _needsSemanticsGeometryUpdate = true;
   SemanticsNode _semantics;
 
-  SemanticsNode get debugSemantics { // only exposed for testing and debugging
+  /// The semantics of this render object.
+  ///
+  /// Exposed only for testing and debugging. To learn about the semantics of
+  /// render objects in production, register as a listener using
+  /// [SemanticsNode.addListener].
+  ///
+  /// Only valid when asserts are enabled. In release builds, always returns
+  /// null.
+  SemanticsNode get debugSemantics {
     SemanticsNode result;
     assert(() {
       result = _semantics;
diff --git a/packages/flutter/lib/src/rendering/performance_overlay.dart b/packages/flutter/lib/src/rendering/performance_overlay.dart
index bc7f2b8..7466b1f 100644
--- a/packages/flutter/lib/src/rendering/performance_overlay.dart
+++ b/packages/flutter/lib/src/rendering/performance_overlay.dart
@@ -41,9 +41,28 @@
   visualizeEngineStatistics,
 }
 
+/// Displays performance statistics.
+///
+/// The overlay show two time series. The first shows how much time was required
+/// on this thread to produce each frame. The second shows how much time was
+/// required on the GPU thread to produce each frame. Ideally, both these values
+/// would be less than the total frame budget for the hardware on which the app
+/// is running. For example, if the hardware has a screen that updates at 60 Hz,
+/// each thread should ideally spend less than 16ms producing each frame. This
+/// ideal condition is indicated by a green vertical line for each thread.
+/// Otherwise, the performance overlay shows a red vertical line.
+///
+/// The simplest way to show the performance overlay is to set
+/// [MaterialApp.showPerformanceOverlay] or [WidgetsApp.showPerformanceOverlay]
+/// to `true`.
 class RenderPerformanceOverlay extends RenderBox {
-  RenderPerformanceOverlay({ int optionsMask: 0, int rasterizerThreshold: 0 })
-    : _optionsMask = optionsMask,
+  /// Creates a performance overlay render object.
+  ///
+  /// The [optionsMask] and [rasterizerThreshold] arguments must not be null.
+  RenderPerformanceOverlay({
+    int optionsMask: 0,
+    int rasterizerThreshold: 0
+  }) : _optionsMask = optionsMask,
       _rasterizerThreshold = rasterizerThreshold;
 
   /// The mask is created by shifting 1 by the index of the specific
@@ -51,6 +70,7 @@
   int get optionsMask => _optionsMask;
   int _optionsMask;
   set optionsMask(int mask) {
+    assert(mask != null);
     if (mask == _optionsMask)
       return;
     _optionsMask = mask;
@@ -63,6 +83,7 @@
   int get rasterizerThreshold => _rasterizerThreshold;
   int _rasterizerThreshold;
   set rasterizerThreshold (int threshold) {
+    assert(threshold != null);
     if (threshold == _rasterizerThreshold)
       return;
     _rasterizerThreshold = threshold;
diff --git a/packages/flutter/lib/src/rendering/proxy_box.dart b/packages/flutter/lib/src/rendering/proxy_box.dart
index b3b964c..097b8cc 100644
--- a/packages/flutter/lib/src/rendering/proxy_box.dart
+++ b/packages/flutter/lib/src/rendering/proxy_box.dart
@@ -121,11 +121,15 @@
 /// A RenderProxyBox subclass that allows you to customize the
 /// hit-testing behavior.
 abstract class RenderProxyBoxWithHitTestBehavior extends RenderProxyBox {
+  /// Initializes member variables for subclasses.
+  ///
+  /// By default, the [behavior] is [HitTestBehavior.deferToChild].
   RenderProxyBoxWithHitTestBehavior({
     this.behavior: HitTestBehavior.deferToChild,
     RenderBox child
   }) : super(child);
 
+  /// How to behave during hit testing.
   HitTestBehavior behavior;
 
   @override
@@ -171,6 +175,9 @@
 /// pixels, you could use `const BoxConstraints(minHeight: 50.0)`` as the
 /// [additionalConstraints].
 class RenderConstrainedBox extends RenderProxyBox {
+  /// Creates a render box that constrains its child.
+  ///
+  /// The [additionalConstraints] argument must not be null and must be valid.
   RenderConstrainedBox({
     RenderBox child,
     BoxConstraints additionalConstraints
@@ -257,6 +264,11 @@
 /// Constrains the child's maxWidth and maxHeight if they're otherwise
 /// unconstrained.
 class RenderLimitedBox extends RenderProxyBox {
+  /// Creates a render box that imposes a maxWidth or maxHeight on its child if
+  /// the child is otherwise unconstrained.
+  ///
+  /// The [maxWidth] and [maxHeight] arguments not be null and must be
+  /// non-negative.
   RenderLimitedBox({
     RenderBox child,
     double maxWidth: double.INFINITY,
@@ -376,13 +388,16 @@
 /// will eventually select a size for the child that meets the layout
 /// constraints but fails to meet the aspect ratio constraints.
 class RenderAspectRatio extends RenderProxyBox {
+  /// Creates as render object with a specific aspect ratio.
+  ///
+  /// The [aspectRatio] argument must be a finite, positive value.
   RenderAspectRatio({
     RenderBox child,
     double aspectRatio
   }) : _aspectRatio = aspectRatio, super(child) {
-    assert(_aspectRatio > 0.0);
-    assert(_aspectRatio.isFinite);
-    assert(_aspectRatio != null);
+    assert(aspectRatio != null);
+    assert(aspectRatio > 0.0);
+    assert(aspectRatio.isFinite);
   }
 
   /// The aspect ratio to attempt to use.
@@ -511,7 +526,7 @@
 ///
 /// This class is relatively expensive. Avoid using it where possible.
 class RenderIntrinsicWidth extends RenderProxyBox {
-
+  /// Creates a render object that sizes itself to its child's intrinsic width.
   RenderIntrinsicWidth({
     double stepWidth,
     double stepHeight,
@@ -618,7 +633,7 @@
 ///
 /// This class is relatively expensive. Avoid using it where possible.
 class RenderIntrinsicHeight extends RenderProxyBox {
-
+  /// Creates a render object that sizes itself to its child's intrinsic height.
   RenderIntrinsicHeight({
     RenderBox child
   }) : super(child);
@@ -686,7 +701,10 @@
 /// buffer. For the value 0.0, the child is simply not painted at all. For the
 /// value 1.0, the child is painted immediately without an intermediate buffer.
 class RenderOpacity extends RenderProxyBox {
-  RenderOpacity({ RenderBox child, double opacity: 1.0 })
+  /// Creates a partially transparent render object.
+  ///
+  /// The [opacity] argument must be between 0.0 and 1.0, inclusive.
+  RenderOpacity({ double opacity: 1.0, RenderBox child })
     : _opacity = opacity, _alpha = _getAlphaFromOpacity(opacity), super(child) {
     assert(opacity != null);
     assert(opacity >= 0.0 && opacity <= 1.0);
@@ -748,12 +766,34 @@
   }
 }
 
+/// Signature for a function that creates a [Shader] for a given [Rect].
+///
+/// Used by [RenderShaderMask].
 typedef Shader ShaderCallback(Rect bounds);
 
+/// Applies a mask generated by a [Shader] to its child.
+///
+/// For example, [RenderShaderMask] can be used to gradually fade out the edge
+/// of a child by using a [ui.Gradient.linear] mask.
 class RenderShaderMask extends RenderProxyBox {
-  RenderShaderMask({ RenderBox child, ShaderCallback shaderCallback, TransferMode transferMode })
-    : _shaderCallback = shaderCallback, _transferMode = transferMode, super(child);
+  /// Creates a render object that applies a mask generated by a [Shader] to its child.
+  ///
+  /// The [shaderCallback] and [transferMode] arguments must not be null.
+  RenderShaderMask({
+    ShaderCallback shaderCallback,
+    TransferMode transferMode: TransferMode.modulate,
+    RenderBox child
+  }) : _shaderCallback = shaderCallback, _transferMode = transferMode, super(child) {
+    assert(shaderCallback != null);
+    assert(transferMode != null);
+  }
 
+  /// Called to creates the [Shader] that generates the mask.
+  ///
+  /// The shader callback is called with the current size of the child so that
+  /// it can customize the shader to the size and location of the child.
+  // TODO(abarth): Use the delegate pattern here to avoid generating spurious
+  // repaints when the ShaderCallback changes identity.
   ShaderCallback get shaderCallback => _shaderCallback;
   ShaderCallback _shaderCallback;
   set shaderCallback (ShaderCallback newShaderCallback) {
@@ -764,6 +804,10 @@
     markNeedsPaint();
   }
 
+  /// The [TransferMode] to use when applying the shader to the child.
+  ///
+  /// The default, [TransferMode.modulate], is useful for applying an alpha blend
+  /// to the child. Other transfer modes can be used to create other effects.
   TransferMode get transferMode => _transferMode;
   TransferMode _transferMode;
   set transferMode (TransferMode newTransferMode) {
@@ -787,12 +831,20 @@
   }
 }
 
+/// Applies a filter to the existing painted content and then paints [child].
 class RenderBackdropFilter extends RenderProxyBox {
+  /// Creates a backdrop filter.
+  ///
+  /// The [filter] argument must not be null.
   RenderBackdropFilter({ RenderBox child, ui.ImageFilter filter })
     : _filter = filter, super(child) {
     assert(filter != null);
   }
 
+  /// The image filter to apply to the existing painted content before painting the child.
+  ///
+  /// For example, consider using [ui.ImageFilter.blur] to create a backdrop
+  /// blur effect
   ui.ImageFilter get filter => _filter;
   ui.ImageFilter _filter;
   set filter (ui.ImageFilter newFilter) {
@@ -877,8 +929,14 @@
 
 /// Clips its child using a rectangle.
 ///
-/// Prevents its child from painting outside its bounds.
+/// By default, [RenderClipRect] prevents its child from painting outside its
+/// bounds, but the size and location of the clip can be customized using a
+/// custom [clipper].
 class RenderClipRect extends _RenderCustomClip<Rect> {
+  /// Creates a rectangular clip.
+  ///
+  /// If [clipper] is null, the clip will match the layout size and position of
+  /// the child.
   RenderClipRect({
     RenderBox child,
     CustomClipper<Rect> clipper
@@ -910,6 +968,7 @@
 /// y radius values and prevents its child from painting outside that rounded
 /// rectangle.
 class RenderClipRRect extends RenderProxyBox {
+  /// Creates a rounded-rectangular clip.
   RenderClipRRect({
     RenderBox child,
     double xRadius,
@@ -962,9 +1021,14 @@
 
 /// Clips its child using an oval.
 ///
-/// Inscribes an oval into its layout dimensions and prevents its child from
-/// painting outside that oval.
+/// By default, inscribes an oval into its layout dimensions and prevents its
+/// child from painting outside that oval, but the size and location of the clip
+/// can be customized using a custom [clipper].
 class RenderClipOval extends _RenderCustomClip<Rect> {
+  /// Creates an oval-shaped clip.
+  ///
+  /// If [clipper] is null, the oval will be inscribed into the layout size and
+  /// position of the child.
   RenderClipOval({
     RenderBox child,
     CustomClipper<Rect> clipper
@@ -1018,6 +1082,12 @@
 ///  * To clip to an oval or circle, consider [RenderClipOval].
 ///  * To clip to a rounded rectangle, consider [RenderClipRRect].
 class RenderClipPath extends _RenderCustomClip<Path> {
+  /// Creates a path clip.
+  ///
+  /// If [clipper] is null, the clip will be a rectangle that matches the layout
+  /// size and location of the child. However, rather than use this default,
+  /// consider using a [RenderClipRect], which can achieve the same effect more
+  /// efficiently.
   RenderClipPath({
     RenderBox child,
     CustomClipper<Path> clipper
@@ -1148,6 +1218,9 @@
 
 /// Applies a transformation before painting its child.
 class RenderTransform extends RenderProxyBox {
+  /// Creates a render object that transforms its child.
+  ///
+  /// The [transform] argument must not be null.
   RenderTransform({
     Matrix4 transform,
     Offset origin,
@@ -1312,12 +1385,16 @@
   }
 }
 
-/// Applies a translation transformation before painting its child. The
-/// translation is expressed as a [FractionalOffset] relative to the
+/// Applies a translation transformation before painting its child.
+///
+/// The translation is expressed as a [FractionalOffset] relative to the
 /// RenderFractionalTranslation box's size. Hit tests will only be detected
 /// inside the bounds of the RenderFractionalTranslation, even if the contents
 /// are offset such that they overflow.
 class RenderFractionalTranslation extends RenderProxyBox {
+  /// Creates a render object that translates its child's painting.
+  ///
+  /// The [translation] argument must not be null.
   RenderFractionalTranslation({
     FractionalOffset translation,
     this.transformHitTests: true,
@@ -1472,20 +1549,29 @@
   bool hitTest(Point position) => null;
 }
 
-/// Delegates its painting
+/// Provides a canvas on which to draw during the paint phase.
 ///
-/// When asked to paint, custom paint first asks painter to paint with the
-/// current canvas and then paints its children. After painting its children,
-/// custom paint asks foregroundPainter to paint. The coodinate system of the
-/// canvas matches the coordinate system of the custom paint object. The
-/// painters are expected to paint within a rectangle starting at the origin
-/// and encompassing a region of the given size. If the painters paints outside
+/// When asked to paint, [CustomPaint] first ask its [painter] to paint on the
+/// current canvas, then it paints its child, and then, after painting its
+/// child, it ask its [foregroundPainter] to paint. The coodinate system of the
+/// canvas matches the coordinate system of the [CustomPaint] object. The
+/// painters are expected to paint within a rectangle starting at the origin and
+/// encompassing a region of the given size. (If the painters paints outside
 /// those bounds, there might be insufficient memory allocated to rasterize the
-/// painting commands and the resulting behavior is undefined.
+/// painting commands and the resulting behavior is undefined.)
 ///
-/// Because custom paint calls its painters during paint, you cannot dirty
-/// layout or paint information during the callback.
+/// Painters are implemented by subclassing [CustomPainter].
+///
+/// Because custom paint calls its painters during paint, you cannot mark the
+/// tree as needing a new layout during the callback (the layout for this frame
+/// has already happened).
+///
+/// See also:
+///
+///  * [CustomPainter],
+///  * [Canvas]
 class RenderCustomPaint extends RenderProxyBox {
+  /// Creates a render object that delgates its painting.
   RenderCustomPaint({
     CustomPainter painter,
     CustomPainter foregroundPainter,
@@ -1633,13 +1719,31 @@
   }
 }
 
+/// Signature for listening to [PointerDownEvent] events.
+///
+/// Used by [Listener] and [RenderPointerListener].
 typedef void PointerDownEventListener(PointerDownEvent event);
+
+/// Signature for listening to [PointerMoveEvent] events.
+///
+/// Used by [Listener] and [RenderPointerListener].
 typedef void PointerMoveEventListener(PointerMoveEvent event);
+
+/// Signature for listening to [PointerUpEvent] events.
+///
+/// Used by [Listener] and [RenderPointerListener].
 typedef void PointerUpEventListener(PointerUpEvent event);
+
+/// Signature for listening to [PointerCancelEvent] events.
+///
+/// Used by [Listener] and [RenderPointerListener].
 typedef void PointerCancelEventListener(PointerCancelEvent event);
 
-/// Calls the callbacks in response to pointer events.
+/// Calls callbacks in response to pointer events.
 class RenderPointerListener extends RenderProxyBoxWithHitTestBehavior {
+  /// Creates a render object that forwards point events to callbacks.
+  ///
+  /// The [behavior] argument defaults to [HitTestBehavior.deferToChild].
   RenderPointerListener({
     this.onPointerDown,
     this.onPointerMove,
@@ -1649,9 +1753,16 @@
     RenderBox child
   }) : super(behavior: behavior, child: child);
 
+  /// Called when a pointer comes into contact with the screen at this object.
   PointerDownEventListener onPointerDown;
+
+  /// Called when a pointer that triggered an [onPointerDown] changes position.
   PointerMoveEventListener onPointerMove;
+
+  /// Called when a pointer that triggered an [onPointerDown] is no longer in contact with the screen.
   PointerUpEventListener onPointerUp;
+
+  /// Called when the input from a pointer that triggered an [onPointerDown] is no longer directed towards this receiver.
   PointerCancelEventListener onPointerCancel;
 
   @override
@@ -1710,6 +1821,7 @@
 /// was not. These counts can also be inspected programmatically using
 /// [debugAsymmetricPaintCount] and [debugSymmetricPaintCount] respectively.
 class RenderRepaintBoundary extends RenderProxyBox {
+  /// Creates a repaint boundary around [child].
   RenderRepaintBoundary({ RenderBox child }) : super(child);
 
   @override
@@ -1720,7 +1832,8 @@
   /// paint at different times. When both paint at the same time, the repaint
   /// boundary is redundant, and may be actually making performance worse.
   ///
-  /// Only valid in checked mode. In release builds, always returns zero.
+  /// Only valid when asserts are enabled. In release builds, always returns
+  /// zero.
   ///
   /// Can be reset using [debugResetMetrics]. See [debugAsymmetricPaintCount]
   /// for the corresponding count of times where only the parent or only the
@@ -1735,7 +1848,8 @@
   /// child, it can improve performance by reducing the number of paint
   /// operations that have to be recorded each frame.
   ///
-  /// Only valid in checked mode. In release builds, always returns zero.
+  /// Only valid when asserts are enabled. In release builds, always returns
+  /// zero.
   ///
   /// Can be reset using [debugResetMetrics]. See [debugSymmetricPaintCount] for
   /// the corresponding count of times where both the parent and the child
@@ -1746,7 +1860,7 @@
   /// Resets the [debugSymmetricPaintCount] and [debugAsymmetricPaintCount]
   /// counts to zero.
   ///
-  /// Only valid in checked mode. Does nothing in release builds.
+  /// Only valid when asserts are enabled. Does nothing in release builds.
   void debugResetMetrics() {
     assert(() {
       _debugSymmetricPaintCount = 0;
@@ -1813,6 +1927,10 @@
 /// the semantics layer (and thus e.g. accessibility tools). If
 /// [ignoringSemantics] is null, it uses the value of [ignoring].
 class RenderIgnorePointer extends RenderProxyBox {
+  /// Creates a render object that is invisivle to hit testing.
+  ///
+  /// The [ignoring] argument must not be null. If [ignoringSemantics], this
+  /// render object will be ignored for semantics if [ignoring] is true.
   RenderIgnorePointer({
     RenderBox child,
     bool ignoring: true,
@@ -1821,6 +1939,10 @@
     assert(_ignoring != null);
   }
 
+  /// Whether this render object is ignored during hit testing.
+  ///
+  /// Regardless of whether this render object is ignored during hit testing, it
+  /// will still consume space during layout and be visible during painting.
   bool get ignoring => _ignoring;
   bool _ignoring;
   set ignoring(bool value) {
@@ -1832,6 +1954,11 @@
       markNeedsSemanticsUpdate();
   }
 
+  /// Whether the semantics of this render object is ignored when compiling the semantics tree.
+  ///
+  /// If null, defaults to value of [ignoring].
+  ///
+  /// See [SemanticsNode] for additional information about the semantics tree.
   bool get ignoringSemantics => _ignoringSemantics;
   bool _ignoringSemantics;
   set ignoringSemantics(bool value) {
@@ -1869,6 +1996,9 @@
 
 /// Holds opaque meta data in the render tree.
 class RenderMetaData extends RenderProxyBoxWithHitTestBehavior {
+  /// Creates a render object that hold opaque metadata.
+  ///
+  /// The [behavior] argument defaults to [HitTestBehavior.deferToChild].
   RenderMetaData({
     this.metaData,
     HitTestBehavior behavior: HitTestBehavior.deferToChild,
diff --git a/packages/flutter/lib/src/rendering/shifted_box.dart b/packages/flutter/lib/src/rendering/shifted_box.dart
index ab8954d..e210cd9 100644
--- a/packages/flutter/lib/src/rendering/shifted_box.dart
+++ b/packages/flutter/lib/src/rendering/shifted_box.dart
@@ -91,6 +91,9 @@
 /// size. Padding then sizes itself to its child's size, inflated by the
 /// padding, effectively creating empty space around the child.
 class RenderPadding extends RenderShiftedBox {
+  /// Creates a render object that insets its child.
+  ///
+  /// The [padding] argument must not be null and must have non-negative insets.
   RenderPadding({
     EdgeInsets padding,
     RenderBox child
@@ -219,12 +222,16 @@
   }
 }
 
+/// Abstract class for one-child-layout render boxes that use a
+/// [FractionalOffset] to align their children.
 abstract class RenderAligningShiftedBox extends RenderShiftedBox {
+  /// Initializes member variables for subclasses.
+  ///
+  /// The [alignment] argument must not be null.
   RenderAligningShiftedBox({
-    RenderBox child,
-    FractionalOffset alignment: FractionalOffset.center
-  }) : _alignment = alignment,
-       super(child) {
+    FractionalOffset alignment: FractionalOffset.center,
+    RenderBox child
+  }) : _alignment = alignment, super(child) {
     assert(alignment != null && alignment.dx != null && alignment.dy != null);
   }
 
@@ -274,7 +281,7 @@
   }
 }
 
-/// Aligns its child box within itself.
+/// Positions its child using a [FractionalOffset].
 ///
 /// For example, to align a box at the bottom right, you would pass this box a
 /// tight constraint that is bigger than the child's natural size,
@@ -285,6 +292,7 @@
 /// dimensions. Using widthFactor and heightFactor you can force this latter
 /// behavior in all cases.
 class RenderPositionedBox extends RenderAligningShiftedBox {
+  /// Creates a render object that positions its child.
   RenderPositionedBox({
     RenderBox child,
     double widthFactor,
@@ -427,6 +435,7 @@
 /// child inside a larger parent, use [RenderPositionedBox] and
 /// [RenderConstrainedBox] rather than RenderOverflowBox.
 class RenderConstrainedOverflowBox extends RenderAligningShiftedBox {
+  /// Creates a render object that lets its child overflow itself.
   RenderConstrainedOverflowBox({
     RenderBox child,
     double minWidth,
@@ -543,9 +552,12 @@
   }
 }
 
-/// A render box that's a specific size but passes its original constraints
+/// A render box that is a specific size but passes its original constraints
 /// through to its child, which will probably overflow.
 class RenderSizedOverflowBox extends RenderAligningShiftedBox {
+  /// Creates a render box of a given size that lets its child overflow.
+  ///
+  /// The [requestedSize] argument must not be null.
   RenderSizedOverflowBox({
     RenderBox child,
     Size requestedSize,
@@ -617,6 +629,10 @@
 ///
 /// It then tries to size itself to the size of its child.
 class RenderFractionallySizedOverflowBox extends RenderAligningShiftedBox {
+  /// Creates a render box that sizes its child to a fraction of the total available space.
+  ///
+  /// If non-null, the [widthFactor] and [heightFactor] arguments must be
+  /// non-negative.
   RenderFractionallySizedOverflowBox({
     RenderBox child,
     double widthFactor,
@@ -755,6 +771,9 @@
 /// of the parent, but the size of the parent cannot depend on the size of the
 /// child.
 class RenderCustomSingleChildLayoutBox extends RenderShiftedBox {
+  /// Creates a render box that defers its layout to a delgate.
+  ///
+  /// The [delegate] argument must not be null.
   RenderCustomSingleChildLayoutBox({
     RenderBox child,
     SingleChildLayoutDelegate delegate
diff --git a/packages/flutter/lib/src/rendering/view.dart b/packages/flutter/lib/src/rendering/view.dart
index 29cf3c7..743b912 100644
--- a/packages/flutter/lib/src/rendering/view.dart
+++ b/packages/flutter/lib/src/rendering/view.dart
@@ -48,6 +48,9 @@
 /// bootstrapping the rendering pipeline. The view has a unique child
 /// [RenderBox], which is required to fill the entire output surface.
 class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox> {
+  /// Creates the root of the render tree.
+  ///
+  /// Typically created by the binding (e.g., [RendererBinding]).
   RenderView({
     RenderBox child,
     this.timeForRotation: const Duration(microseconds: 83333),
@@ -115,6 +118,13 @@
     assert(false); // nobody tells the screen to rotate, the whole rotate() dance is started from our performResize()
   }
 
+  /// Determines the set of render objects located at the given position.
+  ///
+  /// Returns true if the given point is contained in this render object or one
+  /// of its descendants. Adds any render objects that contain the point to the
+  /// given hit test result.
+  ///
+  /// The [position] argument is in the coordinate system of the render view.
   bool hitTest(HitTestResult result, { Point position }) {
     if (child != null)
       child.hitTest(result, position: position);
diff --git a/packages/flutter/lib/src/widgets/basic.dart b/packages/flutter/lib/src/widgets/basic.dart
index 244f065..f0e1be4 100644
--- a/packages/flutter/lib/src/widgets/basic.dart
+++ b/packages/flutter/lib/src/widgets/basic.dart
@@ -95,7 +95,14 @@
   }
 }
 
+/// Applies a mask generated by a [Shader] to its child.
+///
+/// For example, [ShaderMask] can be used to gradually fade out the edge
+/// of a child by using a [ui.Gradient.linear] mask.
 class ShaderMask extends SingleChildRenderObjectWidget {
+  /// Creates a widget that applies a mask generated by a [Shader] to its child.
+  ///
+  /// The [shaderCallback] and [transferMode] arguments must not be null.
   ShaderMask({
     Key key,
     this.shaderCallback,
@@ -106,7 +113,16 @@
     assert(transferMode != null);
   }
 
+  /// Called to creates the [Shader] that generates the mask.
+  ///
+  /// The shader callback is called with the current size of the child so that
+  /// it can customize the shader to the size and location of the child.
   final ShaderCallback shaderCallback;
+
+  /// The [TransferMode] to use when applying the shader to the child.
+  ///
+  /// The default, [TransferMode.modulate], is useful for applying an alpha blend
+  /// to the child. Other transfer modes can be used to create other effects.
   final TransferMode transferMode;
 
   @override
@@ -125,7 +141,11 @@
   }
 }
 
+/// Applies a filter to the existing painted content and then paints [child].
 class BackdropFilter extends SingleChildRenderObjectWidget {
+  /// Creates a backdrop filter.
+  ///
+  /// The [filter] argument must not be null.
   BackdropFilter({
     Key key,
     this.filter,
@@ -134,6 +154,10 @@
     assert(filter != null);
   }
 
+  /// The image filter to apply to the existing painted content before painting the child.
+  ///
+  /// For example, consider using [ui.ImageFilter.blur] to create a backdrop
+  /// blur effect
   final ui.ImageFilter filter;
 
   @override
@@ -183,15 +207,14 @@
 
 /// Provides a canvas on which to draw during the paint phase.
 ///
-/// When asked to paint, [CustomPaint] objects first ask their [painter] to
-/// paint on the current canvas, then they paint their children, and then, after
-/// painting their children, ask their [foregroundPainter] to paint. The
-/// coodinate system of the canvas matches the coordinate system of the
-/// [CustomPaint] object. The painters are expected to paint within a rectangle
-/// starting at the origin and encompassing a region of the given size. (If the
-/// painters paints outside those bounds, there might be insufficient memory
-/// allocated to rasterize the painting commands and the resulting behavior is
-/// undefined.)
+/// When asked to paint, [CustomPaint] first ask its [painter] to paint on the
+/// current canvas, then it paints its child, and then, after painting its
+/// child, it ask its [foregroundPainter] to paint. The coodinate system of the
+/// canvas matches the coordinate system of the [CustomPaint] object. The
+/// painters are expected to paint within a rectangle starting at the origin and
+/// encompassing a region of the given size. (If the painters paints outside
+/// those bounds, there might be insufficient memory allocated to rasterize the
+/// painting commands and the resulting behavior is undefined.)
 ///
 /// Painters are implemented by subclassing [CustomPainter].
 ///
@@ -199,8 +222,12 @@
 /// tree as needing a new layout during the callback (the layout for this frame
 /// has already happened).
 ///
-/// See: [CustomPainter], [Canvas].
+/// See also:
+///
+///  * [CustomPainter],
+///  * [Canvas]
 class CustomPaint extends SingleChildRenderObjectWidget {
+  /// Creates a widget that delgates its painting.
   CustomPaint({ Key key, this.painter, this.foregroundPainter, Widget child })
     : super(key: key, child: child);
 
@@ -233,8 +260,14 @@
 
 /// Clips its child using a rectangle.
 ///
-/// Prevents its child from painting outside its bounds.
+/// By default, [ClipRect] prevents its child from painting outside its
+/// bounds, but the size and location of the clip can be customized using a
+/// custome [clipper].
 class ClipRect extends SingleChildRenderObjectWidget {
+  /// Creates a rectangular clip.
+  ///
+  /// If [clipper] is null, the clip will match the layout size and position of
+  /// the child.
   ClipRect({ Key key, this.clipper, Widget child }) : super(key: key, child: child);
 
   /// If non-null, determines which clip to use.
@@ -260,6 +293,7 @@
 /// y radius values and prevents its child from painting outside that rounded
 /// rectangle.
 class ClipRRect extends SingleChildRenderObjectWidget {
+  /// Creates a rounded-rectangular clip.
   ClipRRect({ Key key, this.xRadius, this.yRadius, Widget child })
     : super(key: key, child: child);
 
@@ -288,9 +322,14 @@
 
 /// Clips its child using an oval.
 ///
-/// Inscribes an oval into its layout dimensions and prevents its child from
-/// painting outside that oval.
+/// By default, inscribes an oval into its layout dimensions and prevents its
+/// child from painting outside that oval, but the size and location of the clip
+/// can be customized using a custom [clipper].
 class ClipOval extends SingleChildRenderObjectWidget {
+  /// Creates an oval-shaped clip.
+  ///
+  /// If [clipper] is null, the oval will be inscribed into the layout size and
+  /// position of the child.
   ClipOval({ Key key, this.clipper, Widget child }) : super(key: key, child: child);
 
   /// If non-null, determines which clip to use.
@@ -331,6 +370,12 @@
 ///  * To clip to an oval or circle, consider [ClipOval].
 ///  * To clip to a rounded rectangle, consider [ClipRRect].
 class ClipPath extends SingleChildRenderObjectWidget {
+  /// Creates a path clip.
+  ///
+  /// If [clipper] is null, the clip will be a rectangle that matches the layout
+  /// size and location of the child. However, rather than use this default,
+  /// consider using a [ClipRect], which can achieve the same effect more
+  /// efficiently.
   ClipPath({ Key key, this.clipper, Widget child }) : super(key: key, child: child);
 
   /// If non-null, determines which clip to use.
@@ -359,8 +404,17 @@
 
 /// Applies a transformation before painting its child.
 class Transform extends SingleChildRenderObjectWidget {
-  Transform({ Key key, this.transform, this.origin, this.alignment, this.transformHitTests: true, Widget child })
-    : super(key: key, child: child) {
+  /// Creates a widget that transforms its child.
+  ///
+  /// The [transform] argument must not be null.
+  Transform({
+    Key key,
+    this.transform,
+    this.origin,
+    this.alignment,
+    this.transformHitTests: true,
+    Widget child
+  }) : super(key: key, child: child) {
     assert(transform != null);
   }
 
@@ -404,8 +458,15 @@
 /// Applies a translation expressed as a fraction of the box's size before
 /// painting its child.
 class FractionalTranslation extends SingleChildRenderObjectWidget {
-  FractionalTranslation({ Key key, this.translation, this.transformHitTests: true, Widget child })
-    : super(key: key, child: child) {
+  /// Creates a widget that translates its child's painting.
+  ///
+  /// The [translation] argument must not be null.
+  FractionalTranslation({
+    Key key,
+    this.translation,
+    this.transformHitTests: true,
+    Widget child
+  }) : super(key: key, child: child) {
     assert(translation != null);
   }
 
@@ -763,6 +824,10 @@
 ///   the child according to a [FractionalOffset] value)
 /// * [OverflowBox]
 class FractionallySizedBox extends SingleChildRenderObjectWidget {
+  /// Creates a widget that sizes its child to a fraction of the total available space.
+  ///
+  /// If non-null, the [widthFactor] and [heightFactor] arguments must be
+  /// non-negative.
   FractionallySizedBox({
     Key key,
     this.alignment: FractionalOffset.center,
@@ -771,6 +836,8 @@
     Widget child
   }) : super(key: key, child: child) {
     assert(alignment != null && alignment.dx != null && alignment.dy != null);
+    assert(widthFactor == null || widthFactor >= 0.0);
+    assert(heightFactor == null || heightFactor >= 0.0);
   }
 
   /// If non-null, the fraction of the incoming width given to the child.
@@ -863,11 +930,12 @@
   }
 }
 
-/// A render object that imposes different constraints on its child than it gets
+/// A widget that imposes different constraints on its child than it gets
 /// from its parent, possibly allowing the child to overflow the parent.
 ///
 /// See [RenderOverflowBox] for details.
 class OverflowBox extends SingleChildRenderObjectWidget {
+  /// Creates a widget that lets its child overflow itself.
   OverflowBox({
     Key key,
     this.alignment: FractionalOffset.center,
@@ -939,7 +1007,12 @@
   }
 }
 
+/// A widget that is a specific size but passes its original constraints
+/// through to its child, which will probably overflow.
 class SizedOverflowBox extends SingleChildRenderObjectWidget {
+  /// Creates a widget of a given size that lets its child overflow.
+  ///
+  /// The [requestedSize] argument must not be null.
   SizedOverflowBox({
     Key key,
     this.alignment: FractionalOffset.center,
@@ -960,6 +1033,7 @@
   /// with the center of the parent.
   final FractionalOffset alignment;
 
+  /// The size this render box should attempt to be.
   final Size size;
 
   @override
@@ -2762,7 +2836,14 @@
 
 // EVENT HANDLING
 
+/// Calls callbacks in response to pointer events.
+///
+/// Rather than listening for raw pointer events, consider listening for
+/// higher-level gestures using [GestureDetector].
 class Listener extends SingleChildRenderObjectWidget {
+  /// Creates a widget that forwards point events to callbacks.
+  ///
+  /// The [behavior] argument defaults to [HitTestBehavior.deferToChild].
   Listener({
     Key key,
     Widget child,
@@ -2775,10 +2856,19 @@
     assert(behavior != null);
   }
 
+  /// Called when a pointer comes into contact with the screen at this object.
   final PointerDownEventListener onPointerDown;
+
+  /// Called when a pointer that triggered an [onPointerDown] changes position.
   final PointerMoveEventListener onPointerMove;
+
+  /// Called when a pointer that triggered an [onPointerDown] is no longer in contact with the screen.
   final PointerUpEventListener onPointerUp;
+
+  /// Called when the input from a pointer that triggered an [onPointerDown] is no longer directed towards this receiver.
   final PointerCancelEventListener onPointerCancel;
+
+  /// How to behave during hit testing.
   final HitTestBehavior behavior;
 
   @override
@@ -2857,12 +2947,42 @@
   RenderRepaintBoundary createRenderObject(BuildContext context) => new RenderRepaintBoundary();
 }
 
+/// Is invisible during hit testing.
+///
+/// When [ignoring] is `true`, this widget (and its subtree) is invisible
+/// to hit testing. It still consumes space during layout and paints its child
+/// as usual. It just cannot be the target of located events because it returns
+/// `false` from [hitTest].
+///
+/// When [ignoringSemantics] is `true`, the subtree will be invisible to
+/// the semantics layer (and thus e.g. accessibility tools). If
+/// [ignoringSemantics] is null, it uses the value of [ignoring].
 class IgnorePointer extends SingleChildRenderObjectWidget {
-  IgnorePointer({ Key key, Widget child, this.ignoring: true, this.ignoringSemantics })
-    : super(key: key, child: child);
+  /// Creates a widget that is invisivle to hit testing.
+  ///
+  /// The [ignoring] argument must not be null. If [ignoringSemantics], this
+  /// render object will be ignored for semantics if [ignoring] is true.
+  IgnorePointer({
+    Key key,
+    Widget child,
+    this.ignoring: true,
+    this.ignoringSemantics
+  }) : super(key: key, child: child) {
+    assert(ignoring != null);
+  }
 
+  /// Whether this widget is ignored during hit testing.
+  ///
+  /// Regardless of whether this widget is ignored during hit testing, it will
+  /// still consume space during layout and be visible during painting.
   final bool ignoring;
-  final bool ignoringSemantics; // if null, defaults to value of ignoring
+
+  /// Whether the semantics of this widget is ignored when compiling the semantics tree.
+  ///
+  /// If null, defaults to value of [ignoring].
+  ///
+  /// See [SemanticsNode] for additional information about the semantics tree.
+  final bool ignoringSemantics;
 
   @override
   RenderIgnorePointer createRenderObject(BuildContext context) => new RenderIgnorePointer(
@@ -2878,6 +2998,45 @@
   }
 }
 
+/// Holds opaque meta data in the render tree.
+class MetaData extends SingleChildRenderObjectWidget {
+  /// Creates a widget that hold opaque metadata.
+  ///
+  /// The [behavior] argument defaults to [HitTestBehavior.deferToChild].
+  MetaData({
+    Key key,
+    Widget child,
+    this.metaData,
+    this.behavior: HitTestBehavior.deferToChild
+  }) : super(key: key, child: child);
+
+  /// Opaque meta data ignored by the render tree
+  final dynamic metaData;
+
+  /// How to behave during hit testing.
+  final HitTestBehavior behavior;
+
+  @override
+  RenderMetaData createRenderObject(BuildContext context) => new RenderMetaData(
+    metaData: metaData,
+    behavior: behavior
+  );
+
+  @override
+  void updateRenderObject(BuildContext context, RenderMetaData renderObject) {
+    renderObject
+      ..metaData = metaData
+      ..behavior = behavior;
+  }
+
+  @override
+  void debugFillDescription(List<String> description) {
+    super.debugFillDescription(description);
+    description.add('behavior: $behavior');
+    description.add('metaData: $metaData');
+  }
+}
+
 
 // UTILITY NODES
 
@@ -2979,38 +3138,6 @@
   RenderExcludeSemantics createRenderObject(BuildContext context) => new RenderExcludeSemantics();
 }
 
-class MetaData extends SingleChildRenderObjectWidget {
-  MetaData({
-    Key key,
-    Widget child,
-    this.metaData,
-    this.behavior: HitTestBehavior.deferToChild
-  }) : super(key: key, child: child);
-
-  final dynamic metaData;
-  final HitTestBehavior behavior;
-
-  @override
-  RenderMetaData createRenderObject(BuildContext context) => new RenderMetaData(
-    metaData: metaData,
-    behavior: behavior
-  );
-
-  @override
-  void updateRenderObject(BuildContext context, RenderMetaData renderObject) {
-    renderObject
-      ..metaData = metaData
-      ..behavior = behavior;
-  }
-
-  @override
-  void debugFillDescription(List<String> description) {
-    super.debugFillDescription(description);
-    description.add('behavior: $behavior');
-    description.add('metaData: $metaData');
-  }
-}
-
 /// Always builds the given child.
 ///
 /// Useful for attaching a key to an existing widget.
diff --git a/packages/flutter/lib/src/widgets/performance_overlay.dart b/packages/flutter/lib/src/widgets/performance_overlay.dart
index 028f5af..f26cd2d 100644
--- a/packages/flutter/lib/src/widgets/performance_overlay.dart
+++ b/packages/flutter/lib/src/widgets/performance_overlay.dart
@@ -13,8 +13,9 @@
 /// required on the GPU thread to produce each frame. Ideally, both these values
 /// would be less than the total frame budget for the hardware on which the app
 /// is running. For example, if the hardware has a screen that updates at 60 Hz,
-/// each thread should ideally spend less than 16 ms producing each frame. This
+/// each thread should ideally spend less than 16ms producing each frame. This
 /// ideal condition is indicated by a green vertical line for each thread.
+/// Otherwise, the performance overlay shows a red vertical line.
 ///
 /// The simplest way to show the performance overlay is to set
 /// [MaterialApp.showPerformanceOverlay] or [WidgetsApp.showPerformanceOverlay]