| Index: pkg/dart_messages/lib/shared_messages.dart
|
| diff --git a/pkg/dart_messages/lib/shared_messages.dart b/pkg/dart_messages/lib/shared_messages.dart
|
| index 44fe300cee323266ede8c1665d6fabca3e0bbed7..fe6ae1ec381f4e178d4d34e5e0932be16b42ab53 100644
|
| --- a/pkg/dart_messages/lib/shared_messages.dart
|
| +++ b/pkg/dart_messages/lib/shared_messages.dart
|
| @@ -77,6 +77,12 @@ class Category {
|
|
|
| static final compileTimeError = new Category("CompileTimeError");
|
|
|
| + static final staticTypeWarning = new Category("StaticTypeWarning");
|
| +
|
| + static final staticWarning = new Category("StaticWarning");
|
| +
|
| + static final hint = new Category("Hint");
|
| +
|
| final String name;
|
|
|
| Category(this.name);
|
| @@ -112,7 +118,12 @@ class Message {
|
| /// generic message.
|
| final String specializationOf;
|
|
|
| - final Category category;
|
| + /// The categories of this message.
|
| + ///
|
| + /// The same message can be used in multiple categories, for example, as
|
| + /// hint and warning.
|
| + final List<Category> categories;
|
| +
|
| final String template;
|
| // The analyzer fills holes positionally (and not named). The following field
|
| // overrides the order of the holes.
|
| @@ -131,7 +142,7 @@ class Message {
|
| {this.id,
|
| this.subId: 0,
|
| this.specializationOf: null,
|
| - this.category,
|
| + this.categories,
|
| this.template,
|
| this.templateHoleOrder,
|
| this.howToFix,
|
| @@ -146,7 +157,8 @@ String get messagesAsJson {
|
| jsonified[name] = {
|
| 'id': message.id,
|
| 'subId': message.subId,
|
| - 'category': message.category.name,
|
| + 'categories':
|
| + message.categories.map((category) => category.name).toList(),
|
| 'template': message.template,
|
| 'templateHoleOrder': message.templateHoleOrder,
|
| 'howToFix': message.howToFix,
|
| @@ -161,7 +173,7 @@ String get messagesAsJson {
|
| final Map<String, Message> MESSAGES = {
|
| 'exampleMessage': new Message(
|
| id: 'use an Id generated by bin/message_id.dart',
|
| - category: Category.analysisOptionsError,
|
| + categories: [Category.analysisOptionsError],
|
| template: "#use #named #arguments",
|
| templateHoleOrder: ["arguments", "named", "use"],
|
| howToFix: "an explanation on how to fix things",
|
| @@ -183,12 +195,10 @@ final Map<String, Message> MESSAGES = {
|
| 'CONST_CONSTRUCTOR_OR_FACTORY_WITH_BODY': new Message(
|
| id: 'LGJGHW',
|
| subId: 0,
|
| - category: Category.parserError,
|
| + categories: [Category.parserError],
|
| template: "Const constructor or factory can't have a body.",
|
| howToFix: "Remove the 'const' keyword or the body.",
|
| - usedBy: [
|
| - dart2js
|
| - ],
|
| + usedBy: [dart2js],
|
| examples: const [
|
| r"""
|
| class C {
|
| @@ -208,12 +218,10 @@ final Map<String, Message> MESSAGES = {
|
| id: 'LGJGHW',
|
| subId: 1,
|
| specializationOf: "CONST_CONSTRUCTOR_OR_FACTORY_WITH_BODY",
|
| - category: Category.parserError,
|
| + categories: [Category.parserError],
|
| template: "Const constructor can't have a body.",
|
| howToFix: "Try removing the 'const' keyword or the body.",
|
| - usedBy: [
|
| - analyzer
|
| - ],
|
| + usedBy: [analyzer],
|
| examples: const [
|
| r"""
|
| class C {
|
| @@ -227,14 +235,12 @@ final Map<String, Message> MESSAGES = {
|
| id: 'LGJGHW',
|
| subId: 2,
|
| specializationOf: "CONST_CONSTRUCTOR_OR_FACTORY_WITH_BODY",
|
| - category: Category.parserError,
|
| + categories: [Category.parserError],
|
| template: "Only redirecting factory constructors can be declared to "
|
| "be 'const'.",
|
| howToFix: "Try removing the 'const' keyword or replacing the body with "
|
| "'=' followed by a valid target.",
|
| - usedBy: [
|
| - analyzer
|
| - ],
|
| + usedBy: [analyzer],
|
| examples: const [
|
| r"""
|
| class C {
|
| @@ -247,12 +253,10 @@ final Map<String, Message> MESSAGES = {
|
| 'EXTRANEOUS_MODIFIER': new Message(
|
| id: 'GRKIQE',
|
| subId: 0,
|
| - category: Category.parserError,
|
| + categories: [Category.parserError],
|
| template: "Can't have modifier '#{modifier}' here.",
|
| howToFix: "Try removing '#{modifier}'.",
|
| - usedBy: [
|
| - dart2js
|
| - ],
|
| + usedBy: [dart2js],
|
| examples: const [
|
| "var String foo; main(){}",
|
| // "var get foo; main(){}",
|
| @@ -276,13 +280,11 @@ final Map<String, Message> MESSAGES = {
|
| 'EXTRANEOUS_MODIFIER_REPLACE': new Message(
|
| id: 'GRKIQE',
|
| subId: 1,
|
| - category: Category.parserError,
|
| + categories: [Category.parserError],
|
| template: "Can't have modifier '#{modifier}' here.",
|
| howToFix: "Try replacing modifier '#{modifier}' with 'var', 'final', "
|
| "or a type.",
|
| - usedBy: [
|
| - dart2js
|
| - ],
|
| + usedBy: [dart2js],
|
| examples: const [
|
| // "get foo; main(){}",
|
| "set foo; main(){}",
|
| @@ -297,13 +299,11 @@ final Map<String, Message> MESSAGES = {
|
| // The specialization could also be 'EXTRANEOUS_MODIFIER_REPLACE', but the
|
| // example below triggers 'EXTRANEOUS_MODIFIER'.
|
| specializationOf: 'EXTRANEOUS_MODIFIER',
|
| - category: Category.parserError,
|
| + categories: [Category.parserError],
|
| template: "Classes can't be declared to be 'const'",
|
| howToFix: "Try removing the 'const' keyword or moving to the class'"
|
| " constructor(s).",
|
| - usedBy: [
|
| - analyzer
|
| - ],
|
| + usedBy: [analyzer],
|
| examples: const [
|
| r"""
|
| const class C {}
|
| @@ -318,12 +318,10 @@ final Map<String, Message> MESSAGES = {
|
| // The specialization could also be 'EXTRANEOUS_MODIFIER_REPLACE', but the
|
| // example below triggers 'EXTRANEOUS_MODIFIER'.
|
| specializationOf: 'EXTRANEOUS_MODIFIER',
|
| - category: Category.parserError,
|
| + categories: [Category.parserError],
|
| template: "Getters, setters and methods can't be declared to be 'const'",
|
| howToFix: "Try removing the 'const' keyword.",
|
| - usedBy: [
|
| - analyzer
|
| - ],
|
| + usedBy: [analyzer],
|
| examples: const [
|
| "const int foo() => 499; main() {}",
|
| "const int get foo => 499; main() {}",
|
| @@ -339,7 +337,7 @@ final Map<String, Message> MESSAGES = {
|
| // The specialization could also be 'EXTRANEOUS_MODIFIER_REPLACE', but the
|
| // example below triggers 'EXTRANEOUS_MODIFIER'.
|
| specializationOf: 'EXTRANEOUS_MODIFIER',
|
| - category: Category.parserError,
|
| + categories: [Category.parserError],
|
| template: "Enums can't be declared to be 'const'",
|
| howToFix: "Try removing the 'const' keyword.",
|
| usedBy: [analyzer],
|
| @@ -351,7 +349,7 @@ final Map<String, Message> MESSAGES = {
|
| // The specialization could also be 'EXTRANEOUS_MODIFIER_REPLACE', but the
|
| // example below triggers 'EXTRANEOUS_MODIFIER'.
|
| specializationOf: 'EXTRANEOUS_MODIFIER',
|
| - category: Category.parserError,
|
| + categories: [Category.parserError],
|
| template: "Type aliases can't be declared to be 'const'",
|
| howToFix: "Try removing the 'const' keyword.",
|
| usedBy: [analyzer],
|
| @@ -363,12 +361,10 @@ final Map<String, Message> MESSAGES = {
|
| // The specialization could also be 'EXTRANEOUS_MODIFIER_REPLACE', but the
|
| // example below triggers 'EXTRANEOUS_MODIFIER'.
|
| specializationOf: 'EXTRANEOUS_MODIFIER',
|
| - category: Category.parserError,
|
| + categories: [Category.parserError],
|
| template: "Members can't be declared to be both 'const' and 'final'",
|
| howToFix: "Try removing either the 'const' or 'final' keyword.",
|
| - usedBy: [
|
| - analyzer
|
| - ],
|
| + usedBy: [analyzer],
|
| examples: const [
|
| "final const int x = 499; main() {}",
|
| "const final int x = 499; main() {}",
|
| @@ -382,12 +378,10 @@ final Map<String, Message> MESSAGES = {
|
| // The specialization could also be 'EXTRANEOUS_MODIFIER_REPLACE', but the
|
| // example below triggers 'EXTRANEOUS_MODIFIER'.
|
| specializationOf: 'EXTRANEOUS_MODIFIER',
|
| - category: Category.parserError,
|
| + categories: [Category.parserError],
|
| template: "Members can't be declared to be both 'const' and 'var'",
|
| howToFix: "Try removing either the 'const' or 'var' keyword.",
|
| - usedBy: [
|
| - analyzer
|
| - ],
|
| + usedBy: [analyzer],
|
| examples: const [
|
| "var const x = 499; main() {}",
|
| "const var x = 499; main() {}",
|
| @@ -399,7 +393,7 @@ final Map<String, Message> MESSAGES = {
|
| // Dart2js currently reports this as an EXTRANEOUS_MODIFIER error.
|
| // TODO(floitsch): make dart2js use this error instead.
|
| id: 'DOTHQH',
|
| - category: Category.parserError,
|
| + categories: [Category.parserError],
|
| template: "Classes can't be declared inside other classes.",
|
| howToFix: "Try moving the class to the top-level.",
|
| usedBy: [analyzer],
|
| @@ -407,7 +401,7 @@ final Map<String, Message> MESSAGES = {
|
|
|
| 'CONSTRUCTOR_WITH_RETURN_TYPE': new Message(
|
| id: 'VOJBWY',
|
| - category: Category.parserError,
|
| + categories: [Category.parserError],
|
| template: "Constructors can't have a return type",
|
| howToFix: "Try removing the return type.",
|
| usedBy: [analyzer, dart2js],
|
| @@ -416,13 +410,10 @@ final Map<String, Message> MESSAGES = {
|
| 'MISSING_EXPRESSION_IN_THROW': new Message(
|
| id: 'FTGGMJ',
|
| subId: 0,
|
| - category: Category.parserError,
|
| + categories: [Category.parserError],
|
| template: "Missing expression after 'throw'.",
|
| howToFix: "Did you mean 'rethrow'?",
|
| - usedBy: [
|
| - analyzer,
|
| - dart2js
|
| - ],
|
| + usedBy: [analyzer, dart2js],
|
| examples: const [
|
| 'main() { throw; }',
|
| 'main() { try { throw 0; } catch(e) { throw; } }'
|
| @@ -434,7 +425,7 @@ final Map<String, Message> MESSAGES = {
|
| */
|
| 'RETHROW_OUTSIDE_CATCH': new Message(
|
| id: 'MWETLC',
|
| - category: Category.compileTimeError,
|
| + categories: [Category.compileTimeError],
|
| template: 'Rethrow must be inside of catch clause',
|
| howToFix: "Try moving the expression into a catch clause, or "
|
| "using a 'throw' expression.",
|
| @@ -447,14 +438,11 @@ final Map<String, Message> MESSAGES = {
|
| */
|
| 'RETURN_IN_GENERATIVE_CONSTRUCTOR': new Message(
|
| id: 'UOTDQH',
|
| - category: Category.compileTimeError,
|
| + categories: [Category.compileTimeError],
|
| template: "Constructors can't return values.",
|
| howToFix:
|
| "Try removing the return statement or using a factory constructor.",
|
| - usedBy: [
|
| - analyzer,
|
| - dart2js
|
| - ],
|
| + usedBy: [analyzer, dart2js],
|
| examples: const [
|
| """
|
| class C {
|
| @@ -473,15 +461,12 @@ final Map<String, Message> MESSAGES = {
|
| 'RETURN_IN_GENERATOR': new Message(
|
| id: 'JRUTUQ',
|
| subId: 0,
|
| - category: Category.compileTimeError,
|
| + categories: [Category.compileTimeError],
|
| template: "Can't return a value from a generator function "
|
| "(using the '#{modifier}' modifier).",
|
| howToFix: "Try removing the value, replacing 'return' with 'yield' or"
|
| " changing the method body modifier",
|
| - usedBy: [
|
| - analyzer,
|
| - dart2js
|
| - ],
|
| + usedBy: [analyzer, dart2js],
|
| examples: const [
|
| """
|
| foo() async* { return 0; }
|
| @@ -492,4 +477,79 @@ final Map<String, Message> MESSAGES = {
|
| main() => foo();
|
| """
|
| ]),
|
| +
|
| + 'NOT_ASSIGNABLE': new Message(
|
| + id: 'FYQYXB',
|
| + subId: 0,
|
| + categories: [Category.staticTypeWarning],
|
| + template: "'#{fromType}' is not assignable to '#{toType}'.",
|
| + usedBy: [dart2js]),
|
| +
|
| + 'FORIN_NOT_ASSIGNABLE': new Message(
|
| + id: 'FYQYXB',
|
| + subId: 1,
|
| + categories: [Category.hint],
|
| + template: "The element type '#{currentType}' of '#{expressionType}' "
|
| + "is not assignable to '#{elementType}'.",
|
| + usedBy: [dart2js],
|
| + examples: const [
|
| + """
|
| + main() {
|
| + List<int> list = <int>[1, 2];
|
| + for (String x in list) x;
|
| + }
|
| + """
|
| + ]),
|
| +
|
| + /**
|
| + * 13.11 Return: It is a static type warning if the type of <i>e</i> may not
|
| + * be assigned to the declared return type of the immediately enclosing
|
| + * function.
|
| + */
|
| + 'RETURN_OF_INVALID_TYPE': new Message(
|
| + id: 'FYQYXB',
|
| + subId: 2,
|
| + specializationOf: 'NOT_ASSIGNABLE',
|
| + categories: [Category.staticTypeWarning],
|
| + template: "The return type '#{fromType}' is not a '#{toType}', as "
|
| + "defined by the method '#{method}'.",
|
| + usedBy: [analyzer],
|
| + examples: const ["int foo() => 'foo'; main() { foo(); }"]),
|
| +
|
| + /**
|
| + * 12.11.1 New: It is a static warning if the static type of <i>a<sub>i</sub>,
|
| + * 1 <= i <= n+ k</i> may not be assigned to the type of the
|
| + * corresponding formal parameter of the constructor <i>T.id</i> (respectively
|
| + * <i>T</i>).
|
| + *
|
| + * 12.11.2 Const: It is a static warning if the static type of
|
| + * <i>a<sub>i</sub>, 1 <= i <= n+ k</i> may not be assigned to the type
|
| + * of the corresponding formal parameter of the constructor <i>T.id</i>
|
| + * (respectively <i>T</i>).
|
| + *
|
| + * 12.14.2 Binding Actuals to Formals: Let <i>T<sub>i</sub></i> be the static
|
| + * type of <i>a<sub>i</sub></i>, let <i>S<sub>i</sub></i> be the type of
|
| + * <i>p<sub>i</sub>, 1 <= i <= n+k</i> and let <i>S<sub>q</sub></i> be
|
| + * the type of the named parameter <i>q</i> of <i>f</i>. It is a static
|
| + * warning if <i>T<sub>j</sub></i> may not be assigned to <i>S<sub>j</sub>, 1
|
| + * <= j <= m</i>.
|
| + *
|
| + * 12.14.2 Binding Actuals to Formals: Furthermore, each <i>q<sub>i</sub>, 1
|
| + * <= i <= l</i>, must have a corresponding named parameter in the set
|
| + * <i>{p<sub>n+1</sub>, … p<sub>n+k</sub>}</i> or a static warning
|
| + * occurs. It is a static warning if <i>T<sub>m+j</sub></i> may not be
|
| + * assigned to <i>S<sub>r</sub></i>, where <i>r = q<sub>j</sub>, 1 <= j
|
| + * <= l</i>.
|
| + */
|
| + 'ARGUMENT_TYPE_NOT_ASSIGNABLE': new Message(
|
| + id: 'FYQYXB',
|
| + subId: 3,
|
| + specializationOf: 'NOT_ASSIGNABLE',
|
| + categories: [Category.hint, Category.staticWarning],
|
| + template: "The argument type '#{fromType}' cannot be assigned to the "
|
| + "parameter type '#{toType}'.",
|
| + usedBy: [analyzer],
|
| + // TODO(floitsch): support hint warnings and ways to specify which
|
| + // category an example should trigger for.
|
| + examples: const ["foo(int x) => x; main() { foo('bar'); }"]),
|
| };
|
|
|