Chromium Code Reviews| Index: dart/sdk/lib/_internal/compiler/implementation/warnings.dart |
| diff --git a/dart/sdk/lib/_internal/compiler/implementation/warnings.dart b/dart/sdk/lib/_internal/compiler/implementation/warnings.dart |
| index 7950a313c8f4f0c5cab3880b80be103b7e1c7e0c..6a2f6f3ad82ac5729967554a0504467cf6d785bc 100644 |
| --- a/dart/sdk/lib/_internal/compiler/implementation/warnings.dart |
| +++ b/dart/sdk/lib/_internal/compiler/implementation/warnings.dart |
| @@ -9,34 +9,33 @@ part of dart2js; |
| * |
| * 1. The message should start with exactly one of "Error", "Internal error", |
| * "Warning", "Info", or "Hint" followed by a colon. It is crucial to users to |
| - * be able to locate errors in the midst of warnings, but we are operating |
| - * under the assumption that these messages will eventually be translated to |
| - * other languages than English, and that it is therefor not possible to |
| - * automatically apply these prefixes. |
| + * be able to locate errors in the midst of warnings. |
| + * TODO(ahe): Remove these prefixes from the error message. |
| * |
| * 2. After the colon, one space and a complete sentence starting with an |
| * uppercase letter, and ending with a period. |
| * |
| - * 3. Reserved words and embedded identifiers should be in quotes (double |
| - * quotes), so prefer single quotes for the complete message. For example, |
| - * 'Error: The class "#{className}" cannot use "super".' Notice that the word |
| - * "class" in the preceding message is not quoted as it refers to the concept |
| - * "class", not the reserved word. On the other hand, "super" refers to the |
| - * reserved word. Do not quote "null" and numeric literals. |
| + * 3. Reserved words and embedded identifiers should be in single quotes, so |
| + * prefer double quotes for the complete message. For example, "Error: The |
| + * class '#{className}' can't use 'super'." Notice that the word 'class' in the |
| + * preceding message is not quoted as it refers to the concept 'class', not the |
| + * reserved word. On the other hand, 'super' refers to the reserved word. Do |
| + * not quote 'null' and numeric literals. |
| * |
| * 4. Do not try to compose messages, as it can make translating them hard. |
| * |
| * 5. Try to keep the error messages short, but informative. |
| * |
| - * 6. Use simple words and terminology, assume the reader of the message does |
| - * not have an advanced degree in math, and that English is not the reader's |
| - * native language. Do not assume any formal computer science training. For |
| - * example, do not use Latin abbreviations (prefer "that is" over "i.e.", and |
| - * "for example" over "e.g."). Also avoid phrases such as "if and only if" and |
| - * "iff", that level of precision is unnecessary. |
| + * 6. Use simple words and terminology, assume the reader of the message |
| + * doesn't have an advanced degree in math, and that English is not the |
| + * reader's native language. Do not assume any formal computer science |
| + * training. For example, do not use Latin abbreviations (prefer "that is" over |
| + * "i.e.", and "for example" over "e.g."). Also avoid phrases such as "if and |
| + * only if" and "iff", that level of precision is unnecessary. |
| * |
| - * 7. Do not use contractions, for example, prefer "cannot" over "can't". This |
| - * is again to benefit readers to whom English is not their first language. |
| + * 7. Prefer contractions when they are in common use, for example, prefer |
| + * "can't" over "cannot". Using "cannot", "must not", "shall not", etc. is |
| + * off-putting to people new to programming. |
| * |
| * 8. Use common terminology, preferably from the Dart Language |
| * Specification. This increases the user's chance of finding a good |
| @@ -47,13 +46,38 @@ part of dart2js; |
| * not want to use this product to begin with with. |
| * |
| * 10. Do not lie, that is, do not write error messages containing phrases like |
| - * "cannot happen". If the user ever saw this message, it would be a |
| - * lie. Prefer messages like: 'Internal error: This function should not be |
| - * called when "x" is null.'. |
| + * "can't happen". If the user ever saw this message, it would be a |
| + * lie. Prefer messages like: "Internal error: This function should not be |
| + * called when 'x' is null.". |
| + * |
| + * 11. Prefer to not use imperative tone. That is, the message should not sound |
| + * accusing or like it is ordering the user around. The computer should |
| + * describe the problem, not criticize for violating the specification. |
| + * |
| + * Other things to keep in mind: |
| + * |
| + * An INFO message should always be preceded by a non-INFO message, and the |
| + * INFO messages are additional details about the preceding non-INFO |
| + * message. For example, consider duplicated elements. First report a WARNING |
| + * or ERROR about the duplicated element, and then report an INFO about the |
| + * location of the existing element. |
| + * |
| + * Generally, we want to provide messages that consists of three sentences: |
| + * 1. what is wrong, 2. why is it wrong, 3. how do I fix it. However, we |
| + * combine the first two in [template] and the last in [howToFix]. |
| */ |
| class MessageKind { |
| + /// Should describe what is wrong and why. |
| final String template; |
| - const MessageKind(this.template); |
| + |
| + /// Should describe how to fix the problem. Elided when using --terse option. |
| + final String howToFix; |
| + |
| + /// Examples will be checked by |
| + /// tests/compiler/dart2js/message_kind_test.dart. |
| + final List<String> examples; |
| + |
| + const MessageKind(this.template, {this.howToFix, this.examples}); |
| /// Do not use this. It is here for legacy and debugging. It violates item 4 |
| /// above. |
| @@ -616,6 +640,102 @@ Error: "#{value}" is not a valid Symbol name because is not: |
| static const MessageKind PACKAGE_ROOT_NOT_SET = const MessageKind( |
| 'Error: Cannot resolve "#{uri}". Package root has not been set.'); |
| + static const MessageKind MIRRORS_EXPECTED_STRING = const MessageKind( |
| + "Hint: Can't use '#{name}' here because it's an instance of '#{type}' " |
| + "and a 'String' value is expected.", |
| + howToFix: "Did you forget to add quotes?", |
| + examples: const [ |
| + """ |
| +// 'main' is a method, not a class. |
| +@MirrorsUsed(symbols: const [Foo]) |
| +import 'dart:mirrors'; |
| + |
| +class Foo {} |
| + |
| +main() {} |
| +"""]); |
| + |
| + static const MessageKind MIRRORS_EXPECTED_STRING_OR_TYPE = const MessageKind( |
| + "Hint: Can't use '#{name}' here because it's an instance of '#{type}' " |
| + "and a 'String' or 'Type' value is expected.", |
| + howToFix: "Did you forget to add quotes?", |
| + examples: const [ |
| + """ |
| +// 'main' is a method, not a class. |
| +@MirrorsUsed(targets: const [main]) |
| +import 'dart:mirrors'; |
| + |
| +main() {} |
| +"""]); |
| + |
| + static const MessageKind MIRRORS_EXPECTED_STRING_OR_LIST = const MessageKind( |
| + "Hint: Can't use '#{name}' here because it's an instance of '#{type}' " |
| + "and a 'String' or 'List' value is expected.", |
| + howToFix: "Did you forget to add quotes?", |
| + examples: const [ |
| + """ |
| +// 'Foo' is not a string. |
| +@MirrorsUsed(symbols: Foo) |
| +import 'dart:mirrors'; |
| + |
| +class Foo {} |
| + |
| +main() {} |
| +"""]); |
| + |
| + static const MessageKind MIRRORS_EXPECTED_STRING_TYPE_OR_LIST = |
| + const MessageKind( |
| + "Hint: Can't use '#{name}' here because it's an instance of '#{type}' " |
| + "but a 'String', 'Type', or 'List' value is expected.", |
| + howToFix: "Did you forget to add quotes?", |
| + examples: const [ |
| + """ |
| +// '1' is not a string. |
| +@MirrorsUsed(targets: 1) |
| +import 'dart:mirrors'; |
| + |
| +main() {} |
| +"""]); |
| + |
| + static const MessageKind MIRRORS_CANNOT_RESOLVE_IN_CURRENT_LIBRARY = |
| + const MessageKind( |
| + "Hint: Can't find '#{name}' in the current library.", |
| + howToFix: "Did you forget to add an import?", |
| + examples: const [ |
| + """ |
| +// 'window' is not in scope because dart:html isn't imported. |
| +@MirrorsUsed(targets: 'window') |
| +import 'dart:mirrors'; |
| + |
| +main() {} |
| +"""]); |
| + |
| + static const MessageKind MIRRORS_CANNOT_RESOLVE_IN_LIBRARY = |
| + const MessageKind( |
| + "Hint: Can't find '#{name}' in the library '#{library}'.", |
| + howToFix: "Did you check the spelling of '#{name}'?", |
|
Johnni Winther
2013/08/07 10:39:17
Strange question to ask (they probably _forgot_ to
karlklose
2013/08/07 10:48:11
It would be much more useful if we could find the
ahe
2013/08/07 13:40:20
I agree with Karl, but I don't have the next close
|
| + examples: const [ |
| + """ |
| +// 'List' is misspelled. |
| +@MirrorsUsed(targets: 'dart.core.Lsit') |
| +import 'dart:mirrors'; |
| + |
| +main() {} |
| +"""]); |
| + |
| + static const MessageKind MIRRORS_CANNOT_FIND_IN_ELEMENT = |
| + const MessageKind( |
| + "Hint: Can't find '#{name}' in '#{element}'.", |
| + howToFix: "Did you check the spelling of '#{name}'?", |
|
Johnni Winther
2013/08/07 10:39:17
Ditto.
|
| + examples: const [ |
| + """ |
| +// 'addAll' is misspelled. |
| +@MirrorsUsed(targets: 'dart.core.List.addAl') |
| +import 'dart:mirrors'; |
| + |
| +main() {} |
| +"""]); |
| + |
| static const MessageKind COMPILER_CRASHED = const MessageKind( |
| 'Error: The compiler crashed when compiling this element.'); |
| @@ -733,12 +853,12 @@ Please include the following information: |
| toString() => template; |
| - Message message([Map arguments = const {}]) { |
| - return new Message(this, arguments); |
| + Message message([Map arguments = const {}, bool terse = false]) { |
| + return new Message(this, arguments, terse); |
| } |
| - CompilationError error([Map arguments = const {}]) { |
| - return new CompilationError(this, arguments); |
| + CompilationError error([Map arguments = const {}, bool terse = false]) { |
| + return new CompilationError(this, arguments, terse); |
| } |
| } |
| @@ -750,11 +870,12 @@ class DualKind { |
| } |
| class Message { |
| - final kind; |
| + final MessageKind kind; |
| final Map arguments; |
| + final bool terse; |
| String message; |
| - Message(this.kind, this.arguments) { |
| + Message(this.kind, this.arguments, this.terse) { |
| assert(() { computeMessage(); return true; }); |
| } |
| @@ -769,6 +890,14 @@ class Message { |
| CURRENT_ELEMENT_SPANNABLE, |
| !message.contains(new RegExp(r'#\{.+\}')), |
| message: 'Missing arguments in error message: "$message"')); |
| + if (!terse && kind.howToFix != null) { |
| + String howToFix = kind.howToFix; |
| + arguments.forEach((key, value) { |
| + String string = slowToString(value); |
| + howToFix = howToFix.replaceAll('#{${key}}', string); |
| + }); |
| + message = '$message\n$howToFix'; |
| + } |
| } |
| return message; |
| } |
| @@ -795,27 +924,27 @@ class Message { |
| class Diagnostic { |
| final Message message; |
| - Diagnostic(MessageKind kind, [Map arguments = const {}]) |
| - : message = new Message(kind, arguments); |
| + Diagnostic(MessageKind kind, Map arguments, bool terse) |
| + : message = new Message(kind, arguments, terse); |
| String toString() => message.toString(); |
| } |
| class TypeWarning extends Diagnostic { |
| - TypeWarning(MessageKind kind, [Map arguments = const {}]) |
| - : super(kind, arguments); |
| + TypeWarning(MessageKind kind, Map arguments, bool terse) |
| + : super(kind, arguments, terse); |
| } |
| class ResolutionWarning extends Diagnostic { |
| - ResolutionWarning(MessageKind kind, [Map arguments = const {}]) |
| - : super(kind, arguments); |
| + ResolutionWarning(MessageKind kind, Map arguments, bool terse) |
| + : super(kind, arguments, terse); |
| } |
| class CompileTimeConstantError extends Diagnostic { |
| - CompileTimeConstantError(MessageKind kind, [Map arguments = const {}]) |
| - : super(kind, arguments); |
| + CompileTimeConstantError(MessageKind kind, Map arguments, bool terse) |
| + : super(kind, arguments, terse); |
| } |
| class CompilationError extends Diagnostic { |
| - CompilationError(MessageKind kind, [Map arguments = const {}]) |
| - : super(kind, arguments); |
| + CompilationError(MessageKind kind, Map arguments, bool terse) |
| + : super(kind, arguments, terse); |
| } |