forEachDiagnostic function

void forEachDiagnostic(
  1. EditorState state,
  2. void f(
    1. Diagnostic d,
    2. int from,
    3. int to
    )
)

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);
  }
}