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
parentData.isPressed = isPressed;
// Force a repaint.
final AbstractNode? targetParent = renderObject.parent;
final RenderObject? targetParent = renderObject.parent;
if (targetParent is RenderObject) {
targetParent.markNeedsPaint();
}
......
......@@ -8,6 +8,10 @@ import 'package:meta/meta.dart';
// during device lab performance tests. When editing this file, check to make sure
// 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.
///
/// AbstractNode has as notion of depth, attachment, and parent, but does not
......@@ -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
/// [depth] will still be 2. The [depth] is automatically maintained by the
/// [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 {
/// The depth of this node in the tree.
///
......
......@@ -4,7 +4,6 @@
import 'dart:math' as math;
import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
......@@ -1202,7 +1201,7 @@ class TableRowInkWell extends InkResponse {
RectCallback getRectCallback(RenderBox referenceBox) {
return () {
RenderObject cell = referenceBox;
AbstractNode? table = cell.parent;
RenderObject? table = cell.parent;
final Matrix4 transform = Matrix4.identity();
while (table is RenderObject && table is! RenderTable) {
table.applyPaintTransform(cell, transform);
......
......@@ -762,7 +762,7 @@ abstract class InkFeature {
final int toDepth = to.depth;
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,
// or either of them is offscreen and thus won't get painted.
if (fromParent is! RenderObject || !fromParent.paintsChild(from)) {
......@@ -773,7 +773,7 @@ abstract class InkFeature {
}
if (fromDepth <= toDepth) {
final AbstractNode? toParent = to.parent;
final RenderObject? toParent = to.parent;
if (toParent is! RenderObject || !toParent.paintsChild(to)) {
return null;
}
......
......@@ -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(!debugNeedsLayout);
assert(() {
final RenderObject? parent = this.parent as RenderObject?;
if (owner!.debugDoingLayout) {
return (RenderObject.debugActiveLayout == parent) && parent!.debugDoingThisLayout;
}
......@@ -2144,7 +2143,6 @@ abstract class RenderBox extends RenderObject {
return ((RenderObject.debugActivePaint == parent) && parent!.debugDoingThisPaint) ||
((RenderObject.debugActivePaint == this) && debugDoingThisPaint);
}
assert(parent == this.parent);
return false;
}());
assert(_debugSetDoingBaseline(true));
......
......@@ -1133,7 +1133,7 @@ class RenderListWheelViewport
// `child` will be the last RenderObject before the viewport when walking up from `target`.
RenderObject child = target;
while (child.parent != this) {
child = child.parent! as RenderObject;
child = child.parent!;
}
final ListWheelParentData parentData = child.parentData! as ListWheelParentData;
......
......@@ -45,7 +45,7 @@ abstract interface class RenderAbstractViewport extends RenderObject {
if (object is RenderAbstractViewport) {
return object;
}
object = object.parent as RenderObject?;
object = object.parent;
}
return null;
}
......@@ -779,7 +779,7 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
RenderBox? pivot;
bool onlySlivers = target is RenderSliver; // ... between viewport and `target` (`target` included).
while (child.parent != this) {
final RenderObject parent = child.parent! as RenderObject;
final RenderObject parent = child.parent!;
if (child is RenderBox) {
pivot = child;
}
......@@ -1205,7 +1205,8 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
} else {
// `descendant` is between leading and trailing edge and hence already
// 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);
}
......
......@@ -2263,7 +2263,7 @@ class LayoutId extends ParentDataWidget<MultiChildLayoutParentData> {
final MultiChildLayoutParentData parentData = renderObject.parentData! as MultiChildLayoutParentData;
if (parentData.id != id) {
parentData.id = id;
final AbstractNode? targetParent = renderObject.parent;
final RenderObject? targetParent = renderObject.parent;
if (targetParent is RenderObject) {
targetParent.markNeedsLayout();
}
......@@ -4348,7 +4348,7 @@ class Positioned extends ParentDataWidget<StackParentData> {
}
if (needsLayout) {
final AbstractNode? targetParent = renderObject.parent;
final RenderObject? targetParent = renderObject.parent;
if (targetParent is RenderObject) {
targetParent.markNeedsLayout();
}
......@@ -5207,7 +5207,7 @@ class Flexible extends ParentDataWidget<FlexParentData> {
}
if (needsLayout) {
final AbstractNode? targetParent = renderObject.parent;
final RenderObject? targetParent = renderObject.parent;
if (targetParent is RenderObject) {
targetParent.markNeedsLayout();
}
......
......@@ -936,6 +936,14 @@ class _RenderTheater extends RenderBox with ContainerRenderObjectMixin<RenderBox
@override
void redepthChildren() => visitChildren(redepthChild);
void _adoptDeferredLayoutBoxChild(_RenderDeferredLayoutBox child) {
adoptChild(child);
}
void _dropDeferredLayoutBoxChild(_RenderDeferredLayoutBox child) {
dropChild(child);
}
Alignment? _alignmentCache;
Alignment get _resolvedAlignment => _alignmentCache ??= AlignmentDirectional.topStart.resolve(textDirection);
......@@ -1706,13 +1714,13 @@ final class _OverlayEntryLocation extends LinkedListEntry<_OverlayEntryLocation>
void _activate(_RenderDeferredLayoutBox child) {
assert(_debugNotDisposed());
assert(_overlayChildRenderBox == null, '$_overlayChildRenderBox');
_theater.adoptChild(child);
_theater._adoptDeferredLayoutBoxChild(child);
_overlayChildRenderBox = child;
}
void _deactivate(_RenderDeferredLayoutBox child) {
assert(_debugNotDisposed());
_theater.dropChild(child);
_theater._dropDeferredLayoutBoxChild(child);
_overlayChildRenderBox = null;
}
......@@ -1980,7 +1988,7 @@ final class _RenderDeferredLayoutBox extends RenderProxyBox with _RenderTheaterM
@override
_RenderTheater get theater {
final AbstractNode? parent = this.parent;
final RenderObject? parent = this.parent;
return parent is _RenderTheater
? parent
: throw FlutterError('$parent of $this is not a _RenderTheater');
......
......@@ -1342,7 +1342,7 @@ class KeepAlive extends ParentDataWidget<KeepAliveParentDataMixin> {
if (parentData.keepAlive != keepAlive) {
// No need to redo layout if it became true.
parentData.keepAlive = keepAlive;
final AbstractNode? targetParent = renderObject.parent;
final RenderObject? targetParent = renderObject.parent;
if (targetParent is RenderObject && !keepAlive) {
targetParent.markNeedsLayout();
}
......@@ -1436,7 +1436,7 @@ class _SliverZeroFlexParentDataWidget extends ParentDataWidget<SliverPhysicalPar
}
if (needsLayout) {
final AbstractNode? targetParent = renderObject.parent;
final RenderObject? targetParent = renderObject.parent;
if (targetParent is RenderObject) {
targetParent.markNeedsLayout();
}
......@@ -1508,7 +1508,7 @@ class SliverCrossAxisExpanded extends ParentDataWidget<SliverPhysicalContainerPa
}
if (needsLayout) {
final AbstractNode? targetParent = renderObject.parent;
final RenderObject? targetParent = renderObject.parent;
if (targetParent is RenderObject) {
targetParent.markNeedsLayout();
}
......
......@@ -417,7 +417,7 @@ class TableCell extends ParentDataWidget<TableCellParentData> {
final TableCellParentData parentData = renderObject.parentData! as TableCellParentData;
if (parentData.verticalAlignment != verticalAlignment) {
parentData.verticalAlignment = verticalAlignment;
final AbstractNode? targetParent = renderObject.parent;
final RenderObject? targetParent = renderObject.parent;
if (targetParent is RenderObject) {
targetParent.markNeedsLayout();
}
......
......@@ -553,7 +553,7 @@ class _ScreenshotPaintingContext extends PaintingContext {
}) {
RenderObject repaintBoundary = renderObject;
while (!repaintBoundary.isRepaintBoundary) {
repaintBoundary = repaintBoundary.parent! as RenderObject;
repaintBoundary = repaintBoundary.parent!;
}
final _ScreenshotData data = _ScreenshotData(target: renderObject);
final _ScreenshotPaintingContext context = _ScreenshotPaintingContext(
......@@ -1632,7 +1632,7 @@ mixin WidgetInspectorService {
final List<RenderObject> chain = <RenderObject>[];
while (renderObject != null) {
chain.add(renderObject);
renderObject = renderObject.parent as RenderObject?;
renderObject = renderObject.parent;
}
return _followDiagnosticableChain(chain.reversed.toList());
}
......@@ -2053,7 +2053,7 @@ mixin WidgetInspectorService {
'renderObject': renderObject.toDiagnosticsNode().toJsonMap(renderObjectSerializationDelegate),
};
final AbstractNode? renderParent = renderObject.parent;
final RenderObject? renderParent = renderObject.parent;
if (renderParent is RenderObject && subtreeDepth > 0) {
final Object? parentCreator = renderParent.debugCreator;
if (parentCreator is DebugCreator) {
......@@ -2948,7 +2948,7 @@ class _RenderInspectorOverlay extends RenderBox {
context.addLayer(_InspectorOverlayLayer(
overlayRect: Rect.fromLTWH(offset.dx, offset.dy, size.width, size.height),
selection: selection,
rootRenderObject: parent is RenderObject ? parent! as RenderObject : null,
rootRenderObject: parent is RenderObject ? parent! : null,
));
}
}
......@@ -3237,14 +3237,14 @@ class _InspectorOverlayLayer extends Layer {
/// overlays in the same app (i.e. an storyboard), a selected or candidate
/// render object may not belong to this tree.
bool _isInInspectorRenderObjectTree(RenderObject child) {
RenderObject? current = child.parent as RenderObject?;
RenderObject? current = child.parent;
while (current != null) {
// We found the widget inspector render object.
if (current is RenderStack
&& current.lastChild is _RenderInspectorOverlay) {
return rootRenderObject == current;
}
current = current.parent as RenderObject?;
current = current.parent;
}
return false;
}
......
......@@ -2283,5 +2283,5 @@ SemanticsNode _findDebugSemantics(RenderObject object) {
if (object.debugSemantics != null) {
return object.debugSemantics!;
}
return _findDebugSemantics(object.parent! as RenderObject);
return _findDebugSemantics(object.parent!);
}
......@@ -1334,5 +1334,5 @@ SemanticsNode findDebugSemantics(RenderObject object) {
if (object.debugSemantics != null) {
return object.debugSemantics!;
}
return findDebugSemantics(object.parent! as RenderObject);
return findDebugSemantics(object.parent!);
}
......@@ -118,7 +118,7 @@ void main() {
expect(parentData!.offset.dy, -(viewHeight / 2.0));
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);
// Do not forget notify parent dirty after the cached data be cleared by `layout()`
......
......@@ -1006,7 +1006,7 @@ void main() {
editable.painter = null;
editable.paintCount = 0;
final AbstractNode? parent = editable.parent;
final RenderObject? parent = editable.parent;
if (parent is RenderConstrainedBox) {
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() {
});
test('Offstage implements paintsChild correctly', () {
final RenderBox box = RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 20));
final RenderBox parent = RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 20));
final RenderConstrainedBox box = 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);
parent.adoptChild(offstage);
parent.child = offstage;
expect(offstage.paintsChild(box), true);
......@@ -817,9 +817,7 @@ void main() {
test('Opacity implements paintsChild correctly', () {
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);
parent.adoptChild(opacity);
expect(opacity.paintsChild(box), true);
......@@ -830,10 +828,8 @@ void main() {
test('AnimatedOpacity sets paint matrix to zero when alpha == 0', () {
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 RenderAnimatedOpacity opacity = RenderAnimatedOpacity(opacity: opacityAnimation, child: box);
parent.adoptChild(opacity);
// Make it listen to the animation.
opacity.attach(PipelineOwner());
......@@ -847,10 +843,8 @@ void main() {
test('AnimatedOpacity sets paint matrix to zero when alpha == 0 (sliver)', () {
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 RenderSliverAnimatedOpacity opacity = RenderSliverAnimatedOpacity(opacity: opacityAnimation, sliver: sliver);
parent.adoptChild(opacity);
// Make it listen to the animation.
opacity.attach(PipelineOwner());
......
......@@ -1188,7 +1188,7 @@ Future<void> main() async {
if (currentNode is RenderAnimatedOpacity && currentNode.opacity.value == 0) {
return false;
}
currentNode = currentNode.parent as RenderObject?;
currentNode = currentNode.parent;
}
return true;
}
......@@ -2919,7 +2919,7 @@ Future<void> main() async {
final ScrollController controller = ScrollController();
RenderAnimatedOpacity? findRenderAnimatedOpacity() {
AbstractNode? parent = tester.renderObject(find.byType(Placeholder));
RenderObject? parent = tester.renderObject(find.byType(Placeholder));
while (parent is RenderObject && parent is! RenderAnimatedOpacity) {
parent = parent.parent;
}
......
......@@ -2,7 +2,6 @@
// 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/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
......@@ -29,7 +28,7 @@ class _ManyRelayoutBoundaries extends StatelessWidget {
void rebuildLayoutBuilderSubtree(RenderBox descendant) {
assert(descendant is! RenderConstrainedLayoutBuilder<BoxConstraints, RenderBox>);
AbstractNode? node = descendant.parent;
RenderObject? node = descendant.parent;
while (node != null) {
if (node is! RenderConstrainedLayoutBuilder<BoxConstraints, RenderBox>) {
node = node.parent;
......@@ -74,7 +73,7 @@ List<RenderObject> _ancestorRenderTheaters(RenderObject child) {
if (node.runtimeType.toString() == '_RenderTheater') {
results.add(node);
}
final AbstractNode? parent = node.parent;
final RenderObject? parent = node.parent;
node = parent is RenderObject? parent : null;
}
return results;
......@@ -1525,14 +1524,14 @@ void main() {
final List<RenderObject> childrenVisited = <RenderObject>[];
theater.visitChildren(childrenVisited.add);
expect(childrenVisited.length, 3);
expect(childrenVisited, containsAllInOrder(<AbstractNode>[child1Box.parent!, child2Box.parent!]));
expect(childrenVisited, containsAllInOrder(<RenderObject>[child1Box.parent!, child2Box.parent!]));
childrenVisited.clear();
setState(() { reparented = true; });
await tester.pump();
theater.visitChildren(childrenVisited.add);
// 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 {
SemanticsNode? node;
while (renderObject != null && node == null) {
node = renderObject.debugSemantics;
renderObject = renderObject.parent as RenderObject?;
renderObject = renderObject.parent;
}
if (node == null) {
throw StateError('No semantics data found');
......
......@@ -24,7 +24,7 @@ Future<ui.Image> captureImage(Element element) {
assert(element.renderObject != null);
RenderObject renderObject = element.renderObject!;
while (!renderObject.isRepaintBoundary) {
renderObject = renderObject.parent! as RenderObject;
renderObject = renderObject.parent!;
}
assert(!renderObject.debugNeedsPaint);
final OffsetLayer layer = renderObject.debugLayer! as OffsetLayer;
......
......@@ -93,7 +93,7 @@ RenderObject _findRepaintBoundary(Element element) {
assert(element.renderObject != null);
RenderObject renderObject = element.renderObject!;
while (!renderObject.isRepaintBoundary) {
renderObject = renderObject.parent! as RenderObject;
renderObject = renderObject.parent!;
}
return renderObject;
}
......
......@@ -87,7 +87,7 @@ class SemanticsController {
RenderObject? renderObject = element.findRenderObject();
SemanticsNode? result = renderObject?.debugSemantics;
while (renderObject != null && (result == null || result.isMergedIntoParent)) {
renderObject = renderObject.parent as RenderObject?;
renderObject = renderObject.parent;
result = renderObject?.debugSemantics;
}
if (result == null) {
......@@ -366,7 +366,7 @@ abstract class WidgetController {
final RenderObject object = element.renderObject!;
RenderObject current = object;
while (current.debugLayer == null) {
current = current.parent! as RenderObject;
current = current.parent!;
}
final ContainerLayer layer = current.debugLayer!;
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