Fix RangeError in unnecessary_string_escapes (#2297)

* Fix RangeError in unnecessary_string_escapes

* Add integration test.

* Update use_raw_strings.
diff --git a/lib/src/rules/unnecessary_string_escapes.dart b/lib/src/rules/unnecessary_string_escapes.dart
index 32a5ffc..dc64add 100644
--- a/lib/src/rules/unnecessary_string_escapes.dart
+++ b/lib/src/rules/unnecessary_string_escapes.dart
@@ -105,7 +105,7 @@
     for (var i = 0; i < lexeme.length; i++) {
       var current = lexeme[i];
       var escaped = false;
-      if (current == r'\') {
+      if (current == r'\' && i < lexeme.length - 1) {
         escaped = true;
         i += 1;
         current = lexeme[i];
diff --git a/lib/src/rules/use_raw_strings.dart b/lib/src/rules/use_raw_strings.dart
index 312a4fd..368cc35 100644
--- a/lib/src/rules/use_raw_strings.dart
+++ b/lib/src/rules/use_raw_strings.dart
@@ -54,7 +54,7 @@
         node.contentsOffset - node.literal.offset,
         node.contentsEnd - node.literal.offset);
     var hasEscape = false;
-    for (var i = 0; i < lexeme.length; i++) {
+    for (var i = 0; i < lexeme.length - 1; i++) {
       var current = lexeme[i];
       if (current == r'\') {
         hasEscape = true;
diff --git a/test/_data/unnecessary_string_escapes/no_closing_quote.dart b/test/_data/unnecessary_string_escapes/no_closing_quote.dart
new file mode 100644
index 0000000..a1782a4
--- /dev/null
+++ b/test/_data/unnecessary_string_escapes/no_closing_quote.dart
@@ -0,0 +1,8 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Note that putting `''` on the new line is important to get a token
+/// with `'\` with no closing quote.
+String unclosedQuote() => '\
+'';
\ No newline at end of file
diff --git a/test/integration_test.dart b/test/integration_test.dart
index 2f39a11..ff29894 100644
--- a/test/integration_test.dart
+++ b/test/integration_test.dart
@@ -40,6 +40,23 @@
       });
     });
 
+    group('unnecessary_string_escapes', () {
+      final currentOut = outSink;
+      final collectingOut = CollectingSink();
+      setUp(() => outSink = collectingOut);
+      tearDown(() {
+        collectingOut.buffer.clear();
+        outSink = currentOut;
+      });
+      test('no_closing_quote', () async {
+        await cli.runLinter([
+          'test/_data/unnecessary_string_escapes/no_closing_quote.dart',
+          '--rules=unnecessary_string_escapes',
+        ], LinterOptions());
+        // No exception.
+      });
+    });
+
     group('exhaustive_cases', () {
       final currentOut = outSink;
       final collectingOut = CollectingSink();