Description
I hit this while trying to update the Dart textmate grammar (which uses this class for testing) to use negative look-aheads. If the input string contains \r\n
and a pattern matches a zero-length string when the scanner is between \r
and \n
, this exception is thrown:
RangeError (length): Invalid value: Valid value range is empty: -1
#0 List.[] (dart:core-patch/growable_array.dart)
dart-lang/tools#1787 List.removeLast (dart:core-patch/growable_array.dart:337:20)
dart-lang/tools#1788 LineScanner._newlinesIn (package:string_scanner/src/line_scanner.dart:122:16)
dart-lang/string_scanner#3 LineScanner.scan (package:string_scanner/src/line_scanner.dart:106:22)
dart-lang/tools#1789 main (file:///D:/Dev/Test%20Projects/string_scanner_cr_lf/bin/string_scanner_cr_lf.dart:15:44)
dart-lang/string_scanner#5 _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:295:33)
dart-lang/tools#1790 _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)
scan()
calls _newlinesIn()
which seems to assume that if the current position is between \r
and \n
then the matched text will always contain at least one newline.
Here's a repro that matches a line starting ///
and then tries to scan for a line that does not start ///
. With the \n
line ending, it works fine, but with \r\n
it throws the error above.
import 'dart:convert';
import 'package:string_scanner/string_scanner.dart';
void main(List<String> arguments) {
for (var lineEnding in ['\n', '\r\n']) {
var scanner = LineScanner('/// test${lineEnding}test');
var startPattern = RegExp(r'^///', multiLine: true);
var endPattern = RegExp(r'^(?!///)', multiLine: true);
print('');
print('Testing with ${jsonEncode(lineEnding)}');
while (!scanner.isDone) {
if (scanner.scan(startPattern)) {
print('');
print('Line ${scanner.line} starts comment');
while (!scanner.isDone && !scanner.scan(endPattern)) {
scanner.readChar();
}
print('Line ${scanner.line} ends comment');
}
if (scanner.isDone) break;
scanner.readChar();
}
}
}
The output looks like:
Testing with "\n"
Line 0 starts comment
Line 1 ends comment
Testing with "\r\n"
Line 0 starts comment
Unhandled exception:
RangeError (length): Invalid value: Valid value range is empty: -1
#0 List.[] (dart:core-patch/growable_array.dart)
dart-lang/tools#1787 List.removeLast (dart:core-patch/growable_array.dart:337:20)
dart-lang/tools#1788 LineScanner._newlinesIn (package:string_scanner/src/line_scanner.dart:122:16)
dart-lang/string_scanner#3 LineScanner.scan (package:string_scanner/src/line_scanner.dart:106:22)
dart-lang/tools#1789 main (file:///D:/Dev/Test%20Projects/string_scanner_cr_lf/bin/string_scanner_cr_lf.dart:17:44)
dart-lang/string_scanner#5 _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:295:33)
dart-lang/tools#1790 _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)