Update formated error for nonexisting constructor

This is an alternative fix for #33452.
This was originally fixed in 8e4d5c0a3842c3801ce9310c6322146505e58469,
but it was pointed out that it doesn't work if there were type arguments.

This should fix the problem in more cases.

Change-Id: I08ed27ecea1a8d471be9675d28b997614248c65e
Reviewed-on: https://dart-review.googlesource.com/68080
Reviewed-by: Aske Simon Christensen <askesc@google.com>
Commit-Queue: Jens Johansen <jensj@google.com>
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index dedcf53..00ccdb9 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -444,6 +444,7 @@
           beginToken.next, beginToken.offset, Constness.explicitConst);
       push(popForValue());
     } else {
+      pop(); // Name last identifier
       String name = pop();
       pop(); // Type arguments (ignored, already reported by parser).
       Object expression = pop();
@@ -2774,6 +2775,7 @@
     push(type);
     push(typeArguments ?? NullValue.TypeArguments);
     push(name);
+    push(suffix ?? identifier ?? NullValue.Identifier);
   }
 
   @override
@@ -2980,6 +2982,8 @@
   void buildConstructorReferenceInvocation(
       Token nameToken, int offset, Constness constness) {
     Arguments arguments = pop();
+    Identifier nameLastIdentifier = pop(NullValue.Identifier);
+    Token nameLastToken = nameLastIdentifier?.token ?? nameToken;
     String name = pop();
     List<DartType> typeArguments = pop();
 
@@ -2988,7 +2992,7 @@
     ConstantContext savedConstantContext = pop();
     if (type is Generator) {
       push(type.invokeConstructor(
-          typeArguments, name, arguments, nameToken, constness));
+          typeArguments, name, arguments, nameToken, nameLastToken, constness));
     } else {
       push(new SyntheticExpressionJudgment(throwNoSuchMethodError(
           forest.literalNull(null)..fileOffset = offset,
@@ -3010,6 +3014,7 @@
   Expression buildConstructorInvocation(
       TypeDeclarationBuilder<TypeBuilder, Object> type,
       Token nameToken,
+      Token nameLastToken,
       Arguments arguments,
       String name,
       List<DartType> typeArguments,
@@ -3095,16 +3100,13 @@
       errorName = debugName(getNodeName(type), name);
     }
     errorName ??= name;
-    if (nameToken.lexeme == type.name && name.isNotEmpty) {
-      nameToken = nameToken.next.next;
-    }
 
     return new UnresolvedTargetInvocationJudgment(
         throwNoSuchMethodError(
             forest.literalNull(null)..fileOffset = charOffset,
             errorName,
             arguments,
-            nameToken.charOffset),
+            nameLastToken.charOffset),
         arguments)
       ..fileOffset = arguments.fileOffset;
   }
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
index bcda4a0..dd98021 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -235,8 +235,13 @@
     return new UnexpectedQualifiedUseGenerator(helper, name, this, false);
   }
 
-  Expression invokeConstructor(List<DartType> typeArguments, String name,
-      Arguments arguments, Token nameToken, Constness constness) {
+  Expression invokeConstructor(
+      List<DartType> typeArguments,
+      String name,
+      Arguments arguments,
+      Token nameToken,
+      Token nameLastToken,
+      Constness constness) {
     if (typeArguments != null) {
       assert(forest.argumentsTypeArguments(arguments).isEmpty);
       forest.argumentsSetTypeArguments(arguments, typeArguments);
@@ -545,11 +550,16 @@
   }
 
   @override
-  Expression invokeConstructor(List<DartType> typeArguments, String name,
-      Arguments arguments, Token nameToken, Constness constness) {
+  Expression invokeConstructor(
+      List<DartType> typeArguments,
+      String name,
+      Arguments arguments,
+      Token nameToken,
+      Token nameLastToken,
+      Constness constness) {
     return helper.wrapInDeferredCheck(
-        suffixGenerator.invokeConstructor(
-            typeArguments, name, arguments, nameToken, constness),
+        suffixGenerator.invokeConstructor(typeArguments, name, arguments,
+            nameToken, nameLastToken, constness),
         prefixGenerator.prefix,
         offsetForToken(suffixGenerator.token));
   }
@@ -654,11 +664,23 @@
   }
 
   @override
-  Expression invokeConstructor(List<DartType> typeArguments, String name,
-      Arguments arguments, Token nameToken, Constness constness) {
+  Expression invokeConstructor(
+      List<DartType> typeArguments,
+      String name,
+      Arguments arguments,
+      Token nameToken,
+      Token nameLastToken,
+      Constness constness) {
     helper.storeTypeUse(offsetForToken(token), declaration.target);
-    return helper.buildConstructorInvocation(declaration, nameToken, arguments,
-        name, typeArguments, offsetForToken(nameToken ?? token), constness);
+    return helper.buildConstructorInvocation(
+        declaration,
+        nameToken,
+        nameLastToken,
+        arguments,
+        name,
+        typeArguments,
+        offsetForToken(nameToken ?? token),
+        constness);
   }
 
   @override
@@ -812,8 +834,13 @@
   }
 
   @override
-  Expression invokeConstructor(List<DartType> typeArguments, String name,
-      Arguments arguments, Token nameToken, Constness constness) {
+  Expression invokeConstructor(
+      List<DartType> typeArguments,
+      String name,
+      Arguments arguments,
+      Token nameToken,
+      Token nameLastToken,
+      Constness constness) {
     helper.storeTypeUse(offsetForToken(token), const InvalidType());
     if (typeArguments != null) {
       assert(forest.argumentsTypeArguments(arguments).isEmpty);
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
index 3072158..0dacced 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
@@ -140,6 +140,7 @@
   Expression buildConstructorInvocation(
       TypeDeclarationBuilder<KernelTypeBuilder, DartType> type,
       Token nameToken,
+      Token nameLastToken,
       Arguments arguments,
       String name,
       List<DartType> typeArguments,
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart
index 0cd8f04..2500bb1 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart
@@ -1330,8 +1330,15 @@
         if (send is IncompletePropertyAccessGenerator) {
           generator = new UnresolvedNameGenerator(helper, send.token, name);
         } else {
-          return helper.buildConstructorInvocation(declaration, send.token,
-              arguments, name.name, null, token.charOffset, Constness.implicit);
+          return helper.buildConstructorInvocation(
+              declaration,
+              send.token,
+              send.token,
+              arguments,
+              name.name,
+              null,
+              token.charOffset,
+              Constness.implicit);
         }
       } else {
         Declaration setter;
@@ -1358,8 +1365,8 @@
 
   @override
   Expression doInvocation(int offset, Arguments arguments) {
-    return helper.buildConstructorInvocation(declaration, token, arguments, "",
-        null, token.charOffset, Constness.implicit);
+    return helper.buildConstructorInvocation(declaration, token, token,
+        arguments, "", null, token.charOffset, Constness.implicit);
   }
 }
 
@@ -1607,11 +1614,16 @@
       Token token, this.prefixGenerator, this.isUnresolved)
       : super(helper, token);
 
-  Expression invokeConstructor(List<DartType> typeArguments, String name,
-      Arguments arguments, Token nameToken, Constness constness) {
+  Expression invokeConstructor(
+      List<DartType> typeArguments,
+      String name,
+      Arguments arguments,
+      Token nameToken,
+      Token nameStringToken,
+      Constness constness) {
     helper.storeTypeUse(offsetForToken(token), const InvalidType());
     return super.invokeConstructor(
-        typeArguments, name, arguments, nameToken, constness);
+        typeArguments, name, arguments, nameToken, nameStringToken, constness);
   }
 }
 
diff --git a/pkg/front_end/testcases/regress/issue_33452.dart b/pkg/front_end/testcases/regress/issue_33452.dart
index faffe5d..bd8c790 100644
--- a/pkg/front_end/testcases/regress/issue_33452.dart
+++ b/pkg/front_end/testcases/regress/issue_33452.dart
@@ -2,9 +2,15 @@
 // 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.
 
-class ExistingClass {}
+class ExistingClass {
+  ExistingClass.existingConstructor();
+}
 
 main() {
   var x = new ExistingClass.nonExistingConstructor();
+  x = new ExistingClass();
+  x = new ExistingClass<String>();
+  x = new ExistingClass<String>.nonExistingConstructor();
+  x = new ExistingClass<String, String>.nonExistingConstructor();
   x = new NonExistingClass();
 }
diff --git a/pkg/front_end/testcases/regress/issue_33452.dart.direct.expect b/pkg/front_end/testcases/regress/issue_33452.dart.direct.expect
index 3d768b8..edcd349 100644
--- a/pkg/front_end/testcases/regress/issue_33452.dart.direct.expect
+++ b/pkg/front_end/testcases/regress/issue_33452.dart.direct.expect
@@ -3,11 +3,15 @@
 import "dart:core" as core;
 
 class ExistingClass extends core::Object {
-  synthetic constructor •() → void
+  constructor existingConstructor() → void
     : super core::Object::•()
     ;
 }
 static method main() → dynamic {
   dynamic x = throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#ExistingClass.nonExistingConstructor, 32, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+  x = throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#ExistingClass, 32, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+  x = throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#ExistingClass, 32, core::List::unmodifiable<dynamic>(<core::Type>[core::String]), const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+  x = throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#ExistingClass.nonExistingConstructor, 32, core::List::unmodifiable<dynamic>(<core::Type>[core::String]), const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+  x = throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#ExistingClass.nonExistingConstructor, 32, core::List::unmodifiable<dynamic>(<core::Type>[core::String, core::String]), const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
   x = throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#NonExistingClass, 32, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
 }
diff --git a/pkg/front_end/testcases/regress/issue_33452.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_33452.dart.direct.transformed.expect
index 3d768b8..edcd349 100644
--- a/pkg/front_end/testcases/regress/issue_33452.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_33452.dart.direct.transformed.expect
@@ -3,11 +3,15 @@
 import "dart:core" as core;
 
 class ExistingClass extends core::Object {
-  synthetic constructor •() → void
+  constructor existingConstructor() → void
     : super core::Object::•()
     ;
 }
 static method main() → dynamic {
   dynamic x = throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#ExistingClass.nonExistingConstructor, 32, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+  x = throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#ExistingClass, 32, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+  x = throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#ExistingClass, 32, core::List::unmodifiable<dynamic>(<core::Type>[core::String]), const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+  x = throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#ExistingClass.nonExistingConstructor, 32, core::List::unmodifiable<dynamic>(<core::Type>[core::String]), const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+  x = throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#ExistingClass.nonExistingConstructor, 32, core::List::unmodifiable<dynamic>(<core::Type>[core::String, core::String]), const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
   x = throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#NonExistingClass, 32, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
 }
diff --git a/pkg/front_end/testcases/regress/issue_33452.dart.outline.expect b/pkg/front_end/testcases/regress/issue_33452.dart.outline.expect
index da89296..6f1e5f7 100644
--- a/pkg/front_end/testcases/regress/issue_33452.dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_33452.dart.outline.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 class ExistingClass extends core::Object {
-  synthetic constructor •() → void
+  constructor existingConstructor() → void
     ;
 }
 static method main() → dynamic
diff --git a/pkg/front_end/testcases/regress/issue_33452.dart.strong.expect b/pkg/front_end/testcases/regress/issue_33452.dart.strong.expect
index d598469..8b82c2c 100644
--- a/pkg/front_end/testcases/regress/issue_33452.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_33452.dart.strong.expect
@@ -1,10 +1,26 @@
 // Errors:
 //
-// pkg/front_end/testcases/regress/issue_33452.dart:8:29: Error: Method not found: 'ExistingClass.nonExistingConstructor'.
+// pkg/front_end/testcases/regress/issue_33452.dart:10:29: Error: Method not found: 'ExistingClass.nonExistingConstructor'.
 //   var x = new ExistingClass.nonExistingConstructor();
 //                             ^^^^^^^^^^^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/regress/issue_33452.dart:9:11: Error: Method not found: 'NonExistingClass'.
+// pkg/front_end/testcases/regress/issue_33452.dart:11:11: Error: Method not found: 'ExistingClass'.
+//   x = new ExistingClass();
+//           ^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/regress/issue_33452.dart:12:11: Error: Method not found: 'ExistingClass'.
+//   x = new ExistingClass<String>();
+//           ^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/regress/issue_33452.dart:13:33: Error: Method not found: 'ExistingClass.nonExistingConstructor'.
+//   x = new ExistingClass<String>.nonExistingConstructor();
+//                                 ^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/regress/issue_33452.dart:14:41: Error: Method not found: 'ExistingClass.nonExistingConstructor'.
+//   x = new ExistingClass<String, String>.nonExistingConstructor();
+//                                         ^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/regress/issue_33452.dart:15:11: Error: Method not found: 'NonExistingClass'.
 //   x = new NonExistingClass();
 //           ^^^^^^^^^^^^^^^^
 
@@ -13,11 +29,15 @@
 import "dart:core" as core;
 
 class ExistingClass extends core::Object {
-  synthetic constructor •() → void
+  constructor existingConstructor() → void
     : super core::Object::•()
     ;
 }
 static method main() → dynamic {
   dynamic x = throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#ExistingClass.nonExistingConstructor, 32, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+  x = throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#ExistingClass, 32, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+  x = throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#ExistingClass, 32, core::List::unmodifiable<dynamic>(<core::Type>[core::String]), const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+  x = throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#ExistingClass.nonExistingConstructor, 32, core::List::unmodifiable<dynamic>(<core::Type>[core::String]), const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+  x = throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#ExistingClass.nonExistingConstructor, 32, core::List::unmodifiable<dynamic>(<core::Type>[core::String, core::String]), const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
   x = throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#NonExistingClass, 32, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
 }
diff --git a/pkg/front_end/testcases/regress/issue_33452.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_33452.dart.strong.transformed.expect
index d598469..8b82c2c 100644
--- a/pkg/front_end/testcases/regress/issue_33452.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_33452.dart.strong.transformed.expect
@@ -1,10 +1,26 @@
 // Errors:
 //
-// pkg/front_end/testcases/regress/issue_33452.dart:8:29: Error: Method not found: 'ExistingClass.nonExistingConstructor'.
+// pkg/front_end/testcases/regress/issue_33452.dart:10:29: Error: Method not found: 'ExistingClass.nonExistingConstructor'.
 //   var x = new ExistingClass.nonExistingConstructor();
 //                             ^^^^^^^^^^^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/regress/issue_33452.dart:9:11: Error: Method not found: 'NonExistingClass'.
+// pkg/front_end/testcases/regress/issue_33452.dart:11:11: Error: Method not found: 'ExistingClass'.
+//   x = new ExistingClass();
+//           ^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/regress/issue_33452.dart:12:11: Error: Method not found: 'ExistingClass'.
+//   x = new ExistingClass<String>();
+//           ^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/regress/issue_33452.dart:13:33: Error: Method not found: 'ExistingClass.nonExistingConstructor'.
+//   x = new ExistingClass<String>.nonExistingConstructor();
+//                                 ^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/regress/issue_33452.dart:14:41: Error: Method not found: 'ExistingClass.nonExistingConstructor'.
+//   x = new ExistingClass<String, String>.nonExistingConstructor();
+//                                         ^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/regress/issue_33452.dart:15:11: Error: Method not found: 'NonExistingClass'.
 //   x = new NonExistingClass();
 //           ^^^^^^^^^^^^^^^^
 
@@ -13,11 +29,15 @@
 import "dart:core" as core;
 
 class ExistingClass extends core::Object {
-  synthetic constructor •() → void
+  constructor existingConstructor() → void
     : super core::Object::•()
     ;
 }
 static method main() → dynamic {
   dynamic x = throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#ExistingClass.nonExistingConstructor, 32, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+  x = throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#ExistingClass, 32, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+  x = throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#ExistingClass, 32, core::List::unmodifiable<dynamic>(<core::Type>[core::String]), const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+  x = throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#ExistingClass.nonExistingConstructor, 32, core::List::unmodifiable<dynamic>(<core::Type>[core::String]), const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+  x = throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#ExistingClass.nonExistingConstructor, 32, core::List::unmodifiable<dynamic>(<core::Type>[core::String, core::String]), const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
   x = throw new core::NoSuchMethodError::withInvocation(null, new core::_InvocationMirror::_withType(#NonExistingClass, 32, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
 }