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

This relands #59120, which was reverted in #59870.
diff --git a/dev/bots/analyze.dart b/dev/bots/analyze.dart
index b0e9353..d4c788b 100644
--- a/dev/bots/analyze.dart
+++ b/dev/bots/analyze.dart
@@ -135,7 +135,7 @@
 final RegExp _findDeprecationPattern = RegExp(r'@[Dd]eprecated');
 final RegExp _deprecationPattern1 = RegExp(r'^( *)@Deprecated\($'); // ignore: flutter_deprecation_syntax (see analyze.dart)
 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'^ *\)$');
 
 /// Some deprecation notices are special, for example they're used to annotate members that
@@ -182,7 +182,7 @@
           if (message == null) {
             final String firstChar = String.fromCharCode(match2[1].runes.first);
             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];
           lineNumber += 1;
@@ -190,6 +190,13 @@
             throw 'Incomplete deprecation notice.';
           match3 = _deprecationPattern3.firstMatch(lines[lineNumber]);
         } 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('?'))
           throw 'Deprecation notice should be a grammatically correct sentence and end with a period.';
         if (!lines[lineNumber].startsWith("$indent  '"))
diff --git a/dev/bots/test/analyze-test-input/root/packages/foo/deprecation.dart b/dev/bots/test/analyze-test-input/root/packages/foo/deprecation.dart
index aad90fb..b430a0a 100644
--- a/dev/bots/test/analyze-test-input/root/packages/foo/deprecation.dart
+++ b/dev/bots/test/analyze-test-input/root/packages/foo/deprecation.dart
@@ -55,6 +55,42 @@
 
 @Deprecated(
   'URLs are not required. '
-  'This feature was deprecated after v2.0.0.'
+  'This feature was deprecated after v1.0.0.'
 )
 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() { }
diff --git a/dev/bots/test/analyze_test.dart b/dev/bots/test/analyze_test.dart
index faba5bb..d3799b3 100644
--- a/dev/bots/test/analyze_test.dart
+++ b/dev/bots/test/analyze_test.dart
@@ -41,7 +41,7 @@
       +
       (
         '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: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'
@@ -49,7 +49,12 @@
         '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: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('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'
diff --git a/dev/integration_tests/flutter_gallery/lib/demo/material/text_form_field_demo.dart b/dev/integration_tests/flutter_gallery/lib/demo/material/text_form_field_demo.dart
index cd87f74..1dbecca 100644
--- a/dev/integration_tests/flutter_gallery/lib/demo/material/text_form_field_demo.dart
+++ b/dev/integration_tests/flutter_gallery/lib/demo/material/text_form_field_demo.dart
@@ -217,7 +217,7 @@
                     validator: _validatePhoneNumber,
                     // TextInputFormatters are applied in sequence.
                     inputFormatters: <TextInputFormatter> [
-                      WhitelistingTextInputFormatter.digitsOnly,
+                      FilteringTextInputFormatter.digitsOnly,
                       // Fit the validating format.
                       _phoneNumberFormatter,
                     ],