Unverified Commit 5575bf3c authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

Improve performance of debugCheckHasDirectionality (#81431)

parent 35ad43f2
...@@ -20,6 +20,8 @@ import 'scaffold.dart' show Scaffold, ScaffoldMessenger; ...@@ -20,6 +20,8 @@ import 'scaffold.dart' show Scaffold, ScaffoldMessenger;
/// assert(debugCheckHasMaterial(context)); /// assert(debugCheckHasMaterial(context));
/// ``` /// ```
/// ///
/// This method can be expensive (it walks the element tree).
///
/// Does nothing if asserts are disabled. Always returns true. /// Does nothing if asserts are disabled. Always returns true.
bool debugCheckHasMaterial(BuildContext context) { bool debugCheckHasMaterial(BuildContext context) {
assert(() { assert(() {
...@@ -62,6 +64,11 @@ bool debugCheckHasMaterial(BuildContext context) { ...@@ -62,6 +64,11 @@ bool debugCheckHasMaterial(BuildContext context) {
/// assert(debugCheckHasMaterialLocalizations(context)); /// assert(debugCheckHasMaterialLocalizations(context));
/// ``` /// ```
/// ///
/// This function has the side-effect of establishing an inheritance
/// relationship with the nearest [Localizations] widget (see
/// [BuildContext.dependOnInheritedWidgetOfExactType]). This is ok if the caller
/// always also calls [Localizations.of] or [Localizations.localeOf].
///
/// Does nothing if asserts are disabled. Always returns true. /// Does nothing if asserts are disabled. Always returns true.
bool debugCheckHasMaterialLocalizations(BuildContext context) { bool debugCheckHasMaterialLocalizations(BuildContext context) {
assert(() { assert(() {
...@@ -102,6 +109,8 @@ bool debugCheckHasMaterialLocalizations(BuildContext context) { ...@@ -102,6 +109,8 @@ bool debugCheckHasMaterialLocalizations(BuildContext context) {
/// assert(debugCheckHasScaffold(context)); /// assert(debugCheckHasScaffold(context));
/// ``` /// ```
/// ///
/// This method can be expensive (it walks the element tree).
///
/// Does nothing if asserts are disabled. Always returns true. /// Does nothing if asserts are disabled. Always returns true.
bool debugCheckHasScaffold(BuildContext context) { bool debugCheckHasScaffold(BuildContext context) {
assert(() { assert(() {
...@@ -133,6 +142,8 @@ bool debugCheckHasScaffold(BuildContext context) { ...@@ -133,6 +142,8 @@ bool debugCheckHasScaffold(BuildContext context) {
/// assert(debugCheckHasScaffoldMessenger(context)); /// assert(debugCheckHasScaffoldMessenger(context));
/// ``` /// ```
/// ///
/// This method can be expensive (it walks the element tree).
///
/// Does nothing if asserts are disabled. Always returns true. /// Does nothing if asserts are disabled. Always returns true.
bool debugCheckHasScaffoldMessenger(BuildContext context) { bool debugCheckHasScaffoldMessenger(BuildContext context) {
assert(() { assert(() {
......
...@@ -310,6 +310,8 @@ class Material extends StatefulWidget { ...@@ -310,6 +310,8 @@ class Material extends StatefulWidget {
/// ```dart /// ```dart
/// MaterialInkController inkController = Material.of(context); /// MaterialInkController inkController = Material.of(context);
/// ``` /// ```
///
/// This method can be expensive (it walks the element tree).
static MaterialInkController? of(BuildContext context) { static MaterialInkController? of(BuildContext context) {
return context.findAncestorRenderObjectOfType<_RenderInkFeatures>(); return context.findAncestorRenderObjectOfType<_RenderInkFeatures>();
} }
......
...@@ -1820,6 +1820,8 @@ class Scaffold extends StatefulWidget { ...@@ -1820,6 +1820,8 @@ class Scaffold extends StatefulWidget {
/// If no instance of this class encloses the given context, will cause an /// If no instance of this class encloses the given context, will cause an
/// assert in debug mode, and throw an exception in release mode. /// assert in debug mode, and throw an exception in release mode.
/// ///
/// This method can be expensive (it walks the element tree).
///
/// {@tool dartpad --template=freeform} /// {@tool dartpad --template=freeform}
/// Typical usage of the [Scaffold.of] function is to call it from within the /// Typical usage of the [Scaffold.of] function is to call it from within the
/// `build` method of a child of a [Scaffold]. /// `build` method of a child of a [Scaffold].
...@@ -1999,6 +2001,8 @@ class Scaffold extends StatefulWidget { ...@@ -1999,6 +2001,8 @@ class Scaffold extends StatefulWidget {
/// If no instance of this class encloses the given context, will return null. /// If no instance of this class encloses the given context, will return null.
/// To throw an exception instead, use [of] instead of this function. /// To throw an exception instead, use [of] instead of this function.
/// ///
/// This method can be expensive (it walks the element tree).
///
/// See also: /// See also:
/// ///
/// * [of], a similar function to this one that throws if no instance /// * [of], a similar function to this one that throws if no instance
...@@ -2066,6 +2070,8 @@ class Scaffold extends StatefulWidget { ...@@ -2066,6 +2070,8 @@ class Scaffold extends StatefulWidget {
/// [Scaffold] so that the client widget gets rebuilt whenever the [hasDrawer] /// [Scaffold] so that the client widget gets rebuilt whenever the [hasDrawer]
/// value changes. /// value changes.
/// ///
/// This method can be expensive (it walks the element tree).
///
/// See also: /// See also:
/// ///
/// * [Scaffold.of], which provides access to the [ScaffoldState] object as a /// * [Scaffold.of], which provides access to the [ScaffoldState] object as a
......
...@@ -392,6 +392,8 @@ class AnimatedList extends StatefulWidget { ...@@ -392,6 +392,8 @@ class AnimatedList extends StatefulWidget {
/// If no [AnimatedList] surrounds the context given, then this function will /// If no [AnimatedList] surrounds the context given, then this function will
/// assert in debug mode and throw an exception in release mode. /// assert in debug mode and throw an exception in release mode.
/// ///
/// This method can be expensive (it walks the element tree).
///
/// See also: /// See also:
/// ///
/// * [maybeOf], a similar function that will return null if no /// * [maybeOf], a similar function that will return null if no
...@@ -429,6 +431,8 @@ class AnimatedList extends StatefulWidget { ...@@ -429,6 +431,8 @@ class AnimatedList extends StatefulWidget {
/// If no [AnimatedList] surrounds the context given, then this function will /// If no [AnimatedList] surrounds the context given, then this function will
/// return null. /// return null.
/// ///
/// This method can be expensive (it walks the element tree).
///
/// See also: /// See also:
/// ///
/// * [of], a similar function that will throw if no [AnimatedList] ancestor /// * [of], a similar function that will throw if no [AnimatedList] ancestor
...@@ -808,6 +812,8 @@ class SliverAnimatedList extends StatefulWidget { ...@@ -808,6 +812,8 @@ class SliverAnimatedList extends StatefulWidget {
/// If no [SliverAnimatedList] surrounds the context given, then this function /// If no [SliverAnimatedList] surrounds the context given, then this function
/// will assert in debug mode and throw an exception in release mode. /// will assert in debug mode and throw an exception in release mode.
/// ///
/// This method can be expensive (it walks the element tree).
///
/// See also: /// See also:
/// ///
/// * [maybeOf], a similar function that will return null if no /// * [maybeOf], a similar function that will return null if no
...@@ -843,6 +849,8 @@ class SliverAnimatedList extends StatefulWidget { ...@@ -843,6 +849,8 @@ class SliverAnimatedList extends StatefulWidget {
/// If no [SliverAnimatedList] surrounds the context given, then this function /// If no [SliverAnimatedList] surrounds the context given, then this function
/// will return null. /// will return null.
/// ///
/// This method can be expensive (it walks the element tree).
///
/// See also: /// See also:
/// ///
/// * [of], a similar function that will throw if no [SliverAnimatedList] /// * [of], a similar function that will throw if no [SliverAnimatedList]
......
...@@ -184,6 +184,8 @@ bool debugItemsHaveDuplicateKeys(Iterable<Widget> items) { ...@@ -184,6 +184,8 @@ bool debugItemsHaveDuplicateKeys(Iterable<Widget> items) {
/// assert(debugCheckHasTable(context)); /// assert(debugCheckHasTable(context));
/// ``` /// ```
/// ///
/// This method can be expensive (it walks the element tree).
///
/// Does nothing if asserts are disabled. Always returns true. /// Does nothing if asserts are disabled. Always returns true.
bool debugCheckHasTable(BuildContext context) { bool debugCheckHasTable(BuildContext context) {
assert(() { assert(() {
...@@ -215,7 +217,7 @@ bool debugCheckHasTable(BuildContext context) { ...@@ -215,7 +217,7 @@ bool debugCheckHasTable(BuildContext context) {
/// Does nothing if asserts are disabled. Always returns true. /// Does nothing if asserts are disabled. Always returns true.
bool debugCheckHasMediaQuery(BuildContext context) { bool debugCheckHasMediaQuery(BuildContext context) {
assert(() { assert(() {
if (context.widget is! MediaQuery && context.findAncestorWidgetOfExactType<MediaQuery>() == null) { if (context.widget is! MediaQuery && context.getElementForInheritedWidgetOfExactType<MediaQuery>() == null) {
throw FlutterError.fromParts(<DiagnosticsNode>[ throw FlutterError.fromParts(<DiagnosticsNode>[
ErrorSummary('No MediaQuery widget ancestor found.'), ErrorSummary('No MediaQuery widget ancestor found.'),
ErrorDescription('${context.widget.runtimeType} widgets require a MediaQuery widget ancestor.'), ErrorDescription('${context.widget.runtimeType} widgets require a MediaQuery widget ancestor.'),
...@@ -267,7 +269,7 @@ bool debugCheckHasMediaQuery(BuildContext context) { ...@@ -267,7 +269,7 @@ bool debugCheckHasMediaQuery(BuildContext context) {
/// Does nothing if asserts are disabled. Always returns true. /// Does nothing if asserts are disabled. Always returns true.
bool debugCheckHasDirectionality(BuildContext context, { String? why, String? hint, String? alternative }) { bool debugCheckHasDirectionality(BuildContext context, { String? why, String? hint, String? alternative }) {
assert(() { assert(() {
if (context.widget is! Directionality && context.findAncestorWidgetOfExactType<Directionality>() == null) { if (context.widget is! Directionality && context.getElementForInheritedWidgetOfExactType<Directionality>() == null) {
why = why == null ? '' : ' $why'; why = why == null ? '' : ' $why';
throw FlutterError.fromParts(<DiagnosticsNode>[ throw FlutterError.fromParts(<DiagnosticsNode>[
ErrorSummary('No Directionality widget found.'), ErrorSummary('No Directionality widget found.'),
...@@ -373,6 +375,8 @@ bool debugCheckHasWidgetsLocalizations(BuildContext context) { ...@@ -373,6 +375,8 @@ bool debugCheckHasWidgetsLocalizations(BuildContext context) {
/// assert(debugCheckHasOverlay(context)); /// assert(debugCheckHasOverlay(context));
/// ``` /// ```
/// ///
/// This method can be expensive (it walks the element tree).
///
/// Does nothing if asserts are disabled. Always returns true. /// Does nothing if asserts are disabled. Always returns true.
bool debugCheckHasOverlay(BuildContext context) { bool debugCheckHasOverlay(BuildContext context) {
assert(() { assert(() {
......
...@@ -146,6 +146,9 @@ abstract class InheritedTheme extends InheritedWidget { ...@@ -146,6 +146,9 @@ abstract class InheritedTheme extends InheritedWidget {
/// this method is called again to re-capture the updated themes. /// this method is called again to re-capture the updated themes.
/// ///
/// To wrap a [Widget] in the captured themes, call [CapturedThemes.wrap]. /// To wrap a [Widget] in the captured themes, call [CapturedThemes.wrap].
///
/// This method can be expensive if there are many widgets between `from` and
/// `to` (it walks the element tree between those nodes).
static CapturedThemes capture({ required BuildContext from, required BuildContext? to }) { static CapturedThemes capture({ required BuildContext from, required BuildContext? to }) {
assert(from != null); assert(from != null);
......
...@@ -2712,6 +2712,8 @@ class Navigator extends StatefulWidget { ...@@ -2712,6 +2712,8 @@ class Navigator extends StatefulWidget {
/// ///
/// If there is no [Navigator] in the give `context`, this function will throw /// If there is no [Navigator] in the give `context`, this function will throw
/// a [FlutterError] in debug mode, and an exception in release mode. /// a [FlutterError] in debug mode, and an exception in release mode.
///
/// This method can be expensive (it walks the element tree).
static NavigatorState of( static NavigatorState of(
BuildContext context, { BuildContext context, {
bool rootNavigator = false, bool rootNavigator = false,
...@@ -2760,6 +2762,8 @@ class Navigator extends StatefulWidget { ...@@ -2760,6 +2762,8 @@ class Navigator extends StatefulWidget {
/// subsequent instances of [Navigator]. /// subsequent instances of [Navigator].
/// ///
/// Will return null if there is no ancestor [Navigator] in the `context`. /// Will return null if there is no ancestor [Navigator] in the `context`.
///
/// This method can be expensive (it walks the element tree).
static NavigatorState? maybeOf( static NavigatorState? maybeOf(
BuildContext context, { BuildContext context, {
bool rootNavigator = false, bool rootNavigator = false,
......
...@@ -284,6 +284,8 @@ class Overlay extends StatefulWidget { ...@@ -284,6 +284,8 @@ class Overlay extends StatefulWidget {
/// If `rootOverlay` is set to true, the state from the furthest instance of /// If `rootOverlay` is set to true, the state from the furthest instance of
/// this class is given instead. Useful for installing overlay entries /// this class is given instead. Useful for installing overlay entries
/// above all subsequent instances of [Overlay]. /// above all subsequent instances of [Overlay].
///
/// This method can be expensive (it walks the element tree).
static OverlayState? of( static OverlayState? of(
BuildContext context, { BuildContext context, {
bool rootOverlay = false, bool rootOverlay = false,
......
...@@ -267,6 +267,8 @@ class PageStorage extends StatelessWidget { ...@@ -267,6 +267,8 @@ class PageStorage extends StatelessWidget {
/// ```dart /// ```dart
/// PageStorageBucket bucket = PageStorage.of(context); /// PageStorageBucket bucket = PageStorage.of(context);
/// ``` /// ```
///
/// This method can be expensive (it walks the element tree).
static PageStorageBucket? of(BuildContext context) { static PageStorageBucket? of(BuildContext context) {
final PageStorage? widget = context.findAncestorWidgetOfExactType<PageStorage>(); final PageStorage? widget = context.findAncestorWidgetOfExactType<PageStorage>();
return widget?.bucket; return widget?.bucket;
......
...@@ -233,6 +233,8 @@ class ReorderableList extends StatefulWidget { ...@@ -233,6 +233,8 @@ class ReorderableList extends StatefulWidget {
/// If no [ReorderableList] surrounds the given context, then this function /// If no [ReorderableList] surrounds the given context, then this function
/// will assert in debug mode and throw an exception in release mode. /// will assert in debug mode and throw an exception in release mode.
/// ///
/// This method can be expensive (it walks the element tree).
///
/// See also: /// See also:
/// ///
/// * [maybeOf], a similar function that will return null if no /// * [maybeOf], a similar function that will return null if no
...@@ -270,6 +272,8 @@ class ReorderableList extends StatefulWidget { ...@@ -270,6 +272,8 @@ class ReorderableList extends StatefulWidget {
/// If no [ReorderableList] surrounds the context given, then this function will /// If no [ReorderableList] surrounds the context given, then this function will
/// return null. /// return null.
/// ///
/// This method can be expensive (it walks the element tree).
///
/// See also: /// See also:
/// ///
/// * [of], a similar function that will throw if no [ReorderableList] ancestor /// * [of], a similar function that will throw if no [ReorderableList] ancestor
...@@ -435,6 +439,8 @@ class SliverReorderableList extends StatefulWidget { ...@@ -435,6 +439,8 @@ class SliverReorderableList extends StatefulWidget {
/// If no [SliverReorderableList] surrounds the context given, this function /// If no [SliverReorderableList] surrounds the context given, this function
/// will assert in debug mode and throw an exception in release mode. /// will assert in debug mode and throw an exception in release mode.
/// ///
/// This method can be expensive (it walks the element tree).
///
/// See also: /// See also:
/// ///
/// * [maybeOf], a similar function that will return null if no /// * [maybeOf], a similar function that will return null if no
...@@ -474,6 +480,8 @@ class SliverReorderableList extends StatefulWidget { ...@@ -474,6 +480,8 @@ class SliverReorderableList extends StatefulWidget {
/// If no [SliverReorderableList] surrounds the context given, this function /// If no [SliverReorderableList] surrounds the context given, this function
/// will return null. /// will return null.
/// ///
/// This method can be expensive (it walks the element tree).
///
/// See also: /// See also:
/// ///
/// * [of], a similar function that will throw if no [SliverReorderableList] /// * [of], a similar function that will throw if no [SliverReorderableList]
......
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