[SelectionOverlay]Move the debug statement to the scope of the assertion. (#108508)

This commit is contained in:
xubaolin 2022-08-02 12:37:04 +08:00 committed by GitHub
parent 611514886b
commit c4df6b6d09
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 48 additions and 21 deletions

View file

@ -132,7 +132,7 @@ class _OverlayExampleState extends State<OverlayExample> {
); );
// Add the OverlayEntry to the Overlay. // Add the OverlayEntry to the Overlay.
Overlay.of(context)!.insert(overlayEntry!); Overlay.of(context, debugRequiredFor: widget)!.insert(overlayEntry!);
} }
// Remove the OverlayEntry. // Remove the OverlayEntry.

View file

@ -363,7 +363,7 @@ class _CupertinoContextMenuState extends State<CupertinoContextMenu> with Ticker
); );
}, },
); );
Overlay.of(context, rootOverlay: true)!.insert(_lastOverlayEntry!); Overlay.of(context, rootOverlay: true, debugRequiredFor: widget)!.insert(_lastOverlayEntry!);
_openController.forward(); _openController.forward();
} }

View file

@ -1004,7 +1004,7 @@ class _BottomNavigationBarState extends State<BottomNavigationBar> with TickerPr
assert(debugCheckHasDirectionality(context)); assert(debugCheckHasDirectionality(context));
assert(debugCheckHasMaterialLocalizations(context)); assert(debugCheckHasMaterialLocalizations(context));
assert(debugCheckHasMediaQuery(context)); assert(debugCheckHasMediaQuery(context));
assert(Overlay.of(context, debugRequiredFor: widget) != null); assert(debugCheckHasOverlay(context));
final BottomNavigationBarThemeData bottomTheme = BottomNavigationBarTheme.of(context); final BottomNavigationBarThemeData bottomTheme = BottomNavigationBarTheme.of(context);
final BottomNavigationBarLandscapeLayout layout = widget.landscapeLayout final BottomNavigationBarLandscapeLayout layout = widget.landscapeLayout

View file

@ -655,7 +655,7 @@ class _RangeSliderState extends State<RangeSlider> with TickerProviderStateMixin
); );
}, },
); );
Overlay.of(context)!.insert(overlayEntry!); Overlay.of(context, debugRequiredFor: widget)!.insert(overlayEntry!);
} }
} }
} }

View file

@ -842,7 +842,7 @@ class _SliderState extends State<Slider> with TickerProviderStateMixin {
); );
}, },
); );
Overlay.of(context)!.insert(overlayEntry!); Overlay.of(context, debugRequiredFor: widget)!.insert(overlayEntry!);
} }
} }
} }

View file

