Unverified Commit 5cfb16b1 authored by Christopher Fujino's avatar Christopher Fujino Committed by GitHub

Re-land "Deprecate WhitelistingTextInputFormatter and...

Re-land "Deprecate WhitelistingTextInputFormatter and BlacklistingTextInputFormatter (#59120)" (#59876)

This relands #59120, which was reverted in #59870.
parent 0d7ff7a9
...@@ -29,6 +29,9 @@ analyzer: ...@@ -29,6 +29,9 @@ analyzer:
missing_return: warning missing_return: warning
# allow having TODOs in the code # allow having TODOs in the code
todo: ignore todo: ignore
# allow self-reference to deprecated members (we do this because otherwise we have
# to annotate every member in every test, assert, etc, when we deprecate something)
deprecated_member_use_from_same_package: ignore
# Ignore analyzer hints for updating pubspecs when using Future or # Ignore analyzer hints for updating pubspecs when using Future or
# Stream and not importing dart:async # Stream and not importing dart:async
# Please see https://github.com/flutter/flutter/pull/24528 for details. # Please see https://github.com/flutter/flutter/pull/24528 for details.
......
...@@ -135,7 +135,7 @@ Future<void> run(List<String> arguments) async { ...@@ -135,7 +135,7 @@ Future<void> run(List<String> arguments) async {
final RegExp _findDeprecationPattern = RegExp(r'@[Dd]eprecated'); final RegExp _findDeprecationPattern = RegExp(r'@[Dd]eprecated');
final RegExp _deprecationPattern1 = RegExp(r'^( *)@Deprecated\($'); // ignore: flutter_deprecation_syntax (see analyze.dart) final RegExp _deprecationPattern1 = RegExp(r'^( *)@Deprecated\($'); // ignore: flutter_deprecation_syntax (see analyze.dart)
final RegExp _deprecationPattern2 = RegExp(r"^ *'(.+) '$"); final RegExp _deprecationPattern2 = RegExp(r"^ *'(.+) '$");
final RegExp _deprecationPattern3 = RegExp(r"^ *'This feature was deprecated after v([0-9]+)\.([0-9]+)\.([0-9]+)\.'$"); final RegExp _deprecationPattern3 = RegExp(r"^ *'This feature was deprecated after v([0-9]+)\.([0-9]+)\.([0-9]+)(\-[0-9]+\.[0-9]+\.pre)?\.'$");
final RegExp _deprecationPattern4 = RegExp(r'^ *\)$'); final RegExp _deprecationPattern4 = RegExp(r'^ *\)$');
/// Some deprecation notices are special, for example they're used to annotate members that /// Some deprecation notices are special, for example they're used to annotate members that
...@@ -182,7 +182,7 @@ Future<void> verifyDeprecations(String workingDirectory, { int minimumMatches = ...@@ -182,7 +182,7 @@ Future<void> verifyDeprecations(String workingDirectory, { int minimumMatches =
if (message == null) { if (message == null) {
final String firstChar = String.fromCharCode(match2[1].runes.first); final String firstChar = String.fromCharCode(match2[1].runes.first);
if (firstChar.toUpperCase() != firstChar) if (firstChar.toUpperCase() != firstChar)
throw 'Deprecation notice should be a grammatically correct sentence and start with a capital letter; see style guide.'; throw 'Deprecation notice should be a grammatically correct sentence and start with a capital letter; see style guide: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo';
} }
message = match2[1]; message = match2[1];
lineNumber += 1; lineNumber += 1;
...@@ -190,6 +190,13 @@ Future<void> verifyDeprecations(String workingDirectory, { int minimumMatches = ...@@ -190,6 +190,13 @@ Future<void> verifyDeprecations(String workingDirectory, { int minimumMatches =
throw 'Incomplete deprecation notice.'; throw 'Incomplete deprecation notice.';
match3 = _deprecationPattern3.firstMatch(lines[lineNumber]); match3 = _deprecationPattern3.firstMatch(lines[lineNumber]);
} while (match3 == null); } while (match3 == null);
final int v1 = int.parse(match3[1]);
final int v2 = int.parse(match3[2]);
final bool hasV4 = match3[4] != null;
if (v1 > 1 || (v1 == 1 && v2 >= 20)) {
if (!hasV4)
throw 'Deprecation notice does not accurately indicate a dev branch version number; please see https://flutter.dev/docs/development/tools/sdk/releases to find the latest dev build version number.';
}
if (!message.endsWith('.') && !message.endsWith('!') && !message.endsWith('?')) if (!message.endsWith('.') && !message.endsWith('!') && !message.endsWith('?'))
throw 'Deprecation notice should be a grammatically correct sentence and end with a period.'; throw 'Deprecation notice should be a grammatically correct sentence and end with a period.';
if (!lines[lineNumber].startsWith("$indent '")) if (!lines[lineNumber].startsWith("$indent '"))
......
...@@ -55,6 +55,42 @@ void test10() { } ...@@ -55,6 +55,42 @@ void test10() { }
@Deprecated( @Deprecated(
'URLs are not required. ' 'URLs are not required. '
'This feature was deprecated after v2.0.0.' 'This feature was deprecated after v1.0.0.'
) )
void test11() { } void test11() { }
@Deprecated(
'Version number test (should fail). '
'This feature was deprecated after v1.19.0.'
)
void test12() { }
@Deprecated(
'Version number test (should fail). '
'This feature was deprecated after v1.20.0.'
)
void test13() { }
@Deprecated(
'Version number test (should fail). '
'This feature was deprecated after v1.21.0.'
)
void test14() { }
@Deprecated(
'Version number test (should fail). '
'This feature was deprecated after v3.1.0.'
)
void test15() { }
@Deprecated(
'Version number test (should be fine). '
'This feature was deprecated after v0.1.0.'
)
void test16() { }
@Deprecated(
'Version number test (should be fine). '
'This feature was deprecated after v1.20.0-1.0.pre.'
)
void test17() { }
...@@ -41,7 +41,7 @@ void main() { ...@@ -41,7 +41,7 @@ void main() {
+ +
( (
'test/analyze-test-input/root/packages/foo/deprecation.dart:12: Deprecation notice does not match required pattern.\n' 'test/analyze-test-input/root/packages/foo/deprecation.dart:12: Deprecation notice does not match required pattern.\n'
'test/analyze-test-input/root/packages/foo/deprecation.dart:18: Deprecation notice should be a grammatically correct sentence and start with a capital letter; see style guide.\n' 'test/analyze-test-input/root/packages/foo/deprecation.dart:18: Deprecation notice should be a grammatically correct sentence and start with a capital letter; see style guide: STYLE_GUIDE_URL\n'
'test/analyze-test-input/root/packages/foo/deprecation.dart:25: Deprecation notice should be a grammatically correct sentence and end with a period.\n' 'test/analyze-test-input/root/packages/foo/deprecation.dart:25: Deprecation notice should be a grammatically correct sentence and end with a period.\n'
'test/analyze-test-input/root/packages/foo/deprecation.dart:29: Deprecation notice does not match required pattern.\n' 'test/analyze-test-input/root/packages/foo/deprecation.dart:29: Deprecation notice does not match required pattern.\n'
'test/analyze-test-input/root/packages/foo/deprecation.dart:32: Deprecation notice does not match required pattern.\n' 'test/analyze-test-input/root/packages/foo/deprecation.dart:32: Deprecation notice does not match required pattern.\n'
...@@ -49,7 +49,12 @@ void main() { ...@@ -49,7 +49,12 @@ void main() {
'test/analyze-test-input/root/packages/foo/deprecation.dart:41: Deprecation notice does not match required pattern.\n' 'test/analyze-test-input/root/packages/foo/deprecation.dart:41: Deprecation notice does not match required pattern.\n'
'test/analyze-test-input/root/packages/foo/deprecation.dart:48: End of deprecation notice does not match required pattern.\n' 'test/analyze-test-input/root/packages/foo/deprecation.dart:48: End of deprecation notice does not match required pattern.\n'
'test/analyze-test-input/root/packages/foo/deprecation.dart:51: Unexpected deprecation notice indent.\n' 'test/analyze-test-input/root/packages/foo/deprecation.dart:51: Unexpected deprecation notice indent.\n'
'test/analyze-test-input/root/packages/foo/deprecation.dart:70: Deprecation notice does not accurately indicate a dev branch version number; please see RELEASES_URL to find the latest dev build version number.\n'
'test/analyze-test-input/root/packages/foo/deprecation.dart:76: Deprecation notice does not accurately indicate a dev branch version number; please see RELEASES_URL to find the latest dev build version number.\n'
'test/analyze-test-input/root/packages/foo/deprecation.dart:82: Deprecation notice does not accurately indicate a dev branch version number; please see RELEASES_URL to find the latest dev build version number.\n'
.replaceAll('/', Platform.isWindows ? r'\' : '/') .replaceAll('/', Platform.isWindows ? r'\' : '/')
.replaceAll('STYLE_GUIDE_URL', 'https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo')
.replaceAll('RELEASES_URL', 'https://flutter.dev/docs/development/tools/sdk/releases')
) )
+ +
'See: https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes\n' 'See: https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes\n'
......
...@@ -217,7 +217,7 @@ class TextFormFieldDemoState extends State<TextFormFieldDemo> { ...@@ -217,7 +217,7 @@ class TextFormFieldDemoState extends State<TextFormFieldDemo> {
validator: _validatePhoneNumber, validator: _validatePhoneNumber,
// TextInputFormatters are applied in sequence. // TextInputFormatters are applied in sequence.
inputFormatters: <TextInputFormatter> [ inputFormatters: <TextInputFormatter> [
WhitelistingTextInputFormatter.digitsOnly, FilteringTextInputFormatter.digitsOnly,
// Fit the validating format. // Fit the validating format.
_phoneNumberFormatter, _phoneNumberFormatter,
], ],
......
...@@ -463,7 +463,7 @@ class _CupertinoNavigationBarState extends State<CupertinoNavigationBar> { ...@@ -463,7 +463,7 @@ class _CupertinoNavigationBarState extends State<CupertinoNavigationBar> {
); );
final Color actionsForegroundColor = CupertinoDynamicColor.resolve( final Color actionsForegroundColor = CupertinoDynamicColor.resolve(
widget.actionsForegroundColor, // ignore: deprecated_member_use_from_same_package widget.actionsForegroundColor,
context, context,
); );
if (!widget.transitionBetweenRoutes || !_isTransitionable(context)) { if (!widget.transitionBetweenRoutes || !_isTransitionable(context)) {
...@@ -694,8 +694,8 @@ class _CupertinoSliverNavigationBarState extends State<CupertinoSliverNavigation ...@@ -694,8 +694,8 @@ class _CupertinoSliverNavigationBarState extends State<CupertinoSliverNavigation
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// Lint ignore to maintain backward compatibility. // Lint ignore to maintain backward compatibility.
final Color actionsForegroundColor = CupertinoDynamicColor.resolve(widget.actionsForegroundColor, context) // ignore: deprecated_member_use_from_same_package final Color actionsForegroundColor = CupertinoDynamicColor.resolve(widget.actionsForegroundColor, context)
?? CupertinoTheme.of(context).primaryColor; ?? CupertinoTheme.of(context).primaryColor;
final _NavigationBarStaticComponents components = _NavigationBarStaticComponents( final _NavigationBarStaticComponents components = _NavigationBarStaticComponents(
keys: keys, keys: keys,
......
...@@ -4,11 +4,6 @@ ...@@ -4,11 +4,6 @@
// @dart = 2.8 // @dart = 2.8
// TODO(shihaohong): remove ignoring deprecated member use analysis
// when AlertDialog.scrollable parameter is removed. See
// https://flutter.dev/go/scrollable-alert-dialog for more details.
// ignore_for_file: deprecated_member_use_from_same_package
import 'dart:async'; import 'dart:async';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
......
...@@ -1927,7 +1927,6 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat ...@@ -1927,7 +1927,6 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
final bool labelIsInitiallyFloating = widget.decoration.floatingLabelBehavior == FloatingLabelBehavior.always final bool labelIsInitiallyFloating = widget.decoration.floatingLabelBehavior == FloatingLabelBehavior.always
|| (widget.decoration.floatingLabelBehavior != FloatingLabelBehavior.never && || (widget.decoration.floatingLabelBehavior != FloatingLabelBehavior.never &&
// ignore: deprecated_member_use_from_same_package
widget.decoration.hasFloatingPlaceholder && widget.decoration.hasFloatingPlaceholder &&
widget._labelShouldWithdraw); widget._labelShouldWithdraw);
...@@ -1976,7 +1975,6 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat ...@@ -1976,7 +1975,6 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
bool get isHovering => widget.isHovering && decoration.enabled; bool get isHovering => widget.isHovering && decoration.enabled;
bool get isEmpty => widget.isEmpty; bool get isEmpty => widget.isEmpty;
bool get _floatingLabelEnabled { bool get _floatingLabelEnabled {
// ignore: deprecated_member_use_from_same_package
return decoration.hasFloatingPlaceholder && decoration.floatingLabelBehavior != FloatingLabelBehavior.never; return decoration.hasFloatingPlaceholder && decoration.floatingLabelBehavior != FloatingLabelBehavior.never;
} }
...@@ -1987,7 +1985,6 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat ...@@ -1987,7 +1985,6 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
_effectiveDecoration = null; _effectiveDecoration = null;
final bool floatBehaviorChanged = widget.decoration.floatingLabelBehavior != old.decoration.floatingLabelBehavior final bool floatBehaviorChanged = widget.decoration.floatingLabelBehavior != old.decoration.floatingLabelBehavior
// ignore: deprecated_member_use_from_same_package
|| widget.decoration.hasFloatingPlaceholder != old.decoration.hasFloatingPlaceholder; || widget.decoration.hasFloatingPlaceholder != old.decoration.hasFloatingPlaceholder;
if (widget._labelShouldWithdraw != old._labelShouldWithdraw || floatBehaviorChanged) { if (widget._labelShouldWithdraw != old._labelShouldWithdraw || floatBehaviorChanged) {
...@@ -2520,7 +2517,7 @@ class InputDecoration { ...@@ -2520,7 +2517,7 @@ class InputDecoration {
'Use floatingLabelBehavior instead. ' 'Use floatingLabelBehavior instead. '
'This feature was deprecated after v1.13.2.' 'This feature was deprecated after v1.13.2.'
) )
this.hasFloatingPlaceholder = true, // ignore: deprecated_member_use_from_same_package this.hasFloatingPlaceholder = true,
this.floatingLabelBehavior = FloatingLabelBehavior.auto, this.floatingLabelBehavior = FloatingLabelBehavior.auto,
this.isCollapsed = false, this.isCollapsed = false,
this.isDense, this.isDense,
...@@ -2566,7 +2563,6 @@ class InputDecoration { ...@@ -2566,7 +2563,6 @@ class InputDecoration {
'Use floatingLabelBehavior instead. ' 'Use floatingLabelBehavior instead. '
'This feature was deprecated after v1.13.2.' 'This feature was deprecated after v1.13.2.'
) )
// ignore: deprecated_member_use_from_same_package
this.hasFloatingPlaceholder = true, this.hasFloatingPlaceholder = true,
this.floatingLabelBehavior = FloatingLabelBehavior.auto, this.floatingLabelBehavior = FloatingLabelBehavior.auto,
this.hintStyle, this.hintStyle,
...@@ -2577,9 +2573,8 @@ class InputDecoration { ...@@ -2577,9 +2573,8 @@ class InputDecoration {
this.border = InputBorder.none, this.border = InputBorder.none,
this.enabled = true, this.enabled = true,
}) : assert(enabled != null), }) : assert(enabled != null),
// ignore: deprecated_member_use_from_same_package
assert(!(!hasFloatingPlaceholder && identical(floatingLabelBehavior, FloatingLabelBehavior.always)), assert(!(!hasFloatingPlaceholder && identical(floatingLabelBehavior, FloatingLabelBehavior.always)),
'hasFloatingPlaceholder=false conflicts with FloatingLabelBehavior.always'), 'hasFloatingPlaceholder=false conflicts with FloatingLabelBehavior.always'),
icon = null, icon = null,
labelText = null, labelText = null,
labelStyle = null, labelStyle = null,
...@@ -3372,7 +3367,6 @@ class InputDecoration { ...@@ -3372,7 +3367,6 @@ class InputDecoration {
errorText: errorText ?? this.errorText, errorText: errorText ?? this.errorText,
errorStyle: errorStyle ?? this.errorStyle, errorStyle: errorStyle ?? this.errorStyle,
errorMaxLines: errorMaxLines ?? this.errorMaxLines, errorMaxLines: errorMaxLines ?? this.errorMaxLines,
// ignore: deprecated_member_use_from_same_package
hasFloatingPlaceholder: hasFloatingPlaceholder ?? this.hasFloatingPlaceholder, hasFloatingPlaceholder: hasFloatingPlaceholder ?? this.hasFloatingPlaceholder,
floatingLabelBehavior: floatingLabelBehavior ?? this.floatingLabelBehavior, floatingLabelBehavior: floatingLabelBehavior ?? this.floatingLabelBehavior,
isCollapsed: isCollapsed ?? this.isCollapsed, isCollapsed: isCollapsed ?? this.isCollapsed,
...@@ -3420,7 +3414,6 @@ class InputDecoration { ...@@ -3420,7 +3414,6 @@ class InputDecoration {
hintStyle: hintStyle ?? theme.hintStyle, hintStyle: hintStyle ?? theme.hintStyle,
errorStyle: errorStyle ?? theme.errorStyle, errorStyle: errorStyle ?? theme.errorStyle,
errorMaxLines: errorMaxLines ?? theme.errorMaxLines, errorMaxLines: errorMaxLines ?? theme.errorMaxLines,
// ignore: deprecated_member_use_from_same_package
hasFloatingPlaceholder: hasFloatingPlaceholder ?? theme.hasFloatingPlaceholder, hasFloatingPlaceholder: hasFloatingPlaceholder ?? theme.hasFloatingPlaceholder,
floatingLabelBehavior: floatingLabelBehavior ?? theme.floatingLabelBehavior, floatingLabelBehavior: floatingLabelBehavior ?? theme.floatingLabelBehavior,
isCollapsed: isCollapsed ?? theme.isCollapsed, isCollapsed: isCollapsed ?? theme.isCollapsed,
...@@ -3462,7 +3455,6 @@ class InputDecoration { ...@@ -3462,7 +3455,6 @@ class InputDecoration {
&& other.errorText == errorText && other.errorText == errorText
&& other.errorStyle == errorStyle && other.errorStyle == errorStyle
&& other.errorMaxLines == errorMaxLines && other.errorMaxLines == errorMaxLines
// ignore: deprecated_member_use_from_same_package
&& other.hasFloatingPlaceholder == hasFloatingPlaceholder && other.hasFloatingPlaceholder == hasFloatingPlaceholder
&& other.floatingLabelBehavior == floatingLabelBehavior && other.floatingLabelBehavior == floatingLabelBehavior
&& other.isDense == isDense && other.isDense == isDense
...@@ -3511,7 +3503,7 @@ class InputDecoration { ...@@ -3511,7 +3503,7 @@ class InputDecoration {
errorText, errorText,
errorStyle, errorStyle,
errorMaxLines, errorMaxLines,
hasFloatingPlaceholder,// ignore: deprecated_member_use_from_same_package hasFloatingPlaceholder,
floatingLabelBehavior, floatingLabelBehavior,
isDense, isDense,
contentPadding, contentPadding,
...@@ -3560,7 +3552,6 @@ class InputDecoration { ...@@ -3560,7 +3552,6 @@ class InputDecoration {
if (errorText != null) 'errorText: "$errorText"', if (errorText != null) 'errorText: "$errorText"',
if (errorStyle != null) 'errorStyle: "$errorStyle"', if (errorStyle != null) 'errorStyle: "$errorStyle"',
if (errorMaxLines != null) 'errorMaxLines: "$errorMaxLines"', if (errorMaxLines != null) 'errorMaxLines: "$errorMaxLines"',
// ignore: deprecated_member_use_from_same_package
if (hasFloatingPlaceholder == false) 'hasFloatingPlaceholder: false', if (hasFloatingPlaceholder == false) 'hasFloatingPlaceholder: false',
if (floatingLabelBehavior != null) 'floatingLabelBehavior: $floatingLabelBehavior', if (floatingLabelBehavior != null) 'floatingLabelBehavior: $floatingLabelBehavior',
if (isDense ?? false) 'isDense: $isDense', if (isDense ?? false) 'isDense: $isDense',
...@@ -3624,7 +3615,6 @@ class InputDecorationTheme with Diagnosticable { ...@@ -3624,7 +3615,6 @@ class InputDecorationTheme with Diagnosticable {
'Use floatingLabelBehavior instead. ' 'Use floatingLabelBehavior instead. '
'This feature was deprecated after v1.13.2.' 'This feature was deprecated after v1.13.2.'
) )
// ignore: deprecated_member_use_from_same_package
this.hasFloatingPlaceholder = true, this.hasFloatingPlaceholder = true,
this.floatingLabelBehavior = FloatingLabelBehavior.auto, this.floatingLabelBehavior = FloatingLabelBehavior.auto,
this.isDense = false, this.isDense = false,
...@@ -3648,7 +3638,6 @@ class InputDecorationTheme with Diagnosticable { ...@@ -3648,7 +3638,6 @@ class InputDecorationTheme with Diagnosticable {
assert(isCollapsed != null), assert(isCollapsed != null),
assert(filled != null), assert(filled != null),
assert(alignLabelWithHint != null), assert(alignLabelWithHint != null),
// ignore: deprecated_member_use_from_same_package
assert(!(!hasFloatingPlaceholder && identical(floatingLabelBehavior, FloatingLabelBehavior.always)), assert(!(!hasFloatingPlaceholder && identical(floatingLabelBehavior, FloatingLabelBehavior.always)),
'hasFloatingPlaceholder=false conflicts with FloatingLabelBehavior.always'); 'hasFloatingPlaceholder=false conflicts with FloatingLabelBehavior.always');
...@@ -4001,7 +3990,6 @@ class InputDecorationTheme with Diagnosticable { ...@@ -4001,7 +3990,6 @@ class InputDecorationTheme with Diagnosticable {
hintStyle: hintStyle ?? this.hintStyle, hintStyle: hintStyle ?? this.hintStyle,
errorStyle: errorStyle ?? this.errorStyle, errorStyle: errorStyle ?? this.errorStyle,
errorMaxLines: errorMaxLines ?? this.errorMaxLines, errorMaxLines: errorMaxLines ?? this.errorMaxLines,
// ignore: deprecated_member_use_from_same_package
hasFloatingPlaceholder: hasFloatingPlaceholder ?? this.hasFloatingPlaceholder, hasFloatingPlaceholder: hasFloatingPlaceholder ?? this.hasFloatingPlaceholder,
floatingLabelBehavior: floatingLabelBehavior ?? this.floatingLabelBehavior, floatingLabelBehavior: floatingLabelBehavior ?? this.floatingLabelBehavior,
isDense: isDense ?? this.isDense, isDense: isDense ?? this.isDense,
...@@ -4033,7 +4021,6 @@ class InputDecorationTheme with Diagnosticable { ...@@ -4033,7 +4021,6 @@ class InputDecorationTheme with Diagnosticable {
hintStyle, hintStyle,
errorStyle, errorStyle,
errorMaxLines, errorMaxLines,
// ignore: deprecated_member_use_from_same_package
hasFloatingPlaceholder, hasFloatingPlaceholder,
floatingLabelBehavior, floatingLabelBehavior,
isDense, isDense,
...@@ -4100,7 +4087,6 @@ class InputDecorationTheme with Diagnosticable { ...@@ -4100,7 +4087,6 @@ class InputDecorationTheme with Diagnosticable {
properties.add(DiagnosticsProperty<TextStyle>('hintStyle', hintStyle, defaultValue: defaultTheme.hintStyle)); properties.add(DiagnosticsProperty<TextStyle>('hintStyle', hintStyle, defaultValue: defaultTheme.hintStyle));
properties.add(DiagnosticsProperty<TextStyle>('errorStyle', errorStyle, defaultValue: defaultTheme.errorStyle)); properties.add(DiagnosticsProperty<TextStyle>('errorStyle', errorStyle, defaultValue: defaultTheme.errorStyle));
properties.add(IntProperty('errorMaxLines', errorMaxLines, defaultValue: defaultTheme.errorMaxLines)); properties.add(IntProperty('errorMaxLines', errorMaxLines, defaultValue: defaultTheme.errorMaxLines));
// ignore: deprecated_member_use_from_same_package
properties.add(DiagnosticsProperty<bool>('hasFloatingPlaceholder', hasFloatingPlaceholder, defaultValue: defaultTheme.hasFloatingPlaceholder)); properties.add(DiagnosticsProperty<bool>('hasFloatingPlaceholder', hasFloatingPlaceholder, defaultValue: defaultTheme.hasFloatingPlaceholder));
properties.add(DiagnosticsProperty<FloatingLabelBehavior>('floatingLabelBehavior', floatingLabelBehavior, defaultValue: defaultTheme.floatingLabelBehavior)); properties.add(DiagnosticsProperty<FloatingLabelBehavior>('floatingLabelBehavior', floatingLabelBehavior, defaultValue: defaultTheme.floatingLabelBehavior));
properties.add(DiagnosticsProperty<bool>('isDense', isDense, defaultValue: defaultTheme.isDense)); properties.add(DiagnosticsProperty<bool>('isDense', isDense, defaultValue: defaultTheme.isDense));
......
...@@ -29,9 +29,9 @@ const double _maxCalendarWidthPortrait = 480.0; ...@@ -29,9 +29,9 @@ const double _maxCalendarWidthPortrait = 480.0;
/// Displays a scrollable calendar grid that allows a user to select a range /// Displays a scrollable calendar grid that allows a user to select a range
/// of dates. /// of dates.
/// //
/// Note: this is not publicly exported (see pickers.dart), as it is an // This is not publicly exported (see pickers.dart), as it is an
/// internal component used by [showDateRangePicker]. // internal component used by [showDateRangePicker].
class CalendarDateRangePicker extends StatefulWidget { class CalendarDateRangePicker extends StatefulWidget {
/// Creates a scrollable calendar grid for picking date ranges. /// Creates a scrollable calendar grid for picking date ranges.
CalendarDateRangePicker({ CalendarDateRangePicker({
......
...@@ -21,7 +21,7 @@ import '../theme.dart'; ...@@ -21,7 +21,7 @@ import '../theme.dart';
import 'date_picker_common.dart'; import 'date_picker_common.dart';
// NOTE: this is the original implementation for the Material Date Picker. // This is the original implementation for the Material Date Picker.
// These classes are deprecated and the whole file can be removed after // These classes are deprecated and the whole file can be removed after
// this has been on stable for long enough for people to migrate to the new // this has been on stable for long enough for people to migrate to the new
// CalendarDatePicker (if needed, as showDatePicker has already been migrated // CalendarDatePicker (if needed, as showDatePicker has already been migrated
...@@ -406,7 +406,6 @@ class MonthPicker extends StatefulWidget { ...@@ -406,7 +406,6 @@ class MonthPicker extends StatefulWidget {
_MonthPickerState createState() => _MonthPickerState(); _MonthPickerState createState() => _MonthPickerState();
} }
// ignore: deprecated_member_use_from_same_package
class _MonthPickerState extends State<MonthPicker> with SingleTickerProviderStateMixin { class _MonthPickerState extends State<MonthPicker> with SingleTickerProviderStateMixin {
static final Animatable<double> _chevronOpacityTween = Tween<double>(begin: 1.0, end: 0.0) static final Animatable<double> _chevronOpacityTween = Tween<double>(begin: 1.0, end: 0.0)
.chain(CurveTween(curve: Curves.easeInOut)); .chain(CurveTween(curve: Curves.easeInOut));
...@@ -428,7 +427,6 @@ class _MonthPickerState extends State<MonthPicker> with SingleTickerProviderStat ...@@ -428,7 +427,6 @@ class _MonthPickerState extends State<MonthPicker> with SingleTickerProviderStat
} }
@override @override
// ignore: deprecated_member_use_from_same_package
void didUpdateWidget(MonthPicker oldWidget) { void didUpdateWidget(MonthPicker oldWidget) {
super.didUpdateWidget(oldWidget); super.didUpdateWidget(oldWidget);
if (widget.selectedDate != oldWidget.selectedDate) { if (widget.selectedDate != oldWidget.selectedDate) {
...@@ -479,7 +477,6 @@ class _MonthPickerState extends State<MonthPicker> with SingleTickerProviderStat ...@@ -479,7 +477,6 @@ class _MonthPickerState extends State<MonthPicker> with SingleTickerProviderStat
Widget _buildItems(BuildContext context, int index) { Widget _buildItems(BuildContext context, int index) {
final DateTime month = _addMonthsToMonthDate(widget.firstDate, index); final DateTime month = _addMonthsToMonthDate(widget.firstDate, index);
// ignore: deprecated_member_use_from_same_package
return DayPicker( return DayPicker(
key: ValueKey<DateTime>(month), key: ValueKey<DateTime>(month),
selectedDate: widget.selectedDate, selectedDate: widget.selectedDate,
...@@ -675,7 +672,6 @@ class YearPicker extends StatefulWidget { ...@@ -675,7 +672,6 @@ class YearPicker extends StatefulWidget {
_YearPickerState createState() => _YearPickerState(); _YearPickerState createState() => _YearPickerState();
} }
// ignore: deprecated_member_use_from_same_package
class _YearPickerState extends State<YearPicker> { class _YearPickerState extends State<YearPicker> {
static const double _itemExtent = 50.0; static const double _itemExtent = 50.0;
ScrollController scrollController; ScrollController scrollController;
......
...@@ -12,7 +12,7 @@ import '../material.dart'; ...@@ -12,7 +12,7 @@ import '../material.dart';
import '../text_theme.dart'; import '../text_theme.dart';
import '../theme.dart'; import '../theme.dart';
// NOTE: This is an internal implementation file. Even though there are public // This is an internal implementation file. Even though there are public
// classes and functions defined here, they are only meant to be used by the // classes and functions defined here, they are only meant to be used by the
// date picker implementation and are not exported as part of the Material library. // date picker implementation and are not exported as part of the Material library.
// See pickers.dart for exactly what is considered part of the public API. // See pickers.dart for exactly what is considered part of the public API.
......
...@@ -4,10 +4,9 @@ ...@@ -4,10 +4,9 @@
// @dart = 2.8 // @dart = 2.8
// Common date utility functions used by the date picker implementation // Common date utility functions used by the date picker implementation
// NOTE: This is an internal implementation file. Even though there are public // This is an internal implementation file. Even though there are public
// classes and functions defined here, they are only meant to be used by the // classes and functions defined here, they are only meant to be used by the
// date picker implementation and are not exported as part of the Material library. // date picker implementation and are not exported as part of the Material library.
// See pickers.dart for exactly what is considered part of the public API. // See pickers.dart for exactly what is considered part of the public API.
......
...@@ -244,16 +244,16 @@ class _InputDatePickerFormFieldState extends State<InputDatePickerFormField> { ...@@ -244,16 +244,16 @@ class _InputDatePickerFormFieldState extends State<InputDatePickerFormField> {
} }
/// A `TextInputFormatter` set up to format dates. /// A `TextInputFormatter` set up to format dates.
/// //
/// Note: this is not publicly exported (see pickers.dart), as it is // This is not publicly exported (see pickers.dart), as it is
/// just meant for internal use by `InputDatePickerFormField` and // just meant for internal use by `InputDatePickerFormField` and
/// `InputDateRangePicker`. // `InputDateRangePicker`.
class DateTextInputFormatter extends TextInputFormatter { class DateTextInputFormatter extends TextInputFormatter {
/// Creates a date formatter with the given separator. /// Creates a date formatter with the given separator.
DateTextInputFormatter( DateTextInputFormatter(
this.separator this.separator
) : _filterFormatter = WhitelistingTextInputFormatter(RegExp('[\\d$_commonSeparators\\$separator]+')); ) : _filterFormatter = FilteringTextInputFormatter.allow(RegExp('[\\d$_commonSeparators\\$separator]+'));
/// List of common separators that are used in dates. This is used to make /// List of common separators that are used in dates. This is used to make
/// sure that if given platform's [TextInputType.datetime] keyboard doesn't /// sure that if given platform's [TextInputType.datetime] keyboard doesn't
...@@ -267,7 +267,7 @@ class DateTextInputFormatter extends TextInputFormatter { ...@@ -267,7 +267,7 @@ class DateTextInputFormatter extends TextInputFormatter {
// Formatter that will filter out all characters except digits and date // Formatter that will filter out all characters except digits and date
// separators. // separators.
final WhitelistingTextInputFormatter _filterFormatter; final TextInputFormatter _filterFormatter;
@override @override
TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) { TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) {
......
...@@ -18,9 +18,9 @@ import 'input_date_picker.dart' show DateTextInputFormatter; ...@@ -18,9 +18,9 @@ import 'input_date_picker.dart' show DateTextInputFormatter;
/// Provides a pair of text fields that allow the user to enter the start and /// Provides a pair of text fields that allow the user to enter the start and
/// end dates that represent a range of dates. /// end dates that represent a range of dates.
/// //
/// Note: this is not publicly exported (see pickers.dart), as it is just an // This is not publicly exported (see pickers.dart), as it is just an
/// internal component used by [showDateRangePicker]. // internal component used by [showDateRangePicker].
class InputDateRangePicker extends StatefulWidget { class InputDateRangePicker extends StatefulWidget {
/// Creates a row with two text fields configured to accept the start and end dates /// Creates a row with two text fields configured to accept the start and end dates
/// of a date range. /// of a date range.
......
...@@ -15,3 +15,9 @@ export 'date_picker_deprecated.dart'; ...@@ -15,3 +15,9 @@ export 'date_picker_deprecated.dart';
export 'date_picker_dialog.dart' show showDatePicker; export 'date_picker_dialog.dart' show showDatePicker;
export 'date_range_picker_dialog.dart' show showDateRangePicker; export 'date_range_picker_dialog.dart' show showDateRangePicker;
export 'input_date_picker.dart' show InputDatePickerFormField; export 'input_date_picker.dart' show InputDatePickerFormField;
// TODO(ianh): Not exporting everything is unusual and we should
// probably change to just exporting everything and making sure it's
// acceptable as a public API, or, worst case, merging the parts
// that really must be public into a single file and make them
// actually private.
...@@ -2092,7 +2092,6 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin { ...@@ -2092,7 +2092,6 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
// Backwards compatibility for deprecated resizeToAvoidBottomPadding property // Backwards compatibility for deprecated resizeToAvoidBottomPadding property
bool get _resizeToAvoidBottomInset { bool get _resizeToAvoidBottomInset {
// ignore: deprecated_member_use_from_same_package
return widget.resizeToAvoidBottomInset ?? widget.resizeToAvoidBottomPadding ?? true; return widget.resizeToAvoidBottomInset ?? widget.resizeToAvoidBottomPadding ?? true;
} }
......
...@@ -9,10 +9,6 @@ import 'package:flutter/painting.dart'; ...@@ -9,10 +9,6 @@ import 'package:flutter/painting.dart';
import 'typography.dart'; import 'typography.dart';
// Eventually we'll get rid of the deprecated members, but for now, we have to use them
// in order to implement them.
// ignore_for_file: deprecated_member_use_from_same_package
/// Material design text theme. /// Material design text theme.
/// ///
/// Definitions for the various typographical styles found in Material Design /// Definitions for the various typographical styles found in Material Design
......
...@@ -218,7 +218,7 @@ class PlatformAssetBundle extends CachingAssetBundle { ...@@ -218,7 +218,7 @@ class PlatformAssetBundle extends CachingAssetBundle {
Future<ByteData> load(String key) async { Future<ByteData> load(String key) async {
final Uint8List encoded = utf8.encoder.convert(Uri(path: Uri.encodeFull(key)).path); final Uint8List encoded = utf8.encoder.convert(Uri(path: Uri.encodeFull(key)).path);
final ByteData asset = final ByteData asset =
await defaultBinaryMessenger.send('flutter/assets', encoded.buffer.asByteData()); // ignore: deprecated_member_use_from_same_package await defaultBinaryMessenger.send('flutter/assets', encoded.buffer.asByteData());
if (asset == null) if (asset == null)
throw FlutterError('Unable to load asset: $key'); throw FlutterError('Unable to load asset: $key');
return asset; return asset;
......
...@@ -48,7 +48,7 @@ class BasicMessageChannel<T> { ...@@ -48,7 +48,7 @@ class BasicMessageChannel<T> {
final MessageCodec<T> codec; final MessageCodec<T> codec;
/// The messenger which sends the bytes for this channel, not null. /// The messenger which sends the bytes for this channel, not null.
BinaryMessenger get binaryMessenger => _binaryMessenger ?? defaultBinaryMessenger; // ignore: deprecated_member_use_from_same_package BinaryMessenger get binaryMessenger => _binaryMessenger ?? defaultBinaryMessenger;
final BinaryMessenger _binaryMessenger; final BinaryMessenger _binaryMessenger;
/// Sends the specified [message] to the platform plugins on this channel. /// Sends the specified [message] to the platform plugins on this channel.
...@@ -142,7 +142,7 @@ class MethodChannel { ...@@ -142,7 +142,7 @@ class MethodChannel {
/// The messenger used by this channel to send platform messages. /// The messenger used by this channel to send platform messages.
/// ///
/// The messenger may not be null. /// The messenger may not be null.
BinaryMessenger get binaryMessenger => _binaryMessenger ?? defaultBinaryMessenger; // ignore: deprecated_member_use_from_same_package BinaryMessenger get binaryMessenger => _binaryMessenger ?? defaultBinaryMessenger;
final BinaryMessenger _binaryMessenger; final BinaryMessenger _binaryMessenger;
@optionalTypeArgs @optionalTypeArgs
...@@ -506,7 +506,7 @@ class EventChannel { ...@@ -506,7 +506,7 @@ class EventChannel {
final MethodCodec codec; final MethodCodec codec;
/// The messenger used by this channel to send platform messages, not null. /// The messenger used by this channel to send platform messages, not null.
BinaryMessenger get binaryMessenger => _binaryMessenger ?? defaultBinaryMessenger; // ignore: deprecated_member_use_from_same_package BinaryMessenger get binaryMessenger => _binaryMessenger ?? defaultBinaryMessenger;
final BinaryMessenger _binaryMessenger; final BinaryMessenger _binaryMessenger;
/// Sets up a broadcast stream for receiving events on this channel. /// Sets up a broadcast stream for receiving events on this channel.
......
...@@ -5709,17 +5709,17 @@ class Listener extends StatelessWidget { ...@@ -5709,17 +5709,17 @@ class Listener extends StatelessWidget {
'Use MouseRegion.onEnter instead. See MouseRegion.opaque for behavioral difference. ' 'Use MouseRegion.onEnter instead. See MouseRegion.opaque for behavioral difference. '
'This feature was deprecated after v1.10.14.' 'This feature was deprecated after v1.10.14.'
) )
this.onPointerEnter, // ignore: deprecated_member_use_from_same_package this.onPointerEnter,
@Deprecated( @Deprecated(
'Use MouseRegion.onExit instead. See MouseRegion.opaque for behavioral difference. ' 'Use MouseRegion.onExit instead. See MouseRegion.opaque for behavioral difference. '
'This feature was deprecated after v1.10.14.' 'This feature was deprecated after v1.10.14.'
) )
this.onPointerExit, // ignore: deprecated_member_use_from_same_package this.onPointerExit,
@Deprecated( @Deprecated(
'Use MouseRegion.onHover instead. See MouseRegion.opaque for behavioral difference. ' 'Use MouseRegion.onHover instead. See MouseRegion.opaque for behavioral difference. '
'This feature was deprecated after v1.10.14.' 'This feature was deprecated after v1.10.14.'
) )
this.onPointerHover, // ignore: deprecated_member_use_from_same_package this.onPointerHover,
this.onPointerUp, this.onPointerUp,
this.onPointerCancel, this.onPointerCancel,
this.onPointerSignal, this.onPointerSignal,
......
...@@ -460,7 +460,7 @@ class EditableText extends StatefulWidget { ...@@ -460,7 +460,7 @@ class EditableText extends StatefulWidget {
keyboardType = keyboardType ?? _inferKeyboardType(autofillHints: autofillHints, maxLines: maxLines), keyboardType = keyboardType ?? _inferKeyboardType(autofillHints: autofillHints, maxLines: maxLines),
inputFormatters = maxLines == 1 inputFormatters = maxLines == 1
? <TextInputFormatter>[ ? <TextInputFormatter>[
BlacklistingTextInputFormatter.singleLineFormatter, FilteringTextInputFormatter.singleLineFormatter,
...inputFormatters ?? const Iterable<TextInputFormatter>.empty(), ...inputFormatters ?? const Iterable<TextInputFormatter>.empty(),
] ]
: inputFormatters, : inputFormatters,
......
...@@ -2846,7 +2846,6 @@ void main() { ...@@ -2846,7 +2846,6 @@ void main() {
isEmpty: true, isEmpty: true,
decoration: const InputDecoration( decoration: const InputDecoration(
border: OutlineInputBorder(borderSide: BorderSide.none), border: OutlineInputBorder(borderSide: BorderSide.none),
// ignore: deprecated_member_use_from_same_package
hasFloatingPlaceholder: false, hasFloatingPlaceholder: false,
labelText: 'label', labelText: 'label',
), ),
...@@ -2871,7 +2870,6 @@ void main() { ...@@ -2871,7 +2870,6 @@ void main() {
// isFocused: false (default) // isFocused: false (default)
decoration: const InputDecoration( decoration: const InputDecoration(
border: OutlineInputBorder(borderSide: BorderSide.none), border: OutlineInputBorder(borderSide: BorderSide.none),
// ignore: deprecated_member_use_from_same_package
hasFloatingPlaceholder: false, hasFloatingPlaceholder: false,
labelText: 'label', labelText: 'label',
), ),
...@@ -3941,7 +3939,6 @@ void main() { ...@@ -3941,7 +3939,6 @@ void main() {
helperMaxLines: 6, helperMaxLines: 6,
hintStyle: TextStyle(), hintStyle: TextStyle(),
errorMaxLines: 5, errorMaxLines: 5,
// ignore: deprecated_member_use_from_same_package
hasFloatingPlaceholder: false, hasFloatingPlaceholder: false,
floatingLabelBehavior: FloatingLabelBehavior.never, floatingLabelBehavior: FloatingLabelBehavior.never,
contentPadding: EdgeInsetsDirectional.only(start: 40.0, top: 12.0, bottom: 12.0), contentPadding: EdgeInsetsDirectional.only(start: 40.0, top: 12.0, bottom: 12.0),
......
...@@ -3157,6 +3157,27 @@ void main() { ...@@ -3157,6 +3157,27 @@ void main() {
testWidgets('Injected formatters are chained', (WidgetTester tester) async { testWidgets('Injected formatters are chained', (WidgetTester tester) async {
final TextEditingController textController = TextEditingController(); final TextEditingController textController = TextEditingController();
await tester.pumpWidget(boilerplate(
child: TextField(
controller: textController,
decoration: null,
inputFormatters: <TextInputFormatter> [
FilteringTextInputFormatter.deny(
RegExp(r'[a-z]'),
replacementString: '#',
),
],
),
));
await tester.enterText(find.byType(TextField), 'a一b二c三\nd四e五f六');
// The default single line formatter replaces \n with empty string.
expect(textController.text, '#一#二#三#四#五#六');
});
testWidgets('Injected formatters are chained (deprecated names)', (WidgetTester tester) async {
final TextEditingController textController = TextEditingController();
await tester.pumpWidget(boilerplate( await tester.pumpWidget(boilerplate(
child: TextField( child: TextField(
controller: textController, controller: textController,
...@@ -3178,6 +3199,33 @@ void main() { ...@@ -3178,6 +3199,33 @@ void main() {
testWidgets('Chained formatters are in sequence', (WidgetTester tester) async { testWidgets('Chained formatters are in sequence', (WidgetTester tester) async {
final TextEditingController textController = TextEditingController(); final TextEditingController textController = TextEditingController();
await tester.pumpWidget(boilerplate(
child: TextField(
controller: textController,
decoration: null,
maxLines: 2,
inputFormatters: <TextInputFormatter> [
FilteringTextInputFormatter.deny(
RegExp(r'[a-z]'),
replacementString: '12\n',
),
FilteringTextInputFormatter.allow(RegExp(r'\n[0-9]')),
],
),
));
await tester.enterText(find.byType(TextField), 'a1b2c3');
// The first formatter turns it into
// 12\n112\n212\n3
// The second formatter turns it into
// \n1\n2\n3
// Multiline is allowed since maxLine != 1.
expect(textController.text, '\n1\n2\n3');
});
testWidgets('Chained formatters are in sequence (deprecated names)', (WidgetTester tester) async {
final TextEditingController textController = TextEditingController();
await tester.pumpWidget(boilerplate( await tester.pumpWidget(boilerplate(
child: TextField( child: TextField(
controller: textController, controller: textController,
...@@ -3205,6 +3253,44 @@ void main() { ...@@ -3205,6 +3253,44 @@ void main() {
testWidgets('Pasted values are formatted', (WidgetTester tester) async { testWidgets('Pasted values are formatted', (WidgetTester tester) async {
final TextEditingController textController = TextEditingController(); final TextEditingController textController = TextEditingController();
await tester.pumpWidget(
overlay(
child: TextField(
controller: textController,
decoration: null,
inputFormatters: <TextInputFormatter> [
FilteringTextInputFormatter.digitsOnly,
],
),
),
);
await tester.enterText(find.byType(TextField), 'a1b\n2c3');
expect(textController.text, '123');
await skipPastScrollingAnimation(tester);
await tester.tapAt(textOffsetToPosition(tester, '123'.indexOf('2')));
await tester.pump();
await tester.pump(const Duration(milliseconds: 200)); // skip past the frame where the opacity is zero
final RenderEditable renderEditable = findRenderEditable(tester);
final List<TextSelectionPoint> endpoints = globalize(
renderEditable.getEndpointsForSelection(textController.selection),
renderEditable,
);
await tester.tapAt(endpoints[0].point + const Offset(1.0, 1.0));
await tester.pump();
await tester.pump(const Duration(milliseconds: 200)); // skip past the frame where the opacity is zero
Clipboard.setData(const ClipboardData(text: '一4二\n5三6'));
await tester.tap(find.text('PASTE'));
await tester.pump();
// Puts 456 before the 2 in 123.
expect(textController.text, '145623');
});
testWidgets('Pasted values are formatted (deprecated names)', (WidgetTester tester) async {
final TextEditingController textController = TextEditingController();
await tester.pumpWidget( await tester.pumpWidget(
overlay( overlay(
child: TextField( child: TextField(
...@@ -3473,7 +3559,28 @@ void main() { ...@@ -3473,7 +3559,28 @@ void main() {
expect(textController.text, '0123456789'); expect(textController.text, '0123456789');
}); });
testWidgets('maxLength still works with other formatters.', (WidgetTester tester) async { testWidgets('maxLength still works with other formatters', (WidgetTester tester) async {
final TextEditingController textController = TextEditingController();
await tester.pumpWidget(boilerplate(
child: TextField(
controller: textController,
maxLength: 10,
inputFormatters: <TextInputFormatter> [
FilteringTextInputFormatter.deny(
RegExp(r'[a-z]'),
replacementString: '#',
),
],
),
));
await tester.enterText(find.byType(TextField), 'a一b二c三\nd四e五f六');
// The default single line formatter replaces \n with empty string.
expect(textController.text, '#一#二#三#四#五');
});
testWidgets('maxLength still works with other formatters (deprecated names)', (WidgetTester tester) async {
final TextEditingController textController = TextEditingController(); final TextEditingController textController = TextEditingController();
await tester.pumpWidget(boilerplate( await tester.pumpWidget(boilerplate(
......
...@@ -86,4 +86,148 @@ void main() { ...@@ -86,4 +86,148 @@ void main() {
}); });
}); });
}); });
test('FilteringTextInputFormatter should return the old value if new value contains non-white-listed character', () {
const TextEditingValue oldValue = TextEditingValue(text: '12345');
const TextEditingValue newValue = TextEditingValue(text: '12345@');
final TextInputFormatter formatter = FilteringTextInputFormatter.digitsOnly;
final TextEditingValue formatted = formatter.formatEditUpdate(oldValue, newValue);
// assert that we are passing digits only at the first time
expect(oldValue.text, equals('12345'));
// The new value is always the oldValue plus a non-digit character (user press @)
expect(newValue.text, equals('12345@'));
// we expect that the formatted value returns the oldValue only since the newValue does not
// satisfy the formatter condition (which is, in this case, digitsOnly)
expect(formatted.text, equals('12345'));
});
test('FilteringTextInputFormatter should move the cursor to the right position', () {
TextEditingValue collapsedValue(String text, int offset) =>
TextEditingValue(
text: text,
selection: TextSelection.collapsed(offset: offset),
);
TextEditingValue oldValue = collapsedValue('123', 0);
TextEditingValue newValue = collapsedValue('123456', 6);
final TextInputFormatter formatter = FilteringTextInputFormatter.digitsOnly;
TextEditingValue formatted = formatter.formatEditUpdate(oldValue, newValue);
// assert that we are passing digits only at the first time
expect(oldValue.text, equals('123'));
// assert that we are passing digits only at the second time
expect(newValue.text, equals('123456'));
// assert that cursor is at the end of the text
expect(formatted.selection.baseOffset, equals(6));
// move cursor at the middle of the text and then add the number 9.
oldValue = newValue.copyWith(selection: const TextSelection.collapsed(offset: 4));
newValue = oldValue.copyWith(text: '1239456');
formatted = formatter.formatEditUpdate(oldValue, newValue);
// cursor must be now at fourth position (right after the number 9)
expect(formatted.selection.baseOffset, equals(4));
});
test('FilteringTextInputFormatter should remove non-allowed characters', () {
const TextEditingValue oldValue = TextEditingValue(text: '12345');
const TextEditingValue newValue = TextEditingValue(text: '12345@');
final TextInputFormatter formatter = FilteringTextInputFormatter.digitsOnly;
final TextEditingValue formatted = formatter.formatEditUpdate(oldValue, newValue);
// assert that we are passing digits only at the first time
expect(oldValue.text, equals('12345'));
// The new value is always the oldValue plus a non-digit character (user press @)
expect(newValue.text, equals('12345@'));
// we expect that the formatted value returns the oldValue only since the difference
// between the oldValue and the newValue is only material that isn't allowed
expect(formatted.text, equals('12345'));
});
test('WhitelistingTextInputFormatter should return the old value if new value contains non-allowed character', () {
const TextEditingValue oldValue = TextEditingValue(text: '12345');
const TextEditingValue newValue = TextEditingValue(text: '12345@');
final WhitelistingTextInputFormatter formatter = WhitelistingTextInputFormatter.digitsOnly;
final TextEditingValue formatted = formatter.formatEditUpdate(oldValue, newValue);
// assert that we are passing digits only at the first time
expect(oldValue.text, equals('12345'));
// The new value is always the oldValue plus a non-digit character (user press @)
expect(newValue.text, equals('12345@'));
// we expect that the formatted value returns the oldValue only since the newValue does not
// satisfy the formatter condition (which is, in this case, digitsOnly)
expect(formatted.text, equals('12345'));
});
test('FilteringTextInputFormatter should move the cursor to the right position', () {
TextEditingValue collapsedValue(String text, int offset) =>
TextEditingValue(
text: text,
selection: TextSelection.collapsed(offset: offset),
);
TextEditingValue oldValue = collapsedValue('123', 0);
TextEditingValue newValue = collapsedValue('123456', 6);
final TextInputFormatter formatter =
FilteringTextInputFormatter.digitsOnly;
TextEditingValue formatted = formatter.formatEditUpdate(oldValue,
newValue);
// assert that we are passing digits only at the first time
expect(oldValue.text, equals('123'));
// assert that we are passing digits only at the second time
expect(newValue.text, equals('123456'));
// assert that cursor is at the end of the text
expect(formatted.selection.baseOffset, equals(6));
// move cursor at the middle of the text and then add the number 9.
oldValue = newValue.copyWith(
selection: const TextSelection.collapsed(offset: 4));
newValue = oldValue.copyWith(text: '1239456');
formatted = formatter.formatEditUpdate(oldValue, newValue);
// cursor must be now at fourth position (right after the number 9)
expect(formatted.selection.baseOffset, equals(4));
});
test('WhitelistingTextInputFormatter should move the cursor to the right position', () {
TextEditingValue collapsedValue(String text, int offset) =>
TextEditingValue(
text: text,
selection: TextSelection.collapsed(offset: offset),
);
TextEditingValue oldValue = collapsedValue('123', 0);
TextEditingValue newValue = collapsedValue('123456', 6);
final WhitelistingTextInputFormatter formatter =
WhitelistingTextInputFormatter.digitsOnly;
TextEditingValue formatted = formatter.formatEditUpdate(oldValue,
newValue);
// assert that we are passing digits only at the first time
expect(oldValue.text, equals('123'));
// assert that we are passing digits only at the second time
expect(newValue.text, equals('123456'));
// assert that cursor is at the end of the text
expect(formatted.selection.baseOffset, equals(6));
// move cursor at the middle of the text and then add the number 9.
oldValue = newValue.copyWith(
selection: const TextSelection.collapsed(offset: 4));
newValue = oldValue.copyWith(text: '1239456');
formatted = formatter.formatEditUpdate(oldValue, newValue);
// cursor must be now at fourth position (right after the number 9)
expect(formatted.selection.baseOffset, equals(4));
});
} }
...@@ -13,10 +13,6 @@ import 'package:flutter/gestures.dart'; ...@@ -13,10 +13,6 @@ import 'package:flutter/gestures.dart';
// The tests in this file are moved from listener_test.dart, which tests several // The tests in this file are moved from listener_test.dart, which tests several
// deprecated APIs. The file should be removed once these parameters are. // deprecated APIs. The file should be removed once these parameters are.
// ignore_for_file: deprecated_member_use_from_same_package
// We have to ignore the lint rule here because we need to use the deprecated
// callbacks in order to test them.
class HoverClient extends StatefulWidget { class HoverClient extends StatefulWidget {
const HoverClient({Key key, this.onHover, this.child}) : super(key: key); const HoverClient({Key key, this.onHover, this.child}) : super(key: key);
......
...@@ -9,11 +9,10 @@ import 'package:flutter/services.dart'; ...@@ -9,11 +9,10 @@ import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
void main() { void main() {
TextEditingValue testOldValue; const TextEditingValue testOldValue = TextEditingValue();
TextEditingValue testNewValue; TextEditingValue testNewValue;
test('withFunction wraps formatting function', () { test('withFunction wraps formatting function', () {
testOldValue = const TextEditingValue();
testNewValue = const TextEditingValue(); testNewValue = const TextEditingValue();
TextEditingValue calledOldValue; TextEditingValue calledOldValue;
...@@ -47,7 +46,62 @@ void main() { ...@@ -47,7 +46,62 @@ void main() {
); );
}); });
test('test blacklisting formatter', () { test('test filtering formatter example', () {
const TextEditingValue intoTheWoods = TextEditingValue(text: 'Into the Woods');
expect(
FilteringTextInputFormatter('o', allow: true, replacementString: '*').formatEditUpdate(testOldValue, intoTheWoods),
const TextEditingValue(text: '*o*oo*'),
);
expect(
FilteringTextInputFormatter('o', allow: false, replacementString: '*').formatEditUpdate(testOldValue, intoTheWoods),
const TextEditingValue(text: 'Int* the W**ds'),
);
expect(
FilteringTextInputFormatter(RegExp('o+'), allow: true, replacementString: '*').formatEditUpdate(testOldValue, intoTheWoods),
const TextEditingValue(text: '*o*oo*'),
);
expect(
FilteringTextInputFormatter(RegExp('o+'), allow: false, replacementString: '*').formatEditUpdate(testOldValue, intoTheWoods),
const TextEditingValue(text: 'Int* the W*ds'),
);
const TextEditingValue selectedIntoTheWoods = TextEditingValue(text: 'Into the Woods', selection: TextSelection(baseOffset: 11, extentOffset: 14));
expect(
FilteringTextInputFormatter('o', allow: true, replacementString: '*').formatEditUpdate(testOldValue, selectedIntoTheWoods),
const TextEditingValue(text: '*o*oo*', selection: TextSelection(baseOffset: 4, extentOffset: 6)),
);
expect(
FilteringTextInputFormatter('o', allow: false, replacementString: '*').formatEditUpdate(testOldValue, selectedIntoTheWoods),
const TextEditingValue(text: 'Int* the W**ds', selection: TextSelection(baseOffset: 11, extentOffset: 14)),
);
expect(
FilteringTextInputFormatter(RegExp('o+'), allow: true, replacementString: '*').formatEditUpdate(testOldValue, selectedIntoTheWoods),
const TextEditingValue(text: '*o*oo*', selection: TextSelection(baseOffset: 4, extentOffset: 6)),
);
expect(
FilteringTextInputFormatter(RegExp('o+'), allow: false, replacementString: '*').formatEditUpdate(testOldValue, selectedIntoTheWoods),
const TextEditingValue(text: 'Int* the W**ds', selection: TextSelection(baseOffset: 11, extentOffset: 14)),
);
});
test('test filtering formatter, deny mode', () {
final TextEditingValue actualValue =
FilteringTextInputFormatter.deny(RegExp(r'[a-z]'))
.formatEditUpdate(testOldValue, testNewValue);
// Expecting
// 1(23
// 4)56
expect(actualValue, const TextEditingValue(
text: '123\n456',
selection: TextSelection(
baseOffset: 1,
extentOffset: 5,
),
));
});
test('test filtering formatter, deny mode (deprecated names)', () {
final TextEditingValue actualValue = final TextEditingValue actualValue =
BlacklistingTextInputFormatter(RegExp(r'[a-z]')) BlacklistingTextInputFormatter(RegExp(r'[a-z]'))
.formatEditUpdate(testOldValue, testNewValue); .formatEditUpdate(testOldValue, testNewValue);
...@@ -65,6 +119,22 @@ void main() { ...@@ -65,6 +119,22 @@ void main() {
}); });
test('test single line formatter', () { test('test single line formatter', () {
final TextEditingValue actualValue =
FilteringTextInputFormatter.singleLineFormatter
.formatEditUpdate(testOldValue, testNewValue);
// Expecting
// a1b(2c3d4)e5f6
expect(actualValue, const TextEditingValue(
text: 'a1b2c3d4e5f6',
selection: TextSelection(
baseOffset: 3,
extentOffset: 8,
),
));
});
test('test single line formatter (deprecated names)', () {
final TextEditingValue actualValue = final TextEditingValue actualValue =
BlacklistingTextInputFormatter.singleLineFormatter BlacklistingTextInputFormatter.singleLineFormatter
.formatEditUpdate(testOldValue, testNewValue); .formatEditUpdate(testOldValue, testNewValue);
...@@ -80,7 +150,23 @@ void main() { ...@@ -80,7 +150,23 @@ void main() {
)); ));
}); });
test('test whitelisting formatter', () { test('test filtering formatter, allow mode', () {
final TextEditingValue actualValue =
FilteringTextInputFormatter.allow(RegExp(r'[a-c]'))
.formatEditUpdate(testOldValue, testNewValue);
// Expecting
// ab(c)
expect(actualValue, const TextEditingValue(
text: 'abc',
selection: TextSelection(
baseOffset: 2,
extentOffset: 3,
),
));
});
test('test filtering formatter, allow mode (deprecated names)', () {
final TextEditingValue actualValue = final TextEditingValue actualValue =
WhitelistingTextInputFormatter(RegExp(r'[a-c]')) WhitelistingTextInputFormatter(RegExp(r'[a-c]'))
.formatEditUpdate(testOldValue, testNewValue); .formatEditUpdate(testOldValue, testNewValue);
...@@ -97,6 +183,22 @@ void main() { ...@@ -97,6 +183,22 @@ void main() {
}); });
test('test digits only formatter', () { test('test digits only formatter', () {
final TextEditingValue actualValue =
FilteringTextInputFormatter.digitsOnly
.formatEditUpdate(testOldValue, testNewValue);
// Expecting
// 1(234)56
expect(actualValue, const TextEditingValue(
text: '123456',
selection: TextSelection(
baseOffset: 1,
extentOffset: 4,
),
));
});
test('test digits only formatter (deprecated names)', () {
final TextEditingValue actualValue = final TextEditingValue actualValue =
WhitelistingTextInputFormatter.digitsOnly WhitelistingTextInputFormatter.digitsOnly
.formatEditUpdate(testOldValue, testNewValue); .formatEditUpdate(testOldValue, testNewValue);
...@@ -246,6 +348,5 @@ void main() { ...@@ -246,6 +348,5 @@ void main() {
), ),
)); ));
}); });
}); });
} }
...@@ -129,9 +129,9 @@ class FlutterDriverExtension { ...@@ -129,9 +129,9 @@ class FlutterDriverExtension {
'waitFor': _waitFor, 'waitFor': _waitFor,
'waitForAbsent': _waitForAbsent, 'waitForAbsent': _waitForAbsent,
'waitForCondition': _waitForCondition, 'waitForCondition': _waitForCondition,
'waitUntilNoTransientCallbacks': _waitUntilNoTransientCallbacks, // ignore: deprecated_member_use_from_same_package 'waitUntilNoTransientCallbacks': _waitUntilNoTransientCallbacks,
'waitUntilNoPendingFrame': _waitUntilNoPendingFrame, // ignore: deprecated_member_use_from_same_package 'waitUntilNoPendingFrame': _waitUntilNoPendingFrame,
'waitUntilFirstFrameRasterized': _waitUntilFirstFrameRasterized, // ignore: deprecated_member_use_from_same_package 'waitUntilFirstFrameRasterized': _waitUntilFirstFrameRasterized,
'get_semantics_id': _getSemanticsId, 'get_semantics_id': _getSemanticsId,
'get_offset': _getOffset, 'get_offset': _getOffset,
'get_diagnostics_tree': _getDiagnosticsTree, 'get_diagnostics_tree': _getDiagnosticsTree,
...@@ -153,9 +153,9 @@ class FlutterDriverExtension { ...@@ -153,9 +153,9 @@ class FlutterDriverExtension {
'waitFor': (Map<String, String> params) => WaitFor.deserialize(params), 'waitFor': (Map<String, String> params) => WaitFor.deserialize(params),
'waitForAbsent': (Map<String, String> params) => WaitForAbsent.deserialize(params), 'waitForAbsent': (Map<String, String> params) => WaitForAbsent.deserialize(params),
'waitForCondition': (Map<String, String> params) => WaitForCondition.deserialize(params), 'waitForCondition': (Map<String, String> params) => WaitForCondition.deserialize(params),
'waitUntilNoTransientCallbacks': (Map<String, String> params) => WaitUntilNoTransientCallbacks.deserialize(params), // ignore: deprecated_member_use_from_same_package 'waitUntilNoTransientCallbacks': (Map<String, String> params) => WaitUntilNoTransientCallbacks.deserialize(params),
'waitUntilNoPendingFrame': (Map<String, String> params) => WaitUntilNoPendingFrame.deserialize(params), // ignore: deprecated_member_use_from_same_package 'waitUntilNoPendingFrame': (Map<String, String> params) => WaitUntilNoPendingFrame.deserialize(params),
'waitUntilFirstFrameRasterized': (Map<String, String> params) => WaitUntilFirstFrameRasterized.deserialize(params), // ignore: deprecated_member_use_from_same_package 'waitUntilFirstFrameRasterized': (Map<String, String> params) => WaitUntilFirstFrameRasterized.deserialize(params),
'get_semantics_id': (Map<String, String> params) => GetSemanticsId.deserialize(params), 'get_semantics_id': (Map<String, String> params) => GetSemanticsId.deserialize(params),
'get_offset': (Map<String, String> params) => GetOffset.deserialize(params), 'get_offset': (Map<String, String> params) => GetOffset.deserialize(params),
'get_diagnostics_tree': (Map<String, String> params) => GetDiagnosticsTree.deserialize(params), 'get_diagnostics_tree': (Map<String, String> params) => GetDiagnosticsTree.deserialize(params),
......
...@@ -41,7 +41,7 @@ void main() { ...@@ -41,7 +41,7 @@ void main() {
}); });
testWidgets('returns immediately when transient callback queue is empty', (WidgetTester tester) async { testWidgets('returns immediately when transient callback queue is empty', (WidgetTester tester) async {
extension.call(const WaitUntilNoTransientCallbacks().serialize()) // ignore: deprecated_member_use_from_same_package extension.call(const WaitUntilNoTransientCallbacks().serialize())
.then<void>(expectAsync1((Map<String, dynamic> r) { .then<void>(expectAsync1((Map<String, dynamic> r) {
result = r; result = r;
})); }));
...@@ -61,7 +61,7 @@ void main() { ...@@ -61,7 +61,7 @@ void main() {
// Intentionally blank. We only care about existence of a callback. // Intentionally blank. We only care about existence of a callback.
}); });
extension.call(const WaitUntilNoTransientCallbacks().serialize()) // ignore: deprecated_member_use_from_same_package extension.call(const WaitUntilNoTransientCallbacks().serialize())
.then<void>(expectAsync1((Map<String, dynamic> r) { .then<void>(expectAsync1((Map<String, dynamic> r) {
result = r; result = r;
})); }));
...@@ -888,7 +888,7 @@ void main() { ...@@ -888,7 +888,7 @@ void main() {
testWidgets('returns immediately when frame is synced', ( testWidgets('returns immediately when frame is synced', (
WidgetTester tester) async { WidgetTester tester) async {
extension.call(const WaitUntilNoPendingFrame().serialize()) // ignore: deprecated_member_use_from_same_package extension.call(const WaitUntilNoPendingFrame().serialize())
.then<void>(expectAsync1((Map<String, dynamic> r) { .then<void>(expectAsync1((Map<String, dynamic> r) {
result = r; result = r;
})); }));
...@@ -909,7 +909,7 @@ void main() { ...@@ -909,7 +909,7 @@ void main() {
// Intentionally blank. We only care about existence of a callback. // Intentionally blank. We only care about existence of a callback.
}); });
extension.call(const WaitUntilNoPendingFrame().serialize()) // ignore: deprecated_member_use_from_same_package extension.call(const WaitUntilNoPendingFrame().serialize())
.then<void>(expectAsync1((Map<String, dynamic> r) { .then<void>(expectAsync1((Map<String, dynamic> r) {
result = r; result = r;
})); }));
...@@ -933,7 +933,7 @@ void main() { ...@@ -933,7 +933,7 @@ void main() {
'waits until no pending scheduled frame', (WidgetTester tester) async { 'waits until no pending scheduled frame', (WidgetTester tester) async {
SchedulerBinding.instance.scheduleFrame(); SchedulerBinding.instance.scheduleFrame();
extension.call(const WaitUntilNoPendingFrame().serialize()) // ignore: deprecated_member_use_from_same_package extension.call(const WaitUntilNoPendingFrame().serialize())
.then<void>(expectAsync1((Map<String, dynamic> r) { .then<void>(expectAsync1((Map<String, dynamic> r) {
result = r; result = r;
})); }));
......
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