Fix header for multispan with null secondary urls (#72)
If a multiple span highlight was created where all the secondary spans
had `null` URLs they were filtered out from the comparison checking
whether multiple files are involved.
This bug was caused during the null safety migration. A similar bug
previously existed if the primary span had a null URL and is also fixed.
- Take a nullable list in `isAllTheSame`. Avoid using `null` as a
sentinel for no item seen, use `.first` and `.skip(1)` to compare all
elements.
- Add tests for the case of primary and secondary spans with a null URL.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6f78c4b..6fda0a0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,8 @@
# 1.8.1
+* Fix a bug where the URL header for the highlights with multiple files would
+ get omitted only one span has a non-null URI.
+
# 1.8.0
* Stable release for null safety.
diff --git a/lib/src/highlighter.dart b/lib/src/highlighter.dart
index 5d28fc3..19d8965 100644
--- a/lib/src/highlighter.dart
+++ b/lib/src/highlighter.dart
@@ -107,8 +107,7 @@
.where((highlight) => isMultiline(highlight.span))
.length)
.reduce(math.max),
- _multipleFiles =
- !isAllTheSame(_lines.map((line) => line.url).whereType<Uri>());
+ _multipleFiles = !isAllTheSame(_lines.map((line) => line.url));
/// Returns whether [lines] contains any adjacent lines from the same source
/// file that aren't adjacent in the original file.
diff --git a/lib/src/utils.dart b/lib/src/utils.dart
index 72c6173..ccc88bd 100644
--- a/lib/src/utils.dart
+++ b/lib/src/utils.dart
@@ -16,12 +16,11 @@
/// Returns whether all elements of [iter] are the same value, according to
/// `==`.
-bool isAllTheSame(Iterable<Object> iter) {
- Object? lastValue;
- for (var value in iter) {
- if (lastValue == null) {
- lastValue = value;
- } else if (value != lastValue) {
+bool isAllTheSame(Iterable<Object?> iter) {
+ if (iter.isEmpty) return true;
+ final firstValue = iter.first;
+ for (var value in iter.skip(1)) {
+ if (value != firstValue) {
return false;
}
}
diff --git a/pubspec.yaml b/pubspec.yaml
index 12382a5..89599df 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
name: source_span
-version: 1.8.1-dev
+version: 1.8.1
description: A library for identifying source spans and locations.
homepage: https://github.com/dart-lang/source_span
diff --git a/test/multiple_highlight_test.dart b/test/multiple_highlight_test.dart
index 6d5ec9d..b0c28a5 100644
--- a/test/multiple_highlight_test.dart
+++ b/test/multiple_highlight_test.dart
@@ -261,14 +261,14 @@
});
});
- test('highlights multiple files with their URLs', () {
- final file2 = SourceFile.fromString('''
+ group('writes headers when highlighting multiple files', () {
+ test('writes all file URLs', () {
+ final span2 = SourceFile.fromString('''
quibble bibble boop
-''', url: 'file2.txt');
+''', url: 'file2.txt').span(8, 14);
- expect(
- file.span(31, 34).highlightMultiple('one', {file2.span(8, 14): 'two'}),
- equals("""
+ expect(
+ file.span(31, 34).highlightMultiple('one', {span2: 'two'}), equals("""
,--> file1.txt
3 | zip zap zop
| ^^^ one
@@ -277,5 +277,38 @@
1 | quibble bibble boop
| ====== two
'"""));
+ });
+
+ test('allows secondary spans to have null URL', () {
+ final span2 = SourceSpan(SourceLocation(1, sourceUrl: null),
+ SourceLocation(4, sourceUrl: null), 'foo');
+
+ expect(
+ file.span(31, 34).highlightMultiple('one', {span2: 'two'}), equals("""
+ ,--> file1.txt
+3 | zip zap zop
+ | ^^^ one
+ '
+ ,
+1 | foo
+ | === two
+ '"""));
+ });
+
+ test('allows primary span to have null URL', () {
+ final span1 = SourceSpan(SourceLocation(1, sourceUrl: null),
+ SourceLocation(4, sourceUrl: null), 'foo');
+
+ expect(
+ span1.highlightMultiple('one', {file.span(31, 34): 'two'}), equals("""
+ ,
+1 | foo
+ | ^^^ one
+ '
+ ,--> file1.txt
+3 | zip zap zop
+ | === two
+ '"""));
+ });
});
}