Unverified Commit 5ab5d82a authored by Michael Goderbauer's avatar Michael Goderbauer Committed by GitHub

Remove AbstractNode from RenderObject and deprecate it (#128973)

It's time to say good bye to an old friend. 
It has outlived its usefulness.
Farewell, AbstractNode! 🫡
parent fc8856eb
...@@ -1556,7 +1556,7 @@ class _ActionButtonParentDataWidget ...@@ -1556,7 +1556,7 @@ class _ActionButtonParentDataWidget
parentData.isPressed = isPressed; parentData.isPressed = isPressed;
// Force a repaint. // Force a repaint.
final AbstractNode? targetParent = renderObject.parent; final RenderObject? targetParent = renderObject.parent;
if (targetParent is RenderObject) { if (targetParent is RenderObject) {
targetParent.markNeedsPaint(); targetParent.markNeedsPaint();
} }
......
...@@ -8,6 +8,10 @@ import 'package:meta/meta.dart'; ...@@ -8,6 +8,10 @@ import 'package:meta/meta.dart';
// during device lab performance tests. When editing this file, check to make sure // during device lab performance tests. When editing this file, check to make sure
// that it didn't break that test. // that it didn't break that test.
/// Deprecated. Unused by the framework and will be removed in a future version
/// of Flutter. If needed, inline any required functionality of this class
/// directly in the subclass.
///
/// An abstract node in a tree. /// An abstract node in a tree.
/// ///
/// AbstractNode has as notion of depth, attachment, and parent, but does not /// AbstractNode has as notion of depth, attachment, and parent, but does not
...@@ -39,6 +43,10 @@ import 'package:meta/meta.dart'; ...@@ -39,6 +43,10 @@ import 'package:meta/meta.dart';
/// moved to be a child of A, sibling of B, then the numbers won't change. C's /// moved to be a child of A, sibling of B, then the numbers won't change. C's
/// [depth] will still be 2. The [depth] is automatically maintained by the /// [depth] will still be 2. The [depth] is automatically maintained by the
/// [adoptChild] and [dropChild] methods. /// [adoptChild] and [dropChild] methods.
@Deprecated(
'If needed, inline any required functionality of AbstractNode in your class directly. '
'This feature was deprecated after v3.12.0-4.0.pre.',
)
class AbstractNode { class AbstractNode {
/// The depth of this node in the tree. /// The depth of this node in the tree.
/// ///
......
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
import 'dart:math' as math; import 'dart:math' as math;
import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
...@@ -1202,7 +1201,7 @@ class TableRowInkWell extends InkResponse { ...@@ -1202,7 +1201,7 @@ class TableRowInkWell extends InkResponse {
RectCallback getRectCallback(RenderBox referenceBox) { RectCallback getRectCallback(RenderBox referenceBox) {
return () { return () {
RenderObject cell = referenceBox; RenderObject cell = referenceBox;
AbstractNode? table = cell.parent; RenderObject? table = cell.parent;
final Matrix4 transform = Matrix4.identity(); final Matrix4 transform = Matrix4.identity();
while (table is RenderObject && table is! RenderTable) { while (table is RenderObject && table is! RenderTable) {
table.applyPaintTransform(cell, transform); table.applyPaintTransform(cell, transform);
......
...@@ -762,7 +762,7 @@ abstract class InkFeature { ...@@ -762,7 +762,7 @@ abstract class InkFeature {
final int toDepth = to.depth; final int toDepth = to.depth;
if (fromDepth >= toDepth) { if (fromDepth >= toDepth) {
final AbstractNode? fromParent = from.parent; final RenderObject? fromParent = from.parent;
// Return early if the 2 render objects are not in the same render tree, // Return early if the 2 render objects are not in the same render tree,
// or either of them is offscreen and thus won't get painted. // or either of them is offscreen and thus won't get painted.
if (fromParent is! RenderObject || !fromParent.paintsChild(from)) { if (fromParent is! RenderObject || !fromParent.paintsChild(from)) {
...@@ -773,7 +773,7 @@ abstract class InkFeature { ...@@ -773,7 +773,7 @@ abstract class InkFeature {
} }
if (fromDepth <= toDepth) { if (fromDepth <= toDepth) {
final AbstractNode? toParent = to.parent; final RenderObject? toParent = to.parent;
if (toParent is! RenderObject || !toParent.paintsChild(to)) { if (toParent is! RenderObject || !toParent.paintsChild(to)) {
return null; return null;
} }
......
...@@ -2136,7 +2136,6 @@ abstract class RenderBox extends RenderObject { ...@@ -2136,7 +2136,6 @@ abstract class RenderBox extends RenderObject {
assert(!_debugDoingBaseline, 'Please see the documentation for computeDistanceToActualBaseline for the required calling conventions of this method.'); assert(!_debugDoingBaseline, 'Please see the documentation for computeDistanceToActualBaseline for the required calling conventions of this method.');
assert(!debugNeedsLayout); assert(!debugNeedsLayout);
assert(() { assert(() {
final RenderObject? parent = this.parent as RenderObject?;
if (owner!.debugDoingLayout) { if (owner!.debugDoingLayout) {
return (RenderObject.debugActiveLayout == parent) && parent!.debugDoingThisLayout; return (RenderObject.debugActiveLayout == parent) && parent!.debugDoingThisLayout;
} }
...@@ -2144,7 +2143,6 @@ abstract class RenderBox extends RenderObject { ...@@ -2144,7 +2143,6 @@ abstract class RenderBox extends RenderObject {
return ((RenderObject.debugActivePaint == parent) && parent!.debugDoingThisPaint) || return ((RenderObject.debugActivePaint == parent) && parent!.debugDoingThisPaint) ||
((RenderObject.debugActivePaint == this) && debugDoingThisPaint); ((RenderObject.debugActivePaint == this) && debugDoingThisPaint);
} }
assert(parent == this.parent);
return false; return false;
}()); }());
assert(_debugSetDoingBaseline(true)); assert(_debugSetDoingBaseline(true));
......
...@@ -1133,7 +1133,7 @@ class RenderListWheelViewport ...@@ -1133,7 +1133,7 @@ class RenderListWheelViewport
// `child` will be the last RenderObject before the viewport when walking up from `target`. // `child` will be the last RenderObject before the viewport when walking up from `target`.
RenderObject child = target; RenderObject child = target;
while (child.parent != this) { while (child.parent != this) {
child = child.parent! as RenderObject; child = child.parent!;
} }
final ListWheelParentData parentData = child.parentData! as ListWheelParentData; final ListWheelParentData parentData = child.parentData! as ListWheelParentData;
......
...@@ -929,11 +929,9 @@ class PipelineOwner { ...@@ -929,11 +929,9 @@ class PipelineOwner {
} }
/// The unique object managed by this pipeline that has no parent. /// The unique object managed by this pipeline that has no parent.
/// RenderObject? get rootNode => _rootNode;
/// This object does not have to be a [RenderObject]. RenderObject? _rootNode;
AbstractNode? get rootNode => _rootNode; set rootNode(RenderObject? value) {
AbstractNode? _rootNode;
set rootNode(AbstractNode? value) {
if (_rootNode == value) { if (_rootNode == value) {
return; return;
} }
...@@ -1572,7 +1570,7 @@ const String _flutterRenderingLibrary = 'package:flutter/rendering.dart'; ...@@ -1572,7 +1570,7 @@ const String _flutterRenderingLibrary = 'package:flutter/rendering.dart';
/// [RenderObject.markNeedsLayout] so that if a parent has queried the intrinsic /// [RenderObject.markNeedsLayout] so that if a parent has queried the intrinsic
/// or baseline information, it gets marked dirty whenever the child's geometry /// or baseline information, it gets marked dirty whenever the child's geometry
/// changes. /// changes.
abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin implements HitTestTarget { abstract class RenderObject with DiagnosticableTreeMixin implements HitTestTarget {
/// Initializes internal fields for subclasses. /// Initializes internal fields for subclasses.
RenderObject() { RenderObject() {
if (kFlutterMemoryAllocationsEnabled) { if (kFlutterMemoryAllocationsEnabled) {
...@@ -1690,30 +1688,93 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im ...@@ -1690,30 +1688,93 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
} }
} }
/// The depth of this node in the tree.
///
/// The depth of nodes in a tree monotonically increases as you traverse down
/// the tree.
///
/// Nodes always have a [depth] greater than their ancestors'. There's no
/// guarantee regarding depth between siblings. The depth of a node is used to
/// ensure that nodes are processed in depth order. The [depth] of a child can
/// be more than one greater than the [depth] of the parent, because the [depth]
/// values are never decreased: all that matters is that it's greater than the
/// parent. Consider a tree with a root node A, a child B, and a grandchild C.
/// Initially, A will have [depth] 0, B [depth] 1, and C [depth] 2. If C is
/// moved to be a child of A, sibling of B, then the numbers won't change. C's
/// [depth] will still be 2. The [depth] is automatically maintained by the
/// [adoptChild] and [dropChild] methods.
int get depth => _depth;
int _depth = 0;
/// Adjust the [depth] of the given [child] to be greater than this node's own
/// [depth].
///
/// Only call this method from overrides of [redepthChildren].
@protected
void redepthChild(RenderObject child) {
assert(child.owner == owner);
if (child._depth <= _depth) {
child._depth = _depth + 1;
child.redepthChildren();
}
}
/// Adjust the [depth] of this node's children, if any.
///
/// Override this method in subclasses with child nodes to call [redepthChild]
/// for each child. Do not call this method directly.
@protected
void redepthChildren() { }
/// The parent of this node in the tree.
RenderObject? get parent => _parent;
RenderObject? _parent;
/// Called by subclasses when they decide a render object is a child. /// Called by subclasses when they decide a render object is a child.
/// ///
/// Only for use by subclasses when changing their child lists. Calling this /// Only for use by subclasses when changing their child lists. Calling this
/// in other cases will lead to an inconsistent tree and probably cause crashes. /// in other cases will lead to an inconsistent tree and probably cause crashes.
@override @mustCallSuper
@protected
void adoptChild(RenderObject child) { void adoptChild(RenderObject child) {
assert(child._parent == null);
assert(() {
RenderObject node = this;
while (node.parent != null) {
node = node.parent!;
}
assert(node != child); // indicates we are about to create a cycle
return true;
}());
setupParentData(child); setupParentData(child);
markNeedsLayout(); markNeedsLayout();
markNeedsCompositingBitsUpdate(); markNeedsCompositingBitsUpdate();
markNeedsSemanticsUpdate(); markNeedsSemanticsUpdate();
super.adoptChild(child); child._parent = this;
if (attached) {
child.attach(_owner!);
}
redepthChild(child);
} }
/// Called by subclasses when they decide a render object is no longer a child. /// Called by subclasses when they decide a render object is no longer a child.
/// ///
/// Only for use by subclasses when changing their child lists. Calling this /// Only for use by subclasses when changing their child lists. Calling this
/// in other cases will lead to an inconsistent tree and probably cause crashes. /// in other cases will lead to an inconsistent tree and probably cause crashes.
@override @mustCallSuper
@protected
void dropChild(RenderObject child) { void dropChild(RenderObject child) {
assert(child._parent == this);
assert(child.attached == attached);
assert(child.parentData != null); assert(child.parentData != null);
child._cleanRelayoutBoundary(); child._cleanRelayoutBoundary();
child.parentData!.detach(); child.parentData!.detach();
child.parentData = null; child.parentData = null;
super.dropChild(child); child._parent = null;
if (attached) {
child.detach();
}
markNeedsLayout(); markNeedsLayout();
markNeedsCompositingBitsUpdate(); markNeedsCompositingBitsUpdate();
markNeedsSemanticsUpdate(); markNeedsSemanticsUpdate();
...@@ -1851,7 +1912,7 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im ...@@ -1851,7 +1912,7 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
} }
if (!activeLayoutRoot._debugMutationsLocked) { if (!activeLayoutRoot._debugMutationsLocked) {
final AbstractNode? p = activeLayoutRoot.debugLayoutParent; final RenderObject? p = activeLayoutRoot.debugLayoutParent;
activeLayoutRoot = p is RenderObject ? p : null; activeLayoutRoot = p is RenderObject ? p : null;
} else { } else {
// activeLayoutRoot found. // activeLayoutRoot found.
...@@ -1946,20 +2007,41 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im ...@@ -1946,20 +2007,41 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
RenderObject? get debugLayoutParent { RenderObject? get debugLayoutParent {
RenderObject? layoutParent; RenderObject? layoutParent;
assert(() { assert(() {
final AbstractNode? parent = this.parent; layoutParent = parent;
layoutParent = parent is RenderObject? ? parent : null;
return true; return true;
}()); }());
return layoutParent; return layoutParent;
} }
@override /// The owner for this node (null if unattached).
PipelineOwner? get owner => super.owner as PipelineOwner?; ///
/// The entire subtree that this node belongs to will have the same owner.
PipelineOwner? get owner => _owner;
PipelineOwner? _owner;
@override /// Whether this node is in a tree whose root is attached to something.
///
/// This becomes true during the call to [attach].
///
/// This becomes false during the call to [detach].
bool get attached => _owner != null;
/// Mark this node as attached to the given owner.
///
/// Typically called only from the [parent]'s [attach] method, and by the
/// [owner] to mark the root of a tree as attached.
///
/// Subclasses with children should override this method to first call their
/// inherited [attach] method, and then [attach] all their children to the
/// same [owner].
///
/// Implementations of this method should start with a call to the inherited
/// method, as in `super.attach(owner)`.
@mustCallSuper
void attach(PipelineOwner owner) { void attach(PipelineOwner owner) {
assert(!_debugDisposed); assert(!_debugDisposed);
super.attach(owner); assert(_owner == null);
_owner = owner;
// If the node was dirtied in some way while unattached, make sure to add // If the node was dirtied in some way while unattached, make sure to add
// it to the appropriate dirty list now that an owner is available // it to the appropriate dirty list now that an owner is available
if (_needsLayout && _relayoutBoundary != null) { if (_needsLayout && _relayoutBoundary != null) {
...@@ -1986,6 +2068,23 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im ...@@ -1986,6 +2068,23 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
} }
} }
/// Mark this node as detached.
///
/// Typically called only from the [parent]'s [detach], and by the [owner] to
/// mark the root of a tree as detached.
///
/// Subclasses with children should override this method to first call their
/// inherited [detach] method, and then [detach] all their children.
///
/// Implementations of this method should end with a call to the inherited
/// method, as in `super.detach()`.
@mustCallSuper
void detach() {
assert(_owner != null);
_owner = null;
assert(parent == null || attached == parent!.attached);
}
/// Whether this render object's layout information is dirty. /// Whether this render object's layout information is dirty.
/// ///
/// This is only set in debug mode. In general, render objects should not need /// This is only set in debug mode. In general, render objects should not need
...@@ -2050,7 +2149,7 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im ...@@ -2050,7 +2149,7 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
while (node != _relayoutBoundary) { while (node != _relayoutBoundary) {
assert(node._relayoutBoundary == _relayoutBoundary); assert(node._relayoutBoundary == _relayoutBoundary);
assert(node.parent != null); assert(node.parent != null);
node = node.parent! as RenderObject; node = node.parent!;
if ((!node._needsLayout) && (!node._debugDoingThisLayout)) { if ((!node._needsLayout) && (!node._debugDoingThisLayout)) {
return false; return false;
} }
...@@ -2144,7 +2243,7 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im ...@@ -2144,7 +2243,7 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
assert(_debugCanPerformMutations); assert(_debugCanPerformMutations);
_needsLayout = true; _needsLayout = true;
assert(this.parent != null); assert(this.parent != null);
final RenderObject parent = this.parent! as RenderObject; final RenderObject parent = this.parent!;
if (!_doingThisLayoutWithCallback) { if (!_doingThisLayoutWithCallback) {
parent.markNeedsLayout(); parent.markNeedsLayout();
} else { } else {
...@@ -2176,7 +2275,7 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im ...@@ -2176,7 +2275,7 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
if (_relayoutBoundary == this) { if (_relayoutBoundary == this) {
return; return;
} }
final RenderObject? parentRelayoutBoundary = (parent as RenderObject?)?._relayoutBoundary; final RenderObject? parentRelayoutBoundary = parent?._relayoutBoundary;
assert(parentRelayoutBoundary != null); assert(parentRelayoutBoundary != null);
if (parentRelayoutBoundary != _relayoutBoundary) { if (parentRelayoutBoundary != _relayoutBoundary) {
_relayoutBoundary = parentRelayoutBoundary; _relayoutBoundary = parentRelayoutBoundary;
...@@ -2317,7 +2416,7 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im ...@@ -2317,7 +2416,7 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
assert(!_debugDoingThisResize); assert(!_debugDoingThisResize);
assert(!_debugDoingThisLayout); assert(!_debugDoingThisLayout);
final bool isRelayoutBoundary = !parentUsesSize || sizedByParent || constraints.isTight || parent is! RenderObject; final bool isRelayoutBoundary = !parentUsesSize || sizedByParent || constraints.isTight || parent is! RenderObject;
final RenderObject relayoutBoundary = isRelayoutBoundary ? this : (parent! as RenderObject)._relayoutBoundary!; final RenderObject relayoutBoundary = isRelayoutBoundary ? this : parent!._relayoutBoundary!;
assert(() { assert(() {
_debugCanParentUseSize = parentUsesSize; _debugCanParentUseSize = parentUsesSize;
return true; return true;
...@@ -2674,7 +2773,7 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im ...@@ -2674,7 +2773,7 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
} }
_needsCompositingBitsUpdate = true; _needsCompositingBitsUpdate = true;
if (parent is RenderObject) { if (parent is RenderObject) {
final RenderObject parent = this.parent! as RenderObject; final RenderObject parent = this.parent!;
if (parent._needsCompositingBitsUpdate) { if (parent._needsCompositingBitsUpdate) {
return; return;
} }
...@@ -2823,9 +2922,7 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im ...@@ -2823,9 +2922,7 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
owner!.requestVisualUpdate(); owner!.requestVisualUpdate();
} }
} else if (parent is RenderObject) { } else if (parent is RenderObject) {
final RenderObject parent = this.parent! as RenderObject; parent!.markNeedsPaint();
parent.markNeedsPaint();
assert(parent == this.parent);
} else { } else {
assert(() { assert(() {
if (debugPrintMarkNeedsPaintStacks) { if (debugPrintMarkNeedsPaintStacks) {
...@@ -2896,7 +2993,7 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im ...@@ -2896,7 +2993,7 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
assert(_needsPaint || _needsCompositedLayerUpdate); assert(_needsPaint || _needsCompositedLayerUpdate);
assert(_layerHandle.layer != null); assert(_layerHandle.layer != null);
assert(!_layerHandle.layer!.attached); assert(!_layerHandle.layer!.attached);
AbstractNode? node = parent; RenderObject? node = parent;
while (node is RenderObject) { while (node is RenderObject) {
if (node.isRepaintBoundary) { if (node.isRepaintBoundary) {
if (node._layerHandle.layer == null) { if (node._layerHandle.layer == null) {
...@@ -2993,7 +3090,7 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im ...@@ -2993,7 +3090,7 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
assert(() { assert(() {
if (_needsCompositingBitsUpdate) { if (_needsCompositingBitsUpdate) {
if (parent is RenderObject) { if (parent is RenderObject) {
final RenderObject parent = this.parent! as RenderObject; final RenderObject parent = this.parent!;
bool visitedByParent = false; bool visitedByParent = false;
parent.visitChildren((RenderObject child) { parent.visitChildren((RenderObject child) {
if (child == this) { if (child == this) {
...@@ -3156,13 +3253,13 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im ...@@ -3156,13 +3253,13 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
final bool ancestorSpecified = ancestor != null; final bool ancestorSpecified = ancestor != null;
assert(attached); assert(attached);
if (ancestor == null) { if (ancestor == null) {
final AbstractNode? rootNode = owner!.rootNode; final RenderObject? rootNode = owner!.rootNode;
if (rootNode is RenderObject) { if (rootNode is RenderObject) {
ancestor = rootNode; ancestor = rootNode;
} }
} }
final List<RenderObject> renderers = <RenderObject>[]; final List<RenderObject> renderers = <RenderObject>[];
for (RenderObject renderer = this; renderer != ancestor; renderer = renderer.parent! as RenderObject) { for (RenderObject renderer = this; renderer != ancestor; renderer = renderer.parent!) {
renderers.add(renderer); renderers.add(renderer);
assert(renderer.parent != null); // Failed to find ancestor in parent chain. assert(renderer.parent != null); // Failed to find ancestor in parent chain.
} }
...@@ -3294,8 +3391,7 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im ...@@ -3294,8 +3391,7 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
if (_semantics != null && !_semantics!.isMergedIntoParent) { if (_semantics != null && !_semantics!.isMergedIntoParent) {
_semantics!.sendEvent(semanticsEvent); _semantics!.sendEvent(semanticsEvent);
} else if (parent != null) { } else if (parent != null) {
final RenderObject renderParent = parent! as RenderObject; parent!.sendSemanticsEvent(semanticsEvent);
renderParent.sendSemanticsEvent(semanticsEvent);
} }
} }
...@@ -3395,7 +3491,7 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im ...@@ -3395,7 +3491,7 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
mayProduceSiblingNodes = false; mayProduceSiblingNodes = false;
} }
node = node.parent! as RenderObject; node = node.parent!;
isEffectiveSemanticsBoundary = node._semanticsConfiguration.isSemanticBoundary; isEffectiveSemanticsBoundary = node._semanticsConfiguration.isSemanticBoundary;
if (isEffectiveSemanticsBoundary && node._semantics == null) { if (isEffectiveSemanticsBoundary && node._semantics == null) {
// We have reached a semantics boundary that doesn't own a semantics node. // We have reached a semantics boundary that doesn't own a semantics node.
...@@ -3678,9 +3774,9 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im ...@@ -3678,9 +3774,9 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
} }
if (_relayoutBoundary != null && _relayoutBoundary != this) { if (_relayoutBoundary != null && _relayoutBoundary != this) {
int count = 1; int count = 1;
RenderObject? target = parent as RenderObject?; RenderObject? target = parent;
while (target != null && target != _relayoutBoundary) { while (target != null && target != _relayoutBoundary) {
target = target.parent as RenderObject?; target = target.parent;
count += 1; count += 1;
} }
header += ' relayoutBoundary=up$count'; header += ' relayoutBoundary=up$count';
...@@ -3782,8 +3878,7 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im ...@@ -3782,8 +3878,7 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
Curve curve = Curves.ease, Curve curve = Curves.ease,
}) { }) {
if (parent is RenderObject) { if (parent is RenderObject) {
final RenderObject renderParent = parent! as RenderObject; parent!.showOnScreen(
renderParent.showOnScreen(
descendant: descendant ?? this, descendant: descendant ?? this,
rect: rect, rect: rect,
duration: duration, duration: duration,
...@@ -4970,11 +5065,11 @@ class _SemanticsGeometry { ...@@ -4970,11 +5065,11 @@ class _SemanticsGeometry {
Matrix4 clipRectTransform, Matrix4 clipRectTransform,
) { ) {
assert(clipRectTransform.isIdentity()); assert(clipRectTransform.isIdentity());
RenderObject intermediateParent = child.parent! as RenderObject; RenderObject intermediateParent = child.parent!;
while (intermediateParent != ancestor) { while (intermediateParent != ancestor) {
intermediateParent.applyPaintTransform(child, transform); intermediateParent.applyPaintTransform(child, transform);
intermediateParent = intermediateParent.parent! as RenderObject; intermediateParent = intermediateParent.parent!;
child = child.parent! as RenderObject; child = child.parent!;
} }
ancestor.applyPaintTransform(child, transform); ancestor.applyPaintTransform(child, transform);
ancestor.applyPaintTransform(child, clipRectTransform); ancestor.applyPaintTransform(child, clipRectTransform);
......
...@@ -45,7 +45,7 @@ abstract interface class RenderAbstractViewport extends RenderObject { ...@@ -45,7 +45,7 @@ abstract interface class RenderAbstractViewport extends RenderObject {
if (object is RenderAbstractViewport) { if (object is RenderAbstractViewport) {
return object; return object;
} }
object = object.parent as RenderObject?; object = object.parent;
} }
return null; return null;
} }
...@@ -779,7 +779,7 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix ...@@ -779,7 +779,7 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
RenderBox? pivot; RenderBox? pivot;
bool onlySlivers = target is RenderSliver; // ... between viewport and `target` (`target` included). bool onlySlivers = target is RenderSliver; // ... between viewport and `target` (`target` included).
while (child.parent != this) { while (child.parent != this) {
final RenderObject parent = child.parent! as RenderObject; final RenderObject parent = child.parent!;
if (child is RenderBox) { if (child is RenderBox) {
pivot = child; pivot = child;
} }
...@@ -1205,7 +1205,8 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix ...@@ -1205,7 +1205,8 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
} else { } else {
// `descendant` is between leading and trailing edge and hence already // `descendant` is between leading and trailing edge and hence already
// fully shown on screen. No action necessary. // fully shown on screen. No action necessary.
final Matrix4 transform = descendant.getTransformTo(viewport.parent! as RenderObject); assert(viewport.parent != null);
final Matrix4 transform = descendant.getTransformTo(viewport.parent);
return MatrixUtils.transformRect(transform, rect ?? descendant.paintBounds); return MatrixUtils.transformRect(transform, rect ?? descendant.paintBounds);
} }
......
...@@ -2263,7 +2263,7 @@ class LayoutId extends ParentDataWidget<MultiChildLayoutParentData> { ...@@ -2263,7 +2263,7 @@ class LayoutId extends ParentDataWidget<MultiChildLayoutParentData> {
final MultiChildLayoutParentData parentData = renderObject.parentData! as MultiChildLayoutParentData; final MultiChildLayoutParentData parentData = renderObject.parentData! as MultiChildLayoutParentData;
if (parentData.id != id) { if (parentData.id != id) {
parentData.id = id; parentData.id = id;
final AbstractNode? targetParent = renderObject.parent; final RenderObject? targetParent = renderObject.parent;
if (targetParent is RenderObject) { if (targetParent is RenderObject) {
targetParent.markNeedsLayout(); targetParent.markNeedsLayout();
} }
...@@ -4348,7 +4348,7 @@ class Positioned extends ParentDataWidget<StackParentData> { ...@@ -4348,7 +4348,7 @@ class Positioned extends ParentDataWidget<StackParentData> {
} }
if (needsLayout) { if (needsLayout) {
final AbstractNode? targetParent = renderObject.parent; final RenderObject? targetParent = renderObject.parent;
if (targetParent is RenderObject) { if (targetParent is RenderObject) {
targetParent.markNeedsLayout(); targetParent.markNeedsLayout();
} }
...@@ -5207,7 +5207,7 @@ class Flexible extends ParentDataWidget<FlexParentData> { ...@@ -5207,7 +5207,7 @@ class Flexible extends ParentDataWidget<FlexParentData> {
} }
if (needsLayout) { if (needsLayout) {
final AbstractNode? targetParent = renderObject.parent; final RenderObject? targetParent = renderObject.parent;
if (targetParent is RenderObject) { if (targetParent is RenderObject) {
targetParent.markNeedsLayout(); targetParent.markNeedsLayout();
} }
......
...@@ -936,6 +936,14 @@ class _RenderTheater extends RenderBox with ContainerRenderObjectMixin<RenderBox ...@@ -936,6 +936,14 @@ class _RenderTheater extends RenderBox with ContainerRenderObjectMixin<RenderBox
@override @override
void redepthChildren() => visitChildren(redepthChild); void redepthChildren() => visitChildren(redepthChild);
void _adoptDeferredLayoutBoxChild(_RenderDeferredLayoutBox child) {
adoptChild(child);
}
void _dropDeferredLayoutBoxChild(_RenderDeferredLayoutBox child) {
dropChild(child);
}
Alignment? _alignmentCache; Alignment? _alignmentCache;
Alignment get _resolvedAlignment => _alignmentCache ??= AlignmentDirectional.topStart.resolve(textDirection); Alignment get _resolvedAlignment => _alignmentCache ??= AlignmentDirectional.topStart.resolve(textDirection);
...@@ -1706,13 +1714,13 @@ final class _OverlayEntryLocation extends LinkedListEntry<_OverlayEntryLocation> ...@@ -1706,13 +1714,13 @@ final class _OverlayEntryLocation extends LinkedListEntry<_OverlayEntryLocation>
void _activate(_RenderDeferredLayoutBox child) { void _activate(_RenderDeferredLayoutBox child) {
assert(_debugNotDisposed()); assert(_debugNotDisposed());
assert(_overlayChildRenderBox == null, '$_overlayChildRenderBox'); assert(_overlayChildRenderBox == null, '$_overlayChildRenderBox');
_theater.adoptChild(child); _theater._adoptDeferredLayoutBoxChild(child);
_overlayChildRenderBox = child; _overlayChildRenderBox = child;
} }
void _deactivate(_RenderDeferredLayoutBox child) { void _deactivate(_RenderDeferredLayoutBox child) {
assert(_debugNotDisposed()); assert(_debugNotDisposed());
_theater.dropChild(child); _theater._dropDeferredLayoutBoxChild(child);
_overlayChildRenderBox = null; _overlayChildRenderBox = null;
} }
...@@ -1980,7 +1988,7 @@ final class _RenderDeferredLayoutBox extends RenderProxyBox with _RenderTheaterM ...@@ -1980,7 +1988,7 @@ final class _RenderDeferredLayoutBox extends RenderProxyBox with _RenderTheaterM
@override @override
_RenderTheater get theater { _RenderTheater get theater {
final AbstractNode? parent = this.parent; final RenderObject? parent = this.parent;
return parent is _RenderTheater return parent is _RenderTheater
? parent ? parent
: throw FlutterError('$parent of $this is not a _RenderTheater'); : throw FlutterError('$parent of $this is not a _RenderTheater');
......
...@@ -1342,7 +1342,7 @@ class KeepAlive extends ParentDataWidget<KeepAliveParentDataMixin> { ...@@ -1342,7 +1342,7 @@ class KeepAlive extends ParentDataWidget<KeepAliveParentDataMixin> {
if (parentData.keepAlive != keepAlive) { if (parentData.keepAlive != keepAlive) {
// No need to redo layout if it became true. // No need to redo layout if it became true.
parentData.keepAlive = keepAlive; parentData.keepAlive = keepAlive;
final AbstractNode? targetParent = renderObject.parent; final RenderObject? targetParent = renderObject.parent;
if (targetParent is RenderObject && !keepAlive) { if (targetParent is RenderObject && !keepAlive) {
targetParent.markNeedsLayout(); targetParent.markNeedsLayout();
} }
...@@ -1436,7 +1436,7 @@ class _SliverZeroFlexParentDataWidget extends ParentDataWidget<SliverPhysicalPar ...@@ -1436,7 +1436,7 @@ class _SliverZeroFlexParentDataWidget extends ParentDataWidget<SliverPhysicalPar
} }
if (needsLayout) { if (needsLayout) {
final AbstractNode? targetParent = renderObject.parent; final RenderObject? targetParent = renderObject.parent;
if (targetParent is RenderObject) { if (targetParent is RenderObject) {
targetParent.markNeedsLayout(); targetParent.markNeedsLayout();
} }
...@@ -1508,7 +1508,7 @@ class SliverCrossAxisExpanded extends ParentDataWidget<SliverPhysicalContainerPa ...@@ -1508,7 +1508,7 @@ class SliverCrossAxisExpanded extends ParentDataWidget<SliverPhysicalContainerPa
} }
if (needsLayout) { if (needsLayout) {
final AbstractNode? targetParent = renderObject.parent; final RenderObject? targetParent = renderObject.parent;
if (targetParent is RenderObject) { if (targetParent is RenderObject) {
targetParent.markNeedsLayout(); targetParent.markNeedsLayout();
} }
......
...@@ -417,7 +417,7 @@ class TableCell extends ParentDataWidget<TableCellParentData> { ...@@ -417,7 +417,7 @@ class TableCell extends ParentDataWidget<TableCellParentData> {
final TableCellParentData parentData = renderObject.parentData! as TableCellParentData; final TableCellParentData parentData = renderObject.parentData! as TableCellParentData;
if (parentData.verticalAlignment != verticalAlignment) { if (parentData.verticalAlignment != verticalAlignment) {
parentData.verticalAlignment = verticalAlignment; parentData.verticalAlignment = verticalAlignment;
final AbstractNode? targetParent = renderObject.parent; final RenderObject? targetParent = renderObject.parent;
if (targetParent is RenderObject) { if (targetParent is RenderObject) {
targetParent.markNeedsLayout(); targetParent.markNeedsLayout();
} }
......
...@@ -553,7 +553,7 @@ class _ScreenshotPaintingContext extends PaintingContext { ...@@ -553,7 +553,7 @@ class _ScreenshotPaintingContext extends PaintingContext {
}) { }) {
RenderObject repaintBoundary = renderObject; RenderObject repaintBoundary = renderObject;
while (!repaintBoundary.isRepaintBoundary) { while (!repaintBoundary.isRepaintBoundary) {
repaintBoundary = repaintBoundary.parent! as RenderObject; repaintBoundary = repaintBoundary.parent!;
} }
final _ScreenshotData data = _ScreenshotData(target: renderObject); final _ScreenshotData data = _ScreenshotData(target: renderObject);
final _ScreenshotPaintingContext context = _ScreenshotPaintingContext( final _ScreenshotPaintingContext context = _ScreenshotPaintingContext(
...@@ -1632,7 +1632,7 @@ mixin WidgetInspectorService { ...@@ -1632,7 +1632,7 @@ mixin WidgetInspectorService {
final List<RenderObject> chain = <RenderObject>[]; final List<RenderObject> chain = <RenderObject>[];
while (renderObject != null) { while (renderObject != null) {
chain.add(renderObject); chain.add(renderObject);
renderObject = renderObject.parent as RenderObject?; renderObject = renderObject.parent;
} }
return _followDiagnosticableChain(chain.reversed.toList()); return _followDiagnosticableChain(chain.reversed.toList());
} }
...@@ -2053,7 +2053,7 @@ mixin WidgetInspectorService { ...@@ -2053,7 +2053,7 @@ mixin WidgetInspectorService {
'renderObject': renderObject.toDiagnosticsNode().toJsonMap(renderObjectSerializationDelegate), 'renderObject': renderObject.toDiagnosticsNode().toJsonMap(renderObjectSerializationDelegate),
}; };
final AbstractNode? renderParent = renderObject.parent; final RenderObject? renderParent = renderObject.parent;
if (renderParent is RenderObject && subtreeDepth > 0) { if (renderParent is RenderObject && subtreeDepth > 0) {
final Object? parentCreator = renderParent.debugCreator; final Object? parentCreator = renderParent.debugCreator;
if (parentCreator is DebugCreator) { if (parentCreator is DebugCreator) {
...@@ -2948,7 +2948,7 @@ class _RenderInspectorOverlay extends RenderBox { ...@@ -2948,7 +2948,7 @@ class _RenderInspectorOverlay extends RenderBox {
context.addLayer(_InspectorOverlayLayer( context.addLayer(_InspectorOverlayLayer(
overlayRect: Rect.fromLTWH(offset.dx, offset.dy, size.width, size.height), overlayRect: Rect.fromLTWH(offset.dx, offset.dy, size.width, size.height),
selection: selection, selection: selection,
rootRenderObject: parent is RenderObject ? parent! as RenderObject : null, rootRenderObject: parent is RenderObject ? parent! : null,
)); ));
} }
} }
...@@ -3237,14 +3237,14 @@ class _InspectorOverlayLayer extends Layer { ...@@ -3237,14 +3237,14 @@ class _InspectorOverlayLayer extends Layer {
/// overlays in the same app (i.e. an storyboard), a selected or candidate /// overlays in the same app (i.e. an storyboard), a selected or candidate
/// render object may not belong to this tree. /// render object may not belong to this tree.
bool _isInInspectorRenderObjectTree(RenderObject child) { bool _isInInspectorRenderObjectTree(RenderObject child) {
RenderObject? current = child.parent as RenderObject?; RenderObject? current = child.parent;
while (current != null) { while (current != null) {
// We found the widget inspector render object. // We found the widget inspector render object.
if (current is RenderStack if (current is RenderStack
&& current.lastChild is _RenderInspectorOverlay) { && current.lastChild is _RenderInspectorOverlay) {
return rootRenderObject == current; return rootRenderObject == current;
} }
current = current.parent as RenderObject?; current = current.parent;
} }
return false; return false;
} }
......
...@@ -2283,5 +2283,5 @@ SemanticsNode _findDebugSemantics(RenderObject object) { ...@@ -2283,5 +2283,5 @@ SemanticsNode _findDebugSemantics(RenderObject object) {
if (object.debugSemantics != null) { if (object.debugSemantics != null) {
return object.debugSemantics!; return object.debugSemantics!;
} }
return _findDebugSemantics(object.parent! as RenderObject); return _findDebugSemantics(object.parent!);
} }
...@@ -1334,5 +1334,5 @@ SemanticsNode findDebugSemantics(RenderObject object) { ...@@ -1334,5 +1334,5 @@ SemanticsNode findDebugSemantics(RenderObject object) {
if (object.debugSemantics != null) { if (object.debugSemantics != null) {
return object.debugSemantics!; return object.debugSemantics!;
} }
return findDebugSemantics(object.parent! as RenderObject); return findDebugSemantics(object.parent!);
} }
...@@ -118,7 +118,7 @@ void main() { ...@@ -118,7 +118,7 @@ void main() {
expect(parentData!.offset.dy, -(viewHeight / 2.0)); expect(parentData!.offset.dy, -(viewHeight / 2.0));
expect(test.calls, 2); // The layout constraints change will clear the cached data. expect(test.calls, 2); // The layout constraints change will clear the cached data.
final RenderObject parent = test.parent! as RenderObject; final RenderObject parent = test.parent!;
expect(parent.debugNeedsLayout, false); expect(parent.debugNeedsLayout, false);
// Do not forget notify parent dirty after the cached data be cleared by `layout()` // Do not forget notify parent dirty after the cached data be cleared by `layout()`
......
...@@ -1006,7 +1006,7 @@ void main() { ...@@ -1006,7 +1006,7 @@ void main() {
editable.painter = null; editable.painter = null;
editable.paintCount = 0; editable.paintCount = 0;
final AbstractNode? parent = editable.parent; final RenderObject? parent = editable.parent;
if (parent is RenderConstrainedBox) { if (parent is RenderConstrainedBox) {
parent.child = null; parent.child = null;
} }
......
// Copyright 2014 The Flutter 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 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
import 'rendering_tester.dart';
class RealRoot extends AbstractNode {
RealRoot(this.child) {
adoptChild(child);
}
final RenderObject child;
@override
void redepthChildren() {
redepthChild(child);
}
@override
void attach(Object owner) {
super.attach(owner);
child.attach(owner as PipelineOwner);
}
@override
void detach() {
super.detach();
child.detach();
}
@override
PipelineOwner? get owner => super.owner as PipelineOwner?;
void layout() {
child.layout(BoxConstraints.tight(const Size(500.0, 500.0)));
}
}
void main() {
TestRenderingFlutterBinding.ensureInitialized();
test('non-RenderObject roots', () {
RenderPositionedBox child;
final RealRoot root = RealRoot(
child = RenderPositionedBox(
child: RenderSizedBox(const Size(100.0, 100.0)),
),
);
root.attach(PipelineOwner());
child.scheduleInitialLayout();
root.layout();
child.markNeedsLayout();
root.layout();
});
}
...@@ -803,10 +803,10 @@ void main() { ...@@ -803,10 +803,10 @@ void main() {
}); });
test('Offstage implements paintsChild correctly', () { test('Offstage implements paintsChild correctly', () {
final RenderBox box = RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 20)); final RenderConstrainedBox box = RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 20));
final RenderBox parent = RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 20)); final RenderConstrainedBox parent = RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 20));
final RenderOffstage offstage = RenderOffstage(offstage: false, child: box); final RenderOffstage offstage = RenderOffstage(offstage: false, child: box);
parent.adoptChild(offstage); parent.child = offstage;
expect(offstage.paintsChild(box), true); expect(offstage.paintsChild(box), true);
...@@ -817,9 +817,7 @@ void main() { ...@@ -817,9 +817,7 @@ void main() {
test('Opacity implements paintsChild correctly', () { test('Opacity implements paintsChild correctly', () {
final RenderBox box = RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 20)); final RenderBox box = RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 20));
final RenderBox parent = RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 20));
final RenderOpacity opacity = RenderOpacity(child: box); final RenderOpacity opacity = RenderOpacity(child: box);
parent.adoptChild(opacity);
expect(opacity.paintsChild(box), true); expect(opacity.paintsChild(box), true);
...@@ -830,10 +828,8 @@ void main() { ...@@ -830,10 +828,8 @@ void main() {
test('AnimatedOpacity sets paint matrix to zero when alpha == 0', () { test('AnimatedOpacity sets paint matrix to zero when alpha == 0', () {
final RenderBox box = RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 20)); final RenderBox box = RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 20));
final RenderBox parent = RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 20));
final AnimationController opacityAnimation = AnimationController(value: 1, vsync: FakeTickerProvider()); final AnimationController opacityAnimation = AnimationController(value: 1, vsync: FakeTickerProvider());
final RenderAnimatedOpacity opacity = RenderAnimatedOpacity(opacity: opacityAnimation, child: box); final RenderAnimatedOpacity opacity = RenderAnimatedOpacity(opacity: opacityAnimation, child: box);
parent.adoptChild(opacity);
// Make it listen to the animation. // Make it listen to the animation.
opacity.attach(PipelineOwner()); opacity.attach(PipelineOwner());
...@@ -847,10 +843,8 @@ void main() { ...@@ -847,10 +843,8 @@ void main() {
test('AnimatedOpacity sets paint matrix to zero when alpha == 0 (sliver)', () { test('AnimatedOpacity sets paint matrix to zero when alpha == 0 (sliver)', () {
final RenderSliver sliver = RenderSliverToBoxAdapter(child: RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 20))); final RenderSliver sliver = RenderSliverToBoxAdapter(child: RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 20)));
final RenderBox parent = RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 20));
final AnimationController opacityAnimation = AnimationController(value: 1, vsync: FakeTickerProvider()); final AnimationController opacityAnimation = AnimationController(value: 1, vsync: FakeTickerProvider());
final RenderSliverAnimatedOpacity opacity = RenderSliverAnimatedOpacity(opacity: opacityAnimation, sliver: sliver); final RenderSliverAnimatedOpacity opacity = RenderSliverAnimatedOpacity(opacity: opacityAnimation, sliver: sliver);
parent.adoptChild(opacity);
// Make it listen to the animation. // Make it listen to the animation.
opacity.attach(PipelineOwner()); opacity.attach(PipelineOwner());
......
...@@ -1188,7 +1188,7 @@ Future<void> main() async { ...@@ -1188,7 +1188,7 @@ Future<void> main() async {
if (currentNode is RenderAnimatedOpacity && currentNode.opacity.value == 0) { if (currentNode is RenderAnimatedOpacity && currentNode.opacity.value == 0) {
return false; return false;
} }
currentNode = currentNode.parent as RenderObject?; currentNode = currentNode.parent;
} }
return true; return true;
} }
...@@ -2919,7 +2919,7 @@ Future<void> main() async { ...@@ -2919,7 +2919,7 @@ Future<void> main() async {
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
RenderAnimatedOpacity? findRenderAnimatedOpacity() { RenderAnimatedOpacity? findRenderAnimatedOpacity() {
AbstractNode? parent = tester.renderObject(find.byType(Placeholder)); RenderObject? parent = tester.renderObject(find.byType(Placeholder));
while (parent is RenderObject && parent is! RenderAnimatedOpacity) { while (parent is RenderObject && parent is! RenderAnimatedOpacity) {
parent = parent.parent; parent = parent.parent;
} }
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
...@@ -29,7 +28,7 @@ class _ManyRelayoutBoundaries extends StatelessWidget { ...@@ -29,7 +28,7 @@ class _ManyRelayoutBoundaries extends StatelessWidget {
void rebuildLayoutBuilderSubtree(RenderBox descendant) { void rebuildLayoutBuilderSubtree(RenderBox descendant) {
assert(descendant is! RenderConstrainedLayoutBuilder<BoxConstraints, RenderBox>); assert(descendant is! RenderConstrainedLayoutBuilder<BoxConstraints, RenderBox>);
AbstractNode? node = descendant.parent; RenderObject? node = descendant.parent;
while (node != null) { while (node != null) {
if (node is! RenderConstrainedLayoutBuilder<BoxConstraints, RenderBox>) { if (node is! RenderConstrainedLayoutBuilder<BoxConstraints, RenderBox>) {
node = node.parent; node = node.parent;
...@@ -74,7 +73,7 @@ List<RenderObject> _ancestorRenderTheaters(RenderObject child) { ...@@ -74,7 +73,7 @@ List<RenderObject> _ancestorRenderTheaters(RenderObject child) {
if (node.runtimeType.toString() == '_RenderTheater') { if (node.runtimeType.toString() == '_RenderTheater') {
results.add(node); results.add(node);
} }
final AbstractNode? parent = node.parent; final RenderObject? parent = node.parent;
node = parent is RenderObject? parent : null; node = parent is RenderObject? parent : null;
} }
return results; return results;
...@@ -1525,14 +1524,14 @@ void main() { ...@@ -1525,14 +1524,14 @@ void main() {
final List<RenderObject> childrenVisited = <RenderObject>[]; final List<RenderObject> childrenVisited = <RenderObject>[];
theater.visitChildren(childrenVisited.add); theater.visitChildren(childrenVisited.add);
expect(childrenVisited.length, 3); expect(childrenVisited.length, 3);
expect(childrenVisited, containsAllInOrder(<AbstractNode>[child1Box.parent!, child2Box.parent!])); expect(childrenVisited, containsAllInOrder(<RenderObject>[child1Box.parent!, child2Box.parent!]));
childrenVisited.clear(); childrenVisited.clear();
setState(() { reparented = true; }); setState(() { reparented = true; });
await tester.pump(); await tester.pump();
theater.visitChildren(childrenVisited.add); theater.visitChildren(childrenVisited.add);
// The child list stays the same. // The child list stays the same.
expect(childrenVisited, containsAllInOrder(<AbstractNode>[child1Box.parent!, child2Box.parent!])); expect(childrenVisited, containsAllInOrder(<RenderObject>[child1Box.parent!, child2Box.parent!]));
}); });
}); });
} }
......
...@@ -320,7 +320,7 @@ mixin CommandHandlerFactory { ...@@ -320,7 +320,7 @@ mixin CommandHandlerFactory {
SemanticsNode? node; SemanticsNode? node;
while (renderObject != null && node == null) { while (renderObject != null && node == null) {
node = renderObject.debugSemantics; node = renderObject.debugSemantics;
renderObject = renderObject.parent as RenderObject?; renderObject = renderObject.parent;
} }
if (node == null) { if (node == null) {
throw StateError('No semantics data found'); throw StateError('No semantics data found');
......
...@@ -24,7 +24,7 @@ Future<ui.Image> captureImage(Element element) { ...@@ -24,7 +24,7 @@ Future<ui.Image> captureImage(Element element) {
assert(element.renderObject != null); assert(element.renderObject != null);
RenderObject renderObject = element.renderObject!; RenderObject renderObject = element.renderObject!;
while (!renderObject.isRepaintBoundary) { while (!renderObject.isRepaintBoundary) {
renderObject = renderObject.parent! as RenderObject; renderObject = renderObject.parent!;
} }
assert(!renderObject.debugNeedsPaint); assert(!renderObject.debugNeedsPaint);
final OffsetLayer layer = renderObject.debugLayer! as OffsetLayer; final OffsetLayer layer = renderObject.debugLayer! as OffsetLayer;
......
...@@ -93,7 +93,7 @@ RenderObject _findRepaintBoundary(Element element) { ...@@ -93,7 +93,7 @@ RenderObject _findRepaintBoundary(Element element) {
assert(element.renderObject != null); assert(element.renderObject != null);
RenderObject renderObject = element.renderObject!; RenderObject renderObject = element.renderObject!;
while (!renderObject.isRepaintBoundary) { while (!renderObject.isRepaintBoundary) {
renderObject = renderObject.parent! as RenderObject; renderObject = renderObject.parent!;
} }
return renderObject; return renderObject;
} }
......
...@@ -87,7 +87,7 @@ class SemanticsController { ...@@ -87,7 +87,7 @@ class SemanticsController {
RenderObject? renderObject = element.findRenderObject(); RenderObject? renderObject = element.findRenderObject();
SemanticsNode? result = renderObject?.debugSemantics; SemanticsNode? result = renderObject?.debugSemantics;
while (renderObject != null && (result == null || result.isMergedIntoParent)) { while (renderObject != null && (result == null || result.isMergedIntoParent)) {
renderObject = renderObject.parent as RenderObject?; renderObject = renderObject.parent;
result = renderObject?.debugSemantics; result = renderObject?.debugSemantics;
} }
if (result == null) { if (result == null) {
...@@ -366,7 +366,7 @@ abstract class WidgetController { ...@@ -366,7 +366,7 @@ abstract class WidgetController {
final RenderObject object = element.renderObject!; final RenderObject object = element.renderObject!;
RenderObject current = object; RenderObject current = object;
while (current.debugLayer == null) { while (current.debugLayer == null) {
current = current.parent! as RenderObject; current = current.parent!;
} }
final ContainerLayer layer = current.debugLayer!; final ContainerLayer layer = current.debugLayer!;
return _walkLayers(layer); return _walkLayers(layer);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment