Report missing semicolon on last consumed token

This moves the location on which a missing semicolon error is reported,
making it easier for a user to understand and fix,
and fixing some of the statement completion tests.

Change-Id: I11b9de57e2b3104238e1edb801ad1cd02e9a63a2
Reviewed-on: https://dart-review.googlesource.com/64900
Commit-Queue: Dan Rubel <danrubel@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index 69f9678..21c4f38 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -2587,7 +2587,7 @@
             expectedError(
                 CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, 10, 8),
             expectedError(ParserErrorCode.EXPECTED_TOKEN, 19, 1),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 21, 4)
+            expectedError(ParserErrorCode.EXPECTED_TOKEN, 19, 1)
           ]
         : [
             expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 0),
@@ -3069,11 +3069,11 @@
             ? [
                 expectedError(
                     ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 9, 5),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 15, 1),
+                expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 5),
                 expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 15, 1),
                 expectedError(
                     ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 17, 5),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 23, 1)
+                expectedError(ParserErrorCode.EXPECTED_TOKEN, 17, 5)
               ]
             : [
                 expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 15, 1),
@@ -3091,7 +3091,7 @@
                 expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 10, 1),
                 expectedError(
                     ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 12, 5),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 18, 1)
+                expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 5)
               ]
             : [
                 expectedError(ParserErrorCode.EXPECTED_CLASS_MEMBER, 10, 1),
@@ -3131,11 +3131,11 @@
             ? [
                 expectedError(
                     ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 0, 5),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 1),
+                expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 5),
                 expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 6, 1),
                 expectedError(
                     ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 8, 5),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 13, 0),
+                expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 5),
               ]
             : [
                 expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 6, 1),
@@ -3172,7 +3172,7 @@
                 expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 0, 1),
                 expectedError(
                     ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 2, 5),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 0),
+                expectedError(ParserErrorCode.EXPECTED_TOKEN, 2, 5),
               ]
             : [
                 expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 0, 1),
@@ -3187,7 +3187,7 @@
             ? [
                 expectedError(
                     ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 0, 1),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 1, 0)
+                expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 1)
               ]
             : [expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 0, 1)]);
   }
@@ -3814,7 +3814,7 @@
       // TODO(danrubel): Investigate better recovery.
       ExpressionStatement statement = result;
       listener
-          .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 1)]);
+          .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 3)]);
       expect(statement.expression.toSource(), 'get');
     } else {
       FunctionDeclarationStatement statement = result;
@@ -3829,7 +3829,7 @@
     // Fasta considers `get` to be an identifier in this situation.
     parseStatement("int get x { return _x; }", expectedEndOffset: 8);
     listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 1)]
+        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 3)]
         : [expectedError(ParserErrorCode.GETTER_IN_FUNCTION, 4, 3)]);
   }
 
@@ -3837,7 +3837,7 @@
     // Fasta considers `get` to be an identifier in this situation.
     parseStatement("get x => _x;", expectedEndOffset: 4);
     listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 1)]
+        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 3)]
         : [expectedError(ParserErrorCode.GETTER_IN_FUNCTION, 0, 3)]);
   }
 
@@ -3845,7 +3845,7 @@
     // Fasta considers `get` to be an identifier in this situation.
     parseStatement("int get x => _x;", expectedEndOffset: 8);
     listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 1)]
+        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 3)]
         : [expectedError(ParserErrorCode.GETTER_IN_FUNCTION, 4, 3)]);
   }
 
@@ -3950,7 +3950,7 @@
     expectNotNullIfNoErrors(statement);
     listener.assertErrors(usingFastaParser
         ? [
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 1),
+            expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1),
             expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 1),
             expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 1)
           ]
@@ -3966,9 +3966,9 @@
     expectNotNullIfNoErrors(statement);
     listener.assertErrors(usingFastaParser
         ? [
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 1),
+            expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1),
             expectedError(ParserErrorCode.MISSING_IDENTIFIER, 9, 1),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 1)
+            expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1)
           ]
         : [
             expectedError(ParserErrorCode.EXPECTED_TOKEN, 5, 1),
@@ -4327,7 +4327,7 @@
   void test_localFunctionDeclarationModifier_factory() {
     parseCompilationUnit("class C { m() { factory f() {} } }",
         errors: usingFastaParser
-            ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 24, 1)]
+            ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 16, 7)]
             : [
                 expectedError(
                     ParserErrorCode.LOCAL_FUNCTION_DECLARATION_MODIFIER, 16, 7)
@@ -4587,7 +4587,7 @@
     // error message is in this case.
     parseStatement("int f { return x;}", expectedEndOffset: 6);
     listener
-        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 1)]);
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 1)]);
   }
 
   void test_missingFunctionParameters_local_nonVoid_expression() {
@@ -4603,7 +4603,7 @@
   void test_missingFunctionParameters_local_void_block() {
     parseStatement("void f { return x;}", expectedEndOffset: 7);
     listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1)]