@ -698,7 +698,7 @@ class TooltipState extends State<Tooltip> with SingleTickerProviderStateMixin {
if (_tooltipMessage.isEmpty) { if (_tooltipMessage.isEmpty) {
return widget.child ?? const SizedBox(); return widget.child ?? const SizedBox();
} }
assert(Overlay.of(context, debugRequiredFor: widget) != null); assert(debugCheckHasOverlay(context));
final ThemeData theme = Theme.of(context); final ThemeData theme = Theme.of(context);
final TooltipThemeData tooltipTheme = TooltipTheme.of(context); final TooltipThemeData tooltipTheme = TooltipTheme.of(context);
final TextStyle defaultTextStyle; final TextStyle defaultTextStyle;

View file

@ -432,7 +432,7 @@ class _RawAutocompleteState<T extends Object> extends State<RawAutocomplete<T>>
); );
}, },
); );
Overlay.of(context, rootOverlay: true)!.insert(newFloatingOptions); Overlay.of(context, rootOverlay: true, debugRequiredFor: widget)!.insert(newFloatingOptions);
_floatingOptions = newFloatingOptions; _floatingOptions = newFloatingOptions;
} else { } else {
_floatingOptions = null; _floatingOptions = null;

View file

@ -9,6 +9,7 @@ import 'package:flutter/services.dart';
import 'basic.dart'; import 'basic.dart';
import 'binding.dart'; import 'binding.dart';
import 'debug.dart';
import 'framework.dart'; import 'framework.dart';
import 'media_query.dart'; import 'media_query.dart';
import 'overlay.dart'; import 'overlay.dart';
@ -598,7 +599,7 @@ class _DraggableState<T extends Object> extends State<Draggable<T>> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
assert(Overlay.of(context, debugRequiredFor: widget, rootOverlay: widget.rootOverlay) != null); assert(debugCheckHasOverlay(context));
final bool canDrag = widget.maxSimultaneousDrags == null || final bool canDrag = widget.maxSimultaneousDrags == null ||
_activeCount < widget.maxSimultaneousDrags!; _activeCount < widget.maxSimultaneousDrags!;
final bool showChild = _activeCount == 0 || widget.childWhenDragging == null; final bool showChild = _activeCount == 0 || widget.childWhenDragging == null;

View file

@ -702,7 +702,7 @@ class SliverReorderableListState extends State<SliverReorderableList> with Ticke
); );
_dragInfo!.startDrag(); _dragInfo!.startDrag();
final OverlayState overlay = Overlay.of(context)!; final OverlayState overlay = Overlay.of(context, debugRequiredFor: widget)!;
assert(_overlayEntry == null); assert(_overlayEntry == null);
_overlayEntry = OverlayEntry(builder: _dragInfo!.createProxy); _overlayEntry = OverlayEntry(builder: _dragInfo!.createProxy);
overlay.insert(_overlayEntry!); overlay.insert(_overlayEntry!);
@ -897,7 +897,7 @@ class SliverReorderableListState extends State<SliverReorderableList> with Ticke
} }
final Widget child = widget.itemBuilder(context, index); final Widget child = widget.itemBuilder(context, index);
assert(child.key != null, 'All list items must have a key'); assert(child.key != null, 'All list items must have a key');
final OverlayState overlay = Overlay.of(context)!; final OverlayState overlay = Overlay.of(context, debugRequiredFor: widget)!;
return _ReorderableItem( return _ReorderableItem(
key: _ReorderableItemGlobalKey(child.key!, index, this), key: _ReorderableItemGlobalKey(child.key!, index, this),
index: index, index: index,
@ -1284,7 +1284,7 @@ class _DragInfo extends Drag {
} }
Offset _overlayOrigin(BuildContext context) { Offset _overlayOrigin(BuildContext context) {
final OverlayState overlay = Overlay.of(context)!; final OverlayState overlay = Overlay.of(context, debugRequiredFor: context.widget)!;
final RenderBox overlayBox = overlay.context.findRenderObject()! as RenderBox; final RenderBox overlayBox = overlay.context.findRenderObject()! as RenderBox;
return overlayBox.localToGlobal(Offset.zero); return overlayBox.localToGlobal(Offset.zero);
} }

View file

@ -12,6 +12,7 @@ import 'package:flutter/services.dart';
import 'actions.dart'; import 'actions.dart';
import 'basic.dart'; import 'basic.dart';
import 'debug.dart';
import 'focus_manager.dart'; import 'focus_manager.dart';
import 'focus_scope.dart'; import 'focus_scope.dart';
import 'framework.dart'; import 'framework.dart';
@ -804,7 +805,7 @@ class _SelectableRegionState extends State<SelectableRegion> with TextSelectionD
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
assert(Overlay.of(context, debugRequiredFor: widget) != null); assert(debugCheckHasOverlay(context));
return CompositedTransformTarget( return CompositedTransformTarget(
link: _toolbarLayerLink, link: _toolbarLayerLink,
child: RawGestureDetector( child: RawGestureDetector(

View file

@ -16,6 +16,7 @@ import 'basic.dart';
import 'binding.dart'; import 'binding.dart';
import 'constants.dart'; import 'constants.dart';
import 'container.dart'; import 'container.dart';
import 'debug.dart';
import 'editable_text.dart'; import 'editable_text.dart';
import 'framework.dart'; import 'framework.dart';
import 'gesture_detector.dart'; import 'gesture_detector.dart';
@ -616,15 +617,8 @@ class SelectionOverlay {
_endHandleType = endHandleType, _endHandleType = endHandleType,
_lineHeightAtEnd = lineHeightAtEnd, _lineHeightAtEnd = lineHeightAtEnd,
_selectionEndpoints = selectionEndpoints, _selectionEndpoints = selectionEndpoints,
_toolbarLocation = toolbarLocation { _toolbarLocation = toolbarLocation,
final OverlayState? overlay = Overlay.of(context, rootOverlay: true); assert(debugCheckHasOverlay(context));
assert(
overlay != null,
'No Overlay widget exists above $context.\n'
'Usually the Navigator created by WidgetsApp provides the overlay. Perhaps your '
'app content was created above the Navigator with the WidgetsApp builder parameter.',
);
}
/// The context in which the selection handles should appear. /// The context in which the selection handles should appear.
/// ///

View file

@ -176,6 +176,37 @@ void main() {
); );
} }
testWidgets('throw if no Overlay widget exists above', (WidgetTester tester) async {
await tester.pumpWidget(
const Directionality(
textDirection: TextDirection.ltr,
child: MediaQuery(
data: MediaQueryData(size: Size(800.0, 600.0)),
child: Center(
child: Material(
child: SelectableText('I love Flutter!'),
),
),
),
),
);
final Offset textFieldStart = tester.getTopLeft(find.byType(SelectableText));
final TestGesture gesture = await tester.startGesture(textFieldStart, kind: PointerDeviceKind.mouse);
await tester.pump(const Duration(seconds: 2));
await gesture.up();
await tester.pumpAndSettle();
final FlutterError error = tester.takeException() as FlutterError;
expect(
error.message,
contains('EditableText widgets require an Overlay widget ancestor'),
);
await tester.pumpWidget(const SizedBox.shrink());
expect(tester.takeException(), isNotNull); // side effect exception
});
testWidgets('Do not crash when remove SelectableText during handle drag', (WidgetTester tester) async { testWidgets('Do not crash when remove SelectableText during handle drag', (WidgetTester tester) async {
// Regression test https://github.com/flutter/flutter/issues/108242 // Regression test https://github.com/flutter/flutter/issues/108242
bool isShow = true; bool isShow = true;