forEachDiagnostic function
Iterate over the marked diagnostics for the given editor state,
calling f for each of them.
Note that, if the document changed since the diagnostics were created,
the Diagnostic object will hold the original outdated position,
whereas the to and from arguments hold the diagnostic's current position.
Implementation
void forEachDiagnostic(
EditorState state,
void Function(Diagnostic d, int from, int to) f,
) {
_ensureLintInitialized();
final lState = state.field(_lintState, false);
if (lState == null || lState.diagnostics.size == 0) return;
final pending = <Diagnostic>[];
final pendingStart = <int>[];
var lastEnd = -1;
final iter = lState.diagnostics.iter();
// iter() already positions at first element via goto() which calls next()
while (iter.value != null) {
// Check if any pending diagnostics ended at this point
for (var i = 0; i < pending.length; i++) {
final spec = iter.value?.spec;
final diags = spec?['diagnostics'] as List<Diagnostic>?;
if (diags == null || !diags.contains(pending[i])) {
f(pending[i], pendingStart[i], lastEnd);
pending.removeAt(i);
pendingStart.removeAt(i);
i--;
}
}
// Add new diagnostics from current position
final spec = iter.value!.spec;
final diags = spec?['diagnostics'] as List<Diagnostic>?;
if (diags != null) {
for (final d in diags) {
if (!pending.contains(d)) {
pending.add(d);
pendingStart.add(iter.from);
}
}
}
lastEnd = iter.to;
iter.next();
}
// Flush remaining pending diagnostics
for (var i = 0; i < pending.length; i++) {
f(pending[i], pendingStart[i], lastEnd);
}
}