You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Dart version and tooling diagnostic info (dart info)
- Dart 3.2.3 (stable) (Tue Dec 5 17:58:33 2023 +0000) on "macos_arm64"
- on macos / Version 14.3 (Build 23D56)
- locale is en-US
I'm experiencing constant hangs when trying to use a Flutter TextInputFormatter that utilizes a regex inside it. The code is as follows:
class_CurrencyInputFormatterextendsTextInputFormatter {
finalOption<CurrencyFormat> currencyFormat;
_CurrencyInputFormatter({requiredthis.currencyFormat});
@overrideTextEditingValueformatEditUpdate(
TextEditingValue oldValue,
TextEditingValue newValue,
) {
final text = newValue.text;
if (text.isEmpty) {
return newValue;
}
final withoutSymbols =RegExp(r'[^\d]').allMatches(text).map((e) => e.group(0)).join();
final number =int.tryParse(withoutSymbols);
if (number ==null) {
return oldValue;
}
returnTextEditingValue(text: number.formatted(currencyFormat));
}
}
I run the app, and the app hangs either after the first character or sometimes before the first character. The logs seem to have a lot going on related to string.dart though I don't recall ever opening that file.
<details open>
<summary>Output of `Capture Logs`</summary>
<br>
!! ⚠️ PLEASE REVIEW THIS LOG FOR SENSITIVE INFORMATION BEFORE SHARING ⚠️ !!
Dart Code extension: 3.82.0
Flutter extension: 3.82.0 (activated)
App: Visual Studio Code
App Host: desktop
Version: mac 1.86.2
Workspace type: Dart, Flutter (LSP)
Dart (3.2.3): /Users/brandontrautmann/fvm/versions/3.16.0/bin/cache/dart-sdk
Flutter (3.16.4): /Users/brandontrautmann/fvm/versions/3.16.0 (No device)
Logging Categories:
General, Analyzer, AnalyzerTiming, CommandProcesses, DartTest, DAP, VmService, DevTools, FlutterDaemon, FlutterRun, FlutterTest, WebDaemon
Thu Feb 29 2024 [19:26:33 GMT-0500 (Eastern Standard Time)] Log file started
[7:26:34 PM] [Analyzer] [Info] ==> Content-Length: 239
[7:26:34 PM] [Analyzer] [Info] ==> {"jsonrpc":"2.0","id":6906,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///Users/brandontrautmann/Development/Lumy/lib/ui/currency.dart"},"position":{"line":77,"character":19}},"clientRequestTime":1709252794537}
[7:26:34 PM] [Analyzer] [Info] <== Content-Length: 392
Content-Type: application/vscode-jsonrpc; charset=utf-8
[7:26:34 PM] [Analyzer] [Info] <== {"id":6906,"jsonrpc":"2.0","result":[{"originSelectionRange":{"end":{"character":25,"line":77},"start":{"character":17,"line":77}},"targetRange":{"end":{"character":25,"line":77},"start":{"character":4,"line":77}},"targetSelectionRange":{"end":{"character":25,"line":77},"start":{"character":17,"line":77}},"targetUri":"file:///Users/brandontrautmann/Development/Lumy/lib/ui/currency.dart"}]}
[7:26:34 PM] [Analyzer] [Info] ==> Content-Length: 239
[7:26:34 PM] [Analyzer] [Info] ==> {"jsonrpc":"2.0","id":6907,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///Users/brandontrautmann/Development/Lumy/lib/ui/currency.dart"},"position":{"line":75,"character":18}},"clientRequestTime":1709252794556}
[7:26:34 PM] [Analyzer] [Info] <== Content-Length: 392
Content-Type: application/vscode-jsonrpc; charset=utf-8
[7:26:34 PM] [Analyzer] [Info] <== {"id":6907,"jsonrpc":"2.0","result":[{"originSelectionRange":{"end":{"character":20,"line":75},"start":{"character":17,"line":75}},"targetRange":{"end":{"character":20,"line":75},"start":{"character":4,"line":75}},"targetSelectionRange":{"end":{"character":20,"line":75},"start":{"character":17,"line":75}},"targetUri":"file:///Users/brandontrautmann/Development/Lumy/lib/ui/currency.dart"}]}
[7:26:34 PM] [Analyzer] [Info] ==> Content-Length: 239
[7:26:34 PM] [Analyzer] [Info] ==> {"jsonrpc":"2.0","id":6908,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///Users/brandontrautmann/Development/Lumy/lib/ui/currency.dart"},"position":{"line":73,"character":16}},"clientRequestTime":1709252794561}
[7:26:34 PM] [Analyzer] [Info] <== Content-Length: 390
Content-Type: application/vscode-jsonrpc; charset=utf-8
[7:26:34 PM] [Analyzer] [Info] <== {"id":6908,"jsonrpc":"2.0","result":[{"originSelectionRange":{"end":{"character":22,"line":73},"start":{"character":9,"line":73}},"targetRange":{"end":{"character":3,"line":128},"start":{"character":2,"line":73}},"targetSelectionRange":{"end":{"character":22,"line":73},"start":{"character":9,"line":73}},"targetUri":"file:///Users/brandontrautmann/Development/Lumy/lib/ui/currency.dart"}]}
[7:26:34 PM] [Analyzer] [Info] ==> Content-Length: 234
[7:26:34 PM] [Analyzer] [Info] ==> {"jsonrpc":"2.0","id":6909,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///Users/brandontrautmann/Development/Lumy/lib/ui/currency.dart"},"position":{"line":73,"character":15}},"clientRequestTime":1709252794727}
[7:26:34 PM] [Analyzer] [Info] <== Content-Length: 349
Content-Type: application/vscode-jsonrpc; charset=utf-8
[7:26:34 PM] [Analyzer] [Info] <== {"id":6909,"jsonrpc":"2.0","result":{"contents":{"kind":"markdown","value":"```dart\nString formatForAxis({\n required Option<CurrencyFormat> currencyFormat,\n required num min,\n required num max,\n required num interval,\n})\n```\n*package:lumy/ui/currency.dart*"},"range":{"end":{"character":22,"line":73},"start":{"character":9,"line":73}}}}
[7:26:37 PM] [DAP] [Info] <== {"seq":374,"type":"event","body":{"category":"console","output":"[GoRouter] going to /set_target_amount\n"},"event":"output"}
[7:26:39 PM] [DAP] [Info] ==> {"command":"setBreakpoints","arguments":{"source":{"adapterData":{"type":"@Script","id":"libraries/@184249395/scripts/package%3Alumy%2Fui%2Fcurrency.dart/18df767a9b3","fixedId":true,"uri":"package:lumy/ui/currency.dart"},"name":"package:lumy/ui/currency.dart","path":"/Users/brandontrautmann/Development/Lumy/lib/ui/currency.dart"},"lines":[45,46,55,56,57,58,65,68],"breakpoints":[{"line":45},{"line":46},{"line":55},{"line":56},{"line":57},{"line":58},{"line":65},{"line":68}],"sourceModified":false},"type":"request","seq":21}
[7:26:39 PM] [DAP] [Info] ==> {"command":"setBreakpoints","arguments":{"source":{"name":"set_frugal_month_target_screen.dart","path":"/Users/brandontrautmann/Development/Lumy/lib/features/frugal_month/set_frugal_month_target_screen.dart"},"lines":[90,91,92,97,99,100,102],"breakpoints":[{"line":90},{"line":91},{"line":92},{"line":97},{"line":99},{"line":100},{"line":102}],"sourceModified":false},"type":"request","seq":22}
[7:26:39 PM] [Analyzer] [Info] ==> Content-Length: 238
[7:26:39 PM] [Analyzer] [Info] ==> {"jsonrpc":"2.0","id":6910,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///Users/brandontrautmann/Development/Lumy/lib/ui/currency.dart"},"position":{"line":73,"character":2}},"clientRequestTime":1709252799995}
[7:26:40 PM] [Analyzer] [Info] <== Content-Length: 421
Content-Type: application/vscode-jsonrpc; charset=utf-8
{"id":6910,"jsonrpc":"2.0","result":[{"originSelectionRange":{"end":{"character":8,"line":73},"start":{"character":2,"line":73}},"targetRange":{"end":{"character":1,"line":723},"start":{"character":0,"line":107}},"targetSelectionRange":{"end":{"character":27,"line":107},"start":{"character":21,"line":107}},"targetUri":"file:///Users/brandontrautmann/fvm/versions/3.16.0/bin/cache/pkg/sky_engine/lib/core/string.dart"}]}
[7:26:40 PM] [Analyzer] [Info] ==> Content-Length: 233
[7:26:40 PM] [Analyzer] [Info] ==> {"jsonrpc":"2.0","id":6911,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///Users/brandontrautmann/Development/Lumy/lib/ui/currency.dart"},"position":{"line":73,"character":3}},"clientRequestTime":1709252800152}
[7:26:40 PM] [Analyzer] [Info] <== Content-Length: 3946
Content-Type: application/vscode-jsonrpc; charset=utf-8
[7:26:40 PM] [Analyzer] [Info] <== {"id":6911,"jsonrpc":"2.0","result":{"contents":{"kind":"markdown","value":"```dart\nabstract final class String implements Comparable<String>, Pattern\n```\n*dart:core*\n\n---\nA sequence of UTF-16 code units.\n\nStrings are mainly used to represent text. A character may be represented by\nmultiple code points, each code point consisting of one or two code\nunits. For example, the Papua New Guinea flag character requires four code\nunits to represent two code points, but should be treated like a single\ncharacter: \"🇵🇬\". Platforms that do not support the flag character may show\nthe letters \"PG\" instead. If the code points are swapped, it instead becomes\nthe Guadeloupe flag \"🇬🇵\" (\"GP\").\n\nA string can be either single or multiline. Single line strings are\nwritten using matching single or double quotes, and multiline strings are\nwritten using triple quotes. The following are all valid Dart strings:\n```dart\n'Single quotes';\n\"Double quotes\";\n'Double quotes in \"single\" quotes';\n\"Single quotes in 'double' quotes\";\n\n'''A\nmultiline\nstring''';\n\n\"\"\"\nAnother\nmultiline\nstring\"\"\";\n```\nStrings are immutable. Although you cannot change a string, you can perform\nan operation on a string which creates a new string:\n```dart\nconst string = 'Dart is fun';\nprint(string.substring(0, 4)); // 'Dart'\n```\nYou can use the plus (`+`) operator to concatenate strings:\n```dart\nconst string = 'Dart ' + 'is ' + 'fun!';\nprint(string); // 'Dart is fun!'\n```\nAdjacent string literals are concatenated automatically:\n```dart\nconst string = 'Dart ' 'is ' 'fun!';\nprint(string); // 'Dart is fun!'\n```\nYou can use `${}` to interpolate the value of Dart expressions\nwithin strings. The curly braces can be omitted when evaluating identifiers:\n```dart\nconst string = 'dartlang';\nprint('$string has ${string.length} letters'); // dartlang has 8 letters\n```\nA string is represented by a sequence of Unicode UTF-16 code units\naccessible through the [codeUnitAt] or the [codeUnits] members:\n```dart\nconst string = 'Dart';\nfinal firstCodeUnit = string.codeUnitAt(0);\nprint(firstCodeUnit); // 68, aka U+0044, the code point for 'D'.\nfinal allCodeUnits = string.codeUnits;\nprint(allCodeUnits); // [68, 97, 114, 116]\n```\nA string representation of the individual code units is accessible through\nthe index operator:\n```dart\nconst string = 'Dart';\nfinal charAtIndex = string[0];\nprint(charAtIndex); // 'D'\n```\nThe characters of a string are encoded in UTF-16. Decoding UTF-16, which\ncombines surrogate pairs, yields Unicode code points. Following a similar\nterminology to Go, Dart uses the name 'rune' for an integer representing a\nUnicode code point. Use the [runes] property to get the runes of a string:\n```dart\nconst string = 'Dart';\nfinal runes = string.runes.toList();\nprint(runes); // [68, 97, 114, 116]\n```\nFor a character outside the Basic Multilingual Plane (plane 0) that is\ncomposed of a surrogate pair, [runes] combines the pair and returns a\nsingle integer. For example, the Unicode character for a\nmusical G-clef ('𝄞') with rune value 0x1D11E consists of a UTF-16 surrogate\npair: `0xD834` and `0xDD1E`. Using [codeUnits] returns the surrogate pair,\nand using `runes` returns their combined value:\n```dart\nconst clef = '\\u{1D11E}';\nfor (final item in clef.codeUnits) {\n print(item.toRadixString(16));\n // d834\n // dd1e\n}\nfor (final item in clef.runes) {\n print(item.toRadixString(16)); // 1d11e\n}\n```\nThe `String` class cannot be extended or implemented. Attempting to do so\nyields a compile-time error.\n\n## Other resources\n\n* [StringBuffer] to efficiently build a string incrementally.\n* [RegExp] to work with regular expressions.\n* [Strings and regular expressions](https://dart.dev/guides/libraries/library-tour#strings-and-regular-expressions)"},"range":{"end":{"character":8,"line":73},"start":{"character":2,"line":73}}}}
[7:26:40 PM] [Analyzer] [Info] ==> Content-Length: 37758
[7:26:40 PM] [Analyzer] [Info] ==> {"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///Users/brandontrautmann/fvm/versions/3.16.0/bin/cache/pkg/sky_engine/lib/core/string.dart","languageId":"dart","version":1,"text":"// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file\n// for details. All rights reserved. Use of this source code is governed by a\n// BSD-style license that can be found in the LICENSE file.\n\npart of dart.core;\n\n/// A sequence of UTF-16 code units.\n///\n/// Strings are mainly used to represent text. A character may be represented by\n/// multiple code points, each code point consisting of one or two code\n/// units. For example, the Papua New Guinea flag character requires four code\n/// units to represent two code points, but should be treated like a single\n/// character: \"🇵🇬\". Platforms that do not support the flag character may show\n/// the letters \"PG\" instead. If the code points are swapped, it instead becomes\n/// the Guadeloupe flag \"🇬🇵\" (\"GP\").\n///\n/// A string can be either single or multiline. Single line strings are\n/// written using matching single or double quotes, and multiline strings are\n/// written using triple quotes. The following are all valid Dart strings:\n/// ```dart\n/// 'Single quotes';\n/// \"Double quotes\";\n/// 'Double quotes in \"single\" quotes';\n/// \"Single quotes in 'double' quotes\";\n///\n/// '''A\n/// multiline\n/// string''';\n///\n/// \"\"\"\n/// Another\n/// multiline\n/// string\"\"\";\n/// ```\n/// Strings are immutable. Although you cannot change a string, you can perform\n/// an operation on a string which creates a new string:\n/// ```dart\n/// const string = 'Dart is fun';\n/// print(string.substring(0, 4)); // 'Dart'\n/// ```\n/// You can use the plus (`+`) operator to concatenate strings:\n/// ```dart\n/// const string = 'Dart ' + 'is ' + 'fun!';\n/// print(string); // 'Dart is fun!'\n/// ```\n/// Adjacent string literals are concatenated automatically:\n/// ```dart\n/// const string = 'Dart ' 'is ' 'fun!';\n/// print(string); // 'Dart is fun!'\n/// ```\n/// You can use `${}` to interpolate the value of Dart expressions\n/// within strings. The curly braces can be omitted when evaluating identifiers:\n/// ```dart\n/// const string = 'dartlang';\n/// print('$string has ${string.length} letters'); // dartlang has 8 letters\n/// ```\n/// A string is represented by a sequence of Unicode UTF-16 code units\n/// accessible through the [codeUnitAt] or the [codeUnits] members:\n/// ```dart\n/// const string = 'Dart';\n/// final firstCodeUnit = string.codeUnitAt(0);\n/// print(firstCodeUnit); // 68, aka U+0044, the code point for 'D'.\n/// final allCodeUnits = string.codeUnits;\n/// print(allCodeUnits); // [68, 97, 114, 116]\n/// ```\n/// A string representation of the individual code units is accessible through\n/// the index operator:\n/// ```dart\n/// const string = 'Dart';\n/// final charAtIndex = string[0];\n/// print(charAtIndex); // 'D'\n/// ```\n/// The characters of a string are encoded in UTF-16. Decoding UTF-16, which\n/// combines surrogate pairs, yields Unicode code points. Following a similar\n/// terminology to Go, Dart uses the name 'rune' for an integer representing a\n/// Unicode code point. Use the [runes] property to get the runes of a string:\n/// ```dart\n/// const string = 'Dart';\n/// final runes = string.runes.toList();\n/// print(runes); // [68, 97, 114, 116]\n/// ```\n/// For a character outside the Basic Multilingual Plane (plane 0) that is\n/// composed of a surrogate pair, [runes] combines the pair and returns a\n/// single integer. For example, the Unicode character for a\n/// musical G-clef ('𝄞') with rune value 0x1D11E consists of a UTF-16 surrogate\n/// pair: `0xD834` and `0xDD1E`. Using [codeUnits] returns the surrogate pair,\n/// and using `runes` returns their combined value:\n/// ```dart\n/// const clef = '\\u{1D11E}';\n/// for (final item in clef.codeUnits) {\n/// print(item.toRadixString(16));\n/// // d834\n/// // dd1e\n/// }\n/// for (final item in clef.runes) {\n/// print(item.toRadixString(16)); // 1d11e\n/// }\n/// ```\n/// The `String` class cannot be extended or implemented. Attempting to do so\n/// yields a compile-time error.\n///\n/// ## Other resources\n///\n/// * [StringBuffer] to efficiently build a string incrementally.\n/// * [RegExp] to work with regular expressions.\n/// * [Strings and regular expressions](https://dart.dev/guides/libraries/library-tour#strings-and-regular-expressions)\n@pragma('vm:entry-point')\nabstract final class String implements Comparable<String>, Pattern {\n /// Allocates a new string containing the specified [charCodes].\n ///\n /// The [charCodes] can be both UTF-16 code units and runes.\n /// If a char-code value is 16-bit, it is used as a code unit:\n /// ```dart\n /// final string = String.fromCharCodes([68]);\n /// print(string); // D\n /// ```\n /// If a char-code value is greater than 16-bits, it is decomposed into a\n /// surrogate pair:\n /// ```dart\n /// final clef = String.fromCharCodes([0x1D11E]);\n /// clef.codeUnitAt(0); // 0xD834\n /// clef.codeUnitAt(1); // 0xDD1E\n /// ```\n /// If [start] and [end] are provided, only the values of [charCodes]\n /// at positions from `start` to, but not including, `end`, are used.\n /// The `start` and `end` values must satisfy\n /// `0 <= start <= end <= charCodes.length`.\n external factory String.fromCharCodes(Iterable<int> charCodes,\n [int start = 0, int? end]);\n\n /// Allocates a new string containing the specified [charCode].\n ///\n /// If the [charCode] can be represented by a single UTF-16 code unit, the new\n /// string contains a single code unit. Otherwise, the [length] is 2 and\n /// the code units form a surrogate pair. See documentation for\n /// [fromCharCodes].\n ///\n /// Creating a [String] with one half of a surrogate pair is allowed.\n external factory String.fromCharCode(int charCode);\n\n /// The string value of the environment declaration [name].\n ///\n /// Environment declarations are provided by the surrounding system compiling\n /// or running the Dart program. Declarations map a string key to a string\n /// value.\n ///\n /// If [name] is not declared in the environment, the result is instead\n /// [defaultValue].\n ///\n /// Example of getting a value:\n /// ```dart\n /// const String.fromEnvironment(\"defaultFloo\", defaultValue: \"no floo\")\n /// ```\n /// In order to check whether a declaration is there at all, use\n /// [bool.hasEnvironment]. Example:\n /// ```dart\n /// const maybeDeclared = bool.hasEnvironment(\"maybeDeclared\")\n /// ? String.fromEnvironment(\"maybeDeclared\")\n /// : null;\n /// ```\n ///\n /// The string value, or lack of a value, associated with a [name]\n /// must be consistent across all calls to `String.fromEnvironment`,\n /// [int.fromEnvironment], [bool.fromEnvironment] and [bool.hasEnvironment]\n /// in a single program.\n ///\n /// This constructor is only guaranteed to work when invoked as `const`.\n /// It may work as a non-constant invocation on some platforms which\n /// have access to compiler options at run-time, but most ahead-of-time\n /// compiled platforms will not have this information.\n // The .fromEnvironment() constructors are special in that we do not want\n // users to call them using \"new\". We prohibit that by giving them bodies\n // that throw, even though const constructors are not allowed to have bodies.\n // Disable those static errors.\n //ignore: const_constructor_with_body\n //ignore: const_factory\n external const factory String.fromEnvironment(String name,\n {String defaultValue = \"\"});\n\n /// The character (as a single-code-unit [String]) at the given [index].\n ///\n /// The returned string represents exactly one UTF-16 code unit, which may be\n /// half of a surrogate pair. A single member of a surrogate pair is an\n /// invalid UTF-16 string:\n /// ```dart\n /// var clef = '\\u{1D11E}';\n /// // These represent invalid UTF-16 strings.\n /// clef[0].codeUnits; // [0xD834]\n /// clef[1].codeUnits; // [0xDD1E]\n /// ```\n /// This method is equivalent to\n /// `String.fromCharCode(this.codeUnitAt(index))`.\n String operator [](int index);\n\n /// Returns the 16-bit UTF-16 code unit at the given [index].\n int codeUnitAt(int index);\n\n /// The length of the string.\n ///\n /// Returns the number of UTF-16 code units in this string. The number\n /// of [runes] might be fewer if the string contains characters outside\n /// the Basic Multilingual Plane (plane 0):\n /// ```dart\n /// 'Dart'.length; // 4\n /// 'Dart'.runes.length; // 4\n ///\n /// var clef = '\\u{1D11E}';\n /// clef.length; // 2\n /// clef.runes.length; // 1\n /// ```\n int get length;\n\n /// A hash code derived from the code units of the string.\n ///\n /// This is compatible with [operator ==]. Strings with the same sequence\n /// of code units have the same hash code.\n int get hashCode;\n\n /// Whether [other] is a `String` with the same sequence of code units.\n ///\n /// This method compares each individual code unit of the strings.\n /// It does not check for Unicode equivalence.\n /// For example, both the following strings represent the string 'Amélie',\n /// but due to their different encoding, are not equal:\n /// ```dart\n /// 'Am\\xe9lie' == 'Ame\\u{301}lie'; // false\n /// ```\n /// The first string encodes 'é' as a single unicode code unit (also\n /// a single rune), whereas the second string encodes it as 'e' with the\n /// combining accent character '◌́'.\n bool operator ==(Object other);\n\n /// Compares this string to [other].\n ///\n /// Returns a negative value if `this` is ordered before `other`,\n /// a positive value if `this` is ordered after `other`,\n /// or zero if `this` and `other` are equivalent.\n ///\n /// The ordering is the same as the ordering of the code units at the first\n /// position where the two strings differ.\n /// If one string is a prefix of the other,\n /// then the shorter string is ordered before the longer string.\n /// If the strings have exactly the same content, they are equivalent with\n /// regard to the ordering.\n /// Ordering does not check for Unicode equivalence.\n /// The comparison is case sensitive.\n /// ```dart\n /// var relation = 'Dart'.compareTo('Go');\n /// print(relation); // < 0\n /// relation = 'Go'.compareTo('Forward');\n /// print(relation); // > 0\n /// relation = 'Forward'.compareTo('Forward');\n /// print(relation); // 0\n /// ```\n int compareTo(String other);\n\n /// Whether this string ends with [other].\n ///\n /// For example:\n /// ```dart\n /// const string = 'Dart is open source';\n /// print(string.endsWith('urce')); // true\n /// ```\n bool endsWith(String other);\n\n /// Whether this string starts with a match of [pattern].\n ///\n /// ```dart\n /// const string = 'Dart is open source';\n /// print(string.startsWith('Dar')); // true\n /// print(string.startsWith(RegExp(r'[A-Z][a-z]'))); // true\n /// ```\n /// If [index] is provided, this method checks if the substring starting\n /// at that index starts with a match of [pattern]:\n /// ```dart\n /// const string = 'Dart';\n /// print(string.startsWith('art', 0)); // false\n /// print(string.startsWith('art', 1)); // true\n /// print(string.startsWith(RegExp(r'\\w{3}'), 2)); // false\n /// ```\n /// [index] must not be negative or greater than [length].\n ///\n /// A [RegExp] containing '^' does not match if the [index] is greater than\n /// zero and the regexp is not multi-line.\n /// The pattern works on the string as a whole, and does not extract\n /// a substring starting at [index] first:\n /// ```dart\n /// const string = 'Dart';\n /// print(string.startsWith(RegExp(r'^art'), 1)); // false\n /// print(string.startsWith(RegExp(r'art'), 1)); // true\n /// ```\n bool startsWith(Pattern pattern, [int index = 0]);\n\n /// Returns the position of the first match of [pattern] in this string,\n /// starting at [start], inclusive:\n /// ```dart\n /// const string = 'Dartisans';\n /// print(string.indexOf('art')); // 1\n /// print(string.indexOf(RegExp(r'[A-Z][a-z]'))); // 0\n /// ```\n /// Returns -1 if no match is found:\n /// ```dart\n /// const string = 'Dartisans';\n /// string.indexOf(RegExp(r'dart')); // -1\n /// ```\n /// The [start] must be non-negative and not greater than [length].\n int indexOf(Pattern pattern, [int start = 0]);\n\n /// The starting position of the last match [pattern] in this string.\n ///\n /// Finds a match of pattern by searching backward starting at [start]:\n /// ```dart\n /// const string = 'Dartisans';\n /// print(string.lastIndexOf('a')); // 6\n /// print(string.lastIndexOf(RegExp(r'a(r|n)'))); // 6\n /// ```\n /// Returns -1 if [pattern] could not be found in this string.\n /// ```dart\n /// const string = 'Dartisans';\n /// print(string.lastIndexOf(RegExp(r'DART'))); // -1\n /// ```\n /// If [start] is omitted, search starts from the end of the string.\n /// If supplied, [start] must be non-negative and not greater than [length].\n int lastIndexOf(Pattern pattern, [int? start]);\n\n /// Whether this string is empty.\n bool get isEmpty;\n\n /// Whether this string is not empty.\n bool get isNotEmpty;\n\n /// Creates a new string by concatenating this string with [other].\n ///\n /// Example:\n /// ```dart\n /// const string = 'dart' + 'lang'; // 'dartlang'\n /// ```\n String operator +(String other);\n\n /// The substring of this string from [start], inclusive, to [end], exclusive.\n ///\n /// Example:\n /// ```dart\n /// const string = 'dartlang';\n /// var result = string.substring(1); // 'artlang'\n /// result = string.substring(1, 4); // 'art'\n /// ```\n ///\n /// Both [start] and [end] must be non-negative and no greater than [length];\n /// [end], if provided, must be greater than or equal to [start].\n String substring(int start, [int? end]);\n\n /// The string without any leading and trailing whitespace.\n ///\n /// If the string contains leading or trailing whitespace, a new string with no\n /// leading and no trailing whitespace is returned:\n /// ```dart\n /// final trimmed = '\\tDart is fun\\n'.trim();\n /// print(trimmed); // 'Dart is fun'\n /// ```\n /// Otherwise, the original string itself is returned:\n /// ```dart\n /// const string1 = 'Dart';\n /// final string2 = string1.trim(); // 'Dart'\n /// print(identical(string1, string2)); // true\n /// ```\n /// Whitespace is defined by the Unicode White_Space property (as defined in\n /// version 6.2 or later) and the BOM character, 0xFEFF.\n ///\n /// Here is the list of trimmed characters according to Unicode version 6.3:\n /// ```plaintext\n /// 0009..000D ; White_Space # Cc <control-0009>..<control-000D>\n /// 0020 ; White_Space # Zs SPACE\n /// 0085 ; White_Space # Cc <control-0085>\n /// 00A0 ; White_Space # Zs NO-BREAK SPACE\n /// 1680 ; White_Space # Zs OGHAM SPACE MARK\n /// 2000..200A ; White_Space # Zs EN QUAD..HAIR SPACE\n /// 2028 ; White_Space # Zl LINE SEPARATOR\n /// 2029 ; White_Space # Zp PARAGRAPH SEPARATOR\n /// 202F ; White_Space # Zs NARROW NO-BREAK SPACE\n /// 205F ; White_Space # Zs MEDIUM MATHEMATICAL SPACE\n /// 3000 ; White_Space # Zs IDEOGRAPHIC SPACE\n ///\n /// FEFF ; BOM ZERO WIDTH NO_BREAK SPACE\n /// ```\n /// Some later versions of Unicode do not include U+0085 as a whitespace\n /// character. Whether it is trimmed depends on the Unicode version\n /// used by the system.\n String trim();\n\n /// The string without any leading whitespace.\n ///\n /// As [trim], but only removes leading whitespace.\n /// ```dart\n /// final string = ' Dart '.trimLeft();\n /// print(string); // 'Dart '\n /// ```\n String trimLeft();\n\n /// The string without any trailing whitespace.\n ///\n /// As [trim], but only removes trailing whitespace.\n /// ```dart\n /// final string = ' Dart '.trimRight();\n /// print(string); // ' Dart'\n /// ```\n String trimRight();\n\n /// Creates a new string by concatenating this string with itself a number\n /// of times.\n ///\n /// The result of `str * n` is equivalent to\n /// `str + str + ...`(n times)`... + str`.\n ///\n /// ```dart\n /// const string = 'Dart';\n /// final multiplied = string * 3;\n /// print(multiplied); // 'DartDartDart'\n /// ```\n /// Returns an empty string if [times] is zero or negative.\n String operator *(int times);\n\n /// Pads this string on the left if it is shorter than [width].\n ///\n /// Returns a new string that prepends [padding] onto this string\n /// one time for each position the length is less than [width].\n ///\n /// ```dart\n /// const string = 'D';\n /// print(string.padLeft(4)); // ' D'\n /// print(string.padLeft(2, 'x')); // 'xD'\n /// print(string.padLeft(4, 'y')); // 'yyyD'\n /// print(string.padLeft(4, '>>')); // '>>>>>>D'\n /// ```\n ///\n /// If [width] is already smaller than or equal to `this.length`,\n /// no padding is added. A negative `width` is treated as zero.\n ///\n /// If [padding] has length different from 1, the result will not\n /// have length `width`. This may be useful for cases where the\n /// padding is a longer string representing a single character, like\n /// `\" \"` or `\"\\u{10002}`\".\n /// In that case, the user should make sure that `this.length` is\n /// the correct measure of the string's length.\n String padLeft(int width, [String padding = ' ']);\n\n /// Pads this string on the right if it is shorter than [width].\n ///\n /// Returns a new string that appends [padding] after this string\n /// one time for each position the length is less than [width].\n ///\n /// ```dart\n /// const string = 'D';\n /// print(string.padRight(4)); // 'D '\n /// print(string.padRight(2, 'x')); // 'Dx'\n /// print(string.padRight(4, 'y')); // 'Dyyy'\n /// print(string.padRight(4, '>>')); // 'D>>>>>>'\n /// ```\n ///\n /// If [width] is already smaller than or equal to `this.length`,\n /// no padding is added. A negative `width` is treated as zero.\n ///\n /// If [padding] has length different from 1, the result will not\n /// have length `width`. This may be useful for cases where the\n /// padding is a longer string representing a single character, like\n /// `\" \"` or `\"\\u{10002}`\".\n /// In that case, the user should make sure that `this.length` is\n /// the correct measure of the string's length.\n String padRight(int width, [String padding = ' ']);\n\n /// Whether this string contains a match of [other].\n ///\n /// Example:\n /// ```dart\n /// const string = 'Dart strings';\n /// final containsD = string.contains('D'); // true\n /// final containsUpperCase = string.contains(RegExp(r'[A-Z]')); // true\n /// ```\n /// If [startIndex] is provided, this method matches only at or after that\n /// index:\n /// ```dart\n /// const string = 'Dart strings';\n /// final containsD = string.contains(RegExp('D'), 0); // true\n /// final caseSensitive = string.contains(RegExp(r'[A-Z]'), 1); // false\n /// ```\n /// The [startIndex] must not be negative or greater than [length].\n bool contains(Pattern other, [int startIndex = 0]);\n\n /// Creates a new string with the first occurrence of [from] replaced by [to].\n ///\n /// Finds the first match of [from] in this string, starting from [startIndex],\n /// and creates a new string where that match is replaced with the [to] string.\n ///\n /// Example:\n /// ```dart\n /// '0.0001'.replaceFirst(RegExp(r'0'), ''); // '.0001'\n /// '0.0001'.replaceFirst(RegExp(r'0'), '7', 1); // '0.7001'\n /// ```\n String replaceFirst(Pattern from, String to, [int startIndex = 0]);\n\n /// Replace the first occurrence of [from] in this string.\n ///\n /// ```dart\n /// const string = 'Dart is fun';\n /// print(string.replaceFirstMapped(\n /// 'fun', (m) => 'open source')); // Dart is open source\n ///\n /// print(string.replaceFirstMapped(\n /// RegExp(r'\\w(\\w*)'), (m) => '<${m[0]}-${m[1]}>')); // <Dart-art> is fun\n /// ```\n ///\n /// Returns a new string, which is this string\n /// except that the first match of [from], starting from [startIndex],\n /// is replaced by the result of calling [replace] with the match object.\n ///\n /// The [startIndex] must be non-negative and no greater than [length].\n String replaceFirstMapped(Pattern from, String replace(Match match),\n [int startIndex = 0]);\n\n /// Replaces all substrings that match [from] with [replace].\n ///\n /// Creates a new string in which the non-overlapping substrings matching\n /// [from] (the ones iterated by `from.allMatches(thisString)`) are replaced\n /// by the literal string [replace].\n /// ```dart\n /// 'resume'.replaceAll(RegExp(r'e'), 'é'); // 'résumé'\n /// ```\n /// Notice that the [replace] string is not interpreted. If the replacement\n /// depends on the match (for example, on a [RegExp]'s capture groups), use\n /// the [replaceAllMapped] method instead.\n String replaceAll(Pattern from, String replace);\n\n /// Replace all substrings that match [from] by a computed string.\n ///\n /// Creates a new string in which the non-overlapping substrings that match\n /// [from] (the ones iterated by `from.allMatches(thisString)`) are replaced\n /// by the result of calling [replace] on the corresponding [Match] object.\n ///\n /// This can be used to replace matches with new content that depends on the\n /// match, unlike [replaceAll] where the replacement string is always the same.\n ///\n /// The [replace] function is called with the [Match] generated\n /// by the pattern, and its result is used as replacement.\n ///\n /// The function defined below converts each word in a string to simplified\n /// 'pig latin' using [replaceAllMapped]:\n /// ```dart\n /// String pigLatin(String words) => words.replaceAllMapped(\n /// RegExp(r'\\b(\\w*?)([aeiou]\\w*)', caseSensitive: false),\n /// (Match m) => \"${m[2]}${m[1]}${m[1]!.isEmpty ? 'way' : 'ay'}\");\n ///\n /// final result = pigLatin('I have a secret now!');\n /// print(result); // 'Iway avehay away ecretsay ownay!'\n /// ```\n String replaceAllMapped(Pattern from, String Function(Match match) replace);\n\n /// Replaces the substring from [start] to [end] with [replacement].\n ///\n /// Creates a new string equivalent to:\n /// ```dart\n /// this.substring(0, start) + replacement + this.substring(end)\n /// ```\n /// Example:\n /// ```dart\n /// const string = 'Dart is fun';\n /// final result = string.replaceRange(8, null, 'open source');\n /// print(result); // Dart is open source\n /// ```\n /// The [start] and [end] indices must specify a valid range of this string.\n /// That is `0 <= start <= end <= this.length`.\n /// If [end] is `null`, it defaults to [length].\n String replaceRange(int start, int? end, String replacement);\n\n /// Splits the string at matches of [pattern] and returns a list of substrings.\n ///\n /// Finds all the matches of `pattern` in this string,\n /// as by using [Pattern.allMatches],\n /// and returns the list of the substrings between the matches,\n /// before the first match, and after the last match.\n /// ```dart\n /// const string = 'Hello world!';\n /// final splitted = string.split(' ');\n /// print(splitted); // [Hello, world!];\n /// ```\n /// If the pattern doesn't match this string at all,\n /// the result is always a list containing only the original string.\n ///\n /// If the [pattern] is a [String], then it's always the case that:\n /// ```dart\n /// string.split(pattern).join(pattern) == string\n /// ```\n ///\n /// If the first match is an empty match at the start of the string,\n /// the empty substring before it is not included in the result.\n /// If the last match is an empty match at the end of the string,\n /// the empty substring after it is not included in the result.\n /// If a match is empty, and it immediately follows a previous\n /// match (it starts at the position where the previous match ended),\n /// then the empty substring between the two matches is not\n /// included in the result.\n /// ```dart\n /// const string = 'abba';\n /// final re = RegExp(r'b*');\n /// // re.allMatches(string) will find four matches:\n /// // * empty match before first \"a\".\n /// // * match of \"bb\"\n /// // * empty match after \"bb\", before second \"a\"\n /// // * empty match after second \"a\".\n /// print(string.split(re)); // [a, a]\n /// ```\n ///\n /// A non-empty match at the start or end of the string, or after another\n /// match, is not treated specially, and will introduce empty substrings\n /// in the result:\n /// ```dart\n /// const string = 'abbaa';\n /// final splitted = string.split('a'); // ['', 'bb', '', '']\n /// ```\n ///\n /// If this string is the empty string, the result is an empty list\n /// if `pattern` matches the empty string, since the empty string\n /// before and after the first-and-last empty match are not included.\n /// (It is still a list containing the original empty string `[\"\"]`\n /// if the pattern doesn't match).\n /// ```dart\n /// const string = '';\n /// print(string.split('')); // []\n /// print(string.split('a')); // []\n /// ```\n ///\n /// Splitting with an empty pattern splits the string into single-code unit\n /// strings.\n /// ```dart\n /// const string = 'Pub';\n /// print(string.split('')); // [P, u, b]\n ///\n /// // Same as:\n /// var codeUnitStrings = [\n /// for (final unit in string.codeUnits) String.fromCharCode(unit)\n /// ];\n /// print(codeUnitStrings); // [P, u, b]\n /// ```\n ///\n /// Splitting happens at UTF-16 code unit boundaries,\n /// and not at rune (Unicode code point) boundaries:\n /// ```dart\n /// // String made up of two code units, but one rune.\n /// const string = '\\u{1D11E}';\n /// final splitted = string.split('');\n /// print(splitted); // ['\\ud834', '\\udd1e'] - 2 unpaired surrogate values\n /// ```\n /// To get a list of strings containing the individual runes of a string,\n /// you should not use split.\n /// You can instead get a string for each rune as follows:\n /// ```dart\n /// const string = '\\u{1F642}';\n /// for (final rune in string.runes) {\n /// print(String.fromCharCode(rune));\n /// }\n /// ```\n List<String> split(Pattern pattern);\n\n /// Splits the string, converts its parts, and combines them into a new\n /// string.\n ///\n /// The [pattern] is used to split the string\n /// into parts and separating matches.\n /// Each match of [Pattern.allMatches] of [pattern] on this string is\n /// used as a match, and the substrings between the end of one match\n /// (or the start of the string) and the start of the next match (or the\n /// end of the string) is treated as a non-matched part.\n /// (There is no omission of leading or trailing empty matchs, like\n /// in [split], all matches and parts between the are included.)\n ///\n /// Each match is converted to a string by calling [onMatch]. If [onMatch]\n /// is omitted, the matched substring is used.\n ///\n /// Each non-matched part is converted to a string by a call to [onNonMatch].\n /// If [onNonMatch] is omitted, the non-matching substring itself is used.\n ///\n /// Then all the converted parts are concatenated into the resulting string.\n /// ```dart\n /// final result = 'Eats shoots leaves'.splitMapJoin(RegExp(r'shoots'),\n /// onMatch: (m) => '${m[0]}', // (or no onMatch at all)\n /// onNonMatch: (n) => '*');\n /// print(result); // *shoots*\n /// ```\n String splitMapJoin(Pattern pattern,\n {String Function(Match)? onMatch, String Function(String)? onNonMatch});\n\n /// An unmodifiable list of the UTF-16 code units of this string.\n List<int> get codeUnits;\n\n /// An [Iterable] of Unicode code-points of this string.\n ///\n /// If the string contains surrogate pairs, they are combined and returned\n /// as one integer by this iterator. Unmatched surrogate halves are treated\n /// like valid 16-bit code-units.\n Runes get runes;\n\n /// Converts all characters in this string to lower case.\n ///\n /// If the string is already in all lower case, this method returns `this`.\n /// ```dart\n /// 'ALPHABET'.toLowerCase(); // 'alphabet'\n /// 'abc'.toLowerCase(); // 'abc'\n /// ```\n /// This function uses the language independent Unicode mapping and thus only\n /// works in some languages.\n // TODO(floitsch): document better. (See EcmaScript for description).\n String toLowerCase();\n\n /// Converts all characters in this string to upper case.\n ///\n /// If the string is already in all upper case, this method returns `this`.\n /// ```dart\n /// 'alphabet'.toUpperCase(); // 'ALPHABET'\n /// 'ABC'.toUpperCase(); // 'ABC'\n /// ```\n /// This function uses the language independent Unicode mapping and thus only\n /// works in some languages.\n // TODO(floitsch): document better. (See EcmaScript for description).\n String toUpperCase();\n}\n\n/// The runes (integer Unicode code points) of a [String].\n///\n/// The characters of a string are encoded in UTF-16. Decoding UTF-16, which\n/// combines surrogate pairs, yields Unicode code points. Following a similar\n/// terminology to Go, Dart uses the name 'rune' for an integer representing a\n/// Unicode code point. Use the `runes` property to get the runes of a string.\n///\n/// Example:\n/// ```dart\n/// const string = 'Dart';\n/// final runes = string.runes.toList();\n/// print(runes); // [68, 97, 114, 116]\n/// ```\n///\n/// For a character outside the Basic Multilingual Plane (plane 0) that is\n/// composed of a surrogate pair, runes combines the pair and returns a\n/// single integer.\n///\n/// For example, the Unicode character for \"Man\" emoji ('👨', `U+1F468`) is\n/// combined from the surrogates `U+d83d` and `U+dc68`.\n///\n/// Example:\n/// ```dart\n/// const emojiMan = '👨';\n/// print(emojiMan.runes); // (128104)\n///\n/// // Surrogate pairs:\n/// for (final item in emojiMan.codeUnits) {\n/// print(item.toRadixString(16));\n/// // d83d\n/// // dc68\n/// }\n/// ```\n///\n/// **See also:**\n/// * [Runes and grapheme clusters](\n/// https://dart.dev/guides/language/language-tour#runes-and-grapheme-clusters)\n/// in\n/// [A tour of the Dart language](https://dart.dev/guides/language/language-tour).\nfinal class Runes extends Iterable<int> {\n /// The string that this is the runes of.\n final String string;\n\n /// Creates a [Runes] iterator for [string].\n Runes(this.string);\n\n RuneIterator get iterator => RuneIterator(string);\n\n int get last {\n if (string.length == 0) {\n throw StateError('No elements.');\n }\n int length = string.length;\n int code = string.codeUnitAt(length - 1);\n if (_isTrailSurrogate(code) && string.length > 1) {\n int previousCode = string.codeUnitAt(length - 2);\n if (_isLeadSurrogate(previousCode)) {\n return _combineSurrogatePair(previousCode, code);\n }\n }\n return code;\n }\n}\n\n// Is then code (a 16-bit unsigned integer) a UTF-16 lead surrogate.\nbool _isLeadSurrogate(int code) => (code & 0xFC00) == 0xD800;\n\n// Is then code (a 16-bit unsigned integer) a UTF-16 trail surrogate.\nbool _isTrailSurrogate(int code) => (code & 0xFC00) == 0xDC00;\n\n// Combine a lead and a trail surrogate value into a single code point.\nint _combineSurrogatePair(int start, int end) {\n return 0x10000 + ((start & 0x3FF) << 10) + (end & 0x3FF);\n}\n\n/// [Iterator] for reading runes (integer Unicode code points) of a Dart string.\nfinal class RuneIterator implements Iterator<int> {\n /// String being iterated.\n final String string;\n\n /// Position before the current code point.\n int _position;\n\n /// Position after the current code point.\n int _nextPosition;\n\n /// Current code point.\n ///\n /// If the iterator has hit either end, the [_currentCodePoint] is -1\n /// and `_position == _nextPosition`.\n int _currentCodePoint = -1;\n\n /// Create an iterator positioned at the beginning of the string.\n RuneIterator(String string)\n : this.string = string,\n _position = 0,\n _nextPosition = 0;\n\n /// Create an iterator positioned before the [index]th code unit of the string.\n ///\n /// When created, there is no [current] value.\n /// A [moveNext] will use the rune starting at [index] the current value,\n /// and a [movePrevious] will use the rune ending just before [index] as\n /// the current value.\n ///\n /// The [index] position must not be in the middle of a surrogate pair.\n RuneIterator.at(String string, int index)\n : string = string,\n _position = index,\n _nextPosition = index {\n RangeError.checkValueInInterval(index, 0, string.length);\n _checkSplitSurrogate(index);\n }\n\n /// Throw an error if the index is in the middle of a surrogate pair.\n void _checkSplitSurrogate(int index) {\n if (index > 0 &&\n index < string.length &&\n _isLeadSurrogate(string.codeUnitAt(index - 1)) &&\n _isTrailSurrogate(string.codeUnitAt(index))) {\n throw ArgumentError('Index inside surrogate pair: $index');\n }\n }\n\n /// The starting position of the current rune in the string.\n ///\n /// Returns -1 if there is no current rune ([current] is -1).\n int get rawIndex => (_position != _nextPosition) ? _position : -1;\n\n /// Resets the iterator to the rune at the specified index of the string.\n ///\n /// Setting a negative [rawIndex], or one greater than or equal to\n /// `string.length`, is an error. So is setting it in the middle of a surrogate\n /// pair.\n ///\n /// Setting the position to the end of the string means that there is no\n /// current rune.\n void set rawIndex(int rawIndex) {\n IndexError.check(rawIndex, string.length,\n indexable: string, name: \"rawIndex\");\n reset(rawIndex);\n moveNext();\n }\n\n /// Resets the iterator to the given index into the string.\n ///\n /// After this the [current] value is unset.\n /// You must call [moveNext] make the rune at the position current,\n /// or [movePrevious] for the last rune before the position.\n ///\n /// The [rawIndex] must be non-negative and no greater than `string.length`.\n /// It must also not be the index of the trailing surrogate of a surrogate\n /// pair.\n void reset([int rawIndex = 0]) {\n RangeError.checkValueInInterval(rawIndex, 0, string.length, \"rawIndex\");\n _checkSplitSurrogate(rawIndex);\n _position = _nextPosition = rawIndex;\n _currentCodePoint = -1;\n }\n\n /// The rune (integer Unicode code point) starting at the current position in\n /// the string.\n ///\n /// The value is -1 if there is no current code point.\n int get current => _currentCodePoint;\n\n /// The number of code units comprising the current rune.\n ///\n /// Returns zero if there is no current rune ([current] is -1).\n int get currentSize => _nextPosition - _position;\n\n /// A string containing the current rune.\n ///\n /// For runes outside the basic multilingual plane, this will be\n /// a String of length 2, containing two code units.\n ///\n /// Returns an empty string if there is no [current] value.\n String get currentAsString {\n if (_position == _nextPosition) return \"\";\n if (_position + 1 == _nextPosition) return string[_position];\n return string.substring(_position, _nextPosition);\n }\n\n /// Move to the next code point.\n ///\n /// Returns `true` and updates [current] if there is a next code point.\n /// Returns `false` otherwise, and then there is no current code point.\n bool moveNext() {\n _position = _nextPosition;\n if (_position == string.length) {\n _currentCodePoint = -1;\n return false;\n }\n int codeUnit = string.codeUnitAt(_position);\n int nextPosition = _position + 1;\n if (_isLeadSurrogate(codeUnit) && nextPosition < string.length) {\n int nextCodeUnit = string.codeUnitAt(nextPosition);\n if (_isTrailSurrogate(nextCodeUnit)) {\n _nextPosition = nextPosition + 1;\n _currentCodePoint = _combineSurrogatePair(codeUnit, nextCodeUnit);\n return true;\n }\n }\n _nextPosition = nextPosition;\n _currentCodePoint = codeUnit;\n return true;\n }\n\n /// Move back to the previous code point.\n ///\n /// Returns `true` and updates [current] if there is a previous code point.\n /// Returns `false` otherwise, and then there is no current code point.\n bool movePrevious() {\n _nextPosition = _position;\n if (_position == 0) {\n _currentCodePoint = -1;\n return false;\n }\n int position = _position - 1;\n int codeUnit = string.codeUnitAt(position);\n if (_isTrailSurrogate(codeUnit) && position > 0) {\n int prevCodeUnit = string.codeUnitAt(position - 1);\n if (_isLeadSurrogate(prevCodeUnit)) {\n _position = position - 1;\n _currentCodePoint = _combineSurrogatePair(prevCodeUnit, codeUnit);\n return true;\n }\n }\n _position = position;\n _currentCodePoint = codeUnit;\n return true;\n }\n}\n"}},"clientRequestTime":1709252800192}
[7:26:40 PM] [Analyzer] [Info] ==> Content-Length: 217
[7:26:40 PM] [Analyzer] [Info] ==> {"jsonrpc":"2.0","method":"textDocument/didClose","params":{"textDocument":{"uri":"file:///Users/brandontrautmann/fvm/versions/3.16.0/bin/cache/pkg/sky_engine/lib/core/string.dart"}},"clientRequestTime":1709252800194}
Thu Feb 29 2024 [19:26:47 GMT-0500 (Eastern Standard Time)] Log file ended
</details>
The text was updated successfully, but these errors were encountered:
btrautmann
changed the title
Create an issue
Analyzer hang related to string.dartMar 1, 2024
The string.dart file is the part of dart:core which declares the String class, so you are using it.
You say that you start the app and that the app hangs. That does not suggest that the analyzer is involved. If the IDE was hanging, that could be related to the analyzer, but a compiled app does not include the analyzer.
That does suggest that it is your code that makes the app hang.
I don't know anything about Flutter widgets, but I can see that your RegExp is most likely wrong.
It collects all non-digits, joins those, and then tries to parse the result as an integer. That will always fall, so the function always returns oldValue.
Try instead:
final withoutSymbols = text.removeAll(RegExp(r'\D+'));
Changing the regex did indeed help 👀 There's probably a Flutter issue that should be filed around that error not being handled/propagated but I'll close this for now. Sorry for the noise!
dart info
)I'm experiencing constant hangs when trying to use a Flutter
TextInputFormatter
that utilizes a regex inside it. The code is as follows:I run the app, and the app hangs either after the first character or sometimes before the first character. The logs seem to have a lot going on related to
string.dart
though I don't recall ever opening that file.The text was updated successfully, but these errors were encountered: