Fix RangeError in doc-imports stripping by detecting index overshoot. Detect when absolute offsets from the analyzer overshoot the normalized string length (due to intermediate non-doc comments like `// ignore` breaking the sequence, or \r\n line endings) and skip stripping to avoid a crash. Added regression tests.
diff --git a/lib/src/model/documentation_comment.dart b/lib/src/model/documentation_comment.dart index 774284a..b76aae1 100644 --- a/lib/src/model/documentation_comment.dart +++ b/lib/src/model/documentation_comment.dart
@@ -866,7 +866,17 @@ var buffer = StringBuffer(); if (commentData.docImports.isEmpty) return content; var firstDocImport = commentData.docImports.first; - buffer.write(content.substring(0, firstDocImport.offset - commentOffset)); + + var relativeOffset = firstDocImport.offset - commentOffset; + if (relativeOffset >= content.length) { + // Safe fallback if indices drift due to line ending normalization. + warn(PackageWarning.deprecated, + message: + 'Index drift detected when removing doc imports. This is often caused by `// ignore` blocks or `\\r\\n` line endings in your documentation. Convert file to use `\\n` and remove intermediate non-doc comments to ensure doc imports are removed properly.'); + return content; + } + + buffer.write(content.substring(0, relativeOffset)); var offset = firstDocImport.end - commentOffset; for (var docImport in commentData.docImports.skip(1)) { buffer
diff --git a/test/documentation_comment_test.dart b/test/documentation_comment_test.dart index 3123358..974edbe 100644 --- a/test/documentation_comment_test.dart +++ b/test/documentation_comment_test.dart
@@ -277,6 +277,33 @@ expect(doc, equals('')); } + void test_docImport_overshoot() async { + // Force \r\n line endings to simulate index drift if the analyzer normalizes it to \n. + // We use many lines to ensure the shift overshoots the string length and throws RangeError. + var lines = List.generate(50, (i) => '/// Line $i').join('\n'); + await writePackageWithCommentedLibrary(''' +$lines +/// @docImport 'dart:async' as async; +'''.replaceAll('\n', '\r\n')); + var doc = libraryModel.documentation; + + // Should not crash! + expect(doc, isNotNull); + } + + void test_docImport_ignoreBlock() async { + await writePackageWithCommentedLibrary(''' +/// Line 1 +// ignore: something +/// Line 2 +/// @docImport 'dart:async' as async; +'''); + var doc = libraryModel.documentation; + + // Should not crash! + expect(doc, isNotNull); + } + void test_animationDirectiveHasFewerThanThreeArguments() async { await writePackageWithCommentedLibrary(''' /// Text.