Unverified Commit a6aaad34 authored by Kostia Sokolovskyi's avatar Kostia Sokolovskyi Committed by GitHub

GestureRecognizer should dispatch creation and disposal events. (#138223)

parent 28ea2f84
...@@ -685,6 +685,7 @@ class _CupertinoContextMenuState extends State<CupertinoContextMenu> with Ticker ...@@ -685,6 +685,7 @@ class _CupertinoContextMenuState extends State<CupertinoContextMenu> with Ticker
@override @override
void dispose() { void dispose() {
_tapGestureRecognizer.dispose();
_openController.dispose(); _openController.dispose();
super.dispose(); super.dispose();
} }
......
...@@ -80,7 +80,17 @@ abstract class GestureRecognizer extends GestureArenaMember with DiagnosticableT ...@@ -80,7 +80,17 @@ abstract class GestureRecognizer extends GestureArenaMember with DiagnosticableT
this.debugOwner, this.debugOwner,
this.supportedDevices, this.supportedDevices,
AllowedButtonsFilter? allowedButtonsFilter, AllowedButtonsFilter? allowedButtonsFilter,
}) : _allowedButtonsFilter = allowedButtonsFilter ?? _defaultButtonAcceptBehavior; }) : _allowedButtonsFilter = allowedButtonsFilter ?? _defaultButtonAcceptBehavior {
// TODO(polina-c): stop duplicating code across disposables
// https://github.com/flutter/flutter/issues/137435
if (kFlutterMemoryAllocationsEnabled) {
MemoryAllocations.instance.dispatchObjectCreated(
library: 'package:flutter/gestures.dart',
className: '$GestureRecognizer',
object: this,
);
}
}
/// The recognizer's owner. /// The recognizer's owner.
/// ///
...@@ -242,7 +252,13 @@ abstract class GestureRecognizer extends GestureArenaMember with DiagnosticableT ...@@ -242,7 +252,13 @@ abstract class GestureRecognizer extends GestureArenaMember with DiagnosticableT
/// recognizer is being unregistered from a [GestureDetector], the /// recognizer is being unregistered from a [GestureDetector], the
/// GestureDetector widget calls this method). /// GestureDetector widget calls this method).
@mustCallSuper @mustCallSuper
void dispose() { } void dispose() {
// TODO(polina-c): stop duplicating code across disposables
// https://github.com/flutter/flutter/issues/137435
if (kFlutterMemoryAllocationsEnabled) {
MemoryAllocations.instance.dispatchObjectDisposed(object: this);
}
}
/// Returns a very short pretty description of the gesture that the /// Returns a very short pretty description of the gesture that the
/// recognizer looks for, like 'tap' or 'horizontal drag'. /// recognizer looks for, like 'tap' or 'horizontal drag'.
......
...@@ -1193,6 +1193,8 @@ class _RenderRangeSlider extends RenderBox with RelayoutWhenSystemFontsChangeMix ...@@ -1193,6 +1193,8 @@ class _RenderRangeSlider extends RenderBox with RelayoutWhenSystemFontsChangeMix
@override @override
void dispose() { void dispose() {
_drag.dispose();
_tap.dispose();
_startLabelPainter.dispose(); _startLabelPainter.dispose();
_endLabelPainter.dispose(); _endLabelPainter.dispose();
super.dispose(); super.dispose();
......
...@@ -1457,6 +1457,8 @@ class _RenderSlider extends RenderBox with RelayoutWhenSystemFontsChangeMixin { ...@@ -1457,6 +1457,8 @@ class _RenderSlider extends RenderBox with RelayoutWhenSystemFontsChangeMixin {
@override @override
void dispose() { void dispose() {
_drag.dispose();
_tap.dispose();
_labelPainter.dispose(); _labelPainter.dispose();
super.dispose(); super.dispose();
} }
......
...@@ -441,6 +441,12 @@ class RenderUiKitView extends RenderDarwinPlatformView<UiKitViewController> { ...@@ -441,6 +441,12 @@ class RenderUiKitView extends RenderDarwinPlatformView<UiKitViewController> {
_gestureRecognizer!.reset(); _gestureRecognizer!.reset();
super.detach(); super.detach();
} }
@override
void dispose() {
_gestureRecognizer?.dispose();
super.dispose();
}
} }
/// A render object for a macOS platform view. /// A render object for a macOS platform view.
...@@ -810,4 +816,10 @@ mixin _PlatformViewGestureMixin on RenderBox implements MouseTrackerAnnotation { ...@@ -810,4 +816,10 @@ mixin _PlatformViewGestureMixin on RenderBox implements MouseTrackerAnnotation {
_gestureRecognizer!.reset(); _gestureRecognizer!.reset();
super.detach(); super.detach();
} }
@override
void dispose() {
_gestureRecognizer?.dispose();
super.dispose();
}
} }
...@@ -671,6 +671,7 @@ class SliverReorderableListState extends State<SliverReorderableList> with Ticke ...@@ -671,6 +671,7 @@ class SliverReorderableListState extends State<SliverReorderableList> with Ticke
@override @override
void dispose() { void dispose() {
_dragReset(); _dragReset();
_recognizer?.dispose();
super.dispose(); super.dispose();
} }
......
...@@ -6,6 +6,7 @@ import 'dart:ui' show VoidCallback; ...@@ -6,6 +6,7 @@ import 'dart:ui' show VoidCallback;
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
import 'gesture_tester.dart'; import 'gesture_tester.dart';
...@@ -49,6 +50,16 @@ void main() { ...@@ -49,6 +50,16 @@ void main() {
expect(recognizer, hasAGoodToStringDeep); expect(recognizer, hasAGoodToStringDeep);
}); });
test('GestureRecognizer dispatches memory events', () async {
await expectLater(
await memoryEvents(
() => TestGestureRecognizer().dispose(),
TestGestureRecognizer
,),
areCreateAndDispose,
);
});
test('OffsetPair', () { test('OffsetPair', () {
const OffsetPair offset1 = OffsetPair( const OffsetPair offset1 = OffsetPair(
local: Offset(10, 20), local: Offset(10, 20),
......
...@@ -1568,6 +1568,7 @@ void main() { ...@@ -1568,6 +1568,7 @@ void main() {
), ),
); );
}, },
buildDefaultDragHandles: false,
itemCount: items.length, itemCount: items.length,
onReorder: handleReorder, onReorder: handleReorder,
), ),
...@@ -1634,6 +1635,7 @@ void main() { ...@@ -1634,6 +1635,7 @@ void main() {
), ),
); );
}, },
buildDefaultDragHandles: false,
itemCount: items.length, itemCount: items.length,
onReorder: handleReorder, onReorder: handleReorder,
onReorderStart: (int index) { onReorderStart: (int index) {
......
...@@ -3650,6 +3650,7 @@ void main() { ...@@ -3650,6 +3650,7 @@ void main() {
double value = 0.0; double value = 0.0;
final ValueNotifier<bool> shouldShowSliderListenable = final ValueNotifier<bool> shouldShowSliderListenable =
ValueNotifier<bool>(true); ValueNotifier<bool>(true);
addTearDown(shouldShowSliderListenable.dispose);
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
......
...@@ -2189,13 +2189,15 @@ void main() { ...@@ -2189,13 +2189,15 @@ void main() {
testWidgetsWithLeakTracking('Tooltip should not ignore users tap on richMessage', (WidgetTester tester) async { testWidgetsWithLeakTracking('Tooltip should not ignore users tap on richMessage', (WidgetTester tester) async {
bool isTapped = false; bool isTapped = false;
final TapGestureRecognizer recognizer = TapGestureRecognizer();
addTearDown(recognizer.dispose);
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
home: Tooltip( home: Tooltip(
richMessage: TextSpan( richMessage: TextSpan(
text: tooltipText, text: tooltipText,
recognizer: TapGestureRecognizer()..onTap = () { recognizer: recognizer..onTap = () {
isTapped = true; isTapped = true;
} }
), ),
......
...@@ -14,12 +14,14 @@ void main() { ...@@ -14,12 +14,14 @@ void main() {
..onTap = () { ..onTap = () {
didTapLeft = true; didTapLeft = true;
}; };
addTearDown(tapLeft.dispose);
bool didTapRight = false; bool didTapRight = false;
final TapGestureRecognizer tapRight = TapGestureRecognizer() final TapGestureRecognizer tapRight = TapGestureRecognizer()
..onTap = () { ..onTap = () {
didTapRight = true; didTapRight = true;
}; };
addTearDown(tapRight.dispose);
const Key textKey = Key('text'); const Key textKey = Key('text');
......
...@@ -638,7 +638,9 @@ void main() { ...@@ -638,7 +638,9 @@ void main() {
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{ gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
Factory<VerticalDragGestureRecognizer>( Factory<VerticalDragGestureRecognizer>(
() { () {
return VerticalDragGestureRecognizer(); final VerticalDragGestureRecognizer recognizer = VerticalDragGestureRecognizer();
addTearDown(recognizer.dispose);
return recognizer;
}, },
), ),
}, },
...@@ -684,7 +686,9 @@ void main() { ...@@ -684,7 +686,9 @@ void main() {
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{ gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
Factory<LongPressGestureRecognizer>( Factory<LongPressGestureRecognizer>(
() { () {
return LongPressGestureRecognizer(); final LongPressGestureRecognizer recognizer = LongPressGestureRecognizer();
addTearDown(recognizer.dispose);
return recognizer;
}, },
), ),
}, },
...@@ -727,7 +731,9 @@ void main() { ...@@ -727,7 +731,9 @@ void main() {
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{ gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
Factory<TapGestureRecognizer>( Factory<TapGestureRecognizer>(
() { () {
return TapGestureRecognizer(); final TapGestureRecognizer recognizer = TapGestureRecognizer();
addTearDown(recognizer.dispose);
return recognizer;
}, },
), ),
}, },
...@@ -853,7 +859,11 @@ void main() { ...@@ -853,7 +859,11 @@ void main() {
viewType: 'webview', viewType: 'webview',
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{ gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
Factory<OneSequenceGestureRecognizer>( Factory<OneSequenceGestureRecognizer>(
() => EagerGestureRecognizer(), () {
final EagerGestureRecognizer recognizer = EagerGestureRecognizer();
addTearDown(recognizer.dispose);
return recognizer;
},
), ),
}, },
layoutDirection: TextDirection.ltr, layoutDirection: TextDirection.ltr,
...@@ -893,7 +903,11 @@ void main() { ...@@ -893,7 +903,11 @@ void main() {
viewType: 'webview', viewType: 'webview',
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{ gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
Factory<EagerGestureRecognizer>( Factory<EagerGestureRecognizer>(
() => EagerGestureRecognizer(), () {
final EagerGestureRecognizer recognizer = EagerGestureRecognizer();
addTearDown(recognizer.dispose);
return recognizer;
},
), ),
}, },
layoutDirection: TextDirection.ltr, layoutDirection: TextDirection.ltr,
...@@ -912,7 +926,9 @@ void main() { ...@@ -912,7 +926,9 @@ void main() {
int factoryInvocationCount = 0; int factoryInvocationCount = 0;
EagerGestureRecognizer constructRecognizer() { EagerGestureRecognizer constructRecognizer() {
factoryInvocationCount += 1; factoryInvocationCount += 1;
return EagerGestureRecognizer(); final EagerGestureRecognizer recognizer = EagerGestureRecognizer();
addTearDown(recognizer.dispose);
return recognizer;
} }
await tester.pumpWidget( await tester.pumpWidget(
...@@ -1728,7 +1744,9 @@ void main() { ...@@ -1728,7 +1744,9 @@ void main() {
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{ gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
Factory<VerticalDragGestureRecognizer>( Factory<VerticalDragGestureRecognizer>(
() { () {
return VerticalDragGestureRecognizer(); final VerticalDragGestureRecognizer recognizer = VerticalDragGestureRecognizer();
addTearDown(recognizer.dispose);
return recognizer;
}, },
), ),
}, },
...@@ -1772,7 +1790,9 @@ void main() { ...@@ -1772,7 +1790,9 @@ void main() {
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{ gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
Factory<LongPressGestureRecognizer>( Factory<LongPressGestureRecognizer>(
() { () {
return LongPressGestureRecognizer(); final LongPressGestureRecognizer recognizer = LongPressGestureRecognizer();
addTearDown(recognizer.dispose);
return recognizer;
}, },
), ),
}, },
...@@ -1814,7 +1834,9 @@ void main() { ...@@ -1814,7 +1834,9 @@ void main() {
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{ gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
Factory<TapGestureRecognizer>( Factory<TapGestureRecognizer>(
() { () {
return TapGestureRecognizer(); final TapGestureRecognizer recognizer = TapGestureRecognizer();
addTearDown(recognizer.dispose);
return recognizer;
}, },
), ),
}, },
...@@ -1937,7 +1959,11 @@ void main() { ...@@ -1937,7 +1959,11 @@ void main() {
viewType: 'webview', viewType: 'webview',
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{ gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
Factory<OneSequenceGestureRecognizer>( Factory<OneSequenceGestureRecognizer>(
() => EagerGestureRecognizer(), () {
final EagerGestureRecognizer recognizer = EagerGestureRecognizer();
addTearDown(recognizer.dispose);
return recognizer;
},
), ),
}, },
layoutDirection: TextDirection.ltr, layoutDirection: TextDirection.ltr,
...@@ -2052,7 +2078,9 @@ void main() { ...@@ -2052,7 +2078,9 @@ void main() {
int factoryInvocationCount = 0; int factoryInvocationCount = 0;
EagerGestureRecognizer constructRecognizer() { EagerGestureRecognizer constructRecognizer() {
factoryInvocationCount += 1; factoryInvocationCount += 1;
return EagerGestureRecognizer(); final EagerGestureRecognizer recognizer = EagerGestureRecognizer();
addTearDown(recognizer.dispose);
return recognizer;
} }
await tester.pumpWidget( await tester.pumpWidget(
...@@ -2653,7 +2681,9 @@ void main() { ...@@ -2653,7 +2681,9 @@ void main() {
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{ gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
Factory<VerticalDragGestureRecognizer>( Factory<VerticalDragGestureRecognizer>(
() { () {
return VerticalDragGestureRecognizer(); final VerticalDragGestureRecognizer recognizer = VerticalDragGestureRecognizer();
addTearDown(recognizer.dispose);
return recognizer;
}, },
), ),
}, },
...@@ -2697,7 +2727,9 @@ void main() { ...@@ -2697,7 +2727,9 @@ void main() {
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{ gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
Factory<LongPressGestureRecognizer>( Factory<LongPressGestureRecognizer>(
() { () {
return LongPressGestureRecognizer(); final LongPressGestureRecognizer recognizer = LongPressGestureRecognizer();
addTearDown(recognizer.dispose);
return recognizer;
}, },
), ),
}, },
...@@ -2739,7 +2771,9 @@ void main() { ...@@ -2739,7 +2771,9 @@ void main() {
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{ gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
Factory<TapGestureRecognizer>( Factory<TapGestureRecognizer>(
() { () {
return TapGestureRecognizer(); final TapGestureRecognizer recognizer = TapGestureRecognizer();
addTearDown(recognizer.dispose);
return recognizer;
}, },
), ),
}, },
...@@ -2862,7 +2896,11 @@ void main() { ...@@ -2862,7 +2896,11 @@ void main() {
viewType: 'webview', viewType: 'webview',
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{ gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
Factory<OneSequenceGestureRecognizer>( Factory<OneSequenceGestureRecognizer>(
() => EagerGestureRecognizer(), () {
final EagerGestureRecognizer recognizer = EagerGestureRecognizer();
addTearDown(recognizer.dispose);
return recognizer;
},
), ),
}, },
layoutDirection: TextDirection.ltr, layoutDirection: TextDirection.ltr,
...@@ -2977,7 +3015,9 @@ void main() { ...@@ -2977,7 +3015,9 @@ void main() {
int factoryInvocationCount = 0; int factoryInvocationCount = 0;
EagerGestureRecognizer constructRecognizer() { EagerGestureRecognizer constructRecognizer() {
factoryInvocationCount += 1; factoryInvocationCount += 1;
return EagerGestureRecognizer(); final EagerGestureRecognizer recognizer = EagerGestureRecognizer();
addTearDown(recognizer.dispose);
return recognizer;
} }
await tester.pumpWidget( await tester.pumpWidget(
...@@ -3241,7 +3281,9 @@ void main() { ...@@ -3241,7 +3281,9 @@ void main() {
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{ gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
Factory<VerticalDragGestureRecognizer>( Factory<VerticalDragGestureRecognizer>(
() { () {
return VerticalDragGestureRecognizer(); final VerticalDragGestureRecognizer recognizer = VerticalDragGestureRecognizer();
addTearDown(recognizer.dispose);
return recognizer;
}, },
), ),
}, },
...@@ -3353,7 +3395,11 @@ void main() { ...@@ -3353,7 +3395,11 @@ void main() {
hitTestBehavior: PlatformViewHitTestBehavior.opaque, hitTestBehavior: PlatformViewHitTestBehavior.opaque,
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{ gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>{
Factory<OneSequenceGestureRecognizer>( Factory<OneSequenceGestureRecognizer>(
() => EagerGestureRecognizer(), () {
final EagerGestureRecognizer recognizer = EagerGestureRecognizer();
addTearDown(recognizer.dispose);
return recognizer;
},
), ),
}, },
), ),
...@@ -3382,7 +3428,9 @@ void main() { ...@@ -3382,7 +3428,9 @@ void main() {
int factoryInvocationCount = 0; int factoryInvocationCount = 0;
EagerGestureRecognizer constructRecognizer() { EagerGestureRecognizer constructRecognizer() {
++factoryInvocationCount; ++factoryInvocationCount;
return EagerGestureRecognizer(); final EagerGestureRecognizer recognizer = EagerGestureRecognizer();
addTearDown(recognizer.dispose);
return recognizer;
} }
final PlatformViewSurface platformViewSurface = PlatformViewSurface( final PlatformViewSurface platformViewSurface = PlatformViewSurface(
...@@ -3406,7 +3454,9 @@ void main() { ...@@ -3406,7 +3454,9 @@ void main() {
int factoryInvocationCount = 0; int factoryInvocationCount = 0;
EagerGestureRecognizer constructRecognizer() { EagerGestureRecognizer constructRecognizer() {
++factoryInvocationCount; ++factoryInvocationCount;
return EagerGestureRecognizer(); final EagerGestureRecognizer recognizer = EagerGestureRecognizer();
addTearDown(recognizer.dispose);
return recognizer;
} }
await tester.pumpWidget( await tester.pumpWidget(
......
...@@ -10,14 +10,21 @@ import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart'; ...@@ -10,14 +10,21 @@ import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
void main() { void main() {
testWidgetsWithLeakTracking('RichText with recognizers without handlers does not throw', (WidgetTester tester) async { testWidgetsWithLeakTracking('RichText with recognizers without handlers does not throw', (WidgetTester tester) async {
final TapGestureRecognizer recognizer1 = TapGestureRecognizer();
addTearDown(recognizer1.dispose);
final LongPressGestureRecognizer recognizer2 = LongPressGestureRecognizer();
addTearDown(recognizer2.dispose);
final DoubleTapGestureRecognizer recognizer3 = DoubleTapGestureRecognizer();
addTearDown(recognizer3.dispose);
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: RichText( child: RichText(
text: TextSpan(text: 'root', children: <InlineSpan>[ text: TextSpan(text: 'root', children: <InlineSpan>[
TextSpan(text: 'one', recognizer: TapGestureRecognizer()), TextSpan(text: 'one', recognizer: recognizer1),
TextSpan(text: 'two', recognizer: LongPressGestureRecognizer()), TextSpan(text: 'two', recognizer: recognizer2),
TextSpan(text: 'three', recognizer: DoubleTapGestureRecognizer()), TextSpan(text: 'three', recognizer: recognizer3),
]), ]),
), ),
), ),
...@@ -42,6 +49,11 @@ void main() { ...@@ -42,6 +49,11 @@ void main() {
}); });
testWidgetsWithLeakTracking('TextSpan Locale works', (WidgetTester tester) async { testWidgetsWithLeakTracking('TextSpan Locale works', (WidgetTester tester) async {
final TapGestureRecognizer recognizer1 = TapGestureRecognizer();
addTearDown(recognizer1.dispose);
final DoubleTapGestureRecognizer recognizer2 = DoubleTapGestureRecognizer();
addTearDown(recognizer2.dispose);
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -50,11 +62,11 @@ void main() { ...@@ -50,11 +62,11 @@ void main() {
text: 'root', text: 'root',
locale: const Locale('es', 'MX'), locale: const Locale('es', 'MX'),
children: <InlineSpan>[ children: <InlineSpan>[
TextSpan(text: 'one', recognizer: TapGestureRecognizer()), TextSpan(text: 'one', recognizer: recognizer1),
const WidgetSpan( const WidgetSpan(
child: SizedBox(), child: SizedBox(),
), ),
TextSpan(text: 'three', recognizer: DoubleTapGestureRecognizer()), TextSpan(text: 'three', recognizer: recognizer2),
] ]
), ),
), ),
...@@ -91,6 +103,11 @@ void main() { ...@@ -91,6 +103,11 @@ void main() {
}); });
testWidgetsWithLeakTracking('TextSpan spellOut works', (WidgetTester tester) async { testWidgetsWithLeakTracking('TextSpan spellOut works', (WidgetTester tester) async {
final TapGestureRecognizer recognizer1 = TapGestureRecognizer();
addTearDown(recognizer1.dispose);
final DoubleTapGestureRecognizer recognizer2 = DoubleTapGestureRecognizer();
addTearDown(recognizer2.dispose);
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -99,11 +116,11 @@ void main() { ...@@ -99,11 +116,11 @@ void main() {
text: 'root', text: 'root',
spellOut: true, spellOut: true,
children: <InlineSpan>[ children: <InlineSpan>[
TextSpan(text: 'one', recognizer: TapGestureRecognizer()), TextSpan(text: 'one', recognizer: recognizer1),
const WidgetSpan( const WidgetSpan(
child: SizedBox(), child: SizedBox(),
), ),
TextSpan(text: 'three', recognizer: DoubleTapGestureRecognizer()), TextSpan(text: 'three', recognizer: recognizer2),
] ]
), ),
), ),
......
...@@ -1573,6 +1573,9 @@ void main() { ...@@ -1573,6 +1573,9 @@ void main() {
testWidgetsWithLeakTracking('Selectable rich text with gesture recognizer has correct semantics', (WidgetTester tester) async { testWidgetsWithLeakTracking('Selectable rich text with gesture recognizer has correct semantics', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
final TapGestureRecognizer recognizer = TapGestureRecognizer();
addTearDown(recognizer.dispose);
await tester.pumpWidget( await tester.pumpWidget(
overlay( overlay(
child: SelectableText.rich( child: SelectableText.rich(
...@@ -1581,8 +1584,7 @@ void main() { ...@@ -1581,8 +1584,7 @@ void main() {
const TextSpan(text: 'text'), const TextSpan(text: 'text'),
TextSpan( TextSpan(
text: 'link', text: 'link',
recognizer: TapGestureRecognizer() recognizer: recognizer..onTap = () { },
..onTap = () { },
), ),
], ],
), ),
...@@ -2467,6 +2469,8 @@ void main() { ...@@ -2467,6 +2469,8 @@ void main() {
const String offScreenText = 'off screen'; const String offScreenText = 'off screen';
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
addTearDown(controller.dispose); addTearDown(controller.dispose);
final TapGestureRecognizer recognizer = TapGestureRecognizer();
addTearDown(recognizer.dispose);
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
...@@ -2478,7 +2482,7 @@ void main() { ...@@ -2478,7 +2482,7 @@ void main() {
const TextSpan(text: onScreenText), const TextSpan(text: onScreenText),
TextSpan( TextSpan(
text: offScreenText, text: offScreenText,
recognizer: TapGestureRecognizer()..onTap = () { }, recognizer: recognizer..onTap = () { },
), ),
], ],
style: textStyle, style: textStyle,
...@@ -4640,6 +4644,8 @@ void main() { ...@@ -4640,6 +4644,8 @@ void main() {
..onTap = () { ..onTap = () {
spyTaps += 1; spyTaps += 1;
}; };
addTearDown(spyRecognizer.dispose);
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
home: Material( home: Material(
...@@ -4690,6 +4696,8 @@ void main() { ...@@ -4690,6 +4696,8 @@ void main() {
..onLongPress = () { ..onLongPress = () {
spyLongPress += 1; spyLongPress += 1;
}; };
addTearDown(spyRecognizer.dispose);
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
home: Material( home: Material(
......
...@@ -13,12 +13,15 @@ void main() { ...@@ -13,12 +13,15 @@ void main() {
testWidgetsWithLeakTracking('Semantics tester visits last child', (WidgetTester tester) async { testWidgetsWithLeakTracking('Semantics tester visits last child', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
const TextStyle textStyle = TextStyle(); const TextStyle textStyle = TextStyle();
final TapGestureRecognizer recognizer = TapGestureRecognizer();
addTearDown(recognizer.dispose);
await tester.pumpWidget( await tester.pumpWidget(
Text.rich( Text.rich(
TextSpan( TextSpan(
children: <TextSpan>[ children: <TextSpan>[
const TextSpan(text: 'hello'), const TextSpan(text: 'hello'),
TextSpan(text: 'world', recognizer: TapGestureRecognizer()..onTap = () { }), TextSpan(text: 'world', recognizer: recognizer..onTap = () { }),
], ],
style: textStyle, style: textStyle,
), ),
......
...@@ -14,20 +14,27 @@ void main() { ...@@ -14,20 +14,27 @@ void main() {
testWidgetsWithLeakTracking('SemanticsNode ids are stable', (WidgetTester tester) async { testWidgetsWithLeakTracking('SemanticsNode ids are stable', (WidgetTester tester) async {
// Regression test for b/151732341. // Regression test for b/151732341.
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
final TapGestureRecognizer recognizer1 = TapGestureRecognizer();
addTearDown(recognizer1.dispose);
final TapGestureRecognizer recognizer2 = TapGestureRecognizer();
addTearDown(recognizer2.dispose);
final TapGestureRecognizer recognizer3 = TapGestureRecognizer();
addTearDown(recognizer3.dispose);
await tester.pumpWidget(Directionality( await tester.pumpWidget(Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: Text.rich( child: Text.rich(
TextSpan( TextSpan(
text: 'Hallo ', text: 'Hallo ',
recognizer: TapGestureRecognizer()..onTap = () {}, recognizer: recognizer1..onTap = () {},
children: <TextSpan>[ children: <TextSpan>[
TextSpan( TextSpan(
text: 'Welt ', text: 'Welt ',
recognizer: TapGestureRecognizer()..onTap = () {}, recognizer: recognizer2..onTap = () {},
), ),
TextSpan( TextSpan(
text: '!!!', text: '!!!',
recognizer: TapGestureRecognizer()..onTap = () {}, recognizer: recognizer3..onTap = () {},
), ),
], ],
), ),
...@@ -64,17 +71,22 @@ void main() { ...@@ -64,17 +71,22 @@ void main() {
expect(labelToNodeIdAfterRebuild['!!!'], labelToNodeId['!!!']); expect(labelToNodeIdAfterRebuild['!!!'], labelToNodeId['!!!']);
expect(labelToNodeIdAfterRebuild.length, 3); expect(labelToNodeIdAfterRebuild.length, 3);
final TapGestureRecognizer recognizer4 = TapGestureRecognizer();
addTearDown(recognizer4.dispose);
final TapGestureRecognizer recognizer5 = TapGestureRecognizer();
addTearDown(recognizer5.dispose);
// Remove one node. // Remove one node.
await tester.pumpWidget(Directionality( await tester.pumpWidget(Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: Text.rich( child: Text.rich(
TextSpan( TextSpan(
text: 'Hallo ', text: 'Hallo ',
recognizer: TapGestureRecognizer()..onTap = () {}, recognizer: recognizer4..onTap = () {},
children: <TextSpan>[ children: <TextSpan>[
TextSpan( TextSpan(
text: 'Welt ', text: 'Welt ',
recognizer: TapGestureRecognizer()..onTap = () {}, recognizer: recognizer5..onTap = () {},
), ),
], ],
), ),
...@@ -94,20 +106,27 @@ void main() { ...@@ -94,20 +106,27 @@ void main() {
expect(labelToNodeIdAfterRemoval['Welt '], labelToNodeId['Welt ']); expect(labelToNodeIdAfterRemoval['Welt '], labelToNodeId['Welt ']);
expect(labelToNodeIdAfterRemoval.length, 2); expect(labelToNodeIdAfterRemoval.length, 2);
final TapGestureRecognizer recognizer6 = TapGestureRecognizer();
addTearDown(recognizer6.dispose);
final TapGestureRecognizer recognizer7 = TapGestureRecognizer();
addTearDown(recognizer7.dispose);
final TapGestureRecognizer recognizer8 = TapGestureRecognizer();
addTearDown(recognizer8.dispose);
await tester.pumpWidget(Directionality( await tester.pumpWidget(Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: Text.rich( child: Text.rich(
TextSpan( TextSpan(
text: 'Hallo ', text: 'Hallo ',
recognizer: TapGestureRecognizer()..onTap = () {}, recognizer: recognizer6..onTap = () {},
children: <TextSpan>[ children: <TextSpan>[
TextSpan( TextSpan(
text: 'Welt ', text: 'Welt ',
recognizer: TapGestureRecognizer()..onTap = () {}, recognizer: recognizer7..onTap = () {},
), ),
TextSpan( TextSpan(
text: '!!!', text: '!!!',
recognizer: TapGestureRecognizer()..onTap = () {}, recognizer: recognizer8..onTap = () {},
), ),
], ],
), ),
......
...@@ -485,6 +485,9 @@ void main() { ...@@ -485,6 +485,9 @@ void main() {
testWidgetsWithLeakTracking('semanticsLabel can be shorter than text', (WidgetTester tester) async { testWidgetsWithLeakTracking('semanticsLabel can be shorter than text', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
final TapGestureRecognizer recognizer = TapGestureRecognizer();
addTearDown(recognizer.dispose);
await tester.pumpWidget(Directionality( await tester.pumpWidget(Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: RichText( child: RichText(
...@@ -496,7 +499,7 @@ void main() { ...@@ -496,7 +499,7 @@ void main() {
), ),
TextSpan( TextSpan(
text: 'Clickable', text: 'Clickable',
recognizer: TapGestureRecognizer()..onTap = () { }, recognizer: recognizer..onTap = () { },
), ),
], ],
), ),
...@@ -534,6 +537,9 @@ void main() { ...@@ -534,6 +537,9 @@ void main() {
testWidgetsWithLeakTracking('recognizers split semantic node', (WidgetTester tester) async { testWidgetsWithLeakTracking('recognizers split semantic node', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
const TextStyle textStyle = TextStyle(); const TextStyle textStyle = TextStyle();
final TapGestureRecognizer recognizer = TapGestureRecognizer();
addTearDown(recognizer.dispose);
await tester.pumpWidget( await tester.pumpWidget(
Text.rich( Text.rich(
TextSpan( TextSpan(
...@@ -541,7 +547,7 @@ void main() { ...@@ -541,7 +547,7 @@ void main() {
const TextSpan(text: 'hello '), const TextSpan(text: 'hello '),
TextSpan( TextSpan(
text: 'world', text: 'world',
recognizer: TapGestureRecognizer()..onTap = () { }, recognizer: recognizer..onTap = () { },
), ),
const TextSpan(text: ' this is a '), const TextSpan(text: ' this is a '),
const TextSpan(text: 'cat-astrophe'), const TextSpan(text: 'cat-astrophe'),
...@@ -593,6 +599,9 @@ void main() { ...@@ -593,6 +599,9 @@ void main() {
const String offScreenText = 'off screen'; const String offScreenText = 'off screen';
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
addTearDown(controller.dispose); addTearDown(controller.dispose);
final TapGestureRecognizer recognizer = TapGestureRecognizer();
addTearDown(recognizer.dispose);
await tester.pumpWidget( await tester.pumpWidget(
SingleChildScrollView( SingleChildScrollView(
controller: controller, controller: controller,
...@@ -602,7 +611,7 @@ void main() { ...@@ -602,7 +611,7 @@ void main() {
const TextSpan(text: onScreenText), const TextSpan(text: onScreenText),
TextSpan( TextSpan(
text: offScreenText, text: offScreenText,
recognizer: TapGestureRecognizer()..onTap = () { }, recognizer: recognizer..onTap = () { },
), ),
], ],
style: textStyle, style: textStyle,
...@@ -658,6 +667,9 @@ void main() { ...@@ -658,6 +667,9 @@ void main() {
testWidgetsWithLeakTracking('recognizers split semantic node when TextSpan overflows', (WidgetTester tester) async { testWidgetsWithLeakTracking('recognizers split semantic node when TextSpan overflows', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
const TextStyle textStyle = TextStyle(); const TextStyle textStyle = TextStyle();
final TapGestureRecognizer recognizer = TapGestureRecognizer();
addTearDown(recognizer.dispose);
await tester.pumpWidget( await tester.pumpWidget(
SizedBox( SizedBox(
height: 10, height: 10,
...@@ -667,7 +679,7 @@ void main() { ...@@ -667,7 +679,7 @@ void main() {
const TextSpan(text: '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n'), const TextSpan(text: '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n'),
TextSpan( TextSpan(
text: 'world', text: 'world',
recognizer: TapGestureRecognizer()..onTap = () { }, recognizer: recognizer..onTap = () { },
), ),
], ],
style: textStyle, style: textStyle,
...@@ -709,6 +721,9 @@ void main() { ...@@ -709,6 +721,9 @@ void main() {
testWidgetsWithLeakTracking('recognizers split semantic nodes with text span labels', (WidgetTester tester) async { testWidgetsWithLeakTracking('recognizers split semantic nodes with text span labels', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
const TextStyle textStyle = TextStyle(); const TextStyle textStyle = TextStyle();
final TapGestureRecognizer recognizer = TapGestureRecognizer();
addTearDown(recognizer.dispose);
await tester.pumpWidget( await tester.pumpWidget(
Text.rich( Text.rich(
TextSpan( TextSpan(
...@@ -716,7 +731,7 @@ void main() { ...@@ -716,7 +731,7 @@ void main() {
const TextSpan(text: 'hello '), const TextSpan(text: 'hello '),
TextSpan( TextSpan(
text: 'world', text: 'world',
recognizer: TapGestureRecognizer()..onTap = () { }, recognizer: recognizer..onTap = () { },
), ),
const TextSpan(text: ' this is a '), const TextSpan(text: ' this is a '),
const TextSpan( const TextSpan(
...@@ -767,6 +782,11 @@ void main() { ...@@ -767,6 +782,11 @@ void main() {
testWidgetsWithLeakTracking('recognizers split semantic node - bidi', (WidgetTester tester) async { testWidgetsWithLeakTracking('recognizers split semantic node - bidi', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
const TextStyle textStyle = TextStyle(); const TextStyle textStyle = TextStyle();
final LongPressGestureRecognizer recognizer1 = LongPressGestureRecognizer();
addTearDown(recognizer1.dispose);
final TapGestureRecognizer recognizer2 = TapGestureRecognizer();
addTearDown(recognizer2.dispose);
await tester.pumpWidget( await tester.pumpWidget(
RichText( RichText(
text: TextSpan( text: TextSpan(
...@@ -775,12 +795,12 @@ void main() { ...@@ -775,12 +795,12 @@ void main() {
const TextSpan(text: 'hello world${Unicode.RLE}${Unicode.RLO} '), const TextSpan(text: 'hello world${Unicode.RLE}${Unicode.RLO} '),
TextSpan( TextSpan(
text: 'BOY', text: 'BOY',
recognizer: LongPressGestureRecognizer()..onLongPress = () { }, recognizer: recognizer1..onLongPress = () { },
), ),
const TextSpan(text: ' HOW DO${Unicode.PDF} you ${Unicode.RLO} DO '), const TextSpan(text: ' HOW DO${Unicode.PDF} you ${Unicode.RLO} DO '),
TextSpan( TextSpan(
text: 'SIR', text: 'SIR',
recognizer: TapGestureRecognizer()..onTap = () { }, recognizer: recognizer2..onTap = () { },
), ),
const TextSpan(text: '${Unicode.PDF}${Unicode.PDF} good bye'), const TextSpan(text: '${Unicode.PDF}${Unicode.PDF} good bye'),
], ],
...@@ -848,13 +868,16 @@ void main() { ...@@ -848,13 +868,16 @@ void main() {
testWidgetsWithLeakTracking('TapGesture recognizers contribute link semantics', (WidgetTester tester) async { testWidgetsWithLeakTracking('TapGesture recognizers contribute link semantics', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
const TextStyle textStyle = TextStyle(); const TextStyle textStyle = TextStyle();
final TapGestureRecognizer recognizer = TapGestureRecognizer();
addTearDown(recognizer.dispose);
await tester.pumpWidget( await tester.pumpWidget(
Text.rich( Text.rich(
TextSpan( TextSpan(
children: <TextSpan>[ children: <TextSpan>[
TextSpan( TextSpan(
text: 'click me', text: 'click me',
recognizer: TapGestureRecognizer()..onTap = () { }, recognizer: recognizer..onTap = () { },
), ),
], ],
style: textStyle, style: textStyle,
...@@ -888,6 +911,9 @@ void main() { ...@@ -888,6 +911,9 @@ void main() {
testWidgetsWithLeakTracking('inline widgets generate semantic nodes', (WidgetTester tester) async { testWidgetsWithLeakTracking('inline widgets generate semantic nodes', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
const TextStyle textStyle = TextStyle(); const TextStyle textStyle = TextStyle();
final TapGestureRecognizer recognizer = TapGestureRecognizer();
addTearDown(recognizer.dispose);
await tester.pumpWidget( await tester.pumpWidget(
Text.rich( Text.rich(
TextSpan( TextSpan(
...@@ -895,7 +921,7 @@ void main() { ...@@ -895,7 +921,7 @@ void main() {
const TextSpan(text: 'a '), const TextSpan(text: 'a '),
TextSpan( TextSpan(
text: 'pebble', text: 'pebble',
recognizer: TapGestureRecognizer()..onTap = () { }, recognizer: recognizer..onTap = () { },
), ),
const TextSpan(text: ' in the '), const TextSpan(text: ' in the '),
WidgetSpan( WidgetSpan(
...@@ -962,6 +988,9 @@ void main() { ...@@ -962,6 +988,9 @@ void main() {
testWidgetsWithLeakTracking('inline widgets semantic nodes scale', (WidgetTester tester) async { testWidgetsWithLeakTracking('inline widgets semantic nodes scale', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
const TextStyle textStyle = TextStyle(); const TextStyle textStyle = TextStyle();
final TapGestureRecognizer recognizer = TapGestureRecognizer();
addTearDown(recognizer.dispose);
await tester.pumpWidget( await tester.pumpWidget(
Text.rich( Text.rich(
TextSpan( TextSpan(
...@@ -969,7 +998,7 @@ void main() { ...@@ -969,7 +998,7 @@ void main() {
const TextSpan(text: 'a '), const TextSpan(text: 'a '),
TextSpan( TextSpan(
text: 'pebble', text: 'pebble',
recognizer: TapGestureRecognizer()..onTap = () { }, recognizer: recognizer..onTap = () { },
), ),
const TextSpan(text: ' in the '), const TextSpan(text: ' in the '),
WidgetSpan( WidgetSpan(
...@@ -1287,6 +1316,8 @@ void main() { ...@@ -1287,6 +1316,8 @@ void main() {
// Regression test for https://github.com/flutter/flutter/issues/65818 // Regression test for https://github.com/flutter/flutter/issues/65818
testWidgetsWithLeakTracking('WidgetSpans with no semantic information are elided from semantics', (WidgetTester tester) async { testWidgetsWithLeakTracking('WidgetSpans with no semantic information are elided from semantics', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
final TapGestureRecognizer recognizer = TapGestureRecognizer();
addTearDown(recognizer.dispose);
// Without the fix for this bug the pump widget will throw a RangeError. // Without the fix for this bug the pump widget will throw a RangeError.
await tester.pumpWidget( await tester.pumpWidget(
RichText( RichText(
...@@ -1296,7 +1327,7 @@ void main() { ...@@ -1296,7 +1327,7 @@ void main() {
TextSpan( TextSpan(
text: 'HELLO', text: 'HELLO',
style: const TextStyle(color: Colors.black), style: const TextStyle(color: Colors.black),
recognizer: TapGestureRecognizer()..onTap = () {}, recognizer: recognizer..onTap = () {},
), ),
]), ]),
), ),
...@@ -1335,6 +1366,9 @@ void main() { ...@@ -1335,6 +1366,9 @@ void main() {
// Regression test for https://github.com/flutter/flutter/issues/69787 // Regression test for https://github.com/flutter/flutter/issues/69787
testWidgetsWithLeakTracking('WidgetSpans with no semantic information are elided from semantics - case 2', (WidgetTester tester) async { testWidgetsWithLeakTracking('WidgetSpans with no semantic information are elided from semantics - case 2', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
final TapGestureRecognizer recognizer = TapGestureRecognizer();
addTearDown(recognizer.dispose);
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -1345,7 +1379,7 @@ void main() { ...@@ -1345,7 +1379,7 @@ void main() {
TextSpan( TextSpan(
text: 'HELLO', text: 'HELLO',
style: const TextStyle(color: Colors.black), style: const TextStyle(color: Colors.black),
recognizer: TapGestureRecognizer()..onTap = () {}, recognizer: recognizer..onTap = () {},
), ),
const WidgetSpan(child: Text('included2')), const WidgetSpan(child: Text('included2')),
]), ]),
...@@ -1386,6 +1420,9 @@ void main() { ...@@ -1386,6 +1420,9 @@ void main() {
// Regression test for https://github.com/flutter/flutter/issues/69787 // Regression test for https://github.com/flutter/flutter/issues/69787
testWidgetsWithLeakTracking('WidgetSpans with no semantic information are elided from semantics - case 3', (WidgetTester tester) async { testWidgetsWithLeakTracking('WidgetSpans with no semantic information are elided from semantics - case 3', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
final TapGestureRecognizer recognizer = TapGestureRecognizer();
addTearDown(recognizer.dispose);
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -1409,7 +1446,7 @@ void main() { ...@@ -1409,7 +1446,7 @@ void main() {
TextSpan( TextSpan(
text: 'HELLO', text: 'HELLO',
style: const TextStyle(color: Colors.black), style: const TextStyle(color: Colors.black),
recognizer: TapGestureRecognizer()..onTap = () {}, recognizer: recognizer..onTap = () {},
), ),
]), ]),
), ),
...@@ -1449,6 +1486,9 @@ void main() { ...@@ -1449,6 +1486,9 @@ void main() {
// Regression test for https://github.com/flutter/flutter/issues/69787 // Regression test for https://github.com/flutter/flutter/issues/69787
testWidgetsWithLeakTracking('WidgetSpans with no semantic information are elided from semantics - case 4', (WidgetTester tester) async { testWidgetsWithLeakTracking('WidgetSpans with no semantic information are elided from semantics - case 4', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester); final SemanticsTester semantics = SemanticsTester(tester);
final TapGestureRecognizer recognizer = TapGestureRecognizer();
addTearDown(recognizer.dispose);
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
...@@ -1473,7 +1513,7 @@ void main() { ...@@ -1473,7 +1513,7 @@ void main() {
), ),
TextSpan( TextSpan(
text: 'next WS is clipped', text: 'next WS is clipped',
recognizer: TapGestureRecognizer()..onTap = () { }, recognizer: recognizer..onTap = () { },
), ),
const WidgetSpan( const WidgetSpan(
child: Icon( child: Icon(
......
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