diff --git a/dev/bots/analyze.dart b/dev/bots/analyze.dart index 49a4e1f0fa..7102ecb51f 100644 --- a/dev/bots/analyze.dart +++ b/dev/bots/analyze.dart @@ -22,6 +22,7 @@ import 'custom_rules/analyze.dart'; import 'custom_rules/avoid_future_catcherror.dart'; import 'custom_rules/no_double_clamp.dart'; import 'custom_rules/no_stop_watches.dart'; +import 'custom_rules/protect_public_state_subtypes.dart'; import 'custom_rules/render_box_intrinsics.dart'; import 'run_command.dart'; import 'utils.dart'; @@ -180,7 +181,12 @@ Future run(List arguments) async { // Only run the private lints when the code is free of type errors. The // lints are easier to write when they can assume, for example, there is no // inheritance cycles. - final List rules = [noDoubleClamp, noStopwatches, renderBoxIntrinsicCalculation]; + final List rules = [ + noDoubleClamp, + noStopwatches, + renderBoxIntrinsicCalculation, + protectPublicStateSubtypes, + ]; final String ruleNames = rules.map((AnalyzeRule rule) => '\n * $rule').join(); printProgress('Analyzing code in the framework with the following rules:$ruleNames'); await analyzeWithRules(flutterRoot, rules, diff --git a/dev/bots/custom_rules/protect_public_state_subtypes.dart b/dev/bots/custom_rules/protect_public_state_subtypes.dart new file mode 100644 index 0000000000..b43891b02a --- /dev/null +++ b/dev/bots/custom_rules/protect_public_state_subtypes.dart @@ -0,0 +1,101 @@ +// 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. + +// TODO(nate-thegrate): remove this file if @protected changes, or add a test if it doesn't. +// https://github.com/dart-lang/sdk/issues/57094 + +import 'package:analyzer/dart/analysis/results.dart'; +import 'package:analyzer/dart/ast/ast.dart'; +import 'package:analyzer/dart/ast/visitor.dart'; +import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/dart/element/type.dart'; + +import '../utils.dart'; +import 'analyze.dart'; + +final AnalyzeRule protectPublicStateSubtypes = _ProtectPublicStateSubtypes(); + +class _ProtectPublicStateSubtypes implements AnalyzeRule { + final Map> _errors = >{}; + + @override + void applyTo(ResolvedUnitResult unit) { + final _StateSubclassVisitor visitor = _StateSubclassVisitor(); + unit.unit.visitChildren(visitor); + final List unprotected = visitor.unprotectedMethods; + if (unprotected.isNotEmpty) { + _errors.putIfAbsent(unit, () => []).addAll(unprotected); + } + } + + @override + void reportViolations(String workingDirectory) { + if (_errors.isEmpty) { + return; + } + + foundError( + [ + for (final MapEntry> entry in _errors.entries) + for (final MethodDeclaration method in entry.value) + '${locationInFile(entry.key, method, workingDirectory)}: $method - missing "@protected" annotation.', + '\nPublic State subtypes should add @protected when overriding methods,', + 'to avoid exposing internal logic to developers.', + ], + ); + } + + @override + String toString() => 'Add "@protected" to public State subtypes'; +} + +class _StateSubclassVisitor extends SimpleAstVisitor { + final List unprotectedMethods = []; + + /// Holds the `State` class [DartType]. + static DartType? stateType; + + static bool isPublicStateSubtype(InterfaceElement element) { + if (!element.isPublic) { + return false; + } + if (stateType != null) { + return element.allSupertypes.contains(stateType); + } + for (final InterfaceType superType in element.allSupertypes) { + if (superType.element.name == 'State') { + stateType = superType; + return true; + } + } + return false; + } + + @override + void visitClassDeclaration(ClassDeclaration node) { + if (isPublicStateSubtype(node.declaredElement!)) { + node.visitChildren(this); + } + } + + /// Checks whether overridden `State` methods have the `@protected` annotation, + /// and adds the declaration to [unprotectedMethods] if not. + @override + void visitMethodDeclaration(MethodDeclaration node) { + switch (node.name.lexeme) { + case 'initState': + case 'didUpdateWidget': + case 'didChangeDependencies': + case 'reassemble': + case 'deactivate': + case 'activate': + case 'dispose': + case 'build': + case 'debugFillProperties': + if (!node.declaredElement!.hasProtected) { + unprotectedMethods.add(node); + } + } + } +} diff --git a/packages/flutter/lib/src/material/drawer.dart b/packages/flutter/lib/src/material/drawer.dart index 82f9db2ee8..1df54b93f9 100644 --- a/packages/flutter/lib/src/material/drawer.dart +++ b/packages/flutter/lib/src/material/drawer.dart @@ -468,6 +468,7 @@ class DrawerController extends StatefulWidget { /// /// Typically used by a [Scaffold] to [open] and [close] the drawer. class DrawerControllerState extends State with SingleTickerProviderStateMixin { + @protected @override void initState() { super.initState(); @@ -481,6 +482,7 @@ class DrawerControllerState extends State with SingleTickerPro ..addStatusListener(_animationStatusChanged); } + @protected @override void dispose() { _historyEntry?.remove(); @@ -489,12 +491,14 @@ class DrawerControllerState extends State with SingleTickerPro super.dispose(); } + @protected @override void didChangeDependencies() { super.didChangeDependencies(); _scrimColorTween = _buildScrimColorTween(); } + @protected @override void didUpdateWidget(DrawerController oldWidget) { super.didUpdateWidget(oldWidget); @@ -751,6 +755,7 @@ class DrawerControllerState extends State with SingleTickerPro } } + @protected @override Widget build(BuildContext context) { assert(debugCheckHasMaterialLocalizations(context)); diff --git a/packages/flutter/lib/src/material/paginated_data_table.dart b/packages/flutter/lib/src/material/paginated_data_table.dart index 06523ca034..96c6342d72 100644 --- a/packages/flutter/lib/src/material/paginated_data_table.dart +++ b/packages/flutter/lib/src/material/paginated_data_table.dart @@ -331,6 +331,7 @@ class PaginatedDataTableState extends State { int _selectedRowCount = 0; final Map _rows = {}; + @protected @override void initState() { super.initState(); @@ -339,6 +340,7 @@ class PaginatedDataTableState extends State { _handleDataSourceChanged(); } + @protected @override void didUpdateWidget(PaginatedDataTable oldWidget) { super.didUpdateWidget(oldWidget); @@ -349,6 +351,7 @@ class PaginatedDataTableState extends State { } } + @protected @override void reassemble() { super.reassemble(); @@ -366,6 +369,7 @@ class PaginatedDataTableState extends State { _updateCaches(); } + @protected @override void dispose() { widget.source.removeListener(_handleDataSourceChanged); @@ -468,6 +472,7 @@ class PaginatedDataTableState extends State { final GlobalKey _tableKey = GlobalKey(); + @protected @override Widget build(BuildContext context) { // TODO(ianh): This whole build function doesn't handle RTL yet. diff --git a/packages/flutter/lib/src/material/popup_menu.dart b/packages/flutter/lib/src/material/popup_menu.dart index fc13494539..1aef889e31 100644 --- a/packages/flutter/lib/src/material/popup_menu.dart +++ b/packages/flutter/lib/src/material/popup_menu.dart @@ -356,6 +356,7 @@ class PopupMenuItemState> extends State { widget.onTap?.call(); } + @protected @override Widget build(BuildContext context) { final ThemeData theme = Theme.of(context); @@ -1544,6 +1545,7 @@ class PopupMenuButtonState extends State> { }; } + @protected @override Widget build(BuildContext context) { final IconThemeData iconTheme = IconTheme.of(context); diff --git a/packages/flutter/lib/src/material/refresh_indicator.dart b/packages/flutter/lib/src/material/refresh_indicator.dart index b26427d41c..4949f063cc 100644 --- a/packages/flutter/lib/src/material/refresh_indicator.dart +++ b/packages/flutter/lib/src/material/refresh_indicator.dart @@ -352,6 +352,7 @@ class RefreshIndicatorState extends State end: 0.0, ); + @protected @override void initState() { super.initState(); @@ -365,12 +366,14 @@ class RefreshIndicatorState extends State _scaleFactor = _scaleController.drive(_oneToZeroTween); } + @protected @override void didChangeDependencies() { _setupColorTween(); super.didChangeDependencies(); } + @protected @override void didUpdateWidget(covariant RefreshIndicator oldWidget) { super.didUpdateWidget(oldWidget); @@ -379,6 +382,7 @@ class RefreshIndicatorState extends State } } + @protected @override void dispose() { _positionController.dispose(); @@ -636,6 +640,7 @@ class RefreshIndicatorState extends State return _pendingRefreshFuture; } + @protected @override Widget build(BuildContext context) { assert(debugCheckHasMaterialLocalizations(context)); diff --git a/packages/flutter/lib/src/material/scaffold.dart b/packages/flutter/lib/src/material/scaffold.dart index 844370f414..70ea06f3ef 100644 --- a/packages/flutter/lib/src/material/scaffold.dart +++ b/packages/flutter/lib/src/material/scaffold.dart @@ -197,6 +197,7 @@ class ScaffoldMessengerState extends State with TickerProvide Timer? _snackBarTimer; bool? _accessibleNavigation; + @protected @override void didChangeDependencies() { final bool accessibleNavigation = MediaQuery.accessibleNavigationOf(context); @@ -604,6 +605,7 @@ class ScaffoldMessengerState extends State with TickerProvide hideCurrentMaterialBanner(); } + @protected @override Widget build(BuildContext context) { assert(debugCheckHasMediaQuery(context)); @@ -632,6 +634,7 @@ class ScaffoldMessengerState extends State with TickerProvide ); } + @protected @override void dispose() { _materialBannerController?.dispose(); @@ -2116,6 +2119,7 @@ class ScaffoldState extends State with TickerProviderStateMixin, Resto @override String? get restorationId => widget.restorationId; + @protected @override void restoreState(RestorationBucket? oldBucket, bool initialRestore) { registerForRestoration(_drawerOpened, 'drawer_open'); @@ -2676,6 +2680,7 @@ class ScaffoldState extends State with TickerProviderStateMixin, Resto return widget.resizeToAvoidBottomInset ?? true; } + @protected @override void initState() { super.initState(); @@ -2695,6 +2700,7 @@ class ScaffoldState extends State with TickerProviderStateMixin, Resto ); } + @protected @override void didUpdateWidget(Scaffold oldWidget) { super.didUpdateWidget(oldWidget); @@ -2732,6 +2738,7 @@ class ScaffoldState extends State with TickerProviderStateMixin, Resto } } + @protected @override void didChangeDependencies() { // Using maybeOf is valid here since both the Scaffold and ScaffoldMessenger @@ -2750,6 +2757,7 @@ class ScaffoldState extends State with TickerProviderStateMixin, Resto super.didChangeDependencies(); } + @protected @override void dispose() { _geometryNotifier.dispose(); @@ -2864,6 +2872,7 @@ class ScaffoldState extends State with TickerProviderStateMixin, Resto }); } + @protected @override Widget build(BuildContext context) { assert(debugCheckHasMediaQuery(context)); diff --git a/packages/flutter/lib/src/material/segmented_button.dart b/packages/flutter/lib/src/material/segmented_button.dart index 322f3c1497..0851dabfc6 100644 --- a/packages/flutter/lib/src/material/segmented_button.dart +++ b/packages/flutter/lib/src/material/segmented_button.dart @@ -426,6 +426,7 @@ class SegmentedButtonState extends State> { @visibleForTesting final Map, MaterialStatesController> statesControllers = , MaterialStatesController>{}; + @protected @override void didUpdateWidget(covariant SegmentedButton oldWidget) { super.didUpdateWidget(oldWidget); @@ -464,6 +465,7 @@ class SegmentedButtonState extends State> { } } + @protected @override Widget build(BuildContext context) { final SegmentedButtonThemeData theme = SegmentedButtonTheme.of(context); @@ -605,6 +607,7 @@ class SegmentedButtonState extends State> { ); } + @protected @override void dispose() { for (final MaterialStatesController controller in statesControllers.values) { diff --git a/packages/flutter/lib/src/material/selection_area.dart b/packages/flutter/lib/src/material/selection_area.dart index be1a26aa2e..41c949032b 100644 --- a/packages/flutter/lib/src/material/selection_area.dart +++ b/packages/flutter/lib/src/material/selection_area.dart @@ -113,6 +113,7 @@ class SelectionAreaState extends State { /// The [State] of the [SelectableRegion] for which this [SelectionArea] wraps. SelectableRegionState get selectableRegion => _selectableRegionKey.currentState!; + @protected @override Widget build(BuildContext context) { assert(debugCheckHasMaterialLocalizations(context)); diff --git a/packages/flutter/lib/src/material/tooltip.dart b/packages/flutter/lib/src/material/tooltip.dart index d994d37af3..1258e285f3 100644 --- a/packages/flutter/lib/src/material/tooltip.dart +++ b/packages/flutter/lib/src/material/tooltip.dart @@ -706,6 +706,7 @@ class TooltipState extends State with SingleTickerProviderStateMixin { return true; } + @protected @override void initState() { super.initState(); @@ -715,6 +716,7 @@ class TooltipState extends State with SingleTickerProviderStateMixin { GestureBinding.instance.pointerRouter.addGlobalRoute(_handleGlobalPointerEvent); } + @protected @override void didChangeDependencies() { super.didChangeDependencies(); @@ -797,6 +799,7 @@ class TooltipState extends State with SingleTickerProviderStateMixin { : SelectionContainer.disabled(child: overlayChild); } + @protected @override void dispose() { GestureBinding.instance.pointerRouter.removeGlobalRoute(_handleGlobalPointerEvent); @@ -815,6 +818,7 @@ class TooltipState extends State with SingleTickerProviderStateMixin { super.dispose(); } + @protected @override Widget build(BuildContext context) { // If message is empty then no need to create a tooltip overlay to show diff --git a/packages/flutter/lib/src/widgets/animated_scroll_view.dart b/packages/flutter/lib/src/widgets/animated_scroll_view.dart index e32073164f..c61ead4cbe 100644 --- a/packages/flutter/lib/src/widgets/animated_scroll_view.dart +++ b/packages/flutter/lib/src/widgets/animated_scroll_view.dart @@ -299,7 +299,7 @@ class AnimatedList extends _AnimatedScrollView { /// [AnimatedList] item input handlers can also refer to their [AnimatedListState] /// with the static [AnimatedList.of] method. class AnimatedListState extends _AnimatedScrollViewState { - + @protected @override Widget build(BuildContext context) { return _wrap( @@ -508,7 +508,7 @@ class AnimatedGrid extends _AnimatedScrollView { /// [AnimatedGrid] item input handlers can also refer to their [AnimatedGridState] /// with the static [AnimatedGrid.of] method. class AnimatedGridState extends _AnimatedScrollViewState { - + @protected @override Widget build(BuildContext context) { return _wrap( @@ -1040,7 +1040,7 @@ class SliverAnimatedList extends _SliverAnimatedMultiBoxAdaptor { /// [SliverAnimatedList] item input handlers can also refer to their /// [SliverAnimatedListState] with the static [SliverAnimatedList.of] method. class SliverAnimatedListState extends _SliverAnimatedMultiBoxAdaptorState { - + @protected @override Widget build(BuildContext context) { return SliverList( @@ -1187,7 +1187,7 @@ class SliverAnimatedGrid extends _SliverAnimatedMultiBoxAdaptor { /// [SliverAnimatedGrid] item input handlers can also refer to their /// [SliverAnimatedGridState] with the static [SliverAnimatedGrid.of] method. class SliverAnimatedGridState extends _SliverAnimatedMultiBoxAdaptorState { - + @protected @override Widget build(BuildContext context) { return SliverGrid( diff --git a/packages/flutter/lib/src/widgets/autofill.dart b/packages/flutter/lib/src/widgets/autofill.dart index ab9a566300..bedcf8328a 100644 --- a/packages/flutter/lib/src/widgets/autofill.dart +++ b/packages/flutter/lib/src/widgets/autofill.dart @@ -213,12 +213,14 @@ class AutofillGroupState extends State with AutofillScopeMixin { _clients.remove(autofillId); } + @protected @override void didChangeDependencies() { super.didChangeDependencies(); _isTopmostAutofillGroup = AutofillGroup.maybeOf(context) == null; } + @protected @override Widget build(BuildContext context) { return _AutofillScope( @@ -227,6 +229,7 @@ class AutofillGroupState extends State with AutofillScopeMixin { ); } + @protected @override void dispose() { super.dispose(); diff --git a/packages/flutter/lib/src/widgets/editable_text.dart b/packages/flutter/lib/src/widgets/editable_text.dart index 9ae6d0f600..6e1a11f01e 100644 --- a/packages/flutter/lib/src/widgets/editable_text.dart +++ b/packages/flutter/lib/src/widgets/editable_text.dart @@ -2979,6 +2979,7 @@ class EditableTextState extends State with AutomaticKeepAliveClien // State lifecycle: + @protected @override void initState() { super.initState(); @@ -3005,6 +3006,7 @@ class EditableTextState extends State with AutomaticKeepAliveClien // cursor) are supposed to run. bool _tickersEnabled = true; + @protected @override void didChangeDependencies() { super.didChangeDependencies(); @@ -3080,6 +3082,7 @@ class EditableTextState extends State with AutomaticKeepAliveClien } } + @protected @override void didUpdateWidget(EditableText oldWidget) { super.didUpdateWidget(oldWidget); @@ -3183,6 +3186,7 @@ class EditableTextState extends State with AutomaticKeepAliveClien } } + @protected @override void dispose() { _internalScrollController?.dispose(); @@ -5178,6 +5182,7 @@ class EditableTextState extends State with AutomaticKeepAliveClien EditableTextTapOutsideIntent: _makeOverridable(_EditableTextTapOutsideAction()), }; + @protected @override Widget build(BuildContext context) { assert(debugCheckHasMediaQuery(context)); diff --git a/packages/flutter/lib/src/widgets/form.dart b/packages/flutter/lib/src/widgets/form.dart index 525cd02b54..7be29d6eaa 100644 --- a/packages/flutter/lib/src/widgets/form.dart +++ b/packages/flutter/lib/src/widgets/form.dart @@ -268,6 +268,7 @@ class FormState extends State
{ } } + @protected @override Widget build(BuildContext context) { switch (widget.autovalidateMode) { @@ -671,24 +672,28 @@ class FormFieldState extends State> with RestorationMixin { @override String? get restorationId => widget.restorationId; + @protected @override void restoreState(RestorationBucket? oldBucket, bool initialRestore) { registerForRestoration(_errorText, 'error_text'); registerForRestoration(_hasInteractedByUser, 'has_interacted_by_user'); } + @protected @override void deactivate() { Form.maybeOf(context)?._unregister(this); super.deactivate(); } + @protected @override void initState() { super.initState(); _errorText = RestorableStringN(widget.forceErrorText); } + @protected @override void didUpdateWidget(FormField oldWidget) { super.didUpdateWidget(oldWidget); @@ -697,6 +702,7 @@ class FormFieldState extends State> with RestorationMixin { } } + @protected @override void dispose() { _errorText.dispose(); @@ -705,6 +711,7 @@ class FormFieldState extends State> with RestorationMixin { super.dispose(); } + @protected @override Widget build(BuildContext context) { if (widget.enabled) { diff --git a/packages/flutter/lib/src/widgets/framework.dart b/packages/flutter/lib/src/widgets/framework.dart index d62671075c..e0d5d9377f 100644 --- a/packages/flutter/lib/src/widgets/framework.dart +++ b/packages/flutter/lib/src/widgets/framework.dart @@ -1495,6 +1495,9 @@ abstract class State with Diagnosticable { properties.add(ObjectFlagProperty('_widget', _widget, ifNull: 'no widget')); properties.add(ObjectFlagProperty('_element', _element, ifNull: 'not mounted')); } + + // If @protected State methods are added or removed, the analysis rule should be + // updated accordingly (dev/bots/custom_rules/protect_public_state_subtypes.dart) } /// A widget that has a child widget provided to it, instead of building a new diff --git a/packages/flutter/lib/src/widgets/gesture_detector.dart b/packages/flutter/lib/src/widgets/gesture_detector.dart index ed69eb7631..1b6b1e1f24 100644 --- a/packages/flutter/lib/src/widgets/gesture_detector.dart +++ b/packages/flutter/lib/src/widgets/gesture_detector.dart @@ -1405,6 +1405,7 @@ class RawGestureDetectorState extends State { Map? _recognizers = const {}; SemanticsGestureDelegate? _semantics; + @protected @override void initState() { super.initState(); @@ -1412,6 +1413,7 @@ class RawGestureDetectorState extends State { _syncAll(widget.gestures); } + @protected @override void didUpdateWidget(RawGestureDetector oldWidget) { super.didUpdateWidget(oldWidget); @@ -1486,6 +1488,7 @@ class RawGestureDetectorState extends State { semanticsGestureHandler!.validActions = actions; // will call _markNeedsSemanticsUpdate(), if required. } + @protected @override void dispose() { for (final GestureRecognizer recognizer in _recognizers!.values) { @@ -1538,6 +1541,7 @@ class RawGestureDetectorState extends State { _semantics!.assignSemantics(renderObject); } + @protected @override Widget build(BuildContext context) { Widget result = Listener( @@ -1556,6 +1560,7 @@ class RawGestureDetectorState extends State { return result; } + @protected @override void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); diff --git a/packages/flutter/lib/src/widgets/implicit_animations.dart b/packages/flutter/lib/src/widgets/implicit_animations.dart index 1271f2478e..7ec291966e 100644 --- a/packages/flutter/lib/src/widgets/implicit_animations.dart +++ b/packages/flutter/lib/src/widgets/implicit_animations.dart @@ -369,6 +369,7 @@ abstract class ImplicitlyAnimatedWidgetState Animation get animation => _animation; late CurvedAnimation _animation = _createCurve(); + @protected @override void initState() { super.initState(); @@ -381,6 +382,7 @@ abstract class ImplicitlyAnimatedWidgetState didUpdateTweens(); } + @protected @override void didUpdateWidget(T oldWidget) { super.didUpdateWidget(oldWidget); @@ -405,6 +407,7 @@ abstract class ImplicitlyAnimatedWidgetState return CurvedAnimation(parent: _controller, curve: widget.curve); } + @protected @override void dispose() { _animation.dispose(); @@ -554,6 +557,7 @@ abstract class ImplicitlyAnimatedWidgetState /// [AnimatedWidgetBaseState] to iterate through the subclasses' widget's fields /// and animate them. abstract class AnimatedWidgetBaseState extends ImplicitlyAnimatedWidgetState { + @protected @override void initState() { super.initState(); diff --git a/packages/flutter/lib/src/widgets/navigator.dart b/packages/flutter/lib/src/widgets/navigator.dart index 0d33acebb0..649f81791a 100644 --- a/packages/flutter/lib/src/widgets/navigator.dart +++ b/packages/flutter/lib/src/widgets/navigator.dart @@ -3706,6 +3706,7 @@ class NavigatorState extends State with TickerProviderStateMixin, Res return true; } + @protected @override void initState() { super.initState(); @@ -3742,6 +3743,7 @@ class NavigatorState extends State with TickerProviderStateMixin, Res int get _nextPagelessRestorationScopeId => _rawNextPagelessRestorationScopeId.value++; + @protected @override void restoreState(RestorationBucket? oldBucket, bool initialRestore) { registerForRestoration(_rawNextPagelessRestorationScopeId, 'id'); @@ -3810,6 +3812,7 @@ class NavigatorState extends State with TickerProviderStateMixin, Res assert(() { _debugLocked = false; return true; }()); } + @protected @override void didToggleBucket(RestorationBucket? oldBucket) { super.didToggleBucket(oldBucket); @@ -3822,6 +3825,7 @@ class NavigatorState extends State with TickerProviderStateMixin, Res @override String? get restorationId => widget.restorationScopeId; + @protected @override void didChangeDependencies() { super.didChangeDependencies(); @@ -3915,6 +3919,7 @@ class NavigatorState extends State with TickerProviderStateMixin, Res } } + @protected @override void didUpdateWidget(Navigator oldWidget) { super.didUpdateWidget(oldWidget); @@ -3969,6 +3974,7 @@ class NavigatorState extends State with TickerProviderStateMixin, Res }()); } + @protected @override void deactivate() { for (final NavigatorObserver observer in _effectiveObservers) { @@ -3978,6 +3984,7 @@ class NavigatorState extends State with TickerProviderStateMixin, Res super.deactivate(); } + @protected @override void activate() { super.activate(); @@ -3988,6 +3995,7 @@ class NavigatorState extends State with TickerProviderStateMixin, Res } } + @protected @override void dispose() { assert(!_debugLocked); @@ -5646,6 +5654,7 @@ class NavigatorState extends State with TickerProviderStateMixin, Res return result; } + @protected @override Widget build(BuildContext context) { assert(!_debugLocked); diff --git a/packages/flutter/lib/src/widgets/nested_scroll_view.dart b/packages/flutter/lib/src/widgets/nested_scroll_view.dart index 439f8e4637..ef41d89586 100644 --- a/packages/flutter/lib/src/widgets/nested_scroll_view.dart +++ b/packages/flutter/lib/src/widgets/nested_scroll_view.dart @@ -425,6 +425,7 @@ class NestedScrollViewState extends State { _NestedScrollCoordinator? _coordinator; + @protected @override void initState() { super.initState(); @@ -436,12 +437,14 @@ class NestedScrollViewState extends State { ); } + @protected @override void didChangeDependencies() { super.didChangeDependencies(); _coordinator!.setParent(widget.controller); } + @protected @override void didUpdateWidget(NestedScrollView oldWidget) { super.didUpdateWidget(oldWidget); @@ -450,6 +453,7 @@ class NestedScrollViewState extends State { } } + @protected @override void dispose() { _coordinator!.dispose(); @@ -476,6 +480,7 @@ class NestedScrollViewState extends State { } } + @protected @override Widget build(BuildContext context) { final ScrollPhysics scrollPhysics = widget.physics?.applyTo(const ClampingScrollPhysics()) diff --git a/packages/flutter/lib/src/widgets/overlay.dart b/packages/flutter/lib/src/widgets/overlay.dart index df6d776ac8..cbc26314dd 100644 --- a/packages/flutter/lib/src/widgets/overlay.dart +++ b/packages/flutter/lib/src/widgets/overlay.dart @@ -604,6 +604,7 @@ class Overlay extends StatefulWidget { class OverlayState extends State with TickerProviderStateMixin { final List _entries = []; + @protected @override void initState() { super.initState(); @@ -808,6 +809,7 @@ class OverlayState extends State with TickerProviderStateMixin { }); } + @protected @override Widget build(BuildContext context) { // This list is filled backwards and then reversed below before @@ -842,6 +844,7 @@ class OverlayState extends State with TickerProviderStateMixin { ); } + @protected @override void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); diff --git a/packages/flutter/lib/src/widgets/reorderable_list.dart b/packages/flutter/lib/src/widgets/reorderable_list.dart index 1900b3ad57..96ea0c0bc9 100644 --- a/packages/flutter/lib/src/widgets/reorderable_list.dart +++ b/packages/flutter/lib/src/widgets/reorderable_list.dart @@ -388,6 +388,7 @@ class ReorderableListState extends State { _sliverReorderableListKey.currentState!.cancelReorder(); } + @protected @override Widget build(BuildContext context) { return CustomScrollView( @@ -630,6 +631,7 @@ class SliverReorderableListState extends State with Ticke Axis get _scrollDirection => axisDirectionToAxis(_scrollable.axisDirection); bool get _reverse => axisDirectionIsReversed(_scrollable.axisDirection); + @protected @override void didChangeDependencies() { super.didChangeDependencies(); @@ -644,6 +646,7 @@ class SliverReorderableListState extends State with Ticke } } + @protected @override void didUpdateWidget(covariant SliverReorderableList oldWidget) { super.didUpdateWidget(oldWidget); @@ -661,6 +664,7 @@ class SliverReorderableListState extends State with Ticke } } + @protected @override void dispose() { _dragReset(); @@ -1030,6 +1034,7 @@ class SliverReorderableListState extends State with Ticke ); } + @protected @override Widget build(BuildContext context) { assert(debugCheckHasOverlay(context)); diff --git a/packages/flutter/lib/src/widgets/scroll_notification_observer.dart b/packages/flutter/lib/src/widgets/scroll_notification_observer.dart index c143d0c109..92248c82cd 100644 --- a/packages/flutter/lib/src/widgets/scroll_notification_observer.dart +++ b/packages/flutter/lib/src/widgets/scroll_notification_observer.dart @@ -216,6 +216,7 @@ class ScrollNotificationObserverState extends State } } + @protected @override Widget build(BuildContext context) { return NotificationListener( @@ -239,6 +240,7 @@ class ScrollNotificationObserverState extends State ); } + @protected @override void dispose() { assert(_debugAssertNotDisposed()); diff --git a/packages/flutter/lib/src/widgets/scrollable.dart b/packages/flutter/lib/src/widgets/scrollable.dart index 57b55cb8fd..976c025c39 100644 --- a/packages/flutter/lib/src/widgets/scrollable.dart +++ b/packages/flutter/lib/src/widgets/scrollable.dart @@ -626,6 +626,7 @@ class ScrollableState extends State with TickerProviderStateMixin, R _effectiveScrollController.attach(position); } + @protected @override void restoreState(RestorationBucket? oldBucket, bool initialRestore) { registerForRestoration(_persistedScrollOffset, 'offset'); @@ -635,6 +636,7 @@ class ScrollableState extends State with TickerProviderStateMixin, R } } + @protected @override void saveOffset(double offset) { assert(debugIsSerializableForRestoration(offset)); @@ -644,6 +646,7 @@ class ScrollableState extends State with TickerProviderStateMixin, R ServicesBinding.instance.restorationManager.flushData(); } + @protected @override void initState() { if (widget.controller == null) { @@ -652,6 +655,7 @@ class ScrollableState extends State with TickerProviderStateMixin, R super.initState(); } + @protected @override void didChangeDependencies() { _mediaQueryGestureSettings = MediaQuery.maybeGestureSettingsOf(context); @@ -680,6 +684,7 @@ class ScrollableState extends State with TickerProviderStateMixin, R return widget.controller?.runtimeType != oldWidget.controller?.runtimeType; } + @protected @override void didUpdateWidget(Scrollable oldWidget) { super.didUpdateWidget(oldWidget); @@ -711,6 +716,7 @@ class ScrollableState extends State with TickerProviderStateMixin, R } } + @protected @override void dispose() { if (widget.controller != null) { @@ -980,6 +986,7 @@ class ScrollableState extends State with TickerProviderStateMixin, R // DESCRIPTION + @protected @override Widget build(BuildContext context) { assert(_position != null); @@ -1064,6 +1071,7 @@ class ScrollableState extends State with TickerProviderStateMixin, R return (>[ ensureVisibleFuture ], this); } + @protected @override void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); @@ -1934,6 +1942,7 @@ class TwoDimensionalScrollableState extends State { return _horizontalInnerScrollableKey.currentState!; } + @protected @override void initState() { if (widget.verticalDetails.controller == null) { @@ -1945,6 +1954,7 @@ class TwoDimensionalScrollableState extends State { super.initState(); } + @protected @override void didUpdateWidget(TwoDimensionalScrollable oldWidget) { super.didUpdateWidget(oldWidget); @@ -1985,6 +1995,7 @@ class TwoDimensionalScrollableState extends State { } } + @protected @override Widget build(BuildContext context) { assert( @@ -2049,6 +2060,7 @@ class TwoDimensionalScrollableState extends State { ); } + @protected @override void dispose() { _verticalFallbackController?.dispose(); diff --git a/packages/flutter/lib/src/widgets/scrollbar.dart b/packages/flutter/lib/src/widgets/scrollbar.dart index 9925d47f6e..1d1aa0869e 100644 --- a/packages/flutter/lib/src/widgets/scrollbar.dart +++ b/packages/flutter/lib/src/widgets/scrollbar.dart @@ -1378,6 +1378,7 @@ class RawScrollbarState extends State with TickerProv @protected bool get enableGestures => widget.interactive ?? true; + @protected @override void initState() { super.initState(); @@ -1404,6 +1405,7 @@ class RawScrollbarState extends State with TickerProv ); } + @protected @override void didChangeDependencies() { super.didChangeDependencies(); @@ -1562,6 +1564,7 @@ class RawScrollbarState extends State with TickerProv ..ignorePointer = !enableGestures; } + @protected @override void didUpdateWidget(T oldWidget) { super.didUpdateWidget(oldWidget); @@ -2159,6 +2162,7 @@ class RawScrollbarState extends State with TickerProv } } + @protected @override void dispose() { _fadeoutAnimationController.dispose(); @@ -2168,6 +2172,7 @@ class RawScrollbarState extends State with TickerProv super.dispose(); } + @protected @override Widget build(BuildContext context) { updateScrollbarPainter(); diff --git a/packages/flutter/lib/src/widgets/selectable_region.dart b/packages/flutter/lib/src/widgets/selectable_region.dart index dace673d58..430eb31674 100644 --- a/packages/flutter/lib/src/widgets/selectable_region.dart +++ b/packages/flutter/lib/src/widgets/selectable_region.dart @@ -375,6 +375,7 @@ class SelectableRegionState extends State with TextSelectionDe FocusNode? _localFocusNode; FocusNode get _focusNode => widget.focusNode ?? (_localFocusNode ??= FocusNode(debugLabel: 'SelectableRegion')); + @protected @override void initState() { super.initState(); @@ -398,6 +399,7 @@ class SelectableRegionState extends State with TextSelectionDe _processTextActions.addAll(await _processTextService.queryTextActions()); } + @protected @override void didChangeDependencies() { super.didChangeDependencies(); @@ -424,6 +426,7 @@ class SelectableRegionState extends State with TextSelectionDe } } + @protected @override void didUpdateWidget(SelectableRegion oldWidget) { super.didUpdateWidget(oldWidget); @@ -1704,6 +1707,7 @@ class SelectableRegionState extends State with TextSelectionDe _selectable = null; } + @protected @override void dispose() { _selectable?.removeListener(_updateSelectionStatus); @@ -1720,6 +1724,7 @@ class SelectableRegionState extends State with TextSelectionDe super.dispose(); } + @protected @override Widget build(BuildContext context) { assert(debugCheckHasOverlay(context)); diff --git a/packages/flutter/lib/src/widgets/undo_history.dart b/packages/flutter/lib/src/widgets/undo_history.dart index 5d0b0feb43..510503f035 100644 --- a/packages/flutter/lib/src/widgets/undo_history.dart +++ b/packages/flutter/lib/src/widgets/undo_history.dart @@ -225,6 +225,7 @@ class UndoHistoryState extends State> with UndoManagerClient { } } + @protected @override void initState() { super.initState(); @@ -243,6 +244,7 @@ class UndoHistoryState extends State> with UndoManagerClient { _effectiveController.onRedo.addListener(redo); } + @protected @override void didUpdateWidget(UndoHistory oldWidget) { super.didUpdateWidget(oldWidget); @@ -265,6 +267,7 @@ class UndoHistoryState extends State> with UndoManagerClient { } } + @protected @override void dispose() { if (UndoManager.client == this) { @@ -280,6 +283,7 @@ class UndoHistoryState extends State> with UndoManagerClient { super.dispose(); } + @protected @override Widget build(BuildContext context) { return Actions(