+        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 5, 1)]
         : [expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 5, 1)]);
   }
 
@@ -4657,7 +4657,7 @@
         ? [
             expectedError(
                 ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 0, 3),
-            expectedError(ParserErrorCode.EXPECTED_TOKEN, 3, 1)
+            expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 3)
           ]
         : [
             expectedError(ParserErrorCode.MISSING_IDENTIFIER, 3, 1),
@@ -5517,7 +5517,7 @@
 ''',
         errors: usingFastaParser
             ? [
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 51, 1),
+                expectedError(ParserErrorCode.EXPECTED_TOKEN, 49, 1),
                 expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 51, 1),
               ]
             : [
@@ -5578,7 +5578,7 @@
   void test_unexpectedToken_endOfFieldDeclarationStatement() {
     parseStatement("String s = (null));", expectedEndOffset: 17);
     listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 17, 1)]
+        ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 16, 1)]
         : [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 17, 1)]);
   }
 
@@ -5627,7 +5627,7 @@
   var x = "''', errors: [
       expectedError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 24, 1),
       expectedError(ScannerErrorCode.EXPECTED_TOKEN, 25, 1),
-      expectedError(ParserErrorCode.EXPECTED_TOKEN, 25, 0)
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 24, 1)
     ]);
   }
 
@@ -11228,7 +11228,7 @@
             ? [
                 expectedError(
                     ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 0, 6),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 0)
+                expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 6)
               ]
             : [expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 0, 6)]);
     NodeList<CompilationUnitMember> declarations = unit.declarations;
@@ -11474,9 +11474,8 @@
   void test_incompleteForEach() {
     ForStatement statement = parseStatement('for (String item i) {}');
     listener.assertErrors([
-      expectedError(ParserErrorCode.EXPECTED_TOKEN, 17, 1),
-      expectedError(
-          ParserErrorCode.EXPECTED_TOKEN, usingFastaParser ? 18 : 17, 1)
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 4),
+      expectedError(ParserErrorCode.EXPECTED_TOKEN, 17, 1)
     ]);
     expect(statement, new TypeMatcher<ForStatement>());
     expect(statement.toSource(), 'for (String item; i;) {}');
@@ -11489,7 +11488,7 @@
   void test_incompleteLocalVariable_atTheEndOfBlock() {
     Statement statement = parseStatement('String v }', expectedEndOffset: 9);
     listener
-        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1)]);
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1)]);
     expect(statement, new TypeMatcher<VariableDeclarationStatement>());
     expect(statement.toSource(), 'String v;');
   }
@@ -11508,7 +11507,7 @@
     Statement statement =
         parseStatement('String v String v2;', expectedEndOffset: 9);
     listener
-        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 6)]);
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1)]);
     expect(statement, new TypeMatcher<VariableDeclarationStatement>());
     expect(statement.toSource(), 'String v;');
   }
@@ -11517,7 +11516,7 @@
     Statement statement =
         parseStatement('String v if (true) {}', expectedEndOffset: 9);
     listener
-        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 2)]);
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1)]);
     expect(statement, new TypeMatcher<VariableDeclarationStatement>());
     expect(statement.toSource(), 'String v;');
   }
@@ -11525,7 +11524,7 @@
   void test_incompleteLocalVariable_beforeNextBlock() {
     Statement statement = parseStatement('String v {}', expectedEndOffset: 9);
     listener
-        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1)]);
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1)]);
     expect(statement, new TypeMatcher<VariableDeclarationStatement>());
     expect(statement.toSource(), 'String v;');
   }
@@ -11534,7 +11533,7 @@
     Statement statement =
         parseStatement('List<String> v {}', expectedEndOffset: 15);
     listener
-        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 15, 1)]);
+        .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 13, 1)]);
     expect(statement, new TypeMatcher<VariableDeclarationStatement>());
     expect(statement.toSource(), 'List<String> v;');
   }
@@ -11990,7 +11989,7 @@
                 expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 4),
                 expectedError(
                     ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 7, 4),
