directiveUris function
Every import / export URI in source, directives only.
Comment-aware, and it stops at the first real declaration — a dart:io
named in a doc comment or a string literal is not a dependency, and a rule
that counted one would be unfixable without rewording prose.
It deliberately stops at the URI itself: show / hide clauses and the
trailing as alias are irrelevant to every question asked here, and a
stricter pattern that silently matched nothing would make each caller pass
for the wrong reason.
Implementation
Iterable<String> directiveUris(String source) sync* {
var inBlockComment = false;
for (final rawLine in const LineSplitter().convert(source)) {
var line = rawLine;
if (inBlockComment) {
final end = line.indexOf('*/');
if (end < 0) continue;
inBlockComment = false;
line = line.substring(end + 2);
}
// A block comment that closes on its own line is removed in place, so a
// `/* … */` before or between directives does not end the scan; one that
// stays open runs to a later line.
var blockStart = line.indexOf('/*');
while (blockStart >= 0) {
final end = line.indexOf('*/', blockStart + 2);
if (end < 0) {
inBlockComment = true;
line = line.substring(0, blockStart);
break;
}
line = line.substring(0, blockStart) + line.substring(end + 2);
blockStart = line.indexOf('/*');
}
final trimmed = line.trim();
if (trimmed.isEmpty || trimmed.startsWith('//')) continue;
final match = directiveLinePattern.firstMatch(line);
if (match != null) {
yield match.group(1)!;
continue;
}
if (trimmed.startsWith('library') ||
trimmed.startsWith('part') ||
trimmed.startsWith('@')) {
continue;
}
// The continuation lines of a directive. A conditional import puts its
// alternative on a line of its own — `if (dart.library.io) 'x.dart'` — and
// that alternative is linked on the platform it names, so it is a
// dependency like any other. Treating the line as "the first declaration"
// ended the scan there and dropped every directive after it.
final conditional = _conditionalUri.firstMatch(trimmed);
if (conditional != null) {
yield conditional.group(1)!;
continue;
}
if (_directiveContinuation.hasMatch(trimmed)) continue;
return; // first real declaration — directives are done
}
}