Enforce and fix prefer_single_quotes (#47)

We will soon be enforcing this with `package:pedantic`.
diff --git a/analysis_options.yaml b/analysis_options.yaml
index f28d5a1..929d6fa 100644
--- a/analysis_options.yaml
+++ b/analysis_options.yaml
@@ -67,7 +67,7 @@
   - prefer_is_empty
   - prefer_is_not_empty
   - prefer_null_aware_operators
-  #- prefer_single_quotes
+  - prefer_single_quotes
   - prefer_typing_uninitialized_variables
   - recursive_getters
   - slash_for_doc_comments
diff --git a/lib/src/file.dart b/lib/src/file.dart
index 717a4d4..a03a875 100644
--- a/lib/src/file.dart
+++ b/lib/src/file.dart
@@ -52,7 +52,7 @@
   /// This constructor is deprecated.
   ///
   /// Use [new SourceFile.fromString] instead.
-  @Deprecated("Will be removed in 2.0.0")
+  @Deprecated('Will be removed in 2.0.0')
   SourceFile(String text, {url}) : this.decoded(text.runes, url: url);
 
   /// Creates a new source file from [text].
@@ -98,10 +98,10 @@
   /// Gets the 0-based line corresponding to [offset].
   int getLine(int offset) {
     if (offset < 0) {
-      throw RangeError("Offset may not be negative, was $offset.");
+      throw RangeError('Offset may not be negative, was $offset.');
     } else if (offset > length) {
-      throw RangeError("Offset $offset must not be greater than the number "
-          "of characters in the file, $length.");
+      throw RangeError('Offset $offset must not be greater than the number '
+          'of characters in the file, $length.');
     }
 
     if (offset < _lineStarts.first) return -1;
@@ -163,24 +163,24 @@
   /// is used to more efficiently compute the column.
   int getColumn(int offset, {int line}) {
     if (offset < 0) {
-      throw RangeError("Offset may not be negative, was $offset.");
+      throw RangeError('Offset may not be negative, was $offset.');
     } else if (offset > length) {
-      throw RangeError("Offset $offset must be not be greater than the "
-          "number of characters in the file, $length.");
+      throw RangeError('Offset $offset must be not be greater than the '
+          'number of characters in the file, $length.');
     }
 
     if (line == null) {
       line = getLine(offset);
     } else if (line < 0) {
-      throw RangeError("Line may not be negative, was $line.");
+      throw RangeError('Line may not be negative, was $line.');
     } else if (line >= lines) {
-      throw RangeError("Line $line must be less than the number of "
-          "lines in the file, $lines.");
+      throw RangeError('Line $line must be less than the number of '
+          'lines in the file, $lines.');
     }
 
     final lineStart = _lineStarts[line];
     if (lineStart > offset) {
-      throw RangeError("Line $line comes after offset $offset.");
+      throw RangeError('Line $line comes after offset $offset.');
     }
 
     return offset - lineStart;
@@ -193,12 +193,12 @@
     column ??= 0;
 
     if (line < 0) {
-      throw RangeError("Line may not be negative, was $line.");
+      throw RangeError('Line may not be negative, was $line.');
     } else if (line >= lines) {
-      throw RangeError("Line $line must be less than the number of "
-          "lines in the file, $lines.");
+      throw RangeError('Line $line must be less than the number of '
+          'lines in the file, $lines.');
     } else if (column < 0) {
-      throw RangeError("Column may not be negative, was $column.");
+      throw RangeError('Column may not be negative, was $column.');
     }
 
     final result = _lineStarts[line] + column;
@@ -241,10 +241,10 @@
 
   FileLocation._(this.file, this.offset) {
     if (offset < 0) {
-      throw RangeError("Offset may not be negative, was $offset.");
+      throw RangeError('Offset may not be negative, was $offset.');
     } else if (offset > file.length) {
-      throw RangeError("Offset $offset must not be greater than the number "
-          "of characters in the file, ${file.length}.");
+      throw RangeError('Offset $offset must not be greater than the number '
+          'of characters in the file, ${file.length}.');
     }
   }
 
@@ -328,7 +328,7 @@
         // ...unless this is a point span, in which case we want to include the
         // next line (or the empty string if this is the end of the file).
         return endLine == file.lines - 1
-            ? ""
+            ? ''
             : file.getText(
                 file.getOffset(endLine), file.getOffset(endLine + 1));
       }
@@ -351,10 +351,10 @@
     if (_end < _start) {
       throw ArgumentError('End $_end must come after start $_start.');
     } else if (_end > file.length) {
-      throw RangeError("End $_end must not be greater than the number "
-          "of characters in the file, ${file.length}.");
+      throw RangeError('End $_end must not be greater than the number '
+          'of characters in the file, ${file.length}.');
     } else if (_start < 0) {
-      throw RangeError("Start may not be negative, was $_start.");
+      throw RangeError('Start may not be negative, was $_start.');
     }
   }
 
@@ -375,11 +375,11 @@
 
     if (other is _FileSpan) {
       if (_start > other._end || other._start > _end) {
-        throw ArgumentError("Spans $this and $other are disjoint.");
+        throw ArgumentError('Spans $this and $other are disjoint.');
       }
     } else {
       if (_start > other.end.offset || other.start.offset > _end) {
-        throw ArgumentError("Spans $this and $other are disjoint.");
+        throw ArgumentError('Spans $this and $other are disjoint.');
       }
     }
 
@@ -409,7 +409,7 @@
   @override
   FileSpan expand(FileSpan other) {
     if (sourceUrl != other.sourceUrl) {
-      throw ArgumentError("Source URLs \"$sourceUrl\" and "
+      throw ArgumentError('Source URLs \"$sourceUrl\" and '
           " \"${other.sourceUrl}\" don't match.");
     }
 
diff --git a/lib/src/location.dart b/lib/src/location.dart
index c03c98c..4f69df5 100644
--- a/lib/src/location.dart
+++ b/lib/src/location.dart
@@ -48,11 +48,11 @@
         line = line == null ? 0 : line,
         column = column == null ? offset : column {
     if (offset < 0) {
-      throw RangeError("Offset may not be negative, was $offset.");
+      throw RangeError('Offset may not be negative, was $offset.');
     } else if (line != null && line < 0) {
-      throw RangeError("Line may not be negative, was $line.");
+      throw RangeError('Line may not be negative, was $line.');
     } else if (column != null && column < 0) {
-      throw RangeError("Column may not be negative, was $column.");
+      throw RangeError('Column may not be negative, was $column.');
     }
   }
 
@@ -61,14 +61,14 @@
   /// This always returns a non-negative value.
   int distance(SourceLocation other) {
     if (sourceUrl != other.sourceUrl) {
-      throw ArgumentError("Source URLs \"$sourceUrl\" and "
+      throw ArgumentError('Source URLs \"$sourceUrl\" and '
           "\"${other.sourceUrl}\" don't match.");
     }
     return (offset - other.offset).abs();
   }
 
   /// Returns a span that covers only a single point: this location.
-  SourceSpan pointSpan() => SourceSpan(this, this, "");
+  SourceSpan pointSpan() => SourceSpan(this, this, '');
 
   /// Compares two locations.
   ///
@@ -76,7 +76,7 @@
   @override
   int compareTo(SourceLocation other) {
     if (sourceUrl != other.sourceUrl) {
-      throw ArgumentError("Source URLs \"$sourceUrl\" and "
+      throw ArgumentError('Source URLs \"$sourceUrl\" and '
           "\"${other.sourceUrl}\" don't match.");
     }
     return offset - other.offset;
diff --git a/lib/src/location_mixin.dart b/lib/src/location_mixin.dart
index bd773ae..bbb73b4 100644
--- a/lib/src/location_mixin.dart
+++ b/lib/src/location_mixin.dart
@@ -23,19 +23,19 @@
   @override
   int distance(SourceLocation other) {
     if (sourceUrl != other.sourceUrl) {
-      throw ArgumentError("Source URLs \"$sourceUrl\" and "
+      throw ArgumentError('Source URLs \"$sourceUrl\" and '
           "\"${other.sourceUrl}\" don't match.");
     }
     return (offset - other.offset).abs();
   }
 
   @override
-  SourceSpan pointSpan() => SourceSpan(this, this, "");
+  SourceSpan pointSpan() => SourceSpan(this, this, '');
 
   @override
   int compareTo(SourceLocation other) {
     if (sourceUrl != other.sourceUrl) {
-      throw ArgumentError("Source URLs \"$sourceUrl\" and "
+      throw ArgumentError('Source URLs \"$sourceUrl\" and '
           "\"${other.sourceUrl}\" don't match.");
     }
     return offset - other.offset;
diff --git a/lib/src/span_mixin.dart b/lib/src/span_mixin.dart
index 8960611..55eae94 100644
--- a/lib/src/span_mixin.dart
+++ b/lib/src/span_mixin.dart
@@ -31,7 +31,7 @@
   @override
   SourceSpan union(SourceSpan other) {
     if (sourceUrl != other.sourceUrl) {
-      throw ArgumentError("Source URLs \"$sourceUrl\" and "
+      throw ArgumentError('Source URLs \"$sourceUrl\" and '
           " \"${other.sourceUrl}\" don't match.");
     }
 
@@ -41,7 +41,7 @@
     final endSpan = end == this.end ? this : other;
 
     if (beginSpan.end.compareTo(endSpan.start) < 0) {
-      throw ArgumentError("Spans $this and $other are disjoint.");
+      throw ArgumentError('Spans $this and $other are disjoint.');
     }
 
     final text = beginSpan.text +
@@ -68,7 +68,7 @@
 
   @override
   String highlight({color}) {
-    if (this is! SourceSpanWithContext && length == 0) return "";
+    if (this is! SourceSpanWithContext && length == 0) return '';
     return Highlighter(this, color: color).highlight();
   }
 
diff --git a/test/file_test.dart b/test/file_test.dart
index 2cfe2d4..499f8ef 100644
--- a/test/file_test.dart
+++ b/test/file_test.dart
@@ -8,236 +8,236 @@
 void main() {
   SourceFile file;
   setUp(() {
-    file = SourceFile.fromString("""
+    file = SourceFile.fromString('''
 foo bar baz
 whiz bang boom
-zip zap zop""", url: "foo.dart");
+zip zap zop''', url: 'foo.dart');
   });
 
-  group("errors", () {
-    group("for span()", () {
-      test("end must come after start", () {
+  group('errors', () {
+    group('for span()', () {
+      test('end must come after start', () {
         expect(() => file.span(10, 5), throwsArgumentError);
       });
 
-      test("start may not be negative", () {
+      test('start may not be negative', () {
         expect(() => file.span(-1, 5), throwsRangeError);
       });
 
-      test("end may not be outside the file", () {
+      test('end may not be outside the file', () {
         expect(() => file.span(10, 100), throwsRangeError);
       });
     });
 
-    group("for location()", () {
-      test("offset may not be negative", () {
+    group('for location()', () {
+      test('offset may not be negative', () {
         expect(() => file.location(-1), throwsRangeError);
       });
 
-      test("offset may not be outside the file", () {
+      test('offset may not be outside the file', () {
         expect(() => file.location(100), throwsRangeError);
       });
     });
 
-    group("for getLine()", () {
-      test("offset may not be negative", () {
+    group('for getLine()', () {
+      test('offset may not be negative', () {
         expect(() => file.getLine(-1), throwsRangeError);
       });
 
-      test("offset may not be outside the file", () {
+      test('offset may not be outside the file', () {
         expect(() => file.getLine(100), throwsRangeError);
       });
     });
 
-    group("for getColumn()", () {
-      test("offset may not be negative", () {
+    group('for getColumn()', () {
+      test('offset may not be negative', () {
         expect(() => file.getColumn(-1), throwsRangeError);
       });
 
-      test("offset may not be outside the file", () {
+      test('offset may not be outside the file', () {
         expect(() => file.getColumn(100), throwsRangeError);
       });
 
-      test("line may not be negative", () {
+      test('line may not be negative', () {
         expect(() => file.getColumn(1, line: -1), throwsRangeError);
       });
 
-      test("line may not be outside the file", () {
+      test('line may not be outside the file', () {
         expect(() => file.getColumn(1, line: 100), throwsRangeError);
       });
 
-      test("line must be accurate", () {
+      test('line must be accurate', () {
         expect(() => file.getColumn(1, line: 1), throwsRangeError);
       });
     });
 
-    group("getOffset()", () {
-      test("line may not be negative", () {
+    group('getOffset()', () {
+      test('line may not be negative', () {
         expect(() => file.getOffset(-1), throwsRangeError);
       });
 
-      test("column may not be negative", () {
+      test('column may not be negative', () {
         expect(() => file.getOffset(1, -1), throwsRangeError);
       });
 
-      test("line may not be outside the file", () {
+      test('line may not be outside the file', () {
         expect(() => file.getOffset(100), throwsRangeError);
       });
 
-      test("column may not be outside the file", () {
+      test('column may not be outside the file', () {
         expect(() => file.getOffset(2, 100), throwsRangeError);
       });
 
-      test("column may not be outside the line", () {
+      test('column may not be outside the line', () {
         expect(() => file.getOffset(1, 20), throwsRangeError);
       });
     });
 
-    group("for getText()", () {
-      test("end must come after start", () {
+    group('for getText()', () {
+      test('end must come after start', () {
         expect(() => file.getText(10, 5), throwsArgumentError);
       });
 
-      test("start may not be negative", () {
+      test('start may not be negative', () {
         expect(() => file.getText(-1, 5), throwsRangeError);
       });
 
-      test("end may not be outside the file", () {
+      test('end may not be outside the file', () {
         expect(() => file.getText(10, 100), throwsRangeError);
       });
     });
 
-    group("for span().union()", () {
-      test("source URLs must match", () {
-        final other = SourceSpan(SourceLocation(10), SourceLocation(11), "_");
+    group('for span().union()', () {
+      test('source URLs must match', () {
+        final other = SourceSpan(SourceLocation(10), SourceLocation(11), '_');
 
         expect(() => file.span(9, 10).union(other), throwsArgumentError);
       });
 
-      test("spans may not be disjoint", () {
+      test('spans may not be disjoint', () {
         expect(() => file.span(9, 10).union(file.span(11, 12)),
             throwsArgumentError);
       });
     });
 
-    test("for span().expand() source URLs must match", () {
-      final other = SourceFile.fromString("""
+    test('for span().expand() source URLs must match', () {
+      final other = SourceFile.fromString('''
 foo bar baz
 whiz bang boom
-zip zap zop""", url: "bar.dart").span(10, 11);
+zip zap zop''', url: 'bar.dart').span(10, 11);
 
       expect(() => file.span(9, 10).expand(other), throwsArgumentError);
     });
   });
 
   test('fields work correctly', () {
-    expect(file.url, equals(Uri.parse("foo.dart")));
+    expect(file.url, equals(Uri.parse('foo.dart')));
     expect(file.lines, equals(3));
     expect(file.length, equals(38));
   });
 
-  group("new SourceFile()", () {
-    test("handles CRLF correctly", () {
-      expect(SourceFile.fromString("foo\r\nbar").getLine(6), equals(1));
+  group('new SourceFile()', () {
+    test('handles CRLF correctly', () {
+      expect(SourceFile.fromString('foo\r\nbar').getLine(6), equals(1));
     });
 
-    test("handles a lone CR correctly", () {
-      expect(SourceFile.fromString("foo\rbar").getLine(5), equals(1));
+    test('handles a lone CR correctly', () {
+      expect(SourceFile.fromString('foo\rbar').getLine(5), equals(1));
     });
   });
 
-  group("span()", () {
-    test("returns a span between the given offsets", () {
+  group('span()', () {
+    test('returns a span between the given offsets', () {
       final span = file.span(5, 10);
       expect(span.start, equals(file.location(5)));
       expect(span.end, equals(file.location(10)));
     });
 
-    test("end defaults to the end of the file", () {
+    test('end defaults to the end of the file', () {
       final span = file.span(5);
       expect(span.start, equals(file.location(5)));
       expect(span.end, equals(file.location(file.length)));
     });
   });
 
-  group("getLine()", () {
-    test("works for a middle character on the line", () {
+  group('getLine()', () {
+    test('works for a middle character on the line', () {
       expect(file.getLine(15), equals(1));
     });
 
-    test("works for the first character of a line", () {
+    test('works for the first character of a line', () {
       expect(file.getLine(12), equals(1));
     });
 
-    test("works for a newline character", () {
+    test('works for a newline character', () {
       expect(file.getLine(11), equals(0));
     });
 
-    test("works for the last offset", () {
+    test('works for the last offset', () {
       expect(file.getLine(file.length), equals(2));
     });
   });
 
-  group("getColumn()", () {
-    test("works for a middle character on the line", () {
+  group('getColumn()', () {
+    test('works for a middle character on the line', () {
       expect(file.getColumn(15), equals(3));
     });
 
-    test("works for the first character of a line", () {
+    test('works for the first character of a line', () {
       expect(file.getColumn(12), equals(0));
     });
 
-    test("works for a newline character", () {
+    test('works for a newline character', () {
       expect(file.getColumn(11), equals(11));
     });
 
-    test("works when line is passed as well", () {
+    test('works when line is passed as well', () {
       expect(file.getColumn(12, line: 1), equals(0));
     });
 
-    test("works for the last offset", () {
+    test('works for the last offset', () {
       expect(file.getColumn(file.length), equals(11));
     });
   });
 
-  group("getOffset()", () {
-    test("works for a middle character on the line", () {
+  group('getOffset()', () {
+    test('works for a middle character on the line', () {
       expect(file.getOffset(1, 3), equals(15));
     });
 
-    test("works for the first character of a line", () {
+    test('works for the first character of a line', () {
       expect(file.getOffset(1), equals(12));
     });
 
-    test("works for a newline character", () {
+    test('works for a newline character', () {
       expect(file.getOffset(0, 11), equals(11));
     });
 
-    test("works for the last offset", () {
+    test('works for the last offset', () {
       expect(file.getOffset(2, 11), equals(file.length));
     });
   });
 
-  group("getText()", () {
-    test("returns a substring of the source", () {
-      expect(file.getText(8, 15), equals("baz\nwhi"));
+  group('getText()', () {
+    test('returns a substring of the source', () {
+      expect(file.getText(8, 15), equals('baz\nwhi'));
     });
 
-    test("end defaults to the end of the file", () {
-      expect(file.getText(20), equals("g boom\nzip zap zop"));
+    test('end defaults to the end of the file', () {
+      expect(file.getText(20), equals('g boom\nzip zap zop'));
     });
   });
 
-  group("FileLocation", () {
-    test("reports the correct line number", () {
+  group('FileLocation', () {
+    test('reports the correct line number', () {
       expect(file.location(15).line, equals(1));
     });
 
-    test("reports the correct column number", () {
+    test('reports the correct column number', () {
       expect(file.location(15).column, equals(3));
     });
 
-    test("pointSpan() returns a FileSpan", () {
+    test('pointSpan() returns a FileSpan', () {
       final location = file.location(15);
       final span = location.pointSpan();
       expect(span, isA<FileSpan>());
@@ -247,46 +247,46 @@
     });
   });
 
-  group("FileSpan", () {
-    test("text returns a substring of the source", () {
-      expect(file.span(8, 15).text, equals("baz\nwhi"));
+  group('FileSpan', () {
+    test('text returns a substring of the source', () {
+      expect(file.span(8, 15).text, equals('baz\nwhi'));
     });
 
-    test("text includes the last char when end is defaulted to EOF", () {
-      expect(file.span(29).text, equals("p zap zop"));
+    test('text includes the last char when end is defaulted to EOF', () {
+      expect(file.span(29).text, equals('p zap zop'));
     });
 
-    group("context", () {
+    group('context', () {
       test("contains the span's text", () {
         final span = file.span(8, 15);
         expect(span.context.contains(span.text), isTrue);
         expect(span.context, equals('foo bar baz\nwhiz bang boom\n'));
       });
 
-      test("contains the previous line for a point span at the end of a line",
+      test('contains the previous line for a point span at the end of a line',
           () {
         final span = file.span(25, 25);
         expect(span.context, equals('whiz bang boom\n'));
       });
 
-      test("contains the next line for a point span at the beginning of a line",
+      test('contains the next line for a point span at the beginning of a line',
           () {
         final span = file.span(12, 12);
         expect(span.context, equals('whiz bang boom\n'));
       });
 
-      group("for a point span at the end of a file", () {
-        test("without a newline, contains the last line", () {
+      group('for a point span at the end of a file', () {
+        test('without a newline, contains the last line', () {
           final span = file.span(file.length, file.length);
           expect(span.context, equals('zip zap zop'));
         });
 
-        test("with a newline, contains an empty line", () {
-          file = SourceFile.fromString("""
+        test('with a newline, contains an empty line', () {
+          file = SourceFile.fromString('''
 foo bar baz
 whiz bang boom
 zip zap zop
-""", url: "foo.dart");
+''', url: 'foo.dart');
 
           final span = file.span(file.length, file.length);
           expect(span.context, isEmpty);
@@ -294,92 +294,92 @@
       });
     });
 
-    group("union()", () {
+    group('union()', () {
       FileSpan span;
       setUp(() {
         span = file.span(5, 12);
       });
 
-      test("works with a preceding adjacent span", () {
+      test('works with a preceding adjacent span', () {
         final other = file.span(0, 5);
         final result = span.union(other);
         expect(result.start, equals(other.start));
         expect(result.end, equals(span.end));
-        expect(result.text, equals("foo bar baz\n"));
+        expect(result.text, equals('foo bar baz\n'));
       });
 
-      test("works with a preceding overlapping span", () {
+      test('works with a preceding overlapping span', () {
         final other = file.span(0, 8);
         final result = span.union(other);
         expect(result.start, equals(other.start));
         expect(result.end, equals(span.end));
-        expect(result.text, equals("foo bar baz\n"));
+        expect(result.text, equals('foo bar baz\n'));
       });
 
-      test("works with a following adjacent span", () {
+      test('works with a following adjacent span', () {
         final other = file.span(12, 16);
         final result = span.union(other);
         expect(result.start, equals(span.start));
         expect(result.end, equals(other.end));
-        expect(result.text, equals("ar baz\nwhiz"));
+        expect(result.text, equals('ar baz\nwhiz'));
       });
 
-      test("works with a following overlapping span", () {
+      test('works with a following overlapping span', () {
         final other = file.span(9, 16);
         final result = span.union(other);
         expect(result.start, equals(span.start));
         expect(result.end, equals(other.end));
-        expect(result.text, equals("ar baz\nwhiz"));
+        expect(result.text, equals('ar baz\nwhiz'));
       });
 
-      test("works with an internal overlapping span", () {
+      test('works with an internal overlapping span', () {
         final other = file.span(7, 10);
         expect(span.union(other), equals(span));
       });
 
-      test("works with an external overlapping span", () {
+      test('works with an external overlapping span', () {
         final other = file.span(0, 16);
         expect(span.union(other), equals(other));
       });
 
-      test("returns a FileSpan for a FileSpan input", () {
+      test('returns a FileSpan for a FileSpan input', () {
         expect(span.union(file.span(0, 5)), isA<FileSpan>());
       });
 
-      test("returns a base SourceSpan for a SourceSpan input", () {
-        final other = SourceSpan(SourceLocation(0, sourceUrl: "foo.dart"),
-            SourceLocation(5, sourceUrl: "foo.dart"), "hey, ");
+      test('returns a base SourceSpan for a SourceSpan input', () {
+        final other = SourceSpan(SourceLocation(0, sourceUrl: 'foo.dart'),
+            SourceLocation(5, sourceUrl: 'foo.dart'), 'hey, ');
         final result = span.union(other);
         expect(result, isNot(isA<FileSpan>()));
         expect(result.start, equals(other.start));
         expect(result.end, equals(span.end));
-        expect(result.text, equals("hey, ar baz\n"));
+        expect(result.text, equals('hey, ar baz\n'));
       });
     });
 
-    group("expand()", () {
+    group('expand()', () {
       FileSpan span;
       setUp(() {
         span = file.span(5, 12);
       });
 
-      test("works with a preceding nonadjacent span", () {
+      test('works with a preceding nonadjacent span', () {
         final other = file.span(0, 3);
         final result = span.expand(other);
         expect(result.start, equals(other.start));
         expect(result.end, equals(span.end));
-        expect(result.text, equals("foo bar baz\n"));
+        expect(result.text, equals('foo bar baz\n'));
       });
 
-      test("works with a preceding overlapping span", () {
+      test('works with a preceding overlapping span', () {
         final other = file.span(0, 8);
         final result = span.expand(other);
         expect(result.start, equals(other.start));
         expect(result.end, equals(span.end));
-        expect(result.text, equals("foo bar baz\n"));
+        expect(result.text, equals('foo bar baz\n'));
       });
 
-      test("works with a following nonadjacent span", () {
+      test('works with a following nonadjacent span', () {
         final other = file.span(14, 16);
         final result = span.expand(other);
         expect(result.start, equals(span.start));
diff --git a/test/highlight_test.dart b/test/highlight_test.dart
index 33719bc..9d95b21 100644
--- a/test/highlight_test.dart
+++ b/test/highlight_test.dart
@@ -22,14 +22,14 @@
 
   SourceFile file;
   setUp(() {
-    file = SourceFile.fromString("""
+    file = SourceFile.fromString('''
 foo bar baz
 whiz bang boom
 zip zap zop
-""");
+''');
   });
 
-  test("points to the span in the source", () {
+  test('points to the span in the source', () {
     expect(file.span(4, 7).highlight(), equals("""
   ,
 1 | foo bar baz
@@ -37,8 +37,8 @@
   '"""));
   });
 
-  test("gracefully handles a missing source URL", () {
-    final span = SourceFile.fromString("foo bar baz").span(4, 7);
+  test('gracefully handles a missing source URL', () {
+    final span = SourceFile.fromString('foo bar baz').span(4, 7);
     expect(span.highlight(), equals("""
   ,
 1 | foo bar baz
@@ -46,8 +46,8 @@
   '"""));
   });
 
-  group("highlights a point span", () {
-    test("in the middle of a line", () {
+  group('highlights a point span', () {
+    test('in the middle of a line', () {
       expect(file.location(4).pointSpan().highlight(), equals("""
   ,
 1 | foo bar baz
@@ -55,7 +55,7 @@
   '"""));
     });
 
-    test("at the beginning of the file", () {
+    test('at the beginning of the file', () {
       expect(file.location(0).pointSpan().highlight(), equals("""
   ,
 1 | foo bar baz
@@ -63,7 +63,7 @@
   '"""));
     });
 
-    test("at the beginning of a line", () {
+    test('at the beginning of a line', () {
       expect(file.location(12).pointSpan().highlight(), equals("""
   ,
 2 | whiz bang boom
@@ -71,7 +71,7 @@
   '"""));
     });
 
-    test("at the end of a line", () {
+    test('at the end of a line', () {
       expect(file.location(11).pointSpan().highlight(), equals("""
   ,
 1 | foo bar baz
@@ -79,7 +79,7 @@
   '"""));
     });
 
-    test("at the end of the file", () {
+    test('at the end of the file', () {
       expect(file.location(38).pointSpan().highlight(), equals("""
   ,
 3 | zip zap zop
@@ -87,7 +87,7 @@
   '"""));
     });
 
-    test("after the end of the file", () {
+    test('after the end of the file', () {
       expect(file.location(39).pointSpan().highlight(), equals("""
   ,
 4 | 
@@ -95,8 +95,8 @@
   '"""));
     });
 
-    test("at the end of the file with no trailing newline", () {
-      file = SourceFile.fromString("zip zap zop");
+    test('at the end of the file with no trailing newline', () {
+      file = SourceFile.fromString('zip zap zop');
       expect(file.location(10).pointSpan().highlight(), equals("""
   ,
 1 | zip zap zop
@@ -104,8 +104,8 @@
   '"""));
     });
 
-    test("after the end of the file with no trailing newline", () {
-      file = SourceFile.fromString("zip zap zop");
+    test('after the end of the file with no trailing newline', () {
+      file = SourceFile.fromString('zip zap zop');
       expect(file.location(11).pointSpan().highlight(), equals("""
   ,
 1 | zip zap zop
@@ -113,8 +113,8 @@
   '"""));
     });
 
-    test("in an empty file", () {
-      expect(SourceFile.fromString("").location(0).pointSpan().highlight(),
+    test('in an empty file', () {
+      expect(SourceFile.fromString('').location(0).pointSpan().highlight(),
           equals("""
   ,
 1 | 
@@ -122,8 +122,8 @@
   '"""));
     });
 
-    test("on an empty line", () {
-      final file = SourceFile.fromString("foo\n\nbar");
+    test('on an empty line', () {
+      final file = SourceFile.fromString('foo\n\nbar');
       expect(file.location(4).pointSpan().highlight(), equals("""
   ,
 2 | 
@@ -132,25 +132,25 @@
     });
   });
 
-  test("highlights a single-line file without a newline", () {
-    expect(SourceFile.fromString("foo bar").span(0, 7).highlight(), equals("""
+  test('highlights a single-line file without a newline', () {
+    expect(SourceFile.fromString('foo bar').span(0, 7).highlight(), equals("""
   ,
 1 | foo bar
   | ^^^^^^^
   '"""));
   });
 
-  test("highlights a single empty line", () {
+  test('highlights a single empty line', () {
     expect(
-        SourceFile.fromString("foo\n\nbar").span(4, 5).highlight(), equals("""
+        SourceFile.fromString('foo\n\nbar').span(4, 5).highlight(), equals("""
   ,
 2 | 
   | ^
   '"""));
   });
 
-  group("with a multiline span", () {
-    test("highlights the middle of the first and last lines", () {
+  group('with a multiline span', () {
+    test('highlights the middle of the first and last lines', () {
       expect(file.span(4, 34).highlight(), equals("""
   ,
 1 |   foo bar baz
@@ -161,7 +161,7 @@
   '"""));
     });
 
-    test("works when it begins at the end of a line", () {
+    test('works when it begins at the end of a line', () {
       expect(file.span(11, 34).highlight(), equals("""
   ,
 1 |   foo bar baz
@@ -172,7 +172,7 @@
   '"""));
     });
 
-    test("works when it ends at the beginning of a line", () {
+    test('works when it ends at the beginning of a line', () {
       expect(file.span(4, 28).highlight(), equals("""
   ,
 1 |   foo bar baz
@@ -183,7 +183,7 @@
   '"""));
     });
 
-    test("highlights the full first line", () {
+    test('highlights the full first line', () {
       expect(file.span(0, 34).highlight(), equals("""
   ,
 1 | / foo bar baz
@@ -194,11 +194,11 @@
     });
 
     test("highlights the full first line even if it's indented", () {
-      final file = SourceFile.fromString("""
+      final file = SourceFile.fromString('''
   foo bar baz
   whiz bang boom
   zip zap zop
-""");
+''');
 
       expect(file.span(2, 38).highlight(), equals("""
   ,
@@ -210,11 +210,11 @@
     });
 
     test("highlights the full first line if it's empty", () {
-      final file = SourceFile.fromString("""
+      final file = SourceFile.fromString('''
 foo
 
 bar
-""");
+''');
 
       expect(file.span(4, 9).highlight(), equals("""
   ,
@@ -223,7 +223,7 @@
   '"""));
     });
 
-    test("highlights the full last line", () {
+    test('highlights the full last line', () {
       expect(file.span(4, 27).highlight(), equals("""
   ,
 1 |   foo bar baz
@@ -232,7 +232,7 @@
   '"""));
     });
 
-    test("highlights the full last line with no trailing newline", () {
+    test('highlights the full last line with no trailing newline', () {
       expect(file.span(4, 26).highlight(), equals("""
   ,
 1 |   foo bar baz
@@ -241,12 +241,12 @@
   '"""));
     });
 
-    test("highlights the full last line with a trailing Windows newline", () {
-      final file = SourceFile.fromString("""
+    test('highlights the full last line with a trailing Windows newline', () {
+      final file = SourceFile.fromString('''
 foo bar baz\r
 whiz bang boom\r
 zip zap zop\r
-""");
+''');
 
       expect(file.span(4, 29).highlight(), equals("""
   ,
@@ -256,7 +256,7 @@
   '"""));
     });
 
-    test("highlights the full last line at the end of the file", () {
+    test('highlights the full last line at the end of the file', () {
       expect(file.span(4, 39).highlight(), equals("""
   ,
 1 |   foo bar baz
@@ -267,12 +267,12 @@
     });
 
     test(
-        "highlights the full last line at the end of the file with no trailing "
-        "newline", () {
-      final file = SourceFile.fromString("""
+        'highlights the full last line at the end of the file with no trailing '
+        'newline', () {
+      final file = SourceFile.fromString('''
 foo bar baz
 whiz bang boom
-zip zap zop""");
+zip zap zop''');
 
       expect(file.span(4, 38).highlight(), equals("""
   ,
@@ -284,11 +284,11 @@
     });
 
     test("highlights the full last line if it's empty", () {
-      final file = SourceFile.fromString("""
+      final file = SourceFile.fromString('''
 foo
 
 bar
-""");
+''');
 
       expect(file.span(0, 5).highlight(), equals("""
   ,
@@ -297,8 +297,8 @@
   '"""));
     });
 
-    test("highlights multiple empty lines", () {
-      final file = SourceFile.fromString("foo\n\n\n\nbar");
+    test('highlights multiple empty lines', () {
+      final file = SourceFile.fromString('foo\n\n\n\nbar');
       expect(file.span(4, 7).highlight(), equals("""
   ,
 2 | / 
@@ -308,8 +308,8 @@
     });
 
     // Regression test for #32
-    test("highlights the end of a line and an empty line", () {
-      final file = SourceFile.fromString("foo\n\n");
+    test('highlights the end of a line and an empty line', () {
+      final file = SourceFile.fromString('foo\n\n');
       expect(file.span(3, 5).highlight(), equals("""
   ,
 1 |   foo
@@ -319,10 +319,10 @@
     });
   });
 
-  group("prints tabs as spaces", () {
-    group("in a single-line span", () {
-      test("before the highlighted section", () {
-        final span = SourceFile.fromString("foo\tbar baz").span(4, 7);
+  group('prints tabs as spaces', () {
+    group('in a single-line span', () {
+      test('before the highlighted section', () {
+        final span = SourceFile.fromString('foo\tbar baz').span(4, 7);
 
         expect(span.highlight(), equals("""
   ,
@@ -331,8 +331,8 @@
   '"""));
       });
 
-      test("within the highlighted section", () {
-        final span = SourceFile.fromString("foo bar\tbaz bang").span(4, 11);
+      test('within the highlighted section', () {
+        final span = SourceFile.fromString('foo bar\tbaz bang').span(4, 11);
 
         expect(span.highlight(), equals("""
   ,
@@ -341,8 +341,8 @@
   '"""));
       });
 
-      test("after the highlighted section", () {
-        final span = SourceFile.fromString("foo bar\tbaz").span(4, 7);
+      test('after the highlighted section', () {
+        final span = SourceFile.fromString('foo bar\tbaz').span(4, 7);
 
         expect(span.highlight(), equals("""
   ,
@@ -352,12 +352,12 @@
       });
     });
 
-    group("in a multi-line span", () {
-      test("before the highlighted section", () {
-        final span = SourceFile.fromString("""
+    group('in a multi-line span', () {
+      test('before the highlighted section', () {
+        final span = SourceFile.fromString('''
 foo\tbar baz
 whiz bang boom
-""").span(4, 21);
+''').span(4, 21);
 
         expect(span.highlight(), equals("""
   ,
@@ -368,11 +368,11 @@
   '"""));
       });
 
-      test("within the first highlighted line", () {
-        final span = SourceFile.fromString("""
+      test('within the first highlighted line', () {
+        final span = SourceFile.fromString('''
 foo bar\tbaz
 whiz bang boom
-""").span(4, 21);
+''').span(4, 21);
 
         expect(span.highlight(), equals("""
   ,
@@ -383,12 +383,12 @@
   '"""));
       });
 
-      test("within a middle highlighted line", () {
-        final span = SourceFile.fromString("""
+      test('within a middle highlighted line', () {
+        final span = SourceFile.fromString('''
 foo bar baz
 whiz\tbang boom
 zip zap zop
-""").span(4, 34);
+''').span(4, 34);
 
         expect(span.highlight(), equals("""
   ,
@@ -400,11 +400,11 @@
   '"""));
       });
 
-      test("within the last highlighted line", () {
-        final span = SourceFile.fromString("""
+      test('within the last highlighted line', () {
+        final span = SourceFile.fromString('''
 foo bar baz
 whiz\tbang boom
-""").span(4, 21);
+''').span(4, 21);
 
         expect(span.highlight(), equals("""
   ,
@@ -415,11 +415,11 @@
   '"""));
       });
 
-      test("after the highlighted section", () {
-        final span = SourceFile.fromString("""
+      test('after the highlighted section', () {
+        final span = SourceFile.fromString('''
 foo bar baz
 whiz bang\tboom
-""").span(4, 21);
+''').span(4, 21);
 
         expect(span.highlight(), equals("""
   ,
@@ -432,13 +432,13 @@
     });
   });
 
-  group("supports lines of preceding and following context for a span", () {
-    test("within a single line", () {
+  group('supports lines of preceding and following context for a span', () {
+    test('within a single line', () {
       final span = SourceSpanWithContext(
-          SourceLocation(20, line: 2, column: 5, sourceUrl: "foo.dart"),
-          SourceLocation(27, line: 2, column: 12, sourceUrl: "foo.dart"),
-          "foo bar",
-          "previous\nlines\n-----foo bar-----\nfollowing line\n");
+          SourceLocation(20, line: 2, column: 5, sourceUrl: 'foo.dart'),
+          SourceLocation(27, line: 2, column: 12, sourceUrl: 'foo.dart'),
+          'foo bar',
+          'previous\nlines\n-----foo bar-----\nfollowing line\n');
 
       expect(span.highlight(), equals("""
   ,
@@ -450,12 +450,12 @@
   '"""));
     });
 
-    test("covering a full line", () {
+    test('covering a full line', () {
       final span = SourceSpanWithContext(
-          SourceLocation(15, line: 2, column: 0, sourceUrl: "foo.dart"),
-          SourceLocation(33, line: 3, column: 0, sourceUrl: "foo.dart"),
-          "-----foo bar-----\n",
-          "previous\nlines\n-----foo bar-----\nfollowing line\n");
+          SourceLocation(15, line: 2, column: 0, sourceUrl: 'foo.dart'),
+          SourceLocation(33, line: 3, column: 0, sourceUrl: 'foo.dart'),
+          '-----foo bar-----\n',
+          'previous\nlines\n-----foo bar-----\nfollowing line\n');
 
       expect(span.highlight(), equals("""
   ,
@@ -467,12 +467,12 @@
   '"""));
     });
 
-    test("covering multiple full lines", () {
+    test('covering multiple full lines', () {
       final span = SourceSpanWithContext(
-          SourceLocation(15, line: 2, column: 0, sourceUrl: "foo.dart"),
-          SourceLocation(23, line: 4, column: 0, sourceUrl: "foo.dart"),
-          "foo\nbar\n",
-          "previous\nlines\nfoo\nbar\nfollowing line\n");
+          SourceLocation(15, line: 2, column: 0, sourceUrl: 'foo.dart'),
+          SourceLocation(23, line: 4, column: 0, sourceUrl: 'foo.dart'),
+          'foo\nbar\n',
+          'previous\nlines\nfoo\nbar\nfollowing line\n');
 
       expect(span.highlight(), equals("""
   ,
@@ -485,7 +485,7 @@
     });
   });
 
-  group("colors", () {
+  group('colors', () {
     test("doesn't colorize if color is false", () {
       expect(file.span(4, 7).highlight(color: false), equals("""
   ,
@@ -494,47 +494,47 @@
   '"""));
     });
 
-    test("colorizes if color is true", () {
-      expect(file.span(4, 7).highlight(color: true), equals("""
+    test('colorizes if color is true', () {
+      expect(file.span(4, 7).highlight(color: true), equals('''
 ${colors.blue}  ,${colors.none}
 ${colors.blue}1 |${colors.none} foo ${colors.red}bar${colors.none} baz
 ${colors.blue}  |${colors.none}     ${colors.red}^^^${colors.none}
-${colors.blue}  '${colors.none}"""));
+${colors.blue}  '${colors.none}'''));
     });
 
     test("uses the given color if it's passed", () {
-      expect(file.span(4, 7).highlight(color: colors.yellow), equals("""
+      expect(file.span(4, 7).highlight(color: colors.yellow), equals('''
 ${colors.blue}  ,${colors.none}
 ${colors.blue}1 |${colors.none} foo ${colors.yellow}bar${colors.none} baz
 ${colors.blue}  |${colors.none}     ${colors.yellow}^^^${colors.none}
-${colors.blue}  '${colors.none}"""));
+${colors.blue}  '${colors.none}'''));
     });
 
-    test("colorizes a multiline span", () {
-      expect(file.span(4, 34).highlight(color: true), equals("""
+    test('colorizes a multiline span', () {
+      expect(file.span(4, 34).highlight(color: true), equals('''
 ${colors.blue}  ,${colors.none}
 ${colors.blue}1 |${colors.none}   foo ${colors.red}bar baz${colors.none}
 ${colors.blue}  |${colors.none} ${colors.red},-----^${colors.none}
 ${colors.blue}2 |${colors.none} ${colors.red}| whiz bang boom${colors.none}
 ${colors.blue}3 |${colors.none} ${colors.red}| zip zap${colors.none} zop
 ${colors.blue}  |${colors.none} ${colors.red}'-------^${colors.none}
-${colors.blue}  '${colors.none}"""));
+${colors.blue}  '${colors.none}'''));
     });
 
-    test("colorizes a multiline span that highlights full lines", () {
-      expect(file.span(0, 39).highlight(color: true), equals("""
+    test('colorizes a multiline span that highlights full lines', () {
+      expect(file.span(0, 39).highlight(color: true), equals('''
 ${colors.blue}  ,${colors.none}
 ${colors.blue}1 |${colors.none} ${colors.red}/ foo bar baz${colors.none}
 ${colors.blue}2 |${colors.none} ${colors.red}| whiz bang boom${colors.none}
 ${colors.blue}3 |${colors.none} ${colors.red}\\ zip zap zop${colors.none}
-${colors.blue}  '${colors.none}"""));
+${colors.blue}  '${colors.none}'''));
     });
   });
 
-  group("line numbers have appropriate padding", () {
-    test("with line number 9", () {
+  group('line numbers have appropriate padding', () {
+    test('with line number 9', () {
       expect(
-          SourceFile.fromString("\n" * 8 + "foo bar baz\n")
+          SourceFile.fromString('\n' * 8 + 'foo bar baz\n')
               .span(8, 11)
               .highlight(),
           equals("""
@@ -544,9 +544,9 @@
   '"""));
     });
 
-    test("with line number 10", () {
+    test('with line number 10', () {
       expect(
-          SourceFile.fromString("\n" * 9 + "foo bar baz\n")
+          SourceFile.fromString('\n' * 9 + 'foo bar baz\n')
               .span(9, 12)
               .highlight(),
           equals("""
diff --git a/test/span_test.dart b/test/span_test.dart
index d53e1e0..1ac9d35 100644
--- a/test/span_test.dart
+++ b/test/span_test.dart
@@ -21,28 +21,28 @@
 
   SourceSpan span;
   setUp(() {
-    span = SourceSpan(SourceLocation(5, sourceUrl: "foo.dart"),
-        SourceLocation(12, sourceUrl: "foo.dart"), "foo bar");
+    span = SourceSpan(SourceLocation(5, sourceUrl: 'foo.dart'),
+        SourceLocation(12, sourceUrl: 'foo.dart'), 'foo bar');
   });
 
   group('errors', () {
     group('for new SourceSpan()', () {
       test('source URLs must match', () {
-        final start = SourceLocation(0, sourceUrl: "foo.dart");
-        final end = SourceLocation(1, sourceUrl: "bar.dart");
-        expect(() => SourceSpan(start, end, "_"), throwsArgumentError);
+        final start = SourceLocation(0, sourceUrl: 'foo.dart');
+        final end = SourceLocation(1, sourceUrl: 'bar.dart');
+        expect(() => SourceSpan(start, end, '_'), throwsArgumentError);
       });
 
       test('end must come after start', () {
         final start = SourceLocation(1);
         final end = SourceLocation(0);
-        expect(() => SourceSpan(start, end, "_"), throwsArgumentError);
+        expect(() => SourceSpan(start, end, '_'), throwsArgumentError);
       });
 
       test('text must be the right length', () {
         final start = SourceLocation(0);
         final end = SourceLocation(1);
-        expect(() => SourceSpan(start, end, "abc"), throwsArgumentError);
+        expect(() => SourceSpan(start, end, 'abc'), throwsArgumentError);
       });
     });
 
@@ -50,30 +50,30 @@
       test('context must contain text', () {
         final start = SourceLocation(2);
         final end = SourceLocation(5);
-        expect(() => SourceSpanWithContext(start, end, "abc", "--axc--"),
+        expect(() => SourceSpanWithContext(start, end, 'abc', '--axc--'),
             throwsArgumentError);
       });
 
       test('text starts at start.column in context', () {
         final start = SourceLocation(3);
         final end = SourceLocation(5);
-        expect(() => SourceSpanWithContext(start, end, "abc", "--abc--"),
+        expect(() => SourceSpanWithContext(start, end, 'abc', '--abc--'),
             throwsArgumentError);
       });
 
       test('text starts at start.column of line in multi-line context', () {
         final start = SourceLocation(4, line: 55, column: 3);
         final end = SourceLocation(7, line: 55, column: 6);
-        expect(() => SourceSpanWithContext(start, end, "abc", "\n--abc--"),
+        expect(() => SourceSpanWithContext(start, end, 'abc', '\n--abc--'),
             throwsArgumentError);
-        expect(() => SourceSpanWithContext(start, end, "abc", "\n----abc--"),
+        expect(() => SourceSpanWithContext(start, end, 'abc', '\n----abc--'),
             throwsArgumentError);
-        expect(() => SourceSpanWithContext(start, end, "abc", "\n\n--abc--"),
+        expect(() => SourceSpanWithContext(start, end, 'abc', '\n\n--abc--'),
             throwsArgumentError);
 
         // However, these are valid:
-        SourceSpanWithContext(start, end, "abc", "\n---abc--");
-        SourceSpanWithContext(start, end, "abc", "\n\n---abc--");
+        SourceSpanWithContext(start, end, 'abc', '\n---abc--');
+        SourceSpanWithContext(start, end, 'abc', '\n\n---abc--');
       });
 
       test('text can occur multiple times in context', () {
@@ -81,109 +81,109 @@
         final end1 = SourceLocation(7, line: 55, column: 5);
         final start2 = SourceLocation(4, line: 55, column: 8);
         final end2 = SourceLocation(7, line: 55, column: 11);
-        SourceSpanWithContext(start1, end1, "abc", "--abc---abc--\n");
-        SourceSpanWithContext(start1, end1, "abc", "--abc--abc--\n");
-        SourceSpanWithContext(start2, end2, "abc", "--abc---abc--\n");
-        SourceSpanWithContext(start2, end2, "abc", "---abc--abc--\n");
+        SourceSpanWithContext(start1, end1, 'abc', '--abc---abc--\n');
+        SourceSpanWithContext(start1, end1, 'abc', '--abc--abc--\n');
+        SourceSpanWithContext(start2, end2, 'abc', '--abc---abc--\n');
+        SourceSpanWithContext(start2, end2, 'abc', '---abc--abc--\n');
         expect(
-            () => SourceSpanWithContext(start1, end1, "abc", "---abc--abc--\n"),
+            () => SourceSpanWithContext(start1, end1, 'abc', '---abc--abc--\n'),
             throwsArgumentError);
         expect(
-            () => SourceSpanWithContext(start2, end2, "abc", "--abc--abc--\n"),
+            () => SourceSpanWithContext(start2, end2, 'abc', '--abc--abc--\n'),
             throwsArgumentError);
       });
     });
 
     group('for union()', () {
       test('source URLs must match', () {
-        final other = SourceSpan(SourceLocation(12, sourceUrl: "bar.dart"),
-            SourceLocation(13, sourceUrl: "bar.dart"), "_");
+        final other = SourceSpan(SourceLocation(12, sourceUrl: 'bar.dart'),
+            SourceLocation(13, sourceUrl: 'bar.dart'), '_');
 
         expect(() => span.union(other), throwsArgumentError);
       });
 
       test('spans may not be disjoint', () {
         final other = SourceSpan(SourceLocation(13, sourceUrl: 'foo.dart'),
-            SourceLocation(14, sourceUrl: 'foo.dart'), "_");
+            SourceLocation(14, sourceUrl: 'foo.dart'), '_');
 
         expect(() => span.union(other), throwsArgumentError);
       });
     });
 
     test('for compareTo() source URLs must match', () {
-      final other = SourceSpan(SourceLocation(12, sourceUrl: "bar.dart"),
-          SourceLocation(13, sourceUrl: "bar.dart"), "_");
+      final other = SourceSpan(SourceLocation(12, sourceUrl: 'bar.dart'),
+          SourceLocation(13, sourceUrl: 'bar.dart'), '_');
 
       expect(() => span.compareTo(other), throwsArgumentError);
     });
   });
 
   test('fields work correctly', () {
-    expect(span.start, equals(SourceLocation(5, sourceUrl: "foo.dart")));
-    expect(span.end, equals(SourceLocation(12, sourceUrl: "foo.dart")));
-    expect(span.sourceUrl, equals(Uri.parse("foo.dart")));
+    expect(span.start, equals(SourceLocation(5, sourceUrl: 'foo.dart')));
+    expect(span.end, equals(SourceLocation(12, sourceUrl: 'foo.dart')));
+    expect(span.sourceUrl, equals(Uri.parse('foo.dart')));
     expect(span.length, equals(7));
   });
 
-  group("union()", () {
-    test("works with a preceding adjacent span", () {
-      final other = SourceSpan(SourceLocation(0, sourceUrl: "foo.dart"),
-          SourceLocation(5, sourceUrl: "foo.dart"), "hey, ");
+  group('union()', () {
+    test('works with a preceding adjacent span', () {
+      final other = SourceSpan(SourceLocation(0, sourceUrl: 'foo.dart'),
+          SourceLocation(5, sourceUrl: 'foo.dart'), 'hey, ');
 
       final result = span.union(other);
       expect(result.start, equals(other.start));
       expect(result.end, equals(span.end));
-      expect(result.text, equals("hey, foo bar"));
+      expect(result.text, equals('hey, foo bar'));
     });
 
-    test("works with a preceding overlapping span", () {
-      final other = SourceSpan(SourceLocation(0, sourceUrl: "foo.dart"),
-          SourceLocation(8, sourceUrl: "foo.dart"), "hey, foo");
+    test('works with a preceding overlapping span', () {
+      final other = SourceSpan(SourceLocation(0, sourceUrl: 'foo.dart'),
+          SourceLocation(8, sourceUrl: 'foo.dart'), 'hey, foo');
 
       final result = span.union(other);
       expect(result.start, equals(other.start));
       expect(result.end, equals(span.end));
-      expect(result.text, equals("hey, foo bar"));
+      expect(result.text, equals('hey, foo bar'));
     });
 
-    test("works with a following adjacent span", () {
-      final other = SourceSpan(SourceLocation(12, sourceUrl: "foo.dart"),
-          SourceLocation(16, sourceUrl: "foo.dart"), " baz");
+    test('works with a following adjacent span', () {
+      final other = SourceSpan(SourceLocation(12, sourceUrl: 'foo.dart'),
+          SourceLocation(16, sourceUrl: 'foo.dart'), ' baz');
 
       final result = span.union(other);
       expect(result.start, equals(span.start));
       expect(result.end, equals(other.end));
-      expect(result.text, equals("foo bar baz"));
+      expect(result.text, equals('foo bar baz'));
     });
 
-    test("works with a following overlapping span", () {
-      final other = SourceSpan(SourceLocation(9, sourceUrl: "foo.dart"),
-          SourceLocation(16, sourceUrl: "foo.dart"), "bar baz");
+    test('works with a following overlapping span', () {
+      final other = SourceSpan(SourceLocation(9, sourceUrl: 'foo.dart'),
+          SourceLocation(16, sourceUrl: 'foo.dart'), 'bar baz');
 
       final result = span.union(other);
       expect(result.start, equals(span.start));
       expect(result.end, equals(other.end));
-      expect(result.text, equals("foo bar baz"));
+      expect(result.text, equals('foo bar baz'));
     });
 
-    test("works with an internal overlapping span", () {
-      final other = SourceSpan(SourceLocation(7, sourceUrl: "foo.dart"),
-          SourceLocation(10, sourceUrl: "foo.dart"), "o b");
+    test('works with an internal overlapping span', () {
+      final other = SourceSpan(SourceLocation(7, sourceUrl: 'foo.dart'),
+          SourceLocation(10, sourceUrl: 'foo.dart'), 'o b');
 
       expect(span.union(other), equals(span));
     });
 
-    test("works with an external overlapping span", () {
-      final other = SourceSpan(SourceLocation(0, sourceUrl: "foo.dart"),
-          SourceLocation(16, sourceUrl: "foo.dart"), "hey, foo bar baz");
+    test('works with an external overlapping span', () {
+      final other = SourceSpan(SourceLocation(0, sourceUrl: 'foo.dart'),
+          SourceLocation(16, sourceUrl: 'foo.dart'), 'hey, foo bar baz');
 
       expect(span.union(other), equals(other));
     });
   });
 
-  group("message()", () {
-    test("prints the text being described", () {
-      expect(span.message("oh no"), equals("""
+  group('message()', () {
+    test('prints the text being described', () {
+      expect(span.message('oh no'), equals("""
 line 1, column 6 of foo.dart: oh no
   ,
 1 | foo bar
@@ -191,10 +191,10 @@
   '"""));
     });
 
-    test("gracefully handles a missing source URL", () {
-      final span = SourceSpan(SourceLocation(5), SourceLocation(12), "foo bar");
+    test('gracefully handles a missing source URL', () {
+      final span = SourceSpan(SourceLocation(5), SourceLocation(12), 'foo bar');
 
-      expect(span.message("oh no"), equalsIgnoringWhitespace("""
+      expect(span.message('oh no'), equalsIgnoringWhitespace("""
 line 1, column 6: oh no
   ,
 1 | foo bar
@@ -202,14 +202,14 @@
   '"""));
     });
 
-    test("gracefully handles empty text", () {
-      final span = SourceSpan(SourceLocation(5), SourceLocation(5), "");
+    test('gracefully handles empty text', () {
+      final span = SourceSpan(SourceLocation(5), SourceLocation(5), '');
 
-      expect(span.message("oh no"), equals("line 1, column 6: oh no"));
+      expect(span.message('oh no'), equals('line 1, column 6: oh no'));
     });
 
     test("doesn't colorize if color is false", () {
-      expect(span.message("oh no", color: false), equals("""
+      expect(span.message('oh no', color: false), equals("""
 line 1, column 6 of foo.dart: oh no
   ,
 1 | foo bar
@@ -217,8 +217,8 @@
   '"""));
     });
 
-    test("colorizes if color is true", () {
-      expect(span.message("oh no", color: true), equals("""
+    test('colorizes if color is true', () {
+      expect(span.message('oh no', color: true), equals("""
 line 1, column 6 of foo.dart: oh no
 ${colors.blue}  ,${colors.none}
 ${colors.blue}1 |${colors.none} ${colors.red}foo bar${colors.none}
@@ -227,7 +227,7 @@
     });
 
     test("uses the given color if it's passed", () {
-      expect(span.message("oh no", color: colors.yellow), equals("""
+      expect(span.message('oh no', color: colors.yellow), equals("""
 line 1, column 6 of foo.dart: oh no
 ${colors.blue}  ,${colors.none}
 ${colors.blue}1 |${colors.none} ${colors.yellow}foo bar${colors.none}
@@ -235,14 +235,14 @@
 ${colors.blue}  '${colors.none}"""));
     });
 
-    test("with context, underlines the right column", () {
+    test('with context, underlines the right column', () {
       final spanWithContext = SourceSpanWithContext(
-          SourceLocation(5, sourceUrl: "foo.dart"),
-          SourceLocation(12, sourceUrl: "foo.dart"),
-          "foo bar",
-          "-----foo bar-----");
+          SourceLocation(5, sourceUrl: 'foo.dart'),
+          SourceLocation(12, sourceUrl: 'foo.dart'),
+          'foo bar',
+          '-----foo bar-----');
 
-      expect(spanWithContext.message("oh no", color: colors.yellow), equals("""
+      expect(spanWithContext.message('oh no', color: colors.yellow), equals("""
 line 1, column 6 of foo.dart: oh no
 ${colors.blue}  ,${colors.none}
 ${colors.blue}1 |${colors.none} -----${colors.yellow}foo bar${colors.none}-----
@@ -251,53 +251,53 @@
     });
   });
 
-  group("compareTo()", () {
-    test("sorts by start location first", () {
-      final other = SourceSpan(SourceLocation(6, sourceUrl: "foo.dart"),
-          SourceLocation(14, sourceUrl: "foo.dart"), "oo bar b");
+  group('compareTo()', () {
+    test('sorts by start location first', () {
+      final other = SourceSpan(SourceLocation(6, sourceUrl: 'foo.dart'),
+          SourceLocation(14, sourceUrl: 'foo.dart'), 'oo bar b');
 
       expect(span.compareTo(other), lessThan(0));
       expect(other.compareTo(span), greaterThan(0));
     });
 
-    test("sorts by length second", () {
-      final other = SourceSpan(SourceLocation(5, sourceUrl: "foo.dart"),
-          SourceLocation(14, sourceUrl: "foo.dart"), "foo bar b");
+    test('sorts by length second', () {
+      final other = SourceSpan(SourceLocation(5, sourceUrl: 'foo.dart'),
+          SourceLocation(14, sourceUrl: 'foo.dart'), 'foo bar b');
 
       expect(span.compareTo(other), lessThan(0));
       expect(other.compareTo(span), greaterThan(0));
     });
 
-    test("considers equal spans equal", () {
+    test('considers equal spans equal', () {
       expect(span.compareTo(span), equals(0));
     });
   });
 
-  group("equality", () {
-    test("two spans with the same locations are equal", () {
-      final other = SourceSpan(SourceLocation(5, sourceUrl: "foo.dart"),
-          SourceLocation(12, sourceUrl: "foo.dart"), "foo bar");
+  group('equality', () {
+    test('two spans with the same locations are equal', () {
+      final other = SourceSpan(SourceLocation(5, sourceUrl: 'foo.dart'),
+          SourceLocation(12, sourceUrl: 'foo.dart'), 'foo bar');
 
       expect(span, equals(other));
     });
 
     test("a different start isn't equal", () {
-      final other = SourceSpan(SourceLocation(0, sourceUrl: "foo.dart"),
-          SourceLocation(12, sourceUrl: "foo.dart"), "hey, foo bar");
+      final other = SourceSpan(SourceLocation(0, sourceUrl: 'foo.dart'),
+          SourceLocation(12, sourceUrl: 'foo.dart'), 'hey, foo bar');
 
       expect(span, isNot(equals(other)));
     });
 
     test("a different end isn't equal", () {
-      final other = SourceSpan(SourceLocation(5, sourceUrl: "foo.dart"),
-          SourceLocation(16, sourceUrl: "foo.dart"), "foo bar baz");
+      final other = SourceSpan(SourceLocation(5, sourceUrl: 'foo.dart'),
+          SourceLocation(16, sourceUrl: 'foo.dart'), 'foo bar baz');
 
       expect(span, isNot(equals(other)));
     });
 
     test("a different source URL isn't equal", () {
-      final other = SourceSpan(SourceLocation(5, sourceUrl: "bar.dart"),
-          SourceLocation(12, sourceUrl: "bar.dart"), "foo bar");
+      final other = SourceSpan(SourceLocation(5, sourceUrl: 'bar.dart'),
+          SourceLocation(12, sourceUrl: 'bar.dart'), 'foo bar');
 
       expect(span, isNot(equals(other)));
     });