-                expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 1),
+                expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 4),
                 expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 11, 1),
                 expectedError(
                     ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 12, 2)
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
index 83b676e..fc453d5 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
@@ -2136,6 +2136,26 @@
     tip: r"""Try re-writing the expression.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String string)> templateExpectedAfterButGot =
+    const Template<Message Function(String string)>(
+        messageTemplate: r"""Expected '#string' after this.""",
+        withArguments: _withArgumentsExpectedAfterButGot);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String string)> codeExpectedAfterButGot =
+    const Code<Message Function(String string)>(
+        "ExpectedAfterButGot", templateExpectedAfterButGot,
+        analyzerCode: "EXPECTED_TOKEN",
+        dart2jsCode: "MISSING_TOKEN_AFTER_THIS");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsExpectedAfterButGot(String string) {
+  return new Message(codeExpectedAfterButGot,
+      message: """Expected '${string}' after this.""",
+      arguments: {'string': string});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeExpectedAnInitializer = messageExpectedAnInitializer;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index 0c820a7..74b59cd 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -88,7 +88,12 @@
         noType,
         noTypeParamOrArg;
 
-import 'util.dart' show findNonSyntheticToken, isOneOf, optional;
+import 'util.dart'
+    show
+        findPreviousNonZeroLengthToken,
+        findNonZeroLengthToken,
+        isOneOf,
+        optional;
 
 /// An event generating parser of Dart programs. This parser expects all tokens
 /// in a linked list (aka a token stream).
@@ -2427,9 +2432,15 @@
     // from the handleError method in element_listener.dart.
     Token next = token.next;
     if (optional(';', next)) return next;
-    Message message = fasta.templateExpectedButGot.withArguments(';');
-    Token newToken = new SyntheticToken(TokenType.SEMICOLON, next.charOffset);
-    return rewriteAndRecover(token, message, newToken).next;
+
+    // Find a token on the same line as where the ';' should be inserted.
+    // Reporting the error on this token makes it easier
+    // for users to understand and fix the error.
+    reportRecoverableError(findPreviousNonZeroLengthToken(token),
+        fasta.templateExpectedAfterButGot.withArguments(';'));
+
+    return rewriter.insertToken(
+        token, new SyntheticToken(TokenType.SEMICOLON, next.charOffset));
   }
 
   /// Report an error at the token after [token] that has the given [message].
@@ -5668,7 +5679,7 @@
       reportErrorToken(token);
     } else {
       // Find a non-synthetic token on which to report the error.
-      token = findNonSyntheticToken(token);
+      token = findNonZeroLengthToken(token);
       listener.handleRecoverableError(message, token, token);
     }
   }
@@ -5679,7 +5690,7 @@
       reportErrorToken(token);
     } else {
       // Find a non-synthetic token on which to report the error.
-      token = findNonSyntheticToken(token);
+      token = findNonZeroLengthToken(token);
       listener.handleRecoverableError(
           template.withArguments(token), token, token);
     }
diff --git a/pkg/front_end/lib/src/fasta/parser/util.dart b/pkg/front_end/lib/src/fasta/parser/util.dart
index 96495e7..ab00611 100644
--- a/pkg/front_end/lib/src/fasta/parser/util.dart
+++ b/pkg/front_end/lib/src/fasta/parser/util.dart
@@ -33,11 +33,24 @@
   return token;
 }
 
-/// Return [token] if it is non-synthetic,
-/// otherwise find the next non-synthetic token.
+/// Return [token] or a token before [token] which is either
+/// not synthetic or synthetic with non-zero length.
+Token findPreviousNonZeroLengthToken(Token token) {
+  while (token.isSynthetic && token.length == 0) {
+    Token previous = token.beforeSynthetic;
+    if (previous == null) {
+      break;
+    }
+    token = previous;
+  }
+  return token;
+}
+
+/// Return [token] or a token after [token] which is either
+/// not synthetic or synthetic with non-zero length.
 /// This may return EOF if there are no more non-synthetic tokens in the stream.
-Token findNonSyntheticToken(Token token) {
-  while (token.isSynthetic && !token.isEof) {
+Token findNonZeroLengthToken(Token token) {
+  while (token.isSynthetic && token.length == 0 && !token.isEof) {
     token = token.next;
   }
   return token;
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index d35824b..7c48b34 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -218,6 +218,7 @@
   statement: "void;"
 
 ExpectedButGot:
+  # Also see ExpectedAfterButGot
   template: "Expected '#string' before this."
   # Consider the second example below: the parser expects a ')' before 'y', but
   # a ',' would also have worked. We don't have enough information to give a
@@ -228,6 +229,32 @@
     - "main() => true ? 1;"
     - "main() => foo(x: 1 y: 2);"
 
+ExpectedAfterButGot:
+  # Also see ExpectedButGot
+  template: "Expected '#string' after this."
+  # This is an alternative to ExpectedButGot when it's better for the error to be
+  # associated with the last consumed token rather than the token being parsed.
+  # Doing so can make it cognitively easier for the user to understand and fix.
+  #
+  # For example, this is ok...
+  #
+  #    x = 7
+  #    class Foo {
+  #    ^^^^^
+  #        Expected ';' before this
+  #
+  # but this is easier for the user...
+  #
+  #    x = 7
+  #        ^
+  #        Expected ';' after this
+  #    class Foo {
+  #
+  analyzerCode: EXPECTED_TOKEN
+  dart2jsCode: MISSING_TOKEN_AFTER_THIS
+  script:
+    - "main() { return true }"
+
 MultipleLibraryDirectives:
   template: "Only one library directive may be declared in a file."
   tip: "Try removing all but one of the library directives."
diff --git a/pkg/front_end/testcases/regress/issue_29976.dart.direct.expect b/pkg/front_end/testcases/regress/issue_29976.dart.direct.expect
index 7bb3ead..ad177b0 100644
--- a/pkg/front_end/testcases/regress/issue_29976.dart.direct.expect
+++ b/pkg/front_end/testcases/regress/issue_29976.dart.direct.expect
@@ -25,9 +25,9 @@
 //   )
 //   ^
 //
-// pkg/front_end/testcases/regress/issue_29976.dart:9:1: Error: Expected ';' before this.
-// }
-// ^
+// pkg/front_end/testcases/regress/issue_29976.dart:8:3: Error: Expected ';' after this.
+//   )
+//   ^
 
 library;
 import self as self;
diff --git a/pkg/front_end/testcases/regress/issue_29976.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_29976.dart.direct.transformed.expect
index 7bb3ead..ad177b0 100644
--- a/pkg/front_end/testcases/regress/issue_29976.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_29976.dart.direct.transformed.expect
@@ -25,9 +25,9 @@
 //   )
 //   ^
 //
-// pkg/front_end/testcases/regress/issue_29976.dart:9:1: Error: Expected ';' before this.
-// }
-// ^
+// pkg/front_end/testcases/regress/issue_29976.dart:8:3: Error: Expected ';' after this.
+//   )
+//   ^
 
 library;
 import self as self;
diff --git a/pkg/front_end/testcases/regress/issue_29976.dart.strong.expect b/pkg/front_end/testcases/regress/issue_29976.dart.strong.expect
index 1e14bbe..125df90 100644
--- a/pkg/front_end/testcases/regress/issue_29976.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_29976.dart.strong.expect
@@ -33,9 +33,9 @@
 //   f(
 //   ^
 //
-// pkg/front_end/testcases/regress/issue_29976.dart:9:1: Error: Expected ';' before this.
-// }
-// ^
+// pkg/front_end/testcases/regress/issue_29976.dart:8:3: Error: Expected ';' after this.
+//   )
+//   ^
 
 library;
 import self as self;
diff --git a/pkg/front_end/testcases/regress/issue_29985.dart.direct.expect b/pkg/front_end/testcases/regress/issue_29985.dart.direct.expect
index 4ef9968..d87258e 100644
--- a/pkg/front_end/testcases/regress/issue_29985.dart.direct.expect
+++ b/pkg/front_end/testcases/regress/issue_29985.dart.direct.expect
@@ -5,9 +5,9 @@
 //   🔛
 //   ^
 //
-// pkg/front_end/testcases/regress/issue_29985.dart:7:1: Error: Expected ';' before this.
-// }
-// ^
+// pkg/front_end/testcases/regress/issue_29985.dart:6:3: Error: Expected ';' after this.
+//   🔛
+//   ^^
 
 library;
 import self as self;
diff --git a/pkg/front_end/testcases/regress/issue_29985.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_29985.dart.direct.transformed.expect
index 4ef9968..d87258e 100644
--- a/pkg/front_end/testcases/regress/issue_29985.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_29985.dart.direct.transformed.expect
@@ -5,9 +5,9 @@
 //   🔛
 //   ^
 //
-// pkg/front_end/testcases/regress/issue_29985.dart:7:1: Error: Expected ';' before this.
-// }
-// ^
+// pkg/front_end/testcases/regress/issue_29985.dart:6:3: Error: Expected ';' after this.
+//   🔛
+//   ^^
 
 library;
 import self as self;
diff --git a/pkg/front_end/testcases/regress/issue_29985.dart.strong.expect b/pkg/front_end/testcases/regress/issue_29985.dart.strong.expect
index 9eae89d..2ec7cc8 100644
--- a/pkg/front_end/testcases/regress/issue_29985.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_29985.dart.strong.expect
@@ -5,9 +5,9 @@
 //   🔛
 //   ^
 //
-// pkg/front_end/testcases/regress/issue_29985.dart:7:1: Error: Expected ';' before this.
-// }
-// ^
+// pkg/front_end/testcases/regress/issue_29985.dart:6:3: Error: Expected ';' after this.
+//   🔛
+//   ^^
 //
 // pkg/front_end/testcases/regress/issue_29985.dart:6:3: Error: Getter not found: '🔛'.
 //   🔛
diff --git a/pkg/front_end/testcases/regress/issue_29985.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_29985.dart.strong.transformed.expect
index 9eae89d..2ec7cc8 100644
--- a/pkg/front_end/testcases/regress/issue_29985.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_29985.dart.strong.transformed.expect
@@ -5,9 +5,9 @@
 //   🔛
 //   ^
 //
-// pkg/front_end/testcases/regress/issue_29985.dart:7:1: Error: Expected ';' before this.
-// }
-// ^
+// pkg/front_end/testcases/regress/issue_29985.dart:6:3: Error: Expected ';' after this.
+//   🔛
+//   ^^
 //
 // pkg/front_end/testcases/regress/issue_29985.dart:6:3: Error: Getter not found: '🔛'.
 //   🔛
diff --git a/pkg/front_end/testcases/regress/issue_31155.dart.direct.expect b/pkg/front_end/testcases/regress/issue_31155.dart.direct.expect
index 226845f..0f54478 100644
--- a/pkg/front_end/testcases/regress/issue_31155.dart.direct.expect
+++ b/pkg/front_end/testcases/regress/issue_31155.dart.direct.expect
@@ -1,8 +1,8 @@
 // Errors:
 //
-// pkg/front_end/testcases/regress/issue_31155.dart:11:19: Error: Expected ';' before this.
+// pkg/front_end/testcases/regress/issue_31155.dart:11:18: Error: Expected ';' after this.
 //   var f = Map<A, B> {};
-//                   ^
+//                  ^
 //
 // pkg/front_end/testcases/regress/issue_31155.dart:11:19: Error: Operator declarations must be preceeded by the keyword 'operator'.
 // Try adding the keyword 'operator'.
diff --git a/pkg/front_end/testcases/regress/issue_31155.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_31155.dart.direct.transformed.expect
index 226845f..0f54478 100644
--- a/pkg/front_end/testcases/regress/issue_31155.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31155.dart.direct.transformed.expect
@@ -1,8 +1,8 @@
 // Errors:
 //
-// pkg/front_end/testcases/regress/issue_31155.dart:11:19: Error: Expected ';' before this.
+// pkg/front_end/testcases/regress/issue_31155.dart:11:18: Error: Expected ';' after this.
 //   var f = Map<A, B> {};
-//                   ^
+//                  ^
 //
 // pkg/front_end/testcases/regress/issue_31155.dart:11:19: Error: Operator declarations must be preceeded by the keyword 'operator'.
 // Try adding the keyword 'operator'.
diff --git a/pkg/front_end/testcases/regress/issue_31155.dart.strong.expect b/pkg/front_end/testcases/regress/issue_31155.dart.strong.expect
index f4bc906..f805c54 100644
--- a/pkg/front_end/testcases/regress/issue_31155.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_31155.dart.strong.expect
@@ -1,8 +1,8 @@
 // Errors:
 //
-// pkg/front_end/testcases/regress/issue_31155.dart:11:19: Error: Expected ';' before this.
+// pkg/front_end/testcases/regress/issue_31155.dart:11:18: Error: Expected ';' after this.
 //   var f = Map<A, B> {};
-//                   ^
+//                  ^
 //
 // pkg/front_end/testcases/regress/issue_31155.dart:11:19: Error: Operator declarations must be preceeded by the keyword 'operator'.
 // Try adding the keyword 'operator'.
diff --git a/pkg/front_end/testcases/regress/issue_31155.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_31155.dart.strong.transformed.expect
index c20c97e..e7de89b 100644
--- a/pkg/front_end/testcases/regress/issue_31155.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31155.dart.strong.transformed.expect
@@ -1,8 +1,8 @@
 // Errors:
 //
-// pkg/front_end/testcases/regress/issue_31155.dart:11:19: Error: Expected ';' before this.
+// pkg/front_end/testcases/regress/issue_31155.dart:11:18: Error: Expected ';' after this.
 //   var f = Map<A, B> {};
-//                   ^
+//                  ^
 //
 // pkg/front_end/testcases/regress/issue_31155.dart:11:19: Error: Operator declarations must be preceeded by the keyword 'operator'.
 // Try adding the keyword 'operator'.
diff --git a/pkg/front_end/testcases/regress/issue_31171.dart.direct.expect b/pkg/front_end/testcases/regress/issue_31171.dart.direct.expect
index fbeb2bc..49b38eb 100644
--- a/pkg/front_end/testcases/regress/issue_31171.dart.direct.expect
+++ b/pkg/front_end/testcases/regress/issue_31171.dart.direct.expect
@@ -4,7 +4,7 @@
 // typedef F = Map<String, dynamic> Function();
 // ^^^^^^^
 //
-// pkg/front_end/testcases/regress/issue_31171.dart:8:1: Error: Expected ';' before this.
+// pkg/front_end/testcases/regress/issue_31171.dart:8:1: Error: Expected ';' after this.
 // typedef F = Map<String, dynamic> Function();
 // ^^^^^^^
 //
diff --git a/pkg/front_end/testcases/regress/issue_31171.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_31171.dart.direct.transformed.expect
index fbeb2bc..49b38eb 100644
--- a/pkg/front_end/testcases/regress/issue_31171.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31171.dart.direct.transformed.expect
@@ -4,7 +4,7 @@
 // typedef F = Map<String, dynamic> Function();
 // ^^^^^^^
 //
-// pkg/front_end/testcases/regress/issue_31171.dart:8:1: Error: Expected ';' before this.
+// pkg/front_end/testcases/regress/issue_31171.dart:8:1: Error: Expected ';' after this.
 // typedef F = Map<String, dynamic> Function();
 // ^^^^^^^
 //
diff --git a/pkg/front_end/testcases/regress/issue_31171.dart.strong.expect b/pkg/front_end/testcases/regress/issue_31171.dart.strong.expect
index fbeb2bc..49b38eb 100644
--- a/pkg/front_end/testcases/regress/issue_31171.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_31171.dart.strong.expect
@@ -4,7 +4,7 @@
 // typedef F = Map<String, dynamic> Function();
 // ^^^^^^^
 //
-// pkg/front_end/testcases/regress/issue_31171.dart:8:1: Error: Expected ';' before this.
+// pkg/front_end/testcases/regress/issue_31171.dart:8:1: Error: Expected ';' after this.
 // typedef F = Map<String, dynamic> Function();
 // ^^^^^^^
 //
diff --git a/pkg/front_end/testcases/regress/issue_31171.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_31171.dart.strong.transformed.expect
index fbeb2bc..49b38eb 100644
--- a/pkg/front_end/testcases/regress/issue_31171.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31171.dart.strong.transformed.expect
@@ -4,7 +4,7 @@
 // typedef F = Map<String, dynamic> Function();
 // ^^^^^^^
 //
-// pkg/front_end/testcases/regress/issue_31171.dart:8:1: Error: Expected ';' before this.
+// pkg/front_end/testcases/regress/issue_31171.dart:8:1: Error: Expected ';' after this.
 // typedef F = Map<String, dynamic> Function();
 // ^^^^^^^
 //
diff --git a/pkg/front_end/testcases/regress/issue_31184.dart.direct.expect b/pkg/front_end/testcases/regress/issue_31184.dart.direct.expect
index 8d617e0..0e18d33 100644
--- a/pkg/front_end/testcases/regress/issue_31184.dart.direct.expect
+++ b/pkg/front_end/testcases/regress/issue_31184.dart.direct.expect
@@ -1,8 +1,8 @@
 // Errors:
 //
-// pkg/front_end/testcases/regress/issue_31184.dart:6:21: Error: Expected ';' before this.
+// pkg/front_end/testcases/regress/issue_31184.dart:6:19: Error: Expected ';' after this.
 //   for (int i = 0, i > 10; i++) {}
-//                     ^
+//                   ^
 //
 // pkg/front_end/testcases/regress/issue_31184.dart:6:21: Error: Expected an identifier, but got '>'.
 //   for (int i = 0, i > 10; i++) {}
diff --git a/pkg/front_end/testcases/regress/issue_31184.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_31184.dart.direct.transformed.expect
index 8d617e0..0e18d33 100644
--- a/pkg/front_end/testcases/regress/issue_31184.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31184.dart.direct.transformed.expect
@@ -1,8 +1,8 @@
 // Errors:
 //
-// pkg/front_end/testcases/regress/issue_31184.dart:6:21: Error: Expected ';' before this.
+// pkg/front_end/testcases/regress/issue_31184.dart:6:19: Error: Expected ';' after this.
 //   for (int i = 0, i > 10; i++) {}
-//                     ^
+//                   ^
 //
 // pkg/front_end/testcases/regress/issue_31184.dart:6:21: Error: Expected an identifier, but got '>'.
 //   for (int i = 0, i > 10; i++) {}
diff --git a/pkg/front_end/testcases/regress/issue_31184.dart.strong.expect b/pkg/front_end/testcases/regress/issue_31184.dart.strong.expect
index 0485037..b3ffbf8 100644
--- a/pkg/front_end/testcases/regress/issue_31184.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_31184.dart.strong.expect
@@ -1,8 +1,8 @@
 // Errors:
 //
-// pkg/front_end/testcases/regress/issue_31184.dart:6:21: Error: Expected ';' before this.
+// pkg/front_end/testcases/regress/issue_31184.dart:6:19: Error: Expected ';' after this.
 //   for (int i = 0, i > 10; i++) {}
-//                     ^
+//                   ^
 //
 // pkg/front_end/testcases/regress/issue_31184.dart:6:21: Error: Expected an identifier, but got '>'.
 //   for (int i = 0, i > 10; i++) {}
diff --git a/pkg/front_end/testcases/regress/issue_31185.dart.direct.expect b/pkg/front_end/testcases/regress/issue_31185.dart.direct.expect
index 3b34000..d3a912f 100644
--- a/pkg/front_end/testcases/regress/issue_31185.dart.direct.expect
+++ b/pkg/front_end/testcases/regress/issue_31185.dart.direct.expect
@@ -1,12 +1,12 @@
 // Errors:
 //
-// pkg/front_end/testcases/regress/issue_31185.dart:8:15: Error: Expected ';' before this.
+// pkg/front_end/testcases/regress/issue_31185.dart:8:12: Error: Expected ';' after this.
 //   return i ++ (i);
-//               ^
+//            ^^
 //
-// pkg/front_end/testcases/regress/issue_31185.dart:12:17: Error: Expected ';' before this.
+// pkg/front_end/testcases/regress/issue_31185.dart:12:14: Error: Expected ';' after this.
 //   return (i) ++ (i);
-//                 ^
+//              ^^
 
 library;
 import self as self;
diff --git a/pkg/front_end/testcases/regress/issue_31185.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_31185.dart.direct.transformed.expect
index 3b34000..d3a912f 100644
--- a/pkg/front_end/testcases/regress/issue_31185.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31185.dart.direct.transformed.expect
@@ -1,12 +1,12 @@
 // Errors:
 //
-// pkg/front_end/testcases/regress/issue_31185.dart:8:15: Error: Expected ';' before this.
+// pkg/front_end/testcases/regress/issue_31185.dart:8:12: Error: Expected ';' after this.
 //   return i ++ (i);
-//               ^
+//            ^^
 //
-// pkg/front_end/testcases/regress/issue_31185.dart:12:17: Error: Expected ';' before this.
+// pkg/front_end/testcases/regress/issue_31185.dart:12:14: Error: Expected ';' after this.
 //   return (i) ++ (i);
-//                 ^
+//              ^^
 
 library;
 import self as self;
diff --git a/pkg/front_end/testcases/regress/issue_31185.dart.strong.expect b/pkg/front_end/testcases/regress/issue_31185.dart.strong.expect
index 96522f4..f26aee4 100644
--- a/pkg/front_end/testcases/regress/issue_31185.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_31185.dart.strong.expect
@@ -1,12 +1,12 @@
 // Errors:
 //
-// pkg/front_end/testcases/regress/issue_31185.dart:8:15: Error: Expected ';' before this.
+// pkg/front_end/testcases/regress/issue_31185.dart:8:12: Error: Expected ';' after this.
 //   return i ++ (i);
-//               ^
+//            ^^
 //
-// pkg/front_end/testcases/regress/issue_31185.dart:12:17: Error: Expected ';' before this.
+// pkg/front_end/testcases/regress/issue_31185.dart:12:14: Error: Expected ';' after this.
 //   return (i) ++ (i);
-//                 ^
+//              ^^
 
 library;
 import self as self;
diff --git a/pkg/front_end/testcases/regress/issue_31185.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_31185.dart.strong.transformed.expect
index a48a597..1e08909 100644
--- a/pkg/front_end/testcases/regress/issue_31185.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31185.dart.strong.transformed.expect
@@ -1,12 +1,12 @@
 // Errors:
 //
-// pkg/front_end/testcases/regress/issue_31185.dart:8:15: Error: Expected ';' before this.
+// pkg/front_end/testcases/regress/issue_31185.dart:8:12: Error: Expected ';' after this.
 //   return i ++ (i);
-//               ^
+//            ^^
 //
-// pkg/front_end/testcases/regress/issue_31185.dart:12:17: Error: Expected ';' before this.
+// pkg/front_end/testcases/regress/issue_31185.dart:12:14: Error: Expected ';' after this.
 //   return (i) ++ (i);
-//                 ^
+//              ^^
 
 library;
 import self as self;
diff --git a/pkg/front_end/testcases/regress/issue_31188.dart.direct.expect b/pkg/front_end/testcases/regress/issue_31188.dart.direct.expect
index 404127d..eb3888b 100644
--- a/pkg/front_end/testcases/regress/issue_31188.dart.direct.expect
+++ b/pkg/front_end/testcases/regress/issue_31188.dart.direct.expect
@@ -1,8 +1,8 @@
 // Errors:
 //
-// pkg/front_end/testcases/regress/issue_31188.dart:7:18: Error: Expected ';' before this.
+// pkg/front_end/testcases/regress/issue_31188.dart:7:17: Error: Expected ';' after this.
 // type T = Map<A, B>
-//                  ^
+//                 ^
 //
 // pkg/front_end/testcases/regress/issue_31188.dart:7:18: Error: Expected a declaration, but got '>'.
 // type T = Map<A, B>
diff --git a/pkg/front_end/testcases/regress/issue_31188.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_31188.dart.direct.transformed.expect
index 404127d..eb3888b 100644
--- a/pkg/front_end/testcases/regress/issue_31188.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31188.dart.direct.transformed.expect
@@ -1,8 +1,8 @@
 // Errors:
 //
-// pkg/front_end/testcases/regress/issue_31188.dart:7:18: Error: Expected ';' before this.
+// pkg/front_end/testcases/regress/issue_31188.dart:7:17: Error: Expected ';' after this.
 // type T = Map<A, B>
-//                  ^
+//                 ^
 //
 // pkg/front_end/testcases/regress/issue_31188.dart:7:18: Error: Expected a declaration, but got '>'.
 // type T = Map<A, B>
diff --git a/pkg/front_end/testcases/regress/issue_31188.dart.strong.expect b/pkg/front_end/testcases/regress/issue_31188.dart.strong.expect
index 51447393..c9a4233 100644
--- a/pkg/front_end/testcases/regress/issue_31188.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_31188.dart.strong.expect
@@ -1,8 +1,8 @@
 // Errors:
 //
-// pkg/front_end/testcases/regress/issue_31188.dart:7:18: Error: Expected ';' before this.
+// pkg/front_end/testcases/regress/issue_31188.dart:7:17: Error: Expected ';' after this.
 // type T = Map<A, B>
-//                  ^
+//                 ^
 //
 // pkg/front_end/testcases/regress/issue_31188.dart:7:18: Error: Expected a declaration, but got '>'.
 // type T = Map<A, B>
diff --git a/pkg/front_end/testcases/regress/issue_31188.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_31188.dart.strong.transformed.expect
index c128307..b9f1830 100644
--- a/pkg/front_end/testcases/regress/issue_31188.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31188.dart.strong.transformed.expect
@@ -1,8 +1,8 @@
 // Errors:
 //
-// pkg/front_end/testcases/regress/issue_31188.dart:7:18: Error: Expected ';' before this.
+// pkg/front_end/testcases/regress/issue_31188.dart:7:17: Error: Expected ';' after this.
 // type T = Map<A, B>
-//                  ^
+//                 ^
 //
 // pkg/front_end/testcases/regress/issue_31188.dart:7:18: Error: Expected a declaration, but got '>'.
 // type T = Map<A, B>
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index a4ff9b6..e81dd2f 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -581,7 +581,7 @@
   EXPECT(Dart_IsError(result));
 
   if (FLAG_use_dart_frontend) {
-    EXPECT_SUBSTRING("Expected ';' before this.", Dart_GetError(result));
+    EXPECT_SUBSTRING("Expected ';' after this.", Dart_GetError(result));
   } else {
     EXPECT_SUBSTRING("semicolon expected", Dart_GetError(result));
   }
@@ -593,7 +593,7 @@
   result = Dart_Invoke(lib, NewString("Func1"), 0, NULL);
   EXPECT(Dart_IsError(result));
   if (FLAG_use_dart_frontend) {
-    EXPECT_SUBSTRING("Expected ';' before this.", Dart_GetError(result));
+    EXPECT_SUBSTRING("Expected ';' after this.", Dart_GetError(result));
   } else {
     EXPECT_SUBSTRING("semicolon expected", Dart_GetError(result));
   }
@@ -605,7 +605,7 @@
   result = Dart_Invoke(lib, NewString("Func1"), 0, NULL);
   EXPECT(Dart_IsError(result));
   if (FLAG_use_dart_frontend) {
-    EXPECT_SUBSTRING("Expected ';' before this.", Dart_GetError(result));
+    EXPECT_SUBSTRING("Expected ';' after this.", Dart_GetError(result));
   } else {
     EXPECT_SUBSTRING("semicolon expected", Dart_GetError(result));
   }
diff --git a/runtime/vm/isolate_reload_test.cc b/runtime/vm/isolate_reload_test.cc
index 71fbf0e..ce3536a 100644
--- a/runtime/vm/isolate_reload_test.cc
+++ b/runtime/vm/isolate_reload_test.cc
@@ -309,7 +309,7 @@
 
   Dart_Handle result = TestCase::ReloadTestScript(kReloadScript);
   if (TestCase::UsingDartFrontend()) {
-    EXPECT_ERROR(result, "Expected ';' before this");
+    EXPECT_ERROR(result, "Expected ';' after this");
   } else {
     EXPECT_ERROR(result, "unexpected token");
   }
@@ -2470,7 +2470,7 @@
 
   lib = TestCase::ReloadTestScript(kReloadScript);
   if (TestCase::UsingDartFrontend()) {
-    EXPECT_ERROR(lib, "Expected ';' before this");
+    EXPECT_ERROR(lib, "Expected ';' after this");
   } else {
     EXPECT_ERROR(lib, "unexpected token");
   }