blob: 32d793588d8e39b601960d2ed36226386ba41c8d [file] [log] [blame]
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// 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.
// An update to this file must be followed by regenerating the corresponding
// json, dart2js and analyzer file. Use `publish.dart` in the bin directory.
//
// Every message in this file must have an id. Use `message_id.dart` in the
// bin directory to generate a fresh one.
// The messages in this file should meet the following guide lines:
//
// 1. The message should be a complete sentence starting with an uppercase
// letter, and ending with a period.
//
// 2. Reserved words and embedded identifiers should be in single quotes, so
// prefer double quotes for the complete message. For example, "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.
//
// 3. Do not try to compose messages, as it can make translating them hard.
//
// 4. Try to keep the error messages short, but informative.
//
// 5. 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.
//
// 6. 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.
//
// 7. Use common terminology, preferably from the Dart Language
// Specification. This increases the user's chance of finding a good
// explanation on the web.
//
// 8. Do not try to be cute or funny. It is extremely frustrating to work on a
// product that crashes with a "tongue-in-cheek" message, especially if you did
// not want to use this product to begin with.
//
// 9. Do not lie, that is, do not write error messages containing phrases like
// "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.".
//
// 10. 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:
//
// 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].
import 'dart:convert';
/// Encodes the category of the message.
///
/// This is currently only used in the analyzer.
// TODO(floitsch): encode severity and type in the category, so we can generate
// the corresponding ErrorCode subclasses.
class Category {
static final analysisOptionsError = new Category("AnalysisOptionsError");
static final analysisOptionsWarning = new Category("AnalysisOptionsWarning");
static final checkedModeCompileTimeError =
new Category("CheckedModeCompileTimeError");
static final parserError = new Category("ParserError");
final String name;
Category(this.name);
}
enum Platform {
dart2js, analyzer,
}
const dart2js = Platform.dart2js;
const analyzer = Platform.analyzer;
class Message {
final String id;
final int subId;
final Category category;
final String template;
// The analyzer fills holes positionally (and not named). The following field
// overrides the order of the holes.
// For example the template "The argument #field in #cls is bad", could have
// the order `["cls", "field"]', which means that the analyzer would first
// provide the class `cls` and then only `field`.
// This list is generally `null`, but when it is provided it must contain all
// holes.
final List<String> templateHoleOrder;
final String howToFix;
final List<String> options;
final List examples;
final List<Platform> usedBy;
Message(
{this.id,
this.subId: 0,
this.category,
this.template,
this.templateHoleOrder,
this.howToFix,
this.options,
this.usedBy: const [],
this.examples});
}
String get messagesAsJson {
var jsonified = {};
MESSAGES.forEach((String name, Message message) {
jsonified[name] = {
'id': message.id,
'subId': message.subId,
'category': message.category.name,
'template': message.template,
'templateHoleOrder': message.templateHoleOrder,
'howToFix': message.howToFix,
'options': message.options,
'usedBy': message.usedBy.map((platform) => platform.toString()).toList(),
'examples': message.examples,
};
});
return JSON.encode(jsonified);
}
final Map<String, Message> MESSAGES = {
'exampleMessage': new Message(
id: 'use an Id generated by bin/message_id.dart',
category: Category.analysisOptionsError,
template: "#use #named #arguments",
templateHoleOrder: ["arguments", "named", "use"],
howToFix: "an explanation on how to fix things",
examples: [
r'''
Some multiline example;
That generates the bug.''',
{
'fileA.dart': '''
or a map from file to content.
again multiline''',
'fileB.dart': '''
with possibly multiple files.
muliline too'''
}
]),
// Const constructors (factory or not) may not have a body.
'CONST_CONSTRUCTOR_OR_FACTORY_WITH_BODY': new Message(
id: 'LGJGHW',
subId: 0,
category: Category.parserError,
template: "Const constructor or factory can't have a body.",
howToFix: "Remove the 'const' keyword or the body.",
usedBy: [dart2js],
examples: const [
r"""
class C {
const C() {}
}
main() => new C();""",
r"""
class C {
const factory C() {}
}
main() => new C();"""
]),
// Const constructors may not have a body.
'CONST_CONSTRUCTOR_WITH_BODY': new Message(
id: 'LGJGHW',
subId: 1,
category: Category.parserError,
template: "Const constructor can't have a body.",
howToFix: "Try removing the 'const' keyword or the body.",
usedBy: [analyzer],
examples: const [
r"""
class C {
const C() {}
}
main() => new C();"""
]),
// Const constructor factories may only redirect (and must not have a body).
'CONST_FACTORY': new Message(
id: 'LGJGHW',
subId: 2,
category: 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],
examples: const [
r"""
class C {
const factory C() {}
}
main() => new C();"""
]),
};