Use LocatedMessage for invalid types

Change-Id: Ib233b40211d1893b1de6bea36e84c91c81a49fa9
Reviewed-on: https://dart-review.googlesource.com/73343
Reviewed-by: Jens Johansen <jensj@google.com>
diff --git a/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart b/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
index 41ae499..1a263f0 100644
--- a/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
@@ -6,9 +6,11 @@
 
 import '../fasta_codes.dart'
     show
-        Message,
+        LocatedMessage,
+        noLength,
         templateMissingExplicitTypeArguments,
-        templateTypeArgumentMismatch;
+        templateTypeArgumentMismatch,
+        templateTypeNotFound;
 
 import '../problems.dart' show unhandled;
 
@@ -34,8 +36,8 @@
 
   NamedTypeBuilder(this.name, this.arguments);
 
-  InvalidTypeBuilder<T, R> buildInvalidType(int charOffset, Uri fileUri,
-      [Message message]);
+  @override
+  InvalidTypeBuilder<T, R> buildInvalidType(LocatedMessage message);
 
   @override
   void bind(TypeDeclarationBuilder declaration) {
@@ -81,18 +83,18 @@
       }
       return;
     }
-    declaration = buildInvalidType(charOffset, fileUri);
+    declaration = buildInvalidType(templateTypeNotFound
+        .withArguments(flattenName(name, charOffset, fileUri))
+        .withLocation(fileUri, charOffset, noLength));
   }
 
   @override
   void check(int charOffset, Uri fileUri) {
     if (arguments != null &&
         arguments.length != declaration.typeVariablesCount) {
-      declaration = buildInvalidType(
-          charOffset,
-          fileUri,
-          templateTypeArgumentMismatch
-              .withArguments(declaration.typeVariablesCount));
+      declaration = buildInvalidType(templateTypeArgumentMismatch
+          .withArguments(declaration.typeVariablesCount)
+          .withLocation(fileUri, charOffset, noLength));
     }
   }
 
diff --git a/pkg/front_end/lib/src/fasta/builder/type_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_builder.dart
index ee13b6f..6f3fad2 100644
--- a/pkg/front_end/lib/src/fasta/builder/type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/type_builder.dart
@@ -4,6 +4,8 @@
 
 library fasta.type_builder;
 
+import '../fasta_codes.dart' show LocatedMessage;
+
 import 'builder.dart'
     show LibraryBuilder, Scope, TypeDeclarationBuilder, TypeVariableBuilder;
 
@@ -40,7 +42,7 @@
 
   build(LibraryBuilder library);
 
-  buildInvalidType(int charOffset, Uri fileUri);
+  buildInvalidType(LocatedMessage message);
 
   String get fullNameForErrors => "${printOn(new StringBuffer())}";
 }
diff --git a/pkg/front_end/lib/src/fasta/builder/unresolved_type.dart b/pkg/front_end/lib/src/fasta/builder/unresolved_type.dart
index 7c5004a..c716335 100644
--- a/pkg/front_end/lib/src/fasta/builder/unresolved_type.dart
+++ b/pkg/front_end/lib/src/fasta/builder/unresolved_type.dart
@@ -22,4 +22,6 @@
 
   /// Normalizes the type arguments in accordance with Dart 1 semantics.
   void normalizeType() => builder.normalize(charOffset, fileUri);
+
+  String toString() => "UnresolvedType(@$charOffset, $builder)";
 }
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
index 6c94030..ba16545 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
@@ -19,7 +19,12 @@
         StringLiteral,
         Typedef;
 
-import '../fasta_codes.dart' show templateUnspecified;
+import '../fasta_codes.dart'
+    show
+        Message,
+        templateDuplicatedDefinition,
+        templateTypeNotFound,
+        templateUnspecified;
 
 import '../problems.dart' show internalProblem, unhandled, unimplemented;
 
@@ -148,7 +153,11 @@
     // mapping `k` to `d` is added to the exported namespace of `L` unless a
     // top-level declaration with the name `k` exists in `L`.
     if (builder.parent == this) return builder;
