dartDocComments function

String dartDocComments(
  1. String source
)

Lifts the /// doc comments of source out of the Dart around them.

A Dart doc comment is markdown, so the resolver needs no second set of rules — it needs the markdown handed to it without the ///. Two properties make the lift worth doing rather than scanning the raw file:

  • Line count is preserved, so a violation is still reported at the line a reader will open.
  • Non-doc lines become empty, which does two jobs at once. It keeps § inside a // note or a string literal out of the scan — neither is read by a reader following a citation — and it makes each declaration's doc comment its own block, so the lookback for a document name cannot reach back past the declaration above.

Without the lift, a citation whose document name wrapped onto the previous line would read as bare: the lookback crosses a soft wrap but not a ///.

Every comment is lifted, // as well as ///, and that is a measured reversal of an earlier position. The rule used to be /// only, on the reasoning that a // note is implementation commentary rather than something a reader follows as documentation. The corpus disagrees with that reading of itself: it carries 492 §-citing // lines, and 362 of them already name their document — authors were applying the citation convention there voluntarily, in comments no gate has ever read. A rule that called them undocumentation would have been describing a practice nobody follows.

It also removed an asymmetry that had no defence: validator.dart cites tom_specs_model_rules.md §10.2 from both a /// and a // comment, and only the first was held. The same citation, in the same file, gated or not by which marker it happened to be written under.

A /** */ block is still not lifted — no Dart file in the corpus uses one, so it would be brace tracking for no reader.

The lift is a parse, not a line scan, and that becomes load-bearing the moment test/ is in scope. A test that exercises this gate writes its fixtures as Dart string literals whose contents are /// lines — that is what a fixture for a doc-comment scanner has to look like. A line scanner reads those as doc comments of the file containing them, so every deliberately-malformed fixture is reported as a defect of the test, and the line-scoped exhibit marker cannot excuse them: the marker sits at the fixture's own line numbers, not the file's. Asking the analyzer which tokens are actually doc comments is what makes the third paragraph above true — it claimed to keep a string literal out of the scan and did not.

Implementation

String dartDocComments(String source) {
  final ParseStringResult parsed;
  try {
    parsed = parseString(content: source, throwIfDiagnostics: false);
  } on Object {
    return _dartDocCommentsByLine(source);
  }

  final lines = List<String>.filled(source.split('\n').length, '');
  final lineInfo = parsed.lineInfo;
  final seen = <int>{};

  for (
    Token? token = parsed.unit.beginToken;
    token != null && token.type != TokenType.EOF;
    token = token.next
  ) {
    for (
      Token? comment = token.precedingComments;
      comment != null;
      comment = comment.next
    ) {
      if (!seen.add(comment.offset)) continue;
      // Every comment form, not `///` alone. Taking them from the parse
      // rather than by line is what keeps a `//` inside a string literal out:
      // the analyzer says which tokens are comments, and a literal is not one.
      if (!comment.lexeme.startsWith('//')) continue;
      final line = lineInfo.getLocation(comment.offset).lineNumber - 1;
      if (line < 0 || line >= lines.length) continue;
      lines[line] = _docLine.firstMatch(comment.lexeme)?.group(1) ?? '';
    }
  }
  return lines.join('\n');
}