locateParseError function
Picks the best error location for text, given the parser's own
parserPosition/parserMessage (which may be unreliable). language
enables language-specific recovery (e.g. a missing ;).
Implementation
ParseErrorLocation locateParseError(
String text, {
int? parserPosition,
String? parserMessage,
String? language,
}) {
final structural = _bracketImbalance(text);
final msg = (parserMessage ?? '').toLowerCase();
// The parser position is trustworthy only when it is concrete: non-zero and
// not the catch-all "end of input expected" that PEG parsers emit at 0.
final parserConcrete =
parserPosition != null &&
parserPosition > 0 &&
parserPosition <= text.length &&
!msg.contains('end of input');
int offset;
String? hint;
if (structural != null) {
// A bracket imbalance is the most fundamental structural fault — trust it
// over any parser position, and describe it (e.g. "'(' is never closed").
offset = structural.offset;
hint = structural.hint;
} else {
// Brackets balance. Prefer a confidently-located missing statement
// terminator (reported at the end of the offending value — the editor
// convention) before trusting the parser's own position.
final missing = (language != null && _semicolonLanguages.contains(language))
? _missingTerminator(text)
: null;
if (missing != null) {
offset = missing.offset;
hint = missing.hint;
} else if (parserConcrete) {
// A concrete parser position; with farthest-failure tracking (Dart) this
// now lands on or next to the real error (e.g. a bad token mid-line).
offset = parserPosition;
} else if (parserPosition != null &&
parserPosition > 0 &&
parserPosition <= text.length) {
offset = parserPosition;
} else {
offset = _firstMeaningfulOffset(text);
}
}
final (start, end) = _tokenRange(text, offset);
return ParseErrorLocation(
offset: offset,
rangeStart: start,
rangeEnd: end,
hint: hint,
);
}