-    return new KernelInvalidTypeBuilder(name, charOffset, fileUri);
+    return new KernelInvalidTypeBuilder(
+        name,
+        templateDuplicatedDefinition
+            .withArguments(name)
+            .withLocation(fileUri, charOffset, name.length));
   }
 
   @override
@@ -157,7 +166,7 @@
   }
 
   void finalizeExports() {
-    unserializableExports?.forEach((String name, String message) {
+    unserializableExports?.forEach((String name, String messageText) {
       Declaration declaration;
       switch (name) {
         case "dynamic":
@@ -168,13 +177,11 @@
           break;
 
         default:
-          declaration = new KernelInvalidTypeBuilder(
-              name,
-              -1,
-              null,
-              message == null
-                  ? null
-                  : templateUnspecified.withArguments(message));
+          Message message = messageText == null
+              ? templateTypeNotFound.withArguments(name)
+              : templateUnspecified.withArguments(messageText);
+          declaration =
+              new KernelInvalidTypeBuilder(name, message.withoutLocation());
       }
       exportScopeBuilder.addMember(name, declaration);
     });
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 4d57271..4934ff9 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
@@ -5457,29 +5457,27 @@
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
     Message Function(
-        Token token,
-        Token
-            token2)> templateNotAPrefixInTypeAnnotation = const Template<
-        Message Function(Token token, Token token2)>(
+        String name,
+        String
+            name2)> templateNotAPrefixInTypeAnnotation = const Template<
+        Message Function(String name, String name2)>(
     messageTemplate:
-        r"""'#lexeme.#lexeme2' can't be used as a type because '#lexeme' doesn't refer to an import prefix.""",
+        r"""'#name.#name2' can't be used as a type because '#name' doesn't refer to an import prefix.""",
     withArguments: _withArgumentsNotAPrefixInTypeAnnotation);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(Token token, Token token2)>
+const Code<Message Function(String name, String name2)>
     codeNotAPrefixInTypeAnnotation =
-    const Code<Message Function(Token token, Token token2)>(
+    const Code<Message Function(String name, String name2)>(
         "NotAPrefixInTypeAnnotation", templateNotAPrefixInTypeAnnotation,
         analyzerCode: "NOT_A_TYPE", severity: Severity.errorLegacyWarning);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsNotAPrefixInTypeAnnotation(Token token, Token token2) {
-  String lexeme = token.lexeme;
-  String lexeme2 = token2.lexeme;
+Message _withArgumentsNotAPrefixInTypeAnnotation(String name, String name2) {
   return new Message(codeNotAPrefixInTypeAnnotation,
       message:
-          """'${lexeme}.${lexeme2}' can't be used as a type because '${lexeme}' doesn't refer to an import prefix.""",
-      arguments: {'token': token, 'token2': token2});
+          """'${name}.${name2}' can't be used as a type because '${name}' doesn't refer to an import prefix.""",
+      arguments: {'name': name, 'name2': name2});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -7272,18 +7270,18 @@
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
     Message Function(
-        Token token,
-        Token
-            token2)> templateUnresolvedPrefixInTypeAnnotation = const Template<
-        Message Function(Token token, Token token2)>(
+        String name,
+        String
+            name2)> templateUnresolvedPrefixInTypeAnnotation = const Template<
+        Message Function(String name, String name2)>(
     messageTemplate:
-        r"""'#lexeme.#lexeme2' can't be used as a type because '#lexeme' isn't defined.""",
+        r"""'#name.#name2' can't be used as a type because '#name' isn't defined.""",
     withArguments: _withArgumentsUnresolvedPrefixInTypeAnnotation);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(Token token, Token token2)>
+const Code<Message Function(String name, String name2)>
     codeUnresolvedPrefixInTypeAnnotation =
-    const Code<Message Function(Token token, Token token2)>(
+    const Code<Message Function(String name, String name2)>(
         "UnresolvedPrefixInTypeAnnotation",
         templateUnresolvedPrefixInTypeAnnotation,
         analyzerCode: "NOT_A_TYPE",
@@ -7291,13 +7289,11 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsUnresolvedPrefixInTypeAnnotation(
-    Token token, Token token2) {
-  String lexeme = token.lexeme;
-  String lexeme2 = token2.lexeme;
+    String name, String name2) {
   return new Message(codeUnresolvedPrefixInTypeAnnotation,
       message:
-          """'${lexeme}.${lexeme2}' can't be used as a type because '${lexeme}' isn't defined.""",
-      arguments: {'token': token, 'token2': token2});
+          """'${name}.${name2}' can't be used as a type because '${name}' isn't defined.""",
+      arguments: {'name': name, 'name2': name2});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
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 eb6b1dc..d24d7af 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -1220,11 +1220,11 @@
   @override
   DartType buildTypeWithBuiltArguments(List<DartType> arguments,
       {bool nonInstanceAccessIsError: false, TypeInferrer typeInferrer}) {
-    Template<Message Function(Token, Token)> template = isUnresolved
+    Template<Message Function(String, String)> template = isUnresolved
         ? templateUnresolvedPrefixInTypeAnnotation
         : templateNotAPrefixInTypeAnnotation;
     helper.addProblem(
-        template.withArguments(prefixGenerator.token, token),
+        template.withArguments(prefixGenerator.token.lexeme, token.lexeme),
         offsetForToken(prefixGenerator.token),
         lengthOfSpan(prefixGenerator.token, token));
     prefixGenerator.storeUnexpectedTypePrefix(typeInferrer);
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_function_type_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_function_type_builder.dart
index edb9fcc..b6ad44c 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_function_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_function_type_builder.dart
@@ -13,7 +13,8 @@
         Supertype,
         TypeParameter;
 
-import '../fasta_codes.dart' show messageSupertypeIsFunction, noLength;
+import '../fasta_codes.dart'
+    show LocatedMessage, messageSupertypeIsFunction, noLength;
 
 import '../problems.dart' show unsupported;
 
@@ -83,8 +84,8 @@
   }
 
   @override
-  buildInvalidType(int charOffset, Uri fileUri) {
-    return unsupported("buildInvalidType", charOffset, fileUri);
+  buildInvalidType(LocatedMessage message) {
+    return unsupported("buildInvalidType", message.charOffset, message.uri);
   }
 
   KernelFunctionTypeBuilder clone(List<TypeBuilder> newTypes) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_invalid_type_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_invalid_type_builder.dart
index f2297e5..a515299 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_invalid_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_invalid_type_builder.dart
@@ -6,8 +6,7 @@
 
 import 'package:kernel/ast.dart' show DartType, InvalidType;
 
-import '../fasta_codes.dart'
-    show LocatedMessage, Message, noLength, templateTypeNotFound;
+import '../fasta_codes.dart' show LocatedMessage;
 
 import 'kernel_builder.dart'
     show InvalidTypeBuilder, KernelTypeBuilder, LibraryBuilder;
@@ -17,11 +16,11 @@
   @override
   final LocatedMessage message;
 
-  KernelInvalidTypeBuilder(String name, int charOffset, Uri fileUri,
-      [Message message])
-      : message = (message ?? templateTypeNotFound.withArguments(name))
-            .withLocation(fileUri, charOffset, noLength),
-        super(name, charOffset, fileUri);
+  final bool suppressMessage;
+
+  KernelInvalidTypeBuilder(String name, this.message,
+      [this.suppressMessage = false])
+      : super(name, message.charOffset, message.uri);
 
   @override
   InvalidType get target => const InvalidType();
@@ -34,8 +33,10 @@
   /// [Arguments] have already been built.
   DartType buildTypesWithBuiltArguments(
       LibraryBuilder library, List<DartType> arguments) {
-    library.addProblem(
-        message.messageObject, message.charOffset, message.length, message.uri);
+    if (!suppressMessage) {
+      library.addProblem(message.messageObject, message.charOffset,
+          message.length, message.uri);
+    }
     return const InvalidType();
   }
 }
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
index ba6a4e2..e666eb4 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
@@ -986,8 +986,16 @@
     var builderTemplate = isExport
         ? templateDuplicatedExportInType
         : templateDuplicatedImportInType;
-    return new KernelInvalidTypeBuilder(name, charOffset, fileUri,
-        builderTemplate.withArguments(name, uri, otherUri));
+    return new KernelInvalidTypeBuilder(
+        name,
+        builderTemplate
+            .withArguments(
+                name,
+                // TODO(ahe): We should probably use a context object here
+                // instead of including URIs in this message.
+                uri,
+                otherUri)
+            .withLocation(fileUri, charOffset, name.length));
   }
 
   int finishDeferredLoadTearoffs() {
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_mixin_application_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_mixin_application_builder.dart
index 3237dc1..95d3634 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_mixin_application_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_mixin_application_builder.dart
@@ -6,6 +6,8 @@
 
 import 'package:kernel/ast.dart' show InterfaceType, Supertype;
 
+import '../fasta_codes.dart' show LocatedMessage;
+
 import '../problems.dart' show unsupported;
 
 import 'kernel_builder.dart'
@@ -47,8 +49,8 @@
   }
 
   @override
-  buildInvalidType(int charOffset, Uri fileUri) {
-    return unsupported("buildInvalidType", charOffset, fileUri);
+  buildInvalidType(LocatedMessage message) {
+    return unsupported("buildInvalidType", message.charOffset, message.uri);
   }
 
   KernelMixinApplicationBuilder clone(List<TypeBuilder> newTypes) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_named_type_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_named_type_builder.dart
index cbccf69..8c361e6 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_named_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_named_type_builder.dart
@@ -6,7 +6,7 @@
 
 import 'package:kernel/ast.dart' show DartType, Supertype;
 
-import '../fasta_codes.dart' show Message;
+import '../fasta_codes.dart' show LocatedMessage;
 
 import '../messages.dart'
     show noLength, templateSupertypeIsIllegal, templateSupertypeIsTypeVariable;
@@ -31,12 +31,11 @@
   KernelNamedTypeBuilder(Object name, List<KernelTypeBuilder> arguments)
       : super(name, arguments);
 
-  KernelInvalidTypeBuilder buildInvalidType(int charOffset, Uri fileUri,
-      [Message message]) {
+  KernelInvalidTypeBuilder buildInvalidType(LocatedMessage message) {
     // TODO(ahe): Consider if it makes sense to pass a QualifiedName to
     // KernelInvalidTypeBuilder?
     return new KernelInvalidTypeBuilder(
-        flattenName(name, charOffset, fileUri), charOffset, fileUri, message);
+        flattenName(name, message.charOffset, message.uri), message);
   }
 
   Supertype handleInvalidSupertype(
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index 5923555..a96b82c 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -29,7 +29,8 @@
         TypeBuilder,
         TypeDeclarationBuilder,
         TypeVariableBuilder,
-        UnresolvedType;
+        UnresolvedType,
+        flattenName;
 
 import '../combinator.dart' show Combinator;
 
@@ -48,12 +49,13 @@
         noLength,
         templateConflictsWithMember,
         templateConflictsWithSetter,
+        templateConstructorWithWrongNameContext,
         templateCouldNotParseUri,
         templateDeferredPrefixDuplicated,
         templateDeferredPrefixDuplicatedCause,
         templateDuplicatedDefinition,
-        templateConstructorWithWrongNameContext,
         templateMissingPartOf,
+        templateNotAPrefixInTypeAnnotation,
         templatePartOfInLibrary,
         templatePartOfLibraryNameMismatch,
         templatePartOfUriMismatch,
@@ -834,8 +836,13 @@
           parent.addType(type);
         } else if (nameOrQualified is QualifiedName) {
           // Attempt to use type variable as prefix.
-          type.builder.bind(
-              type.builder.buildInvalidType(type.charOffset, type.fileUri));
+          type.builder.bind(type.builder.buildInvalidType(
+              templateNotAPrefixInTypeAnnotation
+                  .withArguments(
+                      flattenName(nameOrQualified.qualifier, type.charOffset,
+                          type.fileUri),
+                      nameOrQualified.name)
+                  .withLocation(type.fileUri, type.charOffset, noLength)));
         } else {
           type.builder.bind(builder);
         }
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index fdcc60e..602e60c 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -252,7 +252,6 @@
 NonInstanceTypeVariableUse/example: Fail
 NonPartOfDirectiveInPart/script1: Fail
 NotAConstantExpression/example: Fail
-NotAPrefixInTypeAnnotation/example: Fail
 NotAType/example: Fail
 NotAnLvalue/example: Fail
 NotConstantExpression/example: Fail
@@ -350,7 +349,6 @@
 UnexpectedToken/script1: Fail
 UnmatchedToken/script1: Fail
 UnmatchedToken/script3: Fail
-UnresolvedPrefixInTypeAnnotation/example: Fail
 Unspecified/analyzerCode: Fail
 Unspecified/example: Fail
 UnsupportedPrefixPlus/script: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index dc20f85..76aea60 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -1303,14 +1303,24 @@
   analyzerCode: NOT_A_TYPE
 
 NotAPrefixInTypeAnnotation:
-  template: "'#lexeme.#lexeme2' can't be used as a type because '#lexeme' doesn't refer to an import prefix."
+  template: "'#name.#name2' can't be used as a type because '#name' doesn't refer to an import prefix."
   severity: ERROR_LEGACY_WARNING
   analyzerCode: NOT_A_TYPE
+  declaration:
+    - |
+        class C<T> {
+          T.String method() {}
+        }
+    - |
+        class C<T> {
+          T.String field;
+        }
 
 UnresolvedPrefixInTypeAnnotation:
-  template: "'#lexeme.#lexeme2' can't be used as a type because '#lexeme' isn't defined."
+  template: "'#name.#name2' can't be used as a type because '#name' isn't defined."
   severity: ERROR_LEGACY_WARNING
   analyzerCode: NOT_A_TYPE
+  statement: "T.String x;"
 
 FastaUsageShort:
   template: |
diff --git a/pkg/front_end/testcases/type_variable_prefix.dart.strong.expect b/pkg/front_end/testcases/type_variable_prefix.dart.strong.expect
index 6615790..837254e 100644
--- a/pkg/front_end/testcases/type_variable_prefix.dart.strong.expect
+++ b/pkg/front_end/testcases/type_variable_prefix.dart.strong.expect
@@ -1,6 +1,6 @@
 // Errors:
 //
-// pkg/front_end/testcases/type_variable_prefix.dart:8:3: Error: Type 'T.String' not found.
+// pkg/front_end/testcases/type_variable_prefix.dart:8:3: Error: 'T.String' can't be used as a type because 'T' doesn't refer to an import prefix.
 //   T.String method() => "Hello, World!";
 //   ^
 
diff --git a/pkg/front_end/testcases/type_variable_prefix.dart.strong.transformed.expect b/pkg/front_end/testcases/type_variable_prefix.dart.strong.transformed.expect
index 6e7ca74..9c9e30c 100644
--- a/pkg/front_end/testcases/type_variable_prefix.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/type_variable_prefix.dart.strong.transformed.expect
@@ -1,6 +1,6 @@
 // Errors:
 //
-// pkg/front_end/testcases/type_variable_prefix.dart:8:3: Error: Type 'T.String' not found.
+// pkg/front_end/testcases/type_variable_prefix.dart:8:3: Error: 'T.String' can't be used as a type because 'T' doesn't refer to an import prefix.
 //   T.String method() => "Hello, World!";
 //   ^