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'); }"]), |
}; |