Use message.yaml in parser.

R=johnniwinther@google.com

Review-Url: https://codereview.chromium.org/2778213002 .
This commit is contained in:
Peter von der Ahé 2017-03-29 11:02:21 +02:00
parent e8a718155e
commit a62c5631bf
22 changed files with 1529 additions and 1112 deletions

View file

@ -15,6 +15,8 @@ import 'package:front_end/src/fasta/scanner/token.dart'
show BeginGroupToken, Token;
import 'package:front_end/src/fasta/errors.dart' show internalError;
import 'package:front_end/src/fasta/fasta_codes.dart'
show FastaMessage, codeExpectedExpression;
import 'package:front_end/src/fasta/kernel/kernel_builder.dart'
show Builder, KernelLibraryBuilder, ProcedureBuilder;
import 'package:front_end/src/fasta/parser/identifier_context.dart'
@ -30,7 +32,6 @@ import 'element_store.dart'
ElementStore,
KernelClassElement;
import 'package:analyzer/src/dart/error/syntactic_errors.dart';
import 'package:front_end/src/fasta/parser/error_kind.dart';
import 'token_utils.dart' show toAnalyzerToken, toAnalyzerCommentToken;
class AstBuilder extends ScopeListener {
@ -1046,8 +1047,8 @@ class AstBuilder extends ScopeListener {
}
@override
Token handleUnrecoverableError(Token token, ErrorKind kind, Map arguments) {
if (kind == ErrorKind.ExpectedExpression) {
Token handleUnrecoverableError(Token token, FastaMessage message) {
if (message.code == codeExpectedExpression) {
String lexeme = token.lexeme;
if (identical('async', lexeme) || identical('yield', lexeme)) {
errorReporter?.reportErrorForOffset(
@ -1058,7 +1059,7 @@ class AstBuilder extends ScopeListener {
return token;
}
}
return super.handleUnrecoverableError(token, kind, arguments);
return super.handleUnrecoverableError(token, message);
}
void handleUnaryPrefixExpression(Token token) {

View file

@ -4,6 +4,10 @@
library dart2js.parser.element_listener;
import 'package:front_end/src/fasta/fasta_codes.dart' show FastaMessage;
import 'package:front_end/src/fasta/fasta_codes.dart' as codes;
import '../common.dart';
import '../diagnostics/messages.dart' show MessageTemplate;
import '../elements/elements.dart'
@ -26,11 +30,11 @@ import 'package:front_end/src/fasta/scanner.dart'
show Keyword, BeginGroupToken, ErrorToken, KeywordToken, StringToken, Token;
import 'package:front_end/src/fasta/scanner.dart' as Tokens show EOF_TOKEN;
import 'package:front_end/src/fasta/scanner/precedence.dart' as Precedence
show BAD_INPUT_INFO, IDENTIFIER_INFO;
show IDENTIFIER_INFO;
import '../tree/tree.dart';
import '../util/util.dart' show Link, LinkBuilder;
import 'package:front_end/src/fasta/parser.dart'
show ErrorKind, Listener, ParserError, optional;
show Listener, ParserError, optional;
import 'package:front_end/src/fasta/parser/identifier_context.dart'
show IdentifierContext;
import 'partial_elements.dart'
@ -100,6 +104,9 @@ class ElementListener extends Listener {
stringValidator = new StringValidator(reporter),
interpolationScope = const Link<StringQuoting>();
@override
Uri get uri => compilationUnitElement?.script?.resourceUri;
bool get currentMemberHasParseError {
return !memberErrors.isEmpty && memberErrors.head;
}
@ -500,20 +507,20 @@ class ElementListener extends Listener {
}
@override
Token handleUnrecoverableError(Token token, ErrorKind kind, Map arguments) {
Token next = handleError(token, kind, arguments);
Token handleUnrecoverableError(Token token, FastaMessage message) {
Token next = handleError(token, message);
if (next == null &&
kind != ErrorKind.UnterminatedComment &&
kind != ErrorKind.UnterminatedString) {
throw new ParserError.fromTokens(token, token, kind, arguments);
message.code != codes.codeUnterminatedComment &&
message.code != codes.codeUnterminatedString) {
throw new ParserError.fromTokens(token, token, message);
} else {
return next;
}
}
@override
void handleRecoverableError(Token token, ErrorKind kind, Map arguments) {
handleError(token, kind, arguments);
void handleRecoverableError(Token token, FastaMessage message) {
handleError(token, message);
}
@override
@ -531,12 +538,13 @@ class ElementListener extends Listener {
pushNode(null);
}
Token handleError(Token token, ErrorKind kind, Map arguments) {
Token handleError(Token token, FastaMessage message) {
MessageKind errorCode;
Map<String, dynamic> arguments = message.arguments;
switch (kind) {
case ErrorKind.ExpectedButGot:
String expected = arguments["expected"];
switch (message.code.dart2jsCode) {
case "MISSING_TOKEN_BEFORE_THIS":
String expected = arguments["string"];
if (identical(";", expected)) {
// When a semicolon is missing, it often leads to an error on the
// following line. So we try to find the token preceding the semicolon
@ -559,7 +567,7 @@ class ElementListener extends Listener {
}
break;
case ErrorKind.ExpectedIdentifier:
case "EXPECTED_IDENTIFIER":
if (token is KeywordToken) {
reportErrorFromToken(
token,
@ -574,25 +582,11 @@ class ElementListener extends Listener {
}
return newSyntheticToken(token);
case ErrorKind.ExpectedType:
reportFatalError(reporter.spanFromToken(token),
"Expected a type, but got '${token.lexeme}'.");
case "FASTA_FATAL":
reportFatalError(reporter.spanFromToken(token), message.message);
return null;
case ErrorKind.ExpectedExpression:
reportFatalError(reporter.spanFromToken(token),
"Expected an expression, but got '${token.lexeme}'.");
return null;
case ErrorKind.UnexpectedToken:
String message = "Unexpected token '${token.lexeme}'.";
if (token.info == Precedence.BAD_INPUT_INFO) {
message = token.lexeme;
}
reportFatalError(reporter.spanFromToken(token), message);
return null;
case ErrorKind.ExpectedBlockToSkip:
case "NATIVE_OR_BODY_EXPECTED":
if (optional("native", token)) {
return newSyntheticToken(native.handleNativeBlockToSkip(this, token));
} else {
@ -600,166 +594,118 @@ class ElementListener extends Listener {
}
break;
case ErrorKind.ExpectedFunctionBody:
case "NATIVE_OR_FATAL":
if (optional("native", token)) {
lastErrorWasNativeFunctionBody = true;
return newSyntheticToken(
native.handleNativeFunctionBody(this, token));
} else {
reportFatalError(reporter.spanFromToken(token),
"Expected a function body, but got '${token.lexeme}'.");
reportFatalError(reporter.spanFromToken(token), message.message);
}
return null;
case ErrorKind.ExpectedClassBodyToSkip:
case ErrorKind.ExpectedClassBody:
reportFatalError(reporter.spanFromToken(token),
"Expected a class body, but got '${token.lexeme}'.");
return null;
case ErrorKind.ExpectedDeclaration:
reportFatalError(reporter.spanFromToken(token),
"Expected a declaration, but got '${token.lexeme}'.");
return null;
case ErrorKind.UnmatchedToken:
reportErrorFromToken(token, MessageKind.UNMATCHED_TOKEN, arguments);
case "UNMATCHED_TOKEN":
reportErrorFromToken(token, MessageKind.UNMATCHED_TOKEN,
{"end": arguments["string"], "begin": arguments["token"]});
Token next = token;
while (next.next is ErrorToken) {
next = next.next;
}
return next;
case ErrorKind.EmptyNamedParameterList:
case "EMPTY_NAMED_PARAMETER_LIST":
errorCode = MessageKind.EMPTY_NAMED_PARAMETER_LIST;
break;
case ErrorKind.EmptyOptionalParameterList:
case "EMPTY_OPTIONAL_PARAMETER_LIST":
errorCode = MessageKind.EMPTY_OPTIONAL_PARAMETER_LIST;
break;
case ErrorKind.ExpectedBody:
case "BODY_EXPECTED":
errorCode = MessageKind.BODY_EXPECTED;
break;
case ErrorKind.ExpectedHexDigit:
case "HEX_DIGIT_EXPECTED":
errorCode = MessageKind.HEX_DIGIT_EXPECTED;
break;
case ErrorKind.ExpectedOpenParens:
case "GENERIC":
errorCode = MessageKind.GENERIC;
arguments = {"text": "Expected '('."};
arguments = {"text": message.message};
break;
case ErrorKind.ExpectedString:
reportFatalError(reporter.spanFromToken(token),
"Expected a String, but got '${token.lexeme}'.");
return null;
case ErrorKind.ExtraneousModifier:
case "EXTRANEOUS_MODIFIER":
errorCode = MessageKind.EXTRANEOUS_MODIFIER;
arguments = {"modifier": arguments["token"]};
break;
case ErrorKind.ExtraneousModifierReplace:
case "EXTRANEOUS_MODIFIER_REPLACE":
errorCode = MessageKind.EXTRANEOUS_MODIFIER_REPLACE;
arguments = {"modifier": arguments["token"]};
break;
case ErrorKind.InvalidAwaitFor:
case "INVALID_AWAIT_FOR":
errorCode = MessageKind.INVALID_AWAIT_FOR;
break;
case ErrorKind.AsciiControlCharacter:
case ErrorKind.NonAsciiIdentifier:
case ErrorKind.NonAsciiWhitespace:
case ErrorKind.Encoding:
case "BAD_INPUT_CHARACTER":
errorCode = MessageKind.BAD_INPUT_CHARACTER;
int codePoint = arguments["codePoint"];
String hex = codePoint.toRadixString(16);
String padding = "0000".substring(hex.length);
arguments = {'characterHex': padding};
break;
case ErrorKind.InvalidInlineFunctionType:
case "INVALID_INLINE_FUNCTION_TYPE":
errorCode = MessageKind.INVALID_INLINE_FUNCTION_TYPE;
break;
case ErrorKind.InvalidSyncModifier:
case "INVALID_SYNC_MODIFIER":
errorCode = MessageKind.INVALID_SYNC_MODIFIER;
break;
case ErrorKind.InvalidVoid:
case "VOID_NOT_ALLOWED":
errorCode = MessageKind.VOID_NOT_ALLOWED;
break;
case ErrorKind.UnexpectedDollarInString:
case "MALFORMED_STRING_LITERAL":
errorCode = MessageKind.MALFORMED_STRING_LITERAL;
break;
case ErrorKind.MissingExponent:
case "EXPONENT_MISSING":
errorCode = MessageKind.EXPONENT_MISSING;
break;
case ErrorKind.PositionalParameterWithEquals:
case "POSITIONAL_PARAMETER_WITH_EQUALS":
errorCode = MessageKind.POSITIONAL_PARAMETER_WITH_EQUALS;
break;
case ErrorKind.RequiredParameterWithDefault:
case "REQUIRED_PARAMETER_WITH_DEFAULT":
errorCode = MessageKind.REQUIRED_PARAMETER_WITH_DEFAULT;
break;
case ErrorKind.UnmatchedToken:
case "UNMATCHED_TOKEN":
errorCode = MessageKind.UNMATCHED_TOKEN;
break;
case ErrorKind.UnsupportedPrefixPlus:
case "UNSUPPORTED_PREFIX_PLUS":
errorCode = MessageKind.UNSUPPORTED_PREFIX_PLUS;
break;
case ErrorKind.UnterminatedComment:
case "UNTERMINATED_COMMENT":
errorCode = MessageKind.UNTERMINATED_COMMENT;
break;
case ErrorKind.UnterminatedString:
case "UNTERMINATED_STRING":
errorCode = MessageKind.UNTERMINATED_STRING;
arguments = {"quote": arguments["string"]};
break;
case ErrorKind.UnterminatedToken:
case "UNTERMINATED_TOKEN":
errorCode = MessageKind.UNTERMINATED_TOKEN;
break;
case ErrorKind.StackOverflow:
errorCode = MessageKind.GENERIC;
arguments = {"text": "Stack overflow."};
break;
case ErrorKind.Unspecified:
errorCode = MessageKind.GENERIC;
break;
case ErrorKind.BuiltInIdentifierAsType:
errorCode = MessageKind.GENERIC;
arguments = {"text": "Can't use '${token.lexeme}' as a type."};
break;
case ErrorKind.BuiltInIdentifierInDeclaration:
errorCode = MessageKind.GENERIC;
arguments = {"text": "Can't use '${token.lexeme}' as a name here."};
break;
case ErrorKind.AsyncAsIdentifier:
errorCode = MessageKind.GENERIC;
arguments = {
"text": "'async' can't be used as an identifier in "
"'async', 'async*', or 'sync*' methods."
};
break;
case ErrorKind.AbstractNotSync:
case ErrorKind.AwaitAsIdentifier:
case ErrorKind.AwaitForNotAsync:
case ErrorKind.AwaitNotAsync:
case ErrorKind.FactoryNotSync:
case ErrorKind.GeneratorReturnsValue:
case ErrorKind.OnlyTry:
case ErrorKind.SetterNotSync:
case ErrorKind.YieldAsIdentifier:
case ErrorKind.YieldNotGenerator:
case "FASTA_IGNORED":
return null; // Ignored. This error is already implemented elsewhere.
}
SourceSpan span = reporter.spanFromToken(token);
@ -978,8 +924,8 @@ class ElementListener extends Listener {
reportError(spannable, MessageKind.GENERIC, {'text': message});
// Some parse errors are infeasible to recover from, so we throw an error.
SourceSpan span = reporter.spanFromSpannable(spannable);
throw new ParserError(
span.begin, span.end, ErrorKind.Unspecified, {'text': message});
throw new ParserError(span.begin, span.end,
codes.codeUnspecified.format(uri, span.begin, message));
}
void reportError(Spannable spannable, MessageKind errorCode,

View file

@ -451,7 +451,7 @@ Node parse(ParsingContext parsing, ElementX element, PartialElement partial,
doParse(new Parser(listener));
} on ParserError catch (e) {
partial.hasParseError = true;
return new ErrorNode(element.position, e.kind, e.arguments);
return new ErrorNode(element.position, e.message);
}
Node node = listener.popNode();
assert(listener.nodes.isEmpty);

View file

@ -16,7 +16,7 @@ import '../util/util.dart';
import 'dartstring.dart';
import 'prettyprint.dart';
import 'unparser.dart';
import 'package:front_end/src/fasta/parser.dart' show ErrorKind;
import 'package:front_end/src/fasta/fasta_codes.dart' show FastaMessage;
abstract class Visitor<R> {
const Visitor();
@ -3172,19 +3172,17 @@ class IsInterpolationVisitor extends Visitor<bool> {
class ErrorNode extends Node
implements FunctionExpression, VariableDefinitions, Typedef {
final Token token;
final ErrorKind kind;
final Map arguments;
final FastaMessage message;
final Identifier name;
final NodeList definitions;
ErrorNode.internal(
this.token, this.kind, this.arguments, this.name, this.definitions);
ErrorNode.internal(this.token, this.message, this.name, this.definitions);
factory ErrorNode(Token token, ErrorKind kind, Map arguments) {
factory ErrorNode(Token token, FastaMessage message) {
Identifier name = new Identifier(token);
NodeList definitions =
new NodeList(null, const Link<Node>().prepend(name), null, null);
return new ErrorNode.internal(token, kind, arguments, name, definitions);
return new ErrorNode.internal(token, message, name, definitions);
}
Token get beginToken => token;

View file

@ -0,0 +1,45 @@
// Copyright (c) 2017, 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.
library fasta.codes;
import 'package:front_end/src/fasta/scanner/token.dart' show Token;
part 'fasta_codes_generated.dart';
class FastaCode<T> {
final String template;
final String tip;
final String analyzerCode;
final String dart2jsCode;
final T format;
const FastaCode(
{this.template,
this.tip,
this.analyzerCode,
this.dart2jsCode,
this.format});
}
class FastaMessage {
final Uri uri;
final int charOffset;
final String message;
final String tip;
final FastaCode code;
final Map<String, dynamic> arguments;
const FastaMessage(this.uri, this.charOffset, this.code,
{this.message, this.tip, this.arguments});
}

View file

@ -0,0 +1,913 @@
// Copyright (c) 2017, 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.
// NOTE: THIS FILE IS GENERATED. DO NOT EDIT.
//
// Instead modify 'pkg/front_end/messages.yaml' and run
// 'pkg/front_end/tool/_fasta/generate_messages.dart' to update.
part of fasta.codes;
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_ExpectedClassBodyToSkip> codeExpectedClassBodyToSkip =
const FastaCode<_ExpectedClassBodyToSkip>(
template: r"Expected a class body, but got '#lexeme'.",
dart2jsCode: "FASTA_FATAL",
format: _formatExpectedClassBodyToSkip);
typedef FastaMessage _ExpectedClassBodyToSkip(
Uri uri, int charOffset, Token token);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatExpectedClassBodyToSkip(
Uri uri, int charOffset, Token token) {
String lexeme = token.lexeme;
return new FastaMessage(uri, charOffset, codeExpectedClassBodyToSkip,
message: "Expected a class body, but got '$lexeme'.",
arguments: {'token': token});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_StackOverflow> codeStackOverflow =
const FastaCode<_StackOverflow>(
template: r"Stack overflow.",
dart2jsCode: "GENERIC",
format: _formatStackOverflow);
typedef FastaMessage _StackOverflow(Uri uri, int charOffset);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatStackOverflow(Uri uri, int charOffset) {
return new FastaMessage(uri, charOffset, codeStackOverflow,
message: "Stack overflow.", arguments: {});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_UnexpectedToken> codeUnexpectedToken =
const FastaCode<_UnexpectedToken>(
template: r"Unexpected token '#lexeme'.",
dart2jsCode: "FASTA_FATAL",
format: _formatUnexpectedToken);
typedef FastaMessage _UnexpectedToken(Uri uri, int charOffset, Token token);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatUnexpectedToken(Uri uri, int charOffset, Token token) {
String lexeme = token.lexeme;
return new FastaMessage(uri, charOffset, codeUnexpectedToken,
message: "Unexpected token '$lexeme'.", arguments: {'token': token});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_AwaitAsIdentifier> codeAwaitAsIdentifier = const FastaCode<
_AwaitAsIdentifier>(
template:
r"'await' can't be used as an identifier in 'async', 'async*', or 'sync*' methods.",
dart2jsCode: "FASTA_IGNORED",
format: _formatAwaitAsIdentifier);
typedef FastaMessage _AwaitAsIdentifier(Uri uri, int charOffset);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatAwaitAsIdentifier(Uri uri, int charOffset) {
return new FastaMessage(uri, charOffset, codeAwaitAsIdentifier,
message:
"'await' can't be used as an identifier in 'async', 'async*', or 'sync*' methods.",
arguments: {});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_FactoryNotSync> codeFactoryNotSync =
const FastaCode<_FactoryNotSync>(
template: r"Factories can't use 'async', 'async*', or 'sync*'.",
dart2jsCode: "FASTA_IGNORED",
format: _formatFactoryNotSync);
typedef FastaMessage _FactoryNotSync(Uri uri, int charOffset);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatFactoryNotSync(Uri uri, int charOffset) {
return new FastaMessage(uri, charOffset, codeFactoryNotSync,
message: "Factories can't use 'async', 'async*', or 'sync*'.",
arguments: {});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_YieldNotGenerator> codeYieldNotGenerator =
const FastaCode<_YieldNotGenerator>(
template: r"'yield' can only be used in 'sync*' or 'async*' methods.",
dart2jsCode: "FASTA_IGNORED",
format: _formatYieldNotGenerator);
typedef FastaMessage _YieldNotGenerator(Uri uri, int charOffset);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatYieldNotGenerator(Uri uri, int charOffset) {
return new FastaMessage(uri, charOffset, codeYieldNotGenerator,
message: "'yield' can only be used in 'sync*' or 'async*' methods.",
arguments: {});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_SetterNotSync> codeSetterNotSync =
const FastaCode<_SetterNotSync>(
template: r"Setters can't use 'async', 'async*', or 'sync*'.",
dart2jsCode: "FASTA_IGNORED",
format: _formatSetterNotSync);
typedef FastaMessage _SetterNotSync(Uri uri, int charOffset);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatSetterNotSync(Uri uri, int charOffset) {
return new FastaMessage(uri, charOffset, codeSetterNotSync,
message: "Setters can't use 'async', 'async*', or 'sync*'.",
arguments: {});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_NonAsciiWhitespace> codeNonAsciiWhitespace = const FastaCode<
_NonAsciiWhitespace>(
template:
r"The non-ASCII space character #unicode can only be used in strings and comments.",
analyzerCode: "ILLEGAL_CHARACTER",
dart2jsCode: "BAD_INPUT_CHARACTER",
format: _formatNonAsciiWhitespace);
typedef FastaMessage _NonAsciiWhitespace(
Uri uri, int charOffset, int codePoint);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatNonAsciiWhitespace(Uri uri, int charOffset, int codePoint) {
String unicode = "(U+${codePoint.toRadixString(16).padLeft(4, '0')})";
return new FastaMessage(uri, charOffset, codeNonAsciiWhitespace,
message:
"The non-ASCII space character $unicode can only be used in strings and comments.",
arguments: {'codePoint': codePoint});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_ExpectedIdentifier> codeExpectedIdentifier =
const FastaCode<_ExpectedIdentifier>(
template: r"'#lexeme' is a reserved word and can't be used here.",
tip: r"Try using a different name.",
dart2jsCode: "EXPECTED_IDENTIFIER",
format: _formatExpectedIdentifier);
typedef FastaMessage _ExpectedIdentifier(Uri uri, int charOffset, Token token);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatExpectedIdentifier(Uri uri, int charOffset, Token token) {
String lexeme = token.lexeme;
return new FastaMessage(uri, charOffset, codeExpectedIdentifier,
message: "'$lexeme' is a reserved word and can't be used here.",
tip: "Try using a different name.",
arguments: {'token': token});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_ExpectedBlockToSkip> codeExpectedBlockToSkip =
const FastaCode<_ExpectedBlockToSkip>(
template: r"Expected a function body or '=>'.",
tip: r"Try adding {}.",
dart2jsCode: "NATIVE_OR_BODY_EXPECTED",
format: _formatExpectedBlockToSkip);
typedef FastaMessage _ExpectedBlockToSkip(Uri uri, int charOffset);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatExpectedBlockToSkip(Uri uri, int charOffset) {
return new FastaMessage(uri, charOffset, codeExpectedBlockToSkip,
message: "Expected a function body or '=>'.",
tip: "Try adding {}.",
arguments: {});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<
_RequiredParameterWithDefault> codeRequiredParameterWithDefault =
const FastaCode<_RequiredParameterWithDefault>(
template: r"Non-optional parameters can't have a default value.",
tip:
r"Try removing the default value or making the parameter optional.",
dart2jsCode: "REQUIRED_PARAMETER_WITH_DEFAULT",
format: _formatRequiredParameterWithDefault);
typedef FastaMessage _RequiredParameterWithDefault(Uri uri, int charOffset);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatRequiredParameterWithDefault(Uri uri, int charOffset) {
return new FastaMessage(uri, charOffset, codeRequiredParameterWithDefault,
message: "Non-optional parameters can't have a default value.",
tip: "Try removing the default value or making the parameter optional.",
arguments: {});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_Unspecified> codeUnspecified = const FastaCode<_Unspecified>(
template: r"#string", dart2jsCode: "GENERIC", format: _formatUnspecified);
typedef FastaMessage _Unspecified(Uri uri, int charOffset, String string);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatUnspecified(Uri uri, int charOffset, String string) {
return new FastaMessage(uri, charOffset, codeUnspecified,
message: "$string", arguments: {'string': string});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_MissingExponent> codeMissingExponent = const FastaCode<
_MissingExponent>(
template:
r"Numbers in exponential notation should always contain an exponent (an integer number with an optional sign).",
tip:
r"Make sure there is an exponent, and remove any whitespace before it.",
analyzerCode: "MISSING_DIGIT",
dart2jsCode: "EXPONENT_MISSING",
format: _formatMissingExponent);
typedef FastaMessage _MissingExponent(Uri uri, int charOffset);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatMissingExponent(Uri uri, int charOffset) {
return new FastaMessage(uri, charOffset, codeMissingExponent,
message:
"Numbers in exponential notation should always contain an exponent (an integer number with an optional sign).",
tip:
"Make sure there is an exponent, and remove any whitespace before it.",
arguments: {});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_PositionalParameterWithEquals>
codePositionalParameterWithEquals =
const FastaCode<_PositionalParameterWithEquals>(
template:
r"Positional optional parameters can't use ':' to specify a default value.",
tip: r"Try replacing ':' with '='.",
dart2jsCode: "POSITIONAL_PARAMETER_WITH_EQUALS",
format: _formatPositionalParameterWithEquals);
typedef FastaMessage _PositionalParameterWithEquals(Uri uri, int charOffset);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatPositionalParameterWithEquals(Uri uri, int charOffset) {
return new FastaMessage(uri, charOffset, codePositionalParameterWithEquals,
message:
"Positional optional parameters can't use ':' to specify a default value.",
tip: "Try replacing ':' with '='.",
arguments: {});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<
_UnexpectedDollarInString> codeUnexpectedDollarInString = const FastaCode<
_UnexpectedDollarInString>(
template:
r"A '$' has special meaning inside a string, and must be followed by an identifier or an expression in curly braces ({}).",
tip: r"Try adding a backslash (\) to escape the '$'.",
dart2jsCode: "MALFORMED_STRING_LITERAL",
format: _formatUnexpectedDollarInString);
typedef FastaMessage _UnexpectedDollarInString(Uri uri, int charOffset);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatUnexpectedDollarInString(Uri uri, int charOffset) {
return new FastaMessage(uri, charOffset, codeUnexpectedDollarInString,
message:
"A '\$' has special meaning inside a string, and must be followed by an identifier or an expression in curly braces ({}).",
tip: "Try adding a backslash (\) to escape the '\$'.",
arguments: {});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_ExtraneousModifier> codeExtraneousModifier =
const FastaCode<_ExtraneousModifier>(
template: r"Can't have modifier '#lexeme' here.",
tip: r"Try removing '#lexeme'.",
dart2jsCode: "EXTRANEOUS_MODIFIER",
format: _formatExtraneousModifier);
typedef FastaMessage _ExtraneousModifier(Uri uri, int charOffset, Token token);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatExtraneousModifier(Uri uri, int charOffset, Token token) {
String lexeme = token.lexeme;
return new FastaMessage(uri, charOffset, codeExtraneousModifier,
message: "Can't have modifier '$lexeme' here.",
tip: "Try removing '$lexeme'.",
arguments: {'token': token});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_EmptyOptionalParameterList> codeEmptyOptionalParameterList =
const FastaCode<_EmptyOptionalParameterList>(
template: r"Optional parameter lists cannot be empty.",
tip: r"Try adding an optional parameter to the list.",
dart2jsCode: "EMPTY_OPTIONAL_PARAMETER_LIST",
format: _formatEmptyOptionalParameterList);
typedef FastaMessage _EmptyOptionalParameterList(Uri uri, int charOffset);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatEmptyOptionalParameterList(Uri uri, int charOffset) {
return new FastaMessage(uri, charOffset, codeEmptyOptionalParameterList,
message: "Optional parameter lists cannot be empty.",
tip: "Try adding an optional parameter to the list.",
arguments: {});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_UnterminatedString> codeUnterminatedString =
const FastaCode<_UnterminatedString>(
template: r"String must end with #string.",
analyzerCode: "UNTERMINATED_STRING_LITERAL",
dart2jsCode: "UNTERMINATED_STRING",
format: _formatUnterminatedString);
typedef FastaMessage _UnterminatedString(
Uri uri, int charOffset, String string);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatUnterminatedString(Uri uri, int charOffset, String string) {
return new FastaMessage(uri, charOffset, codeUnterminatedString,
message: "String must end with $string.", arguments: {'string': string});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_AwaitNotAsync> codeAwaitNotAsync =
const FastaCode<_AwaitNotAsync>(
template: r"'await' can only be used in 'async' or 'async*' methods.",
dart2jsCode: "FASTA_IGNORED",
format: _formatAwaitNotAsync);
typedef FastaMessage _AwaitNotAsync(Uri uri, int charOffset);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatAwaitNotAsync(Uri uri, int charOffset) {
return new FastaMessage(uri, charOffset, codeAwaitNotAsync,
message: "'await' can only be used in 'async' or 'async*' methods.",
arguments: {});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_ExpectedFunctionBody> codeExpectedFunctionBody =
const FastaCode<_ExpectedFunctionBody>(
template: r"Expected a function body, but got '#lexeme'.",
dart2jsCode: "NATIVE_OR_FATAL",
format: _formatExpectedFunctionBody);
typedef FastaMessage _ExpectedFunctionBody(
Uri uri, int charOffset, Token token);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatExpectedFunctionBody(Uri uri, int charOffset, Token token) {
String lexeme = token.lexeme;
return new FastaMessage(uri, charOffset, codeExpectedFunctionBody,
message: "Expected a function body, but got '$lexeme'.",
arguments: {'token': token});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_ExpectedHexDigit> codeExpectedHexDigit =
const FastaCode<_ExpectedHexDigit>(
template: r"A hex digit (0-9 or A-F) must follow '0x'.",
analyzerCode: "MISSING_HEX_DIGIT",
dart2jsCode: "HEX_DIGIT_EXPECTED",
format: _formatExpectedHexDigit);
typedef FastaMessage _ExpectedHexDigit(Uri uri, int charOffset);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatExpectedHexDigit(Uri uri, int charOffset) {
return new FastaMessage(uri, charOffset, codeExpectedHexDigit,
message: "A hex digit (0-9 or A-F) must follow '0x'.", arguments: {});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_EmptyNamedParameterList> codeEmptyNamedParameterList =
const FastaCode<_EmptyNamedParameterList>(
template: r"Named parameter lists cannot be empty.",
tip: r"Try adding a named parameter to the list.",
dart2jsCode: "EMPTY_NAMED_PARAMETER_LIST",
format: _formatEmptyNamedParameterList);
typedef FastaMessage _EmptyNamedParameterList(Uri uri, int charOffset);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatEmptyNamedParameterList(Uri uri, int charOffset) {
return new FastaMessage(uri, charOffset, codeEmptyNamedParameterList,
message: "Named parameter lists cannot be empty.",
tip: "Try adding a named parameter to the list.",
arguments: {});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_UnsupportedPrefixPlus> codeUnsupportedPrefixPlus =
const FastaCode<_UnsupportedPrefixPlus>(
template: r"'+' is not a prefix operator. ",
tip: r"Try removing '+'.",
dart2jsCode: "UNSUPPORTED_PREFIX_PLUS",
format: _formatUnsupportedPrefixPlus);
typedef FastaMessage _UnsupportedPrefixPlus(Uri uri, int charOffset);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatUnsupportedPrefixPlus(Uri uri, int charOffset) {
return new FastaMessage(uri, charOffset, codeUnsupportedPrefixPlus,
message: "'+' is not a prefix operator. ",
tip: "Try removing '+'.",
arguments: {});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_ExpectedString> codeExpectedString =
const FastaCode<_ExpectedString>(
template: r"Expected a String, but got '#lexeme'.",
dart2jsCode: "FASTA_FATAL",
format: _formatExpectedString);
typedef FastaMessage _ExpectedString(Uri uri, int charOffset, Token token);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatExpectedString(Uri uri, int charOffset, Token token) {
String lexeme = token.lexeme;
return new FastaMessage(uri, charOffset, codeExpectedString,
message: "Expected a String, but got '$lexeme'.",
arguments: {'token': token});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_AbstractNotSync> codeAbstractNotSync =
const FastaCode<_AbstractNotSync>(
template: r"Abstract methods can't use 'async', 'async*', or 'sync*'.",
dart2jsCode: "FASTA_IGNORED",
format: _formatAbstractNotSync);
typedef FastaMessage _AbstractNotSync(Uri uri, int charOffset);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatAbstractNotSync(Uri uri, int charOffset) {
return new FastaMessage(uri, charOffset, codeAbstractNotSync,
message: "Abstract methods can't use 'async', 'async*', or 'sync*'.",
arguments: {});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_ExpectedDeclaration> codeExpectedDeclaration =
const FastaCode<_ExpectedDeclaration>(
template: r"Expected a declaration, but got '#lexeme'.",
dart2jsCode: "FASTA_FATAL",
format: _formatExpectedDeclaration);
typedef FastaMessage _ExpectedDeclaration(Uri uri, int charOffset, Token token);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatExpectedDeclaration(Uri uri, int charOffset, Token token) {
String lexeme = token.lexeme;
return new FastaMessage(uri, charOffset, codeExpectedDeclaration,
message: "Expected a declaration, but got '$lexeme'.",
arguments: {'token': token});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<
_AsciiControlCharacter> codeAsciiControlCharacter = const FastaCode<
_AsciiControlCharacter>(
template:
r"The control character #unicode can only be used in strings and comments.",
dart2jsCode: "BAD_INPUT_CHARACTER",
format: _formatAsciiControlCharacter);
typedef FastaMessage _AsciiControlCharacter(
Uri uri, int charOffset, int codePoint);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatAsciiControlCharacter(
Uri uri, int charOffset, int codePoint) {
String unicode = "(U+${codePoint.toRadixString(16).padLeft(4, '0')})";
return new FastaMessage(uri, charOffset, codeAsciiControlCharacter,
message:
"The control character $unicode can only be used in strings and comments.",
arguments: {'codePoint': codePoint});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_UnmatchedToken> codeUnmatchedToken =
const FastaCode<_UnmatchedToken>(
template: r"Can't find '#string' to match '#lexeme'.",
dart2jsCode: "UNMATCHED_TOKEN",
format: _formatUnmatchedToken);
typedef FastaMessage _UnmatchedToken(
Uri uri, int charOffset, String string, Token token);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatUnmatchedToken(
Uri uri, int charOffset, String string, Token token) {
String lexeme = token.lexeme;
return new FastaMessage(uri, charOffset, codeUnmatchedToken,
message: "Can't find '$string' to match '$lexeme'.",
arguments: {'string': string, 'token': token});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_InvalidSyncModifier> codeInvalidSyncModifier =
const FastaCode<_InvalidSyncModifier>(
template: r"Invalid modifier 'sync'.",
tip: r"Try replacing 'sync' with 'sync*'.",
dart2jsCode: "INVALID_SYNC_MODIFIER",
format: _formatInvalidSyncModifier);
typedef FastaMessage _InvalidSyncModifier(Uri uri, int charOffset);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatInvalidSyncModifier(Uri uri, int charOffset) {
return new FastaMessage(uri, charOffset, codeInvalidSyncModifier,
message: "Invalid modifier 'sync'.",
tip: "Try replacing 'sync' with 'sync*'.",
arguments: {});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_ExpectedOpenParens> codeExpectedOpenParens =
const FastaCode<_ExpectedOpenParens>(
template: r"Expected '('.",
dart2jsCode: "GENERIC",
format: _formatExpectedOpenParens);
typedef FastaMessage _ExpectedOpenParens(Uri uri, int charOffset);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatExpectedOpenParens(Uri uri, int charOffset) {
return new FastaMessage(uri, charOffset, codeExpectedOpenParens,
message: "Expected '('.", arguments: {});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_UnterminatedComment> codeUnterminatedComment =
const FastaCode<_UnterminatedComment>(
template: r"Comment starting with '/*' must end with '*/'.",
analyzerCode: "UNTERMINATED_MULTI_LINE_COMMENT",
dart2jsCode: "UNTERMINATED_COMMENT",
format: _formatUnterminatedComment);
typedef FastaMessage _UnterminatedComment(Uri uri, int charOffset);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatUnterminatedComment(Uri uri, int charOffset) {
return new FastaMessage(uri, charOffset, codeUnterminatedComment,
message: "Comment starting with '/*' must end with '*/'.", arguments: {});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_ExpectedClassBody> codeExpectedClassBody =
const FastaCode<_ExpectedClassBody>(
template: r"Expected a class body, but got '#lexeme'.",
dart2jsCode: "FASTA_FATAL",
format: _formatExpectedClassBody);
typedef FastaMessage _ExpectedClassBody(Uri uri, int charOffset, Token token);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatExpectedClassBody(Uri uri, int charOffset, Token token) {
String lexeme = token.lexeme;
return new FastaMessage(uri, charOffset, codeExpectedClassBody,
message: "Expected a class body, but got '$lexeme'.",
arguments: {'token': token});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_ExpectedExpression> codeExpectedExpression =
const FastaCode<_ExpectedExpression>(
template: r"Expected an expression, but got '#lexeme'.",
dart2jsCode: "FASTA_FATAL",
format: _formatExpectedExpression);
typedef FastaMessage _ExpectedExpression(Uri uri, int charOffset, Token token);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatExpectedExpression(Uri uri, int charOffset, Token token) {
String lexeme = token.lexeme;
return new FastaMessage(uri, charOffset, codeExpectedExpression,
message: "Expected an expression, but got '$lexeme'.",
arguments: {'token': token});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_InvalidAwaitFor> codeInvalidAwaitFor = const FastaCode<
_InvalidAwaitFor>(
template:
r"'await' is only supported in methods with an 'async' or 'async*' body modifier.",
tip:
r"Try adding 'async' or 'async*' to the method body or removing the 'await' keyword.",
dart2jsCode: "INVALID_AWAIT_FOR",
format: _formatInvalidAwaitFor);
typedef FastaMessage _InvalidAwaitFor(Uri uri, int charOffset);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatInvalidAwaitFor(Uri uri, int charOffset) {
return new FastaMessage(uri, charOffset, codeInvalidAwaitFor,
message:
"'await' is only supported in methods with an 'async' or 'async*' body modifier.",
tip:
"Try adding 'async' or 'async*' to the method body or removing the 'await' keyword.",
arguments: {});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_ExpectedType> codeExpectedType =
const FastaCode<_ExpectedType>(
template: r"Expected a type, but got '#lexeme'.",
dart2jsCode: "FASTA_FATAL",
format: _formatExpectedType);
typedef FastaMessage _ExpectedType(Uri uri, int charOffset, Token token);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatExpectedType(Uri uri, int charOffset, Token token) {
String lexeme = token.lexeme;
return new FastaMessage(uri, charOffset, codeExpectedType,
message: "Expected a type, but got '$lexeme'.",
arguments: {'token': token});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_UnterminatedToken> codeUnterminatedToken =
const FastaCode<_UnterminatedToken>(
template: r"Incomplete token.",
dart2jsCode: "UNTERMINATED_TOKEN",
format: _formatUnterminatedToken);
typedef FastaMessage _UnterminatedToken(Uri uri, int charOffset);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatUnterminatedToken(Uri uri, int charOffset) {
return new FastaMessage(uri, charOffset, codeUnterminatedToken,
message: "Incomplete token.", arguments: {});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_ExpectedButGot> codeExpectedButGot =
const FastaCode<_ExpectedButGot>(
template: r"Expected '#string' before this.",
tip: r"DONT_KNOW_HOW_TO_FIX,",
dart2jsCode: "MISSING_TOKEN_BEFORE_THIS",
format: _formatExpectedButGot);
typedef FastaMessage _ExpectedButGot(Uri uri, int charOffset, String string);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatExpectedButGot(Uri uri, int charOffset, String string) {
return new FastaMessage(uri, charOffset, codeExpectedButGot,
message: "Expected '$string' before this.",
tip: "DONT_KNOW_HOW_TO_FIX,",
arguments: {'string': string});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_AwaitForNotAsync> codeAwaitForNotAsync = const FastaCode<
_AwaitForNotAsync>(
template:
r"Asynchronous for-loop can only be used in 'async' or 'async*' methods.",
dart2jsCode: "FASTA_IGNORED",
format: _formatAwaitForNotAsync);
typedef FastaMessage _AwaitForNotAsync(Uri uri, int charOffset);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatAwaitForNotAsync(Uri uri, int charOffset) {
return new FastaMessage(uri, charOffset, codeAwaitForNotAsync,
message:
"Asynchronous for-loop can only be used in 'async' or 'async*' methods.",
arguments: {});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_Encoding> codeEncoding = const FastaCode<_Encoding>(
template: r"Unable to decode bytes as UTF-8.",
dart2jsCode: "FASTA_FATAL",
format: _formatEncoding);
typedef FastaMessage _Encoding(Uri uri, int charOffset);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatEncoding(Uri uri, int charOffset) {
return new FastaMessage(uri, charOffset, codeEncoding,
message: "Unable to decode bytes as UTF-8.", arguments: {});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_AsyncAsIdentifier> codeAsyncAsIdentifier = const FastaCode<
_AsyncAsIdentifier>(
template:
r"'async' can't be used as an identifier in 'async', 'async*', or 'sync*' methods.",
analyzerCode: "ASYNC_KEYWORD_USED_AS_IDENTIFIER",
dart2jsCode: "GENERIC",
format: _formatAsyncAsIdentifier);
typedef FastaMessage _AsyncAsIdentifier(Uri uri, int charOffset);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatAsyncAsIdentifier(Uri uri, int charOffset) {
return new FastaMessage(uri, charOffset, codeAsyncAsIdentifier,
message:
"'async' can't be used as an identifier in 'async', 'async*', or 'sync*' methods.",
arguments: {});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_YieldAsIdentifier> codeYieldAsIdentifier = const FastaCode<
_YieldAsIdentifier>(
template:
r"'yield' can't be used as an identifier in 'async', 'async*', or 'sync*' methods.",
dart2jsCode: "FASTA_IGNORED",
format: _formatYieldAsIdentifier);
typedef FastaMessage _YieldAsIdentifier(Uri uri, int charOffset);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatYieldAsIdentifier(Uri uri, int charOffset) {
return new FastaMessage(uri, charOffset, codeYieldAsIdentifier,
message:
"'yield' can't be used as an identifier in 'async', 'async*', or 'sync*' methods.",
arguments: {});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_OnlyTry> codeOnlyTry = const FastaCode<_OnlyTry>(
template:
r"Try block should be followed by 'on', 'catch', or 'finally' block.",
tip: r"Did you forget to add a 'finally' block?",
dart2jsCode: "FASTA_IGNORED",
format: _formatOnlyTry);
typedef FastaMessage _OnlyTry(Uri uri, int charOffset);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatOnlyTry(Uri uri, int charOffset) {
return new FastaMessage(uri, charOffset, codeOnlyTry,
message:
"Try block should be followed by 'on', 'catch', or 'finally' block.",
tip: "Did you forget to add a 'finally' block?",
arguments: {});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<
_InvalidInlineFunctionType> codeInvalidInlineFunctionType = const FastaCode<
_InvalidInlineFunctionType>(
template: r"Invalid inline function type.",
tip:
r"Try changing the inline function type (as in 'int f()') to a prefixed function type using the `Function` keyword (as in 'int Function() f').",
dart2jsCode: "INVALID_INLINE_FUNCTION_TYPE",
format: _formatInvalidInlineFunctionType);
typedef FastaMessage _InvalidInlineFunctionType(Uri uri, int charOffset);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatInvalidInlineFunctionType(Uri uri, int charOffset) {
return new FastaMessage(uri, charOffset, codeInvalidInlineFunctionType,
message: "Invalid inline function type.",
tip:
"Try changing the inline function type (as in 'int f()') to a prefixed function type using the `Function` keyword (as in 'int Function() f').",
arguments: {});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_ExpectedBody> codeExpectedBody =
const FastaCode<_ExpectedBody>(
template: r"Expected a function body or '=>'.",
tip: r"Try adding {}.",
dart2jsCode: "BODY_EXPECTED",
format: _formatExpectedBody);
typedef FastaMessage _ExpectedBody(Uri uri, int charOffset);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatExpectedBody(Uri uri, int charOffset) {
return new FastaMessage(uri, charOffset, codeExpectedBody,
message: "Expected a function body or '=>'.",
tip: "Try adding {}.",
arguments: {});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_InvalidVoid> codeInvalidVoid = const FastaCode<_InvalidVoid>(
template: r"Type 'void' can't be used here because it isn't a return type.",
tip:
r"Try removing 'void' keyword or replace it with 'var', 'final', or a type.",
dart2jsCode: "VOID_NOT_ALLOWED",
format: _formatInvalidVoid);
typedef FastaMessage _InvalidVoid(Uri uri, int charOffset);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatInvalidVoid(Uri uri, int charOffset) {
return new FastaMessage(uri, charOffset, codeInvalidVoid,
message: "Type 'void' can't be used here because it isn't a return type.",
tip:
"Try removing 'void' keyword or replace it with 'var', 'final', or a type.",
arguments: {});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_BuiltInIdentifierAsType> codeBuiltInIdentifierAsType =
const FastaCode<_BuiltInIdentifierAsType>(
template: r"Can't use '#lexeme' as a type.",
dart2jsCode: "GENERIC",
format: _formatBuiltInIdentifierAsType);
typedef FastaMessage _BuiltInIdentifierAsType(
Uri uri, int charOffset, Token token);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatBuiltInIdentifierAsType(
Uri uri, int charOffset, Token token) {
String lexeme = token.lexeme;
return new FastaMessage(uri, charOffset, codeBuiltInIdentifierAsType,
message: "Can't use '$lexeme' as a type.", arguments: {'token': token});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_GeneratorReturnsValue> codeGeneratorReturnsValue =
const FastaCode<_GeneratorReturnsValue>(
template: r"'sync*' and 'async*' can't return a value.",
dart2jsCode: "FASTA_IGNORED",
format: _formatGeneratorReturnsValue);
typedef FastaMessage _GeneratorReturnsValue(Uri uri, int charOffset);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatGeneratorReturnsValue(Uri uri, int charOffset) {
return new FastaMessage(uri, charOffset, codeGeneratorReturnsValue,
message: "'sync*' and 'async*' can't return a value.", arguments: {});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_BuiltInIdentifierInDeclaration>
codeBuiltInIdentifierInDeclaration =
const FastaCode<_BuiltInIdentifierInDeclaration>(
template: r"Can't use '#lexeme' as a name here.",
dart2jsCode: "GENERIC",
format: _formatBuiltInIdentifierInDeclaration);
typedef FastaMessage _BuiltInIdentifierInDeclaration(
Uri uri, int charOffset, Token token);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatBuiltInIdentifierInDeclaration(
Uri uri, int charOffset, Token token) {
String lexeme = token.lexeme;
return new FastaMessage(uri, charOffset, codeBuiltInIdentifierInDeclaration,
message: "Can't use '$lexeme' as a name here.",
arguments: {'token': token});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_NonAsciiIdentifier> codeNonAsciiIdentifier = const FastaCode<
_NonAsciiIdentifier>(
template:
r"The non-ASCII character '#character' (#unicode) can't be used in identifiers, only in strings and comments.",
tip:
r"Try using an US-ASCII letter, a digit, '_' (an underscore), or '$' (a dollar sign).",
analyzerCode: "ILLEGAL_CHARACTER",
dart2jsCode: "BAD_INPUT_CHARACTER",
format: _formatNonAsciiIdentifier);
typedef FastaMessage _NonAsciiIdentifier(
Uri uri, int charOffset, String character, int codePoint);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatNonAsciiIdentifier(
Uri uri, int charOffset, String character, int codePoint) {
String unicode = "(U+${codePoint.toRadixString(16).padLeft(4, '0')})";
return new FastaMessage(uri, charOffset, codeNonAsciiIdentifier,
message:
"The non-ASCII character '$character' ($unicode) can't be used in identifiers, only in strings and comments.",
tip: "Try using an US-ASCII letter, a digit, '_' (an underscore), or '\$' (a dollar sign).",
arguments: {'character': character, 'codePoint': codePoint});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_ExtraneousModifierReplace> codeExtraneousModifierReplace =
const FastaCode<_ExtraneousModifierReplace>(
template: r"Can't have modifier '#lexeme' here.",
tip:
r"Try replacing modifier '#lexeme' with 'var', 'final', or a type.",
dart2jsCode: "EXTRANEOUS_MODIFIER_REPLACE",
format: _formatExtraneousModifierReplace);
typedef FastaMessage _ExtraneousModifierReplace(
Uri uri, int charOffset, Token token);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _formatExtraneousModifierReplace(
Uri uri, int charOffset, Token token) {
String lexeme = token.lexeme;
return new FastaMessage(uri, charOffset, codeExtraneousModifierReplace,
message: "Can't have modifier '$lexeme' here.",
tip: "Try replacing modifier '$lexeme' with 'var', 'final', or a type.",
arguments: {'token': token});
}

View file

@ -4,9 +4,10 @@
library fasta.body_builder;
import '../parser/parser.dart' show FormalParameterType, optional;
import '../fasta_codes.dart'
show FastaMessage, codeExpectedButGot, codeExpectedFunctionBody;
import '../parser/error_kind.dart' show ErrorKind;
import '../parser/parser.dart' show FormalParameterType, optional;
import '../parser/identifier_context.dart' show IdentifierContext;
@ -2343,29 +2344,26 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
}
@override
void handleRecoverableError(Token token, ErrorKind kind, Map arguments) {
void handleRecoverableError(Token token, FastaMessage message) {
bool silent = hasParserError;
super.handleRecoverableError(token, kind, arguments);
addCompileTimeError(recoverableErrors.last.beginOffset,
'${recoverableErrors.last.kind} $arguments',
silent: silent);
super.handleRecoverableError(token, message);
addCompileTimeError(message.charOffset, message.message, silent: silent);
}
@override
Token handleUnrecoverableError(Token token, ErrorKind kind, Map arguments) {
if (isDartLibrary && kind == ErrorKind.ExpectedFunctionBody) {
Token handleUnrecoverableError(Token token, FastaMessage message) {
if (isDartLibrary && message.code == codeExpectedFunctionBody) {
Token recover = skipNativeClause(token);
if (recover != null) return recover;
} else if (kind == ErrorKind.UnexpectedToken) {
String expected = arguments["expected"];
} else if (message.code == codeExpectedButGot) {
String expected = message.arguments["string"];
const List<String> trailing = const <String>[")", "}", ";", ","];
if (trailing.contains(token.stringValue) && trailing.contains(expected)) {
arguments.putIfAbsent("actual", () => token.lexeme);
handleRecoverableError(token, ErrorKind.ExpectedButGot, arguments);
handleRecoverableError(token, message);
return newSyntheticToken(token);
}
}
return super.handleUnrecoverableError(token, kind, arguments);
return super.handleUnrecoverableError(token, message);
}
@override

View file

@ -16,8 +16,6 @@ export 'parser/parser.dart' show Parser, optional;
export 'parser/listener.dart' show Listener, ParserError;
export 'parser/error_kind.dart' show ErrorKind;
export 'parser/top_level_parser.dart' show TopLevelParser;
export 'parser/class_member_parser.dart' show ClassMemberParser;

View file

@ -1,63 +0,0 @@
// Copyright (c) 2016, 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.
library fasta.parser.error_kind;
/// Kinds of error codes.
enum ErrorKind {
AbstractNotSync,
AsciiControlCharacter,
AsyncAsIdentifier,
AwaitAsIdentifier,
AwaitForNotAsync,
AwaitNotAsync,
BuiltInIdentifierAsType,
BuiltInIdentifierInDeclaration,
EmptyNamedParameterList,
EmptyOptionalParameterList,
Encoding,
ExpectedBlockToSkip,
ExpectedBody,
ExpectedButGot,
ExpectedClassBody,
/// This error code can be used to support non-compliant (with respect to
/// Dart Language Specification) Dart VM native clauses. See
/// [dart_vm_native.dart].
ExpectedClassBodyToSkip,
ExpectedDeclaration,
ExpectedExpression,
ExpectedFunctionBody,
ExpectedHexDigit,
ExpectedIdentifier,
ExpectedOpenParens,
ExpectedString,
ExpectedType,
ExtraneousModifier,
ExtraneousModifierReplace,
FactoryNotSync,
GeneratorReturnsValue,
InvalidAwaitFor,
InvalidInlineFunctionType,
InvalidSyncModifier,
InvalidVoid,
MissingExponent,
NonAsciiIdentifier,
NonAsciiWhitespace,
OnlyTry,
PositionalParameterWithEquals,
RequiredParameterWithDefault,
SetterNotSync,
StackOverflow,
UnexpectedDollarInString,
UnexpectedToken,
UnmatchedToken,
UnsupportedPrefixPlus,
UnterminatedComment,
UnterminatedString,
UnterminatedToken,
YieldAsIdentifier,
YieldNotGenerator,
Unspecified,
}

View file

@ -4,11 +4,12 @@
library fasta.parser.listener;
import '../fasta_codes.dart' show FastaMessage;
import '../scanner/token.dart' show BeginGroupToken, SymbolToken, Token;
import '../util/link.dart' show Link;
import 'error_kind.dart' show ErrorKind;
import 'package:front_end/src/fasta/scanner/precedence.dart' show RECOVERY_INFO;
import 'parser.dart' show FormalParameterType;
@ -28,6 +29,8 @@ import 'identifier_context.dart' show IdentifierContext;
class Listener {
final List<ParserError> recoverableErrors = <ParserError>[];
Uri get uri => null;
void logEvent(String name) {}
set suppressParseErrors(bool value) {}
@ -1006,14 +1009,13 @@ class Listener {
/// `null`. In the latter case, the parser simply skips to EOF which will
/// often result in additional parser errors as the parser returns from its
/// recursive state.
Token handleUnrecoverableError(Token token, ErrorKind kind, Map arguments) {
throw new ParserError.fromTokens(token, token, kind, arguments);
Token handleUnrecoverableError(Token token, FastaMessage message) {
throw new ParserError.fromTokens(token, token, message);
}
/// The parser noticed a syntax error, but was able to recover from it.
void handleRecoverableError(Token token, ErrorKind kind, Map arguments) {
recoverableErrors
.add(new ParserError.fromTokens(token, token, kind, arguments));
void handleRecoverableError(Token token, FastaMessage message) {
recoverableErrors.add(new ParserError.fromTokens(token, token, message));
}
void handleScript(Token token) {
@ -1036,14 +1038,12 @@ class ParserError {
/// Character offset from the beginning of file where this error ends.
final int endOffset;
final ErrorKind kind;
final FastaMessage message;
final Map arguments;
ParserError(this.beginOffset, this.endOffset, this.message);
ParserError(this.beginOffset, this.endOffset, this.kind, this.arguments);
ParserError.fromTokens(Token begin, Token end, FastaMessage message)
: this(begin.charOffset, end.charOffset + end.charCount, message);
ParserError.fromTokens(Token begin, Token end, ErrorKind kind, Map arguments)
: this(begin.charOffset, end.charOffset + end.charCount, kind, arguments);
String toString() => "@${beginOffset}: $kind $arguments";
String toString() => "@${beginOffset}: ${message.message}\n${message.tip}";
}

View file

@ -4,6 +4,56 @@
library fasta.parser.parser;
import '../fasta_codes.dart'
show
FastaCode,
FastaMessage,
codeAbstractNotSync,
codeAsciiControlCharacter,
codeAsyncAsIdentifier,
codeAwaitAsIdentifier,
codeAwaitForNotAsync,
codeAwaitNotAsync,
codeBuiltInIdentifierAsType,
codeBuiltInIdentifierInDeclaration,
codeEmptyNamedParameterList,
codeEmptyOptionalParameterList,
codeEncoding,
codeExpectedBlockToSkip,
codeExpectedBody,
codeExpectedButGot,
codeExpectedClassBody,
codeExpectedClassBodyToSkip,
codeExpectedDeclaration,
codeExpectedExpression,
codeExpectedFunctionBody,
codeExpectedIdentifier,
codeExpectedOpenParens,
codeExpectedString,
codeExpectedType,
codeExtraneousModifier,
codeExtraneousModifierReplace,
codeFactoryNotSync,
codeGeneratorReturnsValue,
codeInvalidAwaitFor,
codeInvalidInlineFunctionType,
codeInvalidSyncModifier,
codeInvalidVoid,
codeNonAsciiIdentifier,
codeNonAsciiWhitespace,
codeOnlyTry,
codePositionalParameterWithEquals,
codeRequiredParameterWithDefault,
codeSetterNotSync,
codeStackOverflow,
codeUnexpectedToken,
codeUnmatchedToken,
codeUnspecified,
codeUnsupportedPrefixPlus,
codeUnterminatedString,
codeYieldAsIdentifier,
codeYieldNotGenerator;
import '../scanner.dart' show ErrorToken;
import '../scanner/recover.dart' show closeBraceFor, skipToEof;
@ -70,8 +120,6 @@ import 'async_modifier.dart' show AsyncModifier;
import 'listener.dart' show Listener;
import 'error_kind.dart' show ErrorKind;
import 'identifier_context.dart' show IdentifierContext;
/// Returns true if [token] is the symbol or keyword [value].
@ -132,6 +180,8 @@ class FormalParameterType {
class Parser {
final Listener listener;
Uri get uri => listener.uri;
bool mayParseFunctionExpressions = true;
/// Represents parser state: what asynchronous syntax is allowed in the
@ -487,11 +537,12 @@ class Parser {
listener.beginOptionalFormalParameters(token);
if (!optional('(', token)) {
if (optional(';', token)) {
reportRecoverableError(token, ErrorKind.ExpectedOpenParens);
reportRecoverableErrorCode(token, codeExpectedOpenParens);
return token;
}
return reportUnrecoverableError(
token, ErrorKind.ExpectedButGot, {"expected": "("})?.next;
return reportUnrecoverableErrorCodeWithString(
token, codeExpectedButGot, "(")
.next;
}
BeginGroupToken beginGroupToken = token;
Token endToken = beginGroupToken.endGroup;
@ -525,7 +576,7 @@ class Parser {
break;
} else if (identical(value, '[]')) {
--parameterCount;
reportRecoverableError(token, ErrorKind.EmptyOptionalParameterList);
reportRecoverableErrorCode(token, codeEmptyOptionalParameterList);
token = token.next;
break;
}
@ -593,8 +644,8 @@ class Parser {
// The following isn't allowed:
// int Function(int bar(String x)).
if (inFunctionType) {
reportRecoverableError(
inlineFunctionTypeStart, ErrorKind.InvalidInlineFunctionType);
reportRecoverableErrorCode(
inlineFunctionTypeStart, codeInvalidInlineFunctionType);
}
} else if (optional('<', token)) {
Token inlineFunctionTypeStart = token;
@ -607,8 +658,8 @@ class Parser {
// The following isn't allowed:
// int Function(int bar(String x)).
if (inFunctionType) {
reportRecoverableError(
inlineFunctionTypeStart, ErrorKind.InvalidInlineFunctionType);
reportRecoverableErrorCode(
inlineFunctionTypeStart, codeInvalidInlineFunctionType);
}
}
String value = token.stringValue;
@ -618,9 +669,9 @@ class Parser {
token = parseExpression(token.next);
listener.handleValuedFormalParameter(equal, token);
if (kind.isRequired) {
reportRecoverableError(equal, ErrorKind.RequiredParameterWithDefault);
reportRecoverableErrorCode(equal, codeRequiredParameterWithDefault);
} else if (kind.isPositional && identical(':', value)) {
reportRecoverableError(equal, ErrorKind.PositionalParameterWithEquals);
reportRecoverableErrorCode(equal, codePositionalParameterWithEquals);
}
} else {
listener.handleFormalParameterWithoutValue(token);
@ -648,11 +699,11 @@ class Parser {
++parameterCount;
} while (optional(',', token));
if (parameterCount == 0) {
reportRecoverableError(
reportRecoverableErrorCode(
token,
isNamed
? ErrorKind.EmptyNamedParameterList
: ErrorKind.EmptyOptionalParameterList);
? codeEmptyNamedParameterList
: codeEmptyOptionalParameterList);
}
listener.endOptionalFormalParameters(parameterCount, begin, token);
if (isNamed) {
@ -791,17 +842,12 @@ class Parser {
Token skipBlock(Token token) {
if (!optional('{', token)) {
return reportUnrecoverableError(token, ErrorKind.ExpectedBlockToSkip)
?.next;
return reportUnrecoverableErrorCode(token, codeExpectedBlockToSkip).next;
}
BeginGroupToken beginGroupToken = token;
Token endGroup = beginGroupToken.endGroup;
if (endGroup == null) {
return reportUnrecoverableError(beginGroupToken, ErrorKind.UnmatchedToken)
?.next;
} else if (!identical(endGroup.kind, $CLOSE_CURLY_BRACKET)) {
return reportUnrecoverableError(beginGroupToken, ErrorKind.UnmatchedToken)
?.next;
if (endGroup == null || !identical(endGroup.kind, $CLOSE_CURLY_BRACKET)) {
return reportUnmatchedToken(beginGroupToken).next;
}
return beginGroupToken.endGroup;
}
@ -910,7 +956,8 @@ class Parser {
Token parseStringPart(Token token) {
if (token.kind != STRING_TOKEN) {
token = reportUnrecoverableError(token, ErrorKind.ExpectedString)?.next;
token =
reportUnrecoverableErrorCodeWithToken(token, codeExpectedString).next;
}
listener.handleStringPart(token);
return token.next;
@ -919,21 +966,23 @@ class Parser {
Token parseIdentifier(Token token, IdentifierContext context) {
if (!token.isIdentifier()) {
token =
reportUnrecoverableError(token, ErrorKind.ExpectedIdentifier)?.next;
reportUnrecoverableErrorCodeWithToken(token, codeExpectedIdentifier)
.next;
} else if (token.isBuiltInIdentifier &&
!context.isBuiltInIdentifierAllowed) {
if (context.inDeclaration) {
reportRecoverableError(token, ErrorKind.BuiltInIdentifierInDeclaration);
reportRecoverableErrorCodeWithToken(
token, codeBuiltInIdentifierInDeclaration);
} else if (!optional("dynamic", token)) {
reportRecoverableError(token, ErrorKind.BuiltInIdentifierAsType);
reportRecoverableErrorCodeWithToken(token, codeBuiltInIdentifierAsType);
}
} else if (!inPlainSync && token.isPseudo) {
if (optional('await', token)) {
reportRecoverableError(token, ErrorKind.AwaitAsIdentifier);
reportRecoverableErrorCode(token, codeAwaitAsIdentifier);
} else if (optional('yield', token)) {
reportRecoverableError(token, ErrorKind.YieldAsIdentifier);
reportRecoverableErrorCode(token, codeYieldAsIdentifier);
} else if (optional('async', token)) {
reportRecoverableError(token, ErrorKind.AsyncAsIdentifier);
reportRecoverableErrorCode(token, codeAsyncAsIdentifier);
}
}
listener.handleIdentifier(token, context);
@ -942,8 +991,9 @@ class Parser {
Token expect(String string, Token token) {
if (!identical(string, token.stringValue)) {
return reportUnrecoverableError(
token, ErrorKind.ExpectedButGot, {"expected": string})?.next;
return reportUnrecoverableErrorCodeWithString(
token, codeExpectedButGot, string)
.next;
}
return token.next;
}
@ -1010,7 +1060,8 @@ class Parser {
token = parseQualifiedRestOpt(
token, IdentifierContext.typeReferenceContinuation);
} else {
token = reportUnrecoverableError(token, ErrorKind.ExpectedType)?.next;
token =
reportUnrecoverableErrorCodeWithToken(token, codeExpectedType).next;
listener.handleInvalidTypeReference(token);
}
token = parseTypeArgumentsOpt(token);
@ -1086,15 +1137,17 @@ class Parser {
Link<Token> identifiers = findMemberName(token);
if (identifiers.isEmpty) {
return reportUnrecoverableError(start, ErrorKind.ExpectedDeclaration)
?.next;
return reportUnrecoverableErrorCodeWithToken(
start, codeExpectedDeclaration)
.next;
}
Token afterName = identifiers.head;
identifiers = identifiers.tail;
if (identifiers.isEmpty) {
return reportUnrecoverableError(start, ErrorKind.ExpectedDeclaration)
?.next;
return reportUnrecoverableErrorCodeWithToken(
start, codeExpectedDeclaration)
.next;
}
Token name = identifiers.head;
identifiers = identifiers.tail;
@ -1139,8 +1192,7 @@ class Parser {
}
break;
} else {
token =
reportUnrecoverableError(token, ErrorKind.UnexpectedToken)?.next;
token = reportUnexpectedToken(token).next;
if (identical(token.kind, EOF_TOKEN)) return token;
}
}
@ -1207,11 +1259,12 @@ class Parser {
modifierList.remove(varFinalOrConst);
}
listener.handleModifiers(modifierCount);
var kind = hasTypeOrModifier
? ErrorKind.ExtraneousModifier
: ErrorKind.ExtraneousModifierReplace;
for (Token modifier in modifierList) {
reportRecoverableError(modifier, kind, {'modifier': modifier});
reportRecoverableErrorCodeWithToken(
modifier,
hasTypeOrModifier
? codeExtraneousModifier
: codeExtraneousModifierReplace);
}
return null;
}
@ -1256,10 +1309,11 @@ class Parser {
}
if (getOrSet != null) {
var kind = (hasModifier || hasType)
? ErrorKind.ExtraneousModifier
: ErrorKind.ExtraneousModifierReplace;
reportRecoverableError(getOrSet, kind, {'modifier': getOrSet});
reportRecoverableErrorCodeWithToken(
getOrSet,
hasModifier || hasType
? codeExtraneousModifier
: codeExtraneousModifierReplace);
}
if (!hasType) {
@ -1270,12 +1324,12 @@ class Parser {
// TODO(ahe): This error is reported twice, second time is from
// [parseVariablesDeclarationMaybeSemicolon] via
// [PartialFieldListElement.parseNode].
reportRecoverableError(type, ErrorKind.InvalidVoid);
reportRecoverableErrorCode(type, codeInvalidVoid);
} else {
parseType(type);
if (isVar) {
reportRecoverableError(modifiers.head, ErrorKind.ExtraneousModifier,
{'modifier': modifiers.head});
reportRecoverableErrorCodeWithToken(
modifiers.head, codeExtraneousModifier);
}
}
@ -1311,8 +1365,7 @@ class Parser {
if (externalModifier == null && optional('external', modifier)) {
externalModifier = modifier;
} else {
reportRecoverableError(
modifier, ErrorKind.ExtraneousModifier, {'modifier': modifier});
reportRecoverableErrorCodeWithToken(modifier, codeExtraneousModifier);
}
}
if (externalModifier != null) {
@ -1340,7 +1393,7 @@ class Parser {
Token asyncToken = token;
token = parseAsyncModifier(token);
if (getOrSet != null && !inPlainSync && optional("set", getOrSet)) {
reportRecoverableError(asyncToken, ErrorKind.SetterNotSync);
reportRecoverableErrorCode(asyncToken, codeSetterNotSync);
}
token = parseFunctionBody(token, false, externalModifier != null);
asyncState = savedAsyncModifier;
@ -1434,7 +1487,7 @@ class Parser {
if (token.next is BeginGroupToken) {
BeginGroupToken beginGroup = token.next;
if (beginGroup.endGroup == null) {
reportUnrecoverableError(beginGroup, ErrorKind.UnmatchedToken);
token = reportUnmatchedToken(beginGroup).next;
} else {
token = beginGroup.endGroup;
}
@ -1449,7 +1502,7 @@ class Parser {
if (token is BeginGroupToken) {
BeginGroupToken beginGroup = token;
if (beginGroup.endGroup == null) {
reportUnrecoverableError(beginGroup, ErrorKind.UnmatchedToken);
token = reportUnmatchedToken(beginGroup).next;
} else {
token = beginGroup.endGroup.next;
}
@ -1457,14 +1510,14 @@ class Parser {
}
if (!optional('(', token)) {
if (optional(';', token)) {
reportRecoverableError(token, ErrorKind.ExpectedOpenParens);
reportRecoverableErrorCode(token, codeExpectedOpenParens);
}
token = expect("(", token);
}
if (token is BeginGroupToken) {
BeginGroupToken beginGroup = token;
if (beginGroup.endGroup == null) {
reportUnrecoverableError(beginGroup, ErrorKind.UnmatchedToken);
token = reportUnmatchedToken(beginGroup).next;
} else {
token = beginGroup.endGroup.next;
}
@ -1530,7 +1583,7 @@ class Parser {
if (identical(token.kind, STRING_TOKEN)) {
return parseLiteralString(token);
} else {
reportRecoverableError(token, ErrorKind.ExpectedString);
reportRecoverableErrorCodeWithToken(token, codeExpectedString);
return parseRecoverExpression(token);
}
}
@ -1562,7 +1615,7 @@ class Parser {
if (isModifier(token)) {
parseModifier(token);
} else {
reportUnrecoverableError(token, ErrorKind.UnexpectedToken);
reportUnexpectedToken(token);
// Skip the remaining modifiers.
break;
}
@ -1576,7 +1629,7 @@ class Parser {
// change. For example, this is parsed as a local variable declaration:
// `abstract foo;`. Ideally, this example should be handled as a local
// variable having the type `abstract` (which should be reported as
// `ErrorKind.BuiltInIdentifierAsType` by [parseIdentifier]).
// `codeBuiltInIdentifierAsType` by [parseIdentifier]).
int count = 0;
while (identical(token.kind, KEYWORD_TOKEN)) {
if (!isModifier(token)) break;
@ -1686,17 +1739,14 @@ class Parser {
Token skipClassBody(Token token) {
if (!optional('{', token)) {
return reportUnrecoverableError(token, ErrorKind.ExpectedClassBodyToSkip)
?.next;
return reportUnrecoverableErrorCodeWithToken(
token, codeExpectedClassBodyToSkip)
.next;
}
BeginGroupToken beginGroupToken = token;
Token endGroup = beginGroupToken.endGroup;
if (endGroup == null) {
return reportUnrecoverableError(beginGroupToken, ErrorKind.UnmatchedToken)
?.next;
} else if (!identical(endGroup.kind, $CLOSE_CURLY_BRACKET)) {
return reportUnrecoverableError(beginGroupToken, ErrorKind.UnmatchedToken)
?.next;
if (endGroup == null || !identical(endGroup.kind, $CLOSE_CURLY_BRACKET)) {
return reportUnmatchedToken(beginGroupToken).next;
}
return endGroup;
}
@ -1706,7 +1756,8 @@ class Parser {
listener.beginClassBody(token);
if (!optional('{', token)) {
token =
reportUnrecoverableError(token, ErrorKind.ExpectedClassBody)?.next;
reportUnrecoverableErrorCodeWithToken(token, codeExpectedClassBody)
.next;
}
token = token.next;
int count = 0;
@ -1743,15 +1794,17 @@ class Parser {
Link<Token> identifiers = findMemberName(token);
if (identifiers.isEmpty) {
return reportUnrecoverableError(start, ErrorKind.ExpectedDeclaration)
?.next;
return reportUnrecoverableErrorCodeWithToken(
start, codeExpectedDeclaration)
.next;
}
Token afterName = identifiers.head;
identifiers = identifiers.tail;
if (identifiers.isEmpty) {
return reportUnrecoverableError(start, ErrorKind.ExpectedDeclaration)
?.next;
return reportUnrecoverableErrorCodeWithToken(
start, codeExpectedDeclaration)
.next;
}
Token name = identifiers.head;
identifiers = identifiers.tail;
@ -1803,8 +1856,7 @@ class Parser {
isField = true;
break;
} else {
token =
reportUnrecoverableError(token, ErrorKind.UnexpectedToken)?.next;
token = reportUnexpectedToken(token).next;
if (identical(token.kind, EOF_TOKEN)) {
// TODO(ahe): This is a hack, see parseTopLevelMember.
listener.endFields(1, null, start, token);
@ -1837,32 +1889,28 @@ class Parser {
modifierCount++;
externalModifier = modifier;
if (modifierCount != allowedModifierCount) {
reportRecoverableError(
modifier, ErrorKind.ExtraneousModifier, {'modifier': modifier});
reportRecoverableErrorCodeWithToken(modifier, codeExtraneousModifier);
}
allowedModifierCount++;
} else if (staticModifier == null && optional('static', modifier)) {
modifierCount++;
staticModifier = modifier;
if (modifierCount != allowedModifierCount) {
reportRecoverableError(
modifier, ErrorKind.ExtraneousModifier, {'modifier': modifier});
reportRecoverableErrorCodeWithToken(modifier, codeExtraneousModifier);
}
} else if (constModifier == null && optional('const', modifier)) {
modifierCount++;
constModifier = modifier;
if (modifierCount != allowedModifierCount) {
reportRecoverableError(
modifier, ErrorKind.ExtraneousModifier, {'modifier': modifier});
reportRecoverableErrorCodeWithToken(modifier, codeExtraneousModifier);
}
} else {
reportRecoverableError(
modifier, ErrorKind.ExtraneousModifier, {'modifier': modifier});
reportRecoverableErrorCodeWithToken(modifier, codeExtraneousModifier);
}
}
if (getOrSet != null && constModifier != null) {
reportRecoverableError(constModifier, ErrorKind.ExtraneousModifier,
{'modifier': constModifier});
reportRecoverableErrorCodeWithToken(
constModifier, codeExtraneousModifier);
}
parseModifierList(modifiers);
@ -1875,8 +1923,8 @@ class Parser {
if (optional('operator', name)) {
token = parseOperatorName(name);
if (staticModifier != null) {
reportRecoverableError(staticModifier, ErrorKind.ExtraneousModifier,
{'modifier': staticModifier});
reportRecoverableErrorCodeWithToken(
staticModifier, codeExtraneousModifier);
}
} else {
token = parseIdentifier(name, IdentifierContext.methodDeclaration);
@ -1895,7 +1943,7 @@ class Parser {
Token asyncToken = token;
token = parseAsyncModifier(token);
if (getOrSet != null && !inPlainSync && optional("set", getOrSet)) {
reportRecoverableError(asyncToken, ErrorKind.SetterNotSync);
reportRecoverableErrorCode(asyncToken, codeSetterNotSync);
}
if (optional('=', token)) {
token = parseRedirectingFactoryBody(token);
@ -1929,7 +1977,7 @@ class Parser {
Token asyncToken = token;
token = parseAsyncModifier(token);
if (!inPlainSync) {
reportRecoverableError(asyncToken, ErrorKind.FactoryNotSync);
reportRecoverableErrorCode(asyncToken, codeFactoryNotSync);
}
if (optional('=', token)) {
token = parseRedirectingFactoryBody(token);
@ -2081,7 +2129,7 @@ class Parser {
String value = token.stringValue;
if (identical(value, ';')) {
if (!allowAbstract) {
reportRecoverableError(token, ErrorKind.ExpectedBody);
reportRecoverableErrorCode(token, codeExpectedBody);
}
listener.handleNoFunctionBody(token);
} else {
@ -2090,7 +2138,7 @@ class Parser {
expectSemicolon(token);
listener.handleFunctionBodySkipped(token, true);
} else if (identical(value, '=')) {
reportRecoverableError(token, ErrorKind.ExpectedBody);
reportRecoverableErrorCode(token, codeExpectedBody);
token = parseExpression(token.next);
expectSemicolon(token);
listener.handleFunctionBodySkipped(token, true);
@ -2105,7 +2153,7 @@ class Parser {
Token parseFunctionBody(Token token, bool isExpression, bool allowAbstract) {
if (optional(';', token)) {
if (!allowAbstract) {
reportRecoverableError(token, ErrorKind.ExpectedBody);
reportRecoverableErrorCode(token, codeExpectedBody);
}
listener.handleEmptyFunctionBody(token);
return token;
@ -2122,7 +2170,7 @@ class Parser {
} else if (optional('=', token)) {
Token begin = token;
// Recover from a bad factory method.
reportRecoverableError(token, ErrorKind.ExpectedBody);
reportRecoverableErrorCode(token, codeExpectedBody);
token = parseExpression(token.next);
if (!isExpression) {
expectSemicolon(token);
@ -2136,7 +2184,8 @@ class Parser {
int statementCount = 0;
if (!optional('{', token)) {
token =
reportUnrecoverableError(token, ErrorKind.ExpectedFunctionBody)?.next;
reportUnrecoverableErrorCodeWithToken(token, codeExpectedFunctionBody)
.next;
listener.handleInvalidFunctionBody(token);
return token;
}
@ -2194,14 +2243,14 @@ class Parser {
star = token;
token = token.next;
} else {
reportRecoverableError(async, ErrorKind.InvalidSyncModifier);
reportRecoverableErrorCode(async, codeInvalidSyncModifier);
}
}
listener.handleAsyncModifier(async, star);
if (inGenerator && optional('=>', token)) {
reportRecoverableError(token, ErrorKind.GeneratorReturnsValue);
reportRecoverableErrorCode(token, codeGeneratorReturnsValue);
} else if (!inPlainSync && optional(';', token)) {
reportRecoverableError(token, ErrorKind.AbstractNotSync);
reportRecoverableErrorCode(token, codeAbstractNotSync);
}
return token;
}
@ -2212,7 +2261,7 @@ class Parser {
// This happens for degenerate programs, for example, a lot of nested
// if-statements. The language test deep_nesting2_negative_test, for
// example, provokes this.
return reportUnrecoverableError(token, ErrorKind.StackOverflow)?.next;
return reportUnrecoverableErrorCode(token, codeStackOverflow).next;
}
Token result = parseStatementX(token);
statementDepth--;
@ -2233,7 +2282,7 @@ class Parser {
return parseIfStatement(token);
} else if (identical(value, 'await') && optional('for', token.next)) {
if (!inAsync) {
reportRecoverableError(token, ErrorKind.AwaitForNotAsync);
reportRecoverableErrorCode(token, codeAwaitForNotAsync);
}
return parseForStatement(token, token.next);
} else if (identical(value, 'for')) {
@ -2271,7 +2320,7 @@ class Parser {
return parseYieldStatement(token);
case AsyncModifier.Async:
reportRecoverableError(token, ErrorKind.YieldNotGenerator);
reportRecoverableErrorCode(token, codeYieldNotGenerator);
return parseYieldStatement(token);
}
throw "Internal error: Unknown asyncState: '$asyncState'.";
@ -2309,7 +2358,7 @@ class Parser {
} else {
token = parseExpression(token);
if (inGenerator) {
reportRecoverableError(begin.next, ErrorKind.GeneratorReturnsValue);
reportRecoverableErrorCode(begin.next, codeGeneratorReturnsValue);
}
listener.endReturnStatement(true, begin, token);
}
@ -2534,7 +2583,7 @@ class Parser {
BeginGroupToken begin = token;
token = (begin.endGroup != null) ? begin.endGroup : token;
} else if (token is ErrorToken) {
reportErrorToken(token, false)?.next;
reportErrorToken(token, false).next;
}
token = token.next;
}
@ -2549,7 +2598,7 @@ class Parser {
// This happens in degenerate programs, for example, with a lot of nested
// list literals. This is provoked by, for examaple, the language test
// deep_nesting1_negative_test.
return reportUnrecoverableError(token, ErrorKind.StackOverflow)?.next;
return reportUnrecoverableErrorCode(token, codeStackOverflow).next;
}
listener.beginExpression(token);
Token result = optional('throw', token)
@ -2617,8 +2666,7 @@ class Parser {
listener.handleUnaryPostfixAssignmentExpression(token);
token = token.next;
} else {
token = reportUnrecoverableError(token, ErrorKind.UnexpectedToken)
?.next;
token = reportUnexpectedToken(token).next;
}
} else if (identical(info, IS_INFO)) {
token = parseIsOperatorRest(token);
@ -2658,7 +2706,7 @@ class Parser {
token = parseSend(token, IdentifierContext.expressionContinuation);
listener.handleBinaryExpression(cascadeOperator);
} else {
return reportUnrecoverableError(token, ErrorKind.UnexpectedToken)?.next;
return reportUnexpectedToken(token).next;
}
Token mark;
do {
@ -2691,7 +2739,7 @@ class Parser {
}
} else if (identical(value, '+')) {
// Dart no longer allows prefix-plus.
reportRecoverableError(token, ErrorKind.UnsupportedPrefixPlus);
reportRecoverableErrorCode(token, codeUnsupportedPrefixPlus);
return parseUnaryExpression(token.next, allowCascades);
} else if ((identical(value, '!')) ||
(identical(value, '-')) ||
@ -2791,7 +2839,8 @@ class Parser {
}
Token expressionExpected(Token token) {
token = reportUnrecoverableError(token, ErrorKind.ExpectedExpression)?.next;
token = reportUnrecoverableErrorCodeWithToken(token, codeExpectedExpression)
.next;
listener.handleInvalidExpression(token);
return token;
}
@ -2826,7 +2875,7 @@ class Parser {
// [begin] is now known to have type [BeginGroupToken].
token = parseExpression(token);
if (!identical(begin.endGroup, token)) {
reportUnrecoverableError(token, ErrorKind.UnexpectedToken)?.next;
reportUnexpectedToken(token).next;
token = begin.endGroup;
}
listener.handleParenthesizedExpression(begin);
@ -2930,8 +2979,7 @@ class Parser {
}
// Fall through.
}
reportUnrecoverableError(token, ErrorKind.UnexpectedToken);
return null;
return reportUnexpectedToken(token).next;
}
/// genericListLiteral | genericMapLiteral | genericFunctionLiteral.
@ -2958,8 +3006,7 @@ class Parser {
} else if ((optional('[', token)) || (optional('[]', token))) {
return parseLiteralListSuffix(token, constKeyword);
}
reportUnrecoverableError(token, ErrorKind.UnexpectedToken);
return null;
return reportUnexpectedToken(token).next;
}
}
@ -3015,7 +3062,7 @@ class Parser {
token = parseArguments(token);
} else {
listener.handleNoArguments(token);
token = reportUnrecoverableError(token, ErrorKind.UnexpectedToken)?.next;
token = reportUnexpectedToken(token).next;
}
return token;
}
@ -3220,7 +3267,7 @@ class Parser {
if (identical(value, 'is') || identical(value, 'as')) {
// The is- and as-operators cannot be chained, but they can take part of
// expressions like: foo is Foo || foo is Bar.
reportUnrecoverableError(token, ErrorKind.UnexpectedToken);
reportUnexpectedToken(token);
}
return token;
}
@ -3233,7 +3280,7 @@ class Parser {
String value = token.stringValue;
if (identical(value, 'is') || identical(value, 'as')) {
// The is- and as-operators cannot be chained.
reportUnrecoverableError(token, ErrorKind.UnexpectedToken);
reportUnexpectedToken(token);
}
return token;
}
@ -3308,7 +3355,7 @@ class Parser {
return parseForInRest(awaitToken, forKeyword, leftParenthesis, token);
} else {
if (awaitToken != null) {
reportRecoverableError(awaitToken, ErrorKind.InvalidAwaitFor);
reportRecoverableErrorCode(awaitToken, codeInvalidAwaitFor);
}
return parseForRest(forKeyword, leftParenthesis, token);
}
@ -3421,7 +3468,7 @@ class Parser {
listener.beginAwaitExpression(awaitToken);
token = expect('await', token);
if (!inAsync) {
reportRecoverableError(awaitToken, ErrorKind.AwaitNotAsync);
reportRecoverableErrorCode(awaitToken, codeAwaitNotAsync);
}
token = parsePrecedenceExpression(token, POSTFIX_PRECEDENCE, allowCascades);
listener.endAwaitExpression(awaitToken, token);
@ -3489,7 +3536,7 @@ class Parser {
listener.handleFinallyBlock(finallyKeyword);
} else {
if (catchCount == 0) {
reportRecoverableError(tryKeyword, ErrorKind.OnlyTry);
reportRecoverableErrorCode(tryKeyword, codeOnlyTry);
}
}
listener.endTryStatement(catchCount, tryKeyword, finallyKeyword);
@ -3568,8 +3615,8 @@ class Parser {
} else {
if (expressionCount == 0) {
// TODO(ahe): This is probably easy to recover from.
reportUnrecoverableError(
token, ErrorKind.ExpectedButGot, {"expected": "case"});
reportUnrecoverableErrorCodeWithString(
token, codeExpectedButGot, "case");
}
break;
}
@ -3650,65 +3697,102 @@ class Parser {
/// Don't call this method. Should only be used as a last resort when there
/// is no feasible way to recover from a parser error.
Token reportUnrecoverableError(Token token, ErrorKind kind, [Map arguments]) {
Token reportUnrecoverableError(Token token, FastaMessage format()) {
Token next;
if (token is ErrorToken) {
next = reportErrorToken(token, false);
} else {
arguments ??= {};
arguments.putIfAbsent("actual", () => token.lexeme);
next = listener.handleUnrecoverableError(token, kind, arguments);
next = listener.handleUnrecoverableError(token, format());
}
return next ?? skipToEof(token);
}
void reportRecoverableError(Token token, ErrorKind kind, [Map arguments]) {
void reportRecoverableError(Token token, FastaMessage format()) {
if (token is ErrorToken) {
reportErrorToken(token, true);
} else {
arguments ??= {};
listener.handleRecoverableError(token, kind, arguments);
listener.handleRecoverableError(token, format());
}
}
Token reportErrorToken(ErrorToken token, bool isRecoverable) {
ErrorKind kind = token.errorCode;
Map arguments = const {};
switch (kind) {
case ErrorKind.AsciiControlCharacter:
case ErrorKind.NonAsciiIdentifier:
case ErrorKind.NonAsciiWhitespace:
case ErrorKind.Encoding:
String hex = token.character.toRadixString(16);
if (hex.length < 4) {
String padding = "0000".substring(hex.length);
hex = "$padding$hex";
}
arguments = {'characterHex': hex};
break;
case ErrorKind.UnterminatedString:
arguments = {'quote': token.start};
break;
case ErrorKind.UnmatchedToken:
String begin = token.begin.lexeme;
String end = closeBraceFor(begin);
arguments = {'begin': begin, 'end': end};
break;
case ErrorKind.Unspecified:
arguments = {"text": token.assertionMessage};
break;
default:
break;
FastaCode code = token.errorCode;
FastaMessage message;
if (code == codeAsciiControlCharacter) {
message = codeAsciiControlCharacter.format(
uri, token.charOffset, token.character);
} else if (code == codeNonAsciiWhitespace) {
message =
codeNonAsciiWhitespace.format(uri, token.charOffset, token.character);
} else if (code == codeEncoding) {
message = codeEncoding.format(uri, token.charOffset);
} else if (code == codeNonAsciiIdentifier) {
message = codeNonAsciiIdentifier.format(uri, token.charOffset,
new String.fromCharCodes([token.character]), token.character);
} else if (code == codeUnterminatedString) {
message =
codeUnterminatedString.format(uri, token.charOffset, token.start);
} else if (code == codeUnmatchedToken) {
Token begin = token.begin;
message = codeUnmatchedToken.format(
uri, token.charOffset, closeBraceFor(begin.lexeme), begin);
} else if (code == codeUnspecified) {
message =
codeUnspecified.format(uri, token.charOffset, token.assertionMessage);
} else {
message = code.format(uri, token.charOffset);
}
if (isRecoverable) {
listener.handleRecoverableError(token, kind, arguments);
listener.handleRecoverableError(token, message);
return null;
} else {
return listener.handleUnrecoverableError(token, kind, arguments);
Token next = listener.handleUnrecoverableError(token, message);
return next ?? skipToEof(token);
}
}
Token reportUnmatchedToken(BeginGroupToken token) {
return reportUnrecoverableError(
token,
() => codeUnmatchedToken.format(
uri, token.charOffset, closeBraceFor(token.lexeme), token));
}
Token reportUnexpectedToken(Token token) {
return reportUnrecoverableError(
token, () => codeUnexpectedToken.format(uri, token.charOffset, token));
}
void reportRecoverableErrorCode(Token token, FastaCode<NoArgument> code) {
reportRecoverableError(token, () => code.format(uri, token.charOffset));
}
Token reportUnrecoverableErrorCode(Token token, FastaCode<NoArgument> code) {
return reportUnrecoverableError(
token, () => code.format(uri, token.charOffset));
}
void reportRecoverableErrorCodeWithToken(
Token token, FastaCode<TokenArgument> code) {
reportRecoverableError(
token, () => code.format(uri, token.charOffset, token));
}
Token reportUnrecoverableErrorCodeWithToken(
Token token, FastaCode<TokenArgument> code) {
return reportUnrecoverableError(
token, () => code.format(uri, token.charOffset, token));
}
Token reportUnrecoverableErrorCodeWithString(
Token token, FastaCode<StringArgument> code, String string) {
return reportUnrecoverableError(
token, () => code.format(uri, token.charOffset, string));
}
}
typedef FastaMessage NoArgument(Uri uri, int charOffset);
typedef FastaMessage TokenArgument(Uri uri, int charOffset, Token token);
typedef FastaMessage StringArgument(Uri uri, int charOffset, String string);

View file

@ -1,592 +0,0 @@
// Copyright (c) 2017, 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.
// NOTE: THIS FILE IS GENERATED. DO NOT EDIT.
//
// Instead modify 'pkg/front_end/messages.yaml' and run
// 'pkg/front_end/tool/_fasta/generate_messages.dart' to update.
library fasta.problems;
import 'package:front_end/src/fasta/scanner/token.dart' show Token;
import 'package:front_end/src/fasta/parser/error_kind.dart' show ErrorKind;
problemExpectedClassBodyToSkip(Token token) {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
String lexeme = token.lexeme;
return {
'message': "Expected a class body, but got '$lexeme'.",
'code': ErrorKind.ExpectedClassBodyToSkip,
'arguments': {
'token': token,
},
};
}
problemStackOverflow() {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
return {
'message': "Stack overflow.",
'code': ErrorKind.StackOverflow,
'arguments': {},
};
}
problemUnexpectedToken(Token token) {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
String lexeme = token.lexeme;
return {
'message': "Unexpected token '$lexeme'.",
'code': ErrorKind.UnexpectedToken,
'arguments': {
'token': token,
},
};
}
problemAwaitAsIdentifier() {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
return {
'message':
"'await' can't be used as an identifier in 'async', 'async*', or 'sync*' methods.",
'code': ErrorKind.AwaitAsIdentifier,
'arguments': {},
};
}
problemFactoryNotSync() {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
return {
'message': "Factories can't use 'async', 'async*', or 'sync*'.",
'code': ErrorKind.FactoryNotSync,
'arguments': {},
};
}
problemYieldNotGenerator() {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
return {
'message': "'yield' can only be used in 'sync*' or 'async*' methods.",
'code': ErrorKind.YieldNotGenerator,
'arguments': {},
};
}
problemSetterNotSync() {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
return {
'message': "Setters can't use 'async', 'async*', or 'sync*'.",
'code': ErrorKind.SetterNotSync,
'arguments': {},
};
}
problemNonAsciiWhitespace(int codePoint) {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
String unicode = "(U+${codePoint.toRadixString(16).padLeft(4, '0')})";
return {
'message':
"The non-ASCII space character $unicode can only be used in strings and comments.",
'code': ErrorKind.NonAsciiWhitespace,
'arguments': {
'codePoint': codePoint,
},
};
}
problemExpectedIdentifier(Token token) {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
String lexeme = token.lexeme;
return {
'message': "'$lexeme' is a reserved word and can't be used here.",
'tip': "Try using a different name.",
'code': ErrorKind.ExpectedIdentifier,
'arguments': {
'token': token,
},
};
}
problemExpectedBlockToSkip() {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
return {
'message': "Expected a function body or '=>'.",
'tip': "Try adding {}.",
'code': ErrorKind.ExpectedBlockToSkip,
'arguments': {},
};
}
problemRequiredParameterWithDefault() {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
return {
'message': "Non-optional parameters can't have a default value.",
'tip': "Try removing the default value or making the parameter optional.",
'code': ErrorKind.RequiredParameterWithDefault,
'arguments': {},
};
}
problemUnspecified(String string) {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
return {
'message': "$string",
'code': ErrorKind.Unspecified,
'arguments': {
'string': string,
},
};
}
problemMissingExponent() {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
return {
'message':
"Numbers in exponential notation should always contain an exponent (an integer number with an optional sign).",
'tip':
"Make sure there is an exponent, and remove any whitespace before it.",
'code': ErrorKind.MissingExponent,
'arguments': {},
};
}
problemPositionalParameterWithEquals() {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
return {
'message':
"Positional optional parameters can't use ':' to specify a default value.",
'tip': "Try replacing ':' with '='.",
'code': ErrorKind.PositionalParameterWithEquals,
'arguments': {},
};
}
problemUnexpectedDollarInString() {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
return {
'message':
"A '\$' has special meaning inside a string, and must be followed by an identifier or an expression in curly braces ({}).",
'tip': "Try adding a backslash (\) to escape the '\$'.",
'code': ErrorKind.UnexpectedDollarInString,
'arguments': {},
};
}
problemExtraneousModifier(Token token) {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
String lexeme = token.lexeme;
return {
'message': "Can't have modifier '$lexeme' here.",
'tip': "Try removing '$lexeme'.",
'code': ErrorKind.ExtraneousModifier,
'arguments': {
'token': token,
},
};
}
problemEmptyOptionalParameterList() {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
return {
'message': "Optional parameter lists cannot be empty.",
'tip': "Try adding an optional parameter to the list.",
'code': ErrorKind.EmptyOptionalParameterList,
'arguments': {},
};
}
problemUnterminatedString(String string) {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
return {
'message': "String must end with $string.",
'code': ErrorKind.UnterminatedString,
'arguments': {
'string': string,
},
};
}
problemAwaitNotAsync() {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
return {
'message': "'await' can only be used in 'async' or 'async*' methods.",
'code': ErrorKind.AwaitNotAsync,
'arguments': {},
};
}
problemExpectedFunctionBody(Token token) {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
String lexeme = token.lexeme;
return {
'message': "Expected a function body, but got '$lexeme'.",
'code': ErrorKind.ExpectedFunctionBody,
'arguments': {
'token': token,
},
};
}
problemExpectedHexDigit() {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
return {
'message': "A hex digit (0-9 or A-F) must follow '0x'.",
'code': ErrorKind.ExpectedHexDigit,
'arguments': {},
};
}
problemEmptyNamedParameterList() {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
return {
'message': "Named parameter lists cannot be empty.",
'tip': "Try adding a named parameter to the list.",
'code': ErrorKind.EmptyNamedParameterList,
'arguments': {},
};
}
problemUnsupportedPrefixPlus() {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
return {
'message': "'+' is not a prefix operator. ",
'tip': "Try removing '+'.",
'code': ErrorKind.UnsupportedPrefixPlus,
'arguments': {},
};
}
problemExpectedString(Token token) {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
String lexeme = token.lexeme;
return {
'message': "Expected a String, but got '$lexeme'.",
'code': ErrorKind.ExpectedString,
'arguments': {
'token': token,
},
};
}
problemAbstractNotSync() {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
return {
'message': "Abstract methods can't use 'async', 'async*', or 'sync*'.",
'code': ErrorKind.AbstractNotSync,
'arguments': {},
};
}
problemExpectedDeclaration(Token token) {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
String lexeme = token.lexeme;
return {
'message': "Expected a declaration, but got '$lexeme'.",
'code': ErrorKind.ExpectedDeclaration,
'arguments': {
'token': token,
},
};
}
problemAsciiControlCharacter(int codePoint) {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
String unicode = "(U+${codePoint.toRadixString(16).padLeft(4, '0')})";
return {
'message':
"The control character $unicode can only be used in strings and comments.",
'code': ErrorKind.AsciiControlCharacter,
'arguments': {
'codePoint': codePoint,
},
};
}
problemUnmatchedToken(String string, Token token) {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
String lexeme = token.lexeme;
return {
'message': "Can't find '$string' to match '$lexeme'.",
'code': ErrorKind.UnmatchedToken,
'arguments': {
'string': string,
'token': token,
},
};
}
problemInvalidSyncModifier() {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
return {
'message': "Invalid modifier 'sync'.",
'tip': "Try replacing 'sync' with 'sync*'.",
'code': ErrorKind.InvalidSyncModifier,
'arguments': {},
};
}
problemExpectedOpenParens() {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
return {
'message': "Expected '('.",
'code': ErrorKind.ExpectedOpenParens,
'arguments': {},
};
}
problemUnterminatedComment() {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
return {
'message': "Comment starting with '/*' must end with '*/'.",
'code': ErrorKind.UnterminatedComment,
'arguments': {},
};
}
problemExpectedClassBody(Token token) {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
String lexeme = token.lexeme;
return {
'message': "Expected a class body, but got '$lexeme'.",
'code': ErrorKind.ExpectedClassBody,
'arguments': {
'token': token,
},
};
}
problemExpectedExpression(Token token) {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
String lexeme = token.lexeme;
return {
'message': "Expected an expression, but got '$lexeme'.",
'code': ErrorKind.ExpectedExpression,
'arguments': {
'token': token,
},
};
}
problemInvalidAwaitFor() {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
return {
'message':
"'await' is only supported in methods with an 'async' or 'async*' body modifier.",
'tip':
"Try adding 'async' or 'async*' to the method body or removing the 'await' keyword.",
'code': ErrorKind.InvalidAwaitFor,
'arguments': {},
};
}
problemExpectedType(Token token) {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
String lexeme = token.lexeme;
return {
'message': "Expected a type, but got '$lexeme'.",
'code': ErrorKind.ExpectedType,
'arguments': {
'token': token,
},
};
}
problemUnterminatedToken() {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
return {
'message': "Incomplete token.",
'code': ErrorKind.UnterminatedToken,
'arguments': {},
};
}
problemExpectedButGot(Token token) {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
String lexeme = token.lexeme;
return {
'message': "Expected '$lexeme' before this.",
'tip': "DONT_KNOW_HOW_TO_FIX,",
'code': ErrorKind.ExpectedButGot,
'arguments': {
'token': token,
},
};
}
problemAwaitForNotAsync() {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
return {
'message':
"Asynchronous for-loop can only be used in 'async' or 'async*' methods.",
'code': ErrorKind.AwaitForNotAsync,
'arguments': {},
};
}
problemEncoding() {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
return {
'message': "Unable to decode bytes as UTF-8.",
'code': ErrorKind.Encoding,
'arguments': {},
};
}
problemAsyncAsIdentifier() {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
return {
'message':
"'async' can't be used as an identifier in 'async', 'async*', or 'sync*' methods.",
'code': ErrorKind.AsyncAsIdentifier,
'arguments': {},
};
}
problemYieldAsIdentifier() {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
return {
'message':
"'yield' can't be used as an identifier in 'async', 'async*', or 'sync*' methods.",
'code': ErrorKind.YieldAsIdentifier,
'arguments': {},
};
}
problemOnlyTry() {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
return {
'message':
"Try block should be followed by 'on', 'catch', or 'finally' block.",
'tip': "Did you forget to add a 'finally' block?",
'code': ErrorKind.OnlyTry,
'arguments': {},
};
}
problemInvalidInlineFunctionType() {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
return {
'message': "Invalid inline function type.",
'tip':
"Try changing the inline function type (as in 'int f()') to a prefixed function type using the `Function` keyword (as in 'int Function() f').",
'code': ErrorKind.InvalidInlineFunctionType,
'arguments': {},
};
}
problemExpectedBody() {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
return {
'message': "Expected a function body or '=>'.",
'tip': "Try adding {}.",
'code': ErrorKind.ExpectedBody,
'arguments': {},
};
}
problemInvalidVoid() {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
return {
'message': "Type 'void' can't be used here because it isn't a return type.",
'tip':
"Try removing 'void' keyword or replace it with 'var', 'final', or a type.",
'code': ErrorKind.InvalidVoid,
'arguments': {},
};
}
problemBuiltInIdentifierAsType(Token token) {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
String lexeme = token.lexeme;
return {
'message': "Can't use '$lexeme' as a type.",
'code': ErrorKind.BuiltInIdentifierAsType,
'arguments': {
'token': token,
},
};
}
problemGeneratorReturnsValue() {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
return {
'message': "'sync*' and 'async*' can't return a value.",
'code': ErrorKind.GeneratorReturnsValue,
'arguments': {},
};
}
problemBuiltInIdentifierInDeclaration(Token token) {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
String lexeme = token.lexeme;
return {
'message': "Can't use '$lexeme' as a name here.",
'code': ErrorKind.BuiltInIdentifierInDeclaration,
'arguments': {
'token': token,
},
};
}
problemNonAsciiIdentifier(String character, int codePoint) {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
String unicode = "(U+${codePoint.toRadixString(16).padLeft(4, '0')})";
return {
'message':
"The non-ASCII character '$character' ($unicode) can't be used in identifiers, only in strings and comments.",
'tip':
"Try using an US-ASCII letter, a digit, '_' (an underscore), or '\$' (a dollar sign).",
'code': ErrorKind.NonAsciiIdentifier,
'arguments': {
'character': character,
'codePoint': codePoint,
},
};
}
problemExtraneousModifierReplace(Token token) {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
String lexeme = token.lexeme;
return {
'message': "Can't have modifier '$lexeme' here.",
'tip': "Try replacing modifier '$lexeme' with 'var', 'final', or a type.",
'code': ErrorKind.ExtraneousModifierReplace,
'arguments': {
'token': token,
},
};
}

View file

@ -4,17 +4,26 @@
library dart_scanner.error_token;
// TODO(ahe): ErrorKind doesn't belong in dart_parser. Move to compiler_util or
// this package?
import '../parser/error_kind.dart' show ErrorKind;
import '../fasta_codes.dart'
show
FastaCode,
codeAsciiControlCharacter,
codeEncoding,
codeExpectedHexDigit,
codeMissingExponent,
codeNonAsciiIdentifier,
codeNonAsciiWhitespace,
codeUnexpectedDollarInString,
codeUnmatchedToken,
codeUnterminatedComment,
codeUnterminatedString,
codeUnterminatedToken;
import '../scanner.dart'
show BeginGroupToken, Token, unicodeReplacementCharacter;
import 'precedence.dart' show BAD_INPUT_INFO, PrecedenceInfo;
export '../parser/error_kind.dart' show ErrorKind;
ErrorToken buildUnexpectedCharacterToken(int character, int charOffset) {
if (character < 0x1f) {
return new AsciiControlCharacterToken(character, charOffset);
@ -70,7 +79,7 @@ abstract class ErrorToken extends Token {
String get assertionMessage;
ErrorKind get errorCode;
FastaCode get errorCode;
int get character => null;
@ -94,7 +103,7 @@ class EncodingErrorToken extends ErrorToken {
String get assertionMessage => "Unable to decode bytes as UTF-8.";
ErrorKind get errorCode => ErrorKind.Encoding;
FastaCode get errorCode => codeEncoding;
}
/// Represents a non-ASCII character outside a string or comment.
@ -116,7 +125,7 @@ class NonAsciiIdentifierToken extends ErrorToken {
" or '\$' (a dollar sign).";
}
ErrorKind get errorCode => ErrorKind.NonAsciiIdentifier;
FastaCode get errorCode => codeNonAsciiIdentifier;
}
/// Represents a non-ASCII whitespace outside a string or comment.
@ -133,7 +142,7 @@ class NonAsciiWhitespaceToken extends ErrorToken {
"and comments.";
}
ErrorKind get errorCode => ErrorKind.NonAsciiWhitespace;
FastaCode get errorCode => codeNonAsciiWhitespace;
}
/// Represents an ASCII control character outside a string or comment.
@ -151,7 +160,7 @@ class AsciiControlCharacterToken extends ErrorToken {
"comments.";
}
ErrorKind get errorCode => ErrorKind.AsciiControlCharacter;
FastaCode get errorCode => codeAsciiControlCharacter;
}
/// Represents an unterminated string.
@ -168,10 +177,10 @@ class UnterminatedToken extends ErrorToken {
int get charCount => endOffset - charOffset;
ErrorKind get errorCode {
FastaCode get errorCode {
switch (start) {
case '1e':
return ErrorKind.MissingExponent;
return codeMissingExponent;
case '"':
case "'":
@ -181,19 +190,19 @@ class UnterminatedToken extends ErrorToken {
case "r'":
case 'r"""':
case "r'''":
return ErrorKind.UnterminatedString;
return codeUnterminatedString;
case '0x':
return ErrorKind.ExpectedHexDigit;
return codeExpectedHexDigit;
case r'$':
return ErrorKind.UnexpectedDollarInString;
return codeUnexpectedDollarInString;
case '/*':
return ErrorKind.UnterminatedComment;
return codeUnterminatedComment;
default:
return ErrorKind.UnterminatedToken;
return codeUnterminatedToken;
}
}
}
@ -213,5 +222,5 @@ class UnmatchedToken extends ErrorToken {
String get assertionMessage => "'$begin' isn't closed.";
ErrorKind get errorCode => ErrorKind.UnmatchedToken;
FastaCode get errorCode => codeUnmatchedToken;
}

View file

@ -4,9 +4,23 @@
library fasta.scanner.recover;
import '../fasta_codes.dart'
show
FastaCode,
codeAsciiControlCharacter,
codeEncoding,
codeExpectedHexDigit,
codeMissingExponent,
codeNonAsciiIdentifier,
codeNonAsciiWhitespace,
codeUnexpectedDollarInString,
codeUnmatchedToken,
codeUnterminatedComment,
codeUnterminatedString;
import 'token.dart' show StringToken, SymbolToken, Token;
import 'error_token.dart' show NonAsciiIdentifierToken, ErrorKind, ErrorToken;
import 'error_token.dart' show NonAsciiIdentifierToken, ErrorToken;
import 'precedence.dart' as Precedence;
@ -161,52 +175,34 @@ Token defaultRecoveryStrategy(
next = next.next;
} while (next is ErrorToken && first.errorCode == next.errorCode);
switch (first.errorCode) {
case ErrorKind.Encoding:
case ErrorKind.NonAsciiWhitespace:
case ErrorKind.AsciiControlCharacter:
treatAsWhitespace = true;
break;
case ErrorKind.NonAsciiIdentifier:
current = recoverIdentifier(first);
assert(current.next != null);
break;
case ErrorKind.MissingExponent:
current = recoverExponent();
assert(current.next != null);
break;
case ErrorKind.UnterminatedString:
current = recoverString();
assert(current.next != null);
break;
case ErrorKind.ExpectedHexDigit:
current = recoverHexDigit();
assert(current.next != null);
break;
case ErrorKind.UnexpectedDollarInString:
current = recoverStringInterpolation();
assert(current.next != null);
break;
case ErrorKind.UnterminatedComment:
current = recoverComment();
assert(current.next != null);
break;
case ErrorKind.UnmatchedToken:
current = recoverUnmatched();
assert(current.next != null);
break;
case ErrorKind.UnterminatedToken: // TODO(ahe): Can this happen?
default:
treatAsWhitespace = true;
break;
FastaCode code = first.errorCode;
if (code == codeEncoding ||
code == codeNonAsciiWhitespace ||
code == codeAsciiControlCharacter) {
treatAsWhitespace = true;
} else if (code == codeNonAsciiIdentifier) {
current = recoverIdentifier(first);
assert(current.next != null);
} else if (code == codeMissingExponent) {
current = recoverExponent();
assert(current.next != null);
} else if (code == codeUnterminatedString) {
current = recoverString();
assert(current.next != null);
} else if (code == codeExpectedHexDigit) {
current = recoverHexDigit();
assert(current.next != null);
} else if (code == codeUnexpectedDollarInString) {
current = recoverStringInterpolation();
assert(current.next != null);
} else if (code == codeUnterminatedComment) {
current = recoverComment();
assert(current.next != null);
} else if (code == codeUnmatchedToken) {
current = recoverUnmatched();
assert(current.next != null);
} else {
treatAsWhitespace = true;
}
if (treatAsWhitespace) continue;
}

View file

@ -10,6 +10,8 @@ import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
import 'package:kernel/core_types.dart' show CoreTypes;
import '../fasta_codes.dart' show FastaMessage, codeExpectedBlockToSkip;
import '../parser/parser.dart' show Parser, optional;
import '../scanner/token.dart' show BeginGroupToken, Token;
@ -17,8 +19,6 @@ import '../scanner/token.dart' show BeginGroupToken, Token;
import '../parser/dart_vm_native.dart'
show removeNativeClause, skipNativeClause;
import '../parser/error_kind.dart' show ErrorKind;
import '../util/link.dart' show Link;
import '../errors.dart' show Crash, InputError, inputError, internalError;
@ -462,15 +462,15 @@ class DietListener extends StackListener {
}
@override
Token handleUnrecoverableError(Token token, ErrorKind kind, Map arguments) {
if (isDartLibrary && kind == ErrorKind.ExpectedBlockToSkip) {
Token handleUnrecoverableError(Token token, FastaMessage message) {
if (isDartLibrary && message.code == codeExpectedBlockToSkip) {
Token recover = skipNativeClause(token);
if (recover != null) {
assert(isTargetingDartVm);
return recover;
}
}
return super.handleUnrecoverableError(token, kind, arguments);
return super.handleUnrecoverableError(token, message);
}
@override

View file

@ -4,16 +4,16 @@
library fasta.diet_parser;
import '../scanner/token.dart' show BeginGroupToken, Token;
import '../fasta_codes.dart' show codeExpectedOpenParens;
import '../parser/class_member_parser.dart' show ClassMemberParser;
import '../parser/error_kind.dart' show ErrorKind;
import '../parser/listener.dart' show Listener;
import '../parser/parser.dart' show optional;
import '../scanner/token.dart' show BeginGroupToken, Token;
// TODO(ahe): Move this to parser package.
class DietParser extends ClassMemberParser {
DietParser(Listener listener) : super(listener);
@ -26,10 +26,10 @@ class DietParser extends ClassMemberParser {
listener.beginOptionalFormalParameters(token);
if (!optional('(', token)) {
if (optional(';', token)) {
reportRecoverableError(token, ErrorKind.ExpectedOpenParens, {});
reportRecoverableErrorCode(token, codeExpectedOpenParens);
return token;
}
return reportUnrecoverableError(token, ErrorKind.UnexpectedToken)?.next;
return reportUnexpectedToken(token).next;
}
BeginGroupToken beginGroupToken = token;
Token endToken = beginGroupToken.endGroup;

View file

@ -6,6 +6,8 @@ library fasta.outline_builder;
import 'package:kernel/ast.dart' show AsyncMarker, ProcedureKind;
import '../fasta_codes.dart' show FastaMessage, codeExpectedBlockToSkip;
import '../parser/parser.dart' show FormalParameterType, optional;
import '../parser/identifier_context.dart' show IdentifierContext;
@ -26,8 +28,6 @@ import 'source_library_builder.dart' show SourceLibraryBuilder;
import 'unhandled_listener.dart' show NullValue, Unhandled, UnhandledListener;
import '../parser/error_kind.dart' show ErrorKind;
import '../parser/dart_vm_native.dart'
show removeNativeClause, skipNativeClause;
@ -782,15 +782,15 @@ class OutlineBuilder extends UnhandledListener {
}
@override
Token handleUnrecoverableError(Token token, ErrorKind kind, Map arguments) {
if (isDartLibrary && kind == ErrorKind.ExpectedBlockToSkip) {
Token handleUnrecoverableError(Token token, FastaMessage message) {
if (isDartLibrary && message.code == codeExpectedBlockToSkip) {
Token recover = skipNativeClause(token);
if (recover != null) {
nativeMethodName = unescapeString(token.next.lexeme);
return recover;
}
}
return super.handleUnrecoverableError(token, kind, arguments);
return super.handleUnrecoverableError(token, message);
}
@override

View file

@ -4,7 +4,9 @@
library fasta.stack_listener;
import '../parser.dart' show ErrorKind, Listener;
import '../fasta_codes.dart' show FastaMessage;
import '../parser.dart' show Listener;
import '../parser/identifier_context.dart' show IdentifierContext;
@ -52,6 +54,7 @@ enum NullValue {
abstract class StackListener extends Listener {
final Stack stack = new Stack();
@override
Uri get uri;
// TODO(ahe): This doesn't belong here. Only implemented by body_builder.dart
@ -238,14 +241,14 @@ abstract class StackListener extends Listener {
}
@override
void handleRecoverableError(Token token, ErrorKind kind, Map arguments) {
super.handleRecoverableError(token, kind, arguments);
debugEvent("Error: ${recoverableErrors.last}");
void handleRecoverableError(Token token, FastaMessage message) {
debugEvent("Error: ${message.message}");
super.handleRecoverableError(token, message);
}
@override
Token handleUnrecoverableError(Token token, ErrorKind kind, Map arguments) {
throw inputError(uri, token.charOffset, "$kind $arguments");
Token handleUnrecoverableError(Token token, FastaMessage message) {
throw inputError(uri, token.charOffset, message.message);
}
void nit(String message, [int charOffset = -1]) {

View file

@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:front_end/src/base/errors.dart';
import 'package:front_end/src/fasta/fasta_codes.dart';
import 'package:front_end/src/fasta/scanner/error_token.dart';
import 'package:front_end/src/fasta/scanner/token.dart';
import 'package:front_end/src/fasta/scanner/token_constants.dart';
@ -89,35 +90,39 @@ void translateErrorToken(ErrorToken token, ReportError reportError) {
}
var errorCode = token.errorCode;
switch (errorCode) {
case ErrorKind.UnterminatedString:
switch (errorCode.analyzerCode) {
case "UNTERMINATED_STRING_LITERAL":
// TODO(paulberry,ahe): Fasta reports the error location as the entire
// string; analyzer expects the end of the string.
charOffset = endOffset;
return _makeError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, null);
case ErrorKind.UnmatchedToken:
return null;
case ErrorKind.UnterminatedComment:
case "UNTERMINATED_MULTI_LINE_COMMENT":
// TODO(paulberry,ahe): Fasta reports the error location as the entire
// comment; analyzer expects the end of the comment.
charOffset = endOffset;
return _makeError(ScannerErrorCode.UNTERMINATED_MULTI_LINE_COMMENT, null);
case ErrorKind.MissingExponent:
case "MISSING_DIGIT":
// TODO(paulberry,ahe): Fasta reports the error location as the entire
// number; analyzer expects the end of the number.
charOffset = endOffset - 1;
return _makeError(ScannerErrorCode.MISSING_DIGIT, null);
case ErrorKind.ExpectedHexDigit:
case "MISSING_HEX_DIGIT":
// TODO(paulberry,ahe): Fasta reports the error location as the entire
// number; analyzer expects the end of the number.
charOffset = endOffset - 1;
return _makeError(ScannerErrorCode.MISSING_HEX_DIGIT, null);
case ErrorKind.NonAsciiIdentifier:
case ErrorKind.NonAsciiWhitespace:
case "ILLEGAL_CHARACTER":
return _makeError(ScannerErrorCode.ILLEGAL_CHARACTER, [token.character]);
case ErrorKind.UnexpectedDollarInString:
return null;
default:
if (errorCode == codeUnmatchedToken ||
errorCode == codeUnexpectedDollarInString) {
return null;
}
throw new UnimplementedError('$errorCode');
}
}

View file

@ -12,6 +12,9 @@
# 3. Examples that produce the message (one of expression, statement,
# declaration, member, script, or bytes).
#
# In addition, an entry can contain an analyzer error code (analyzerCode) and a
# dart2js error code (dart2jsCode).
#
# ## Parameter Substitution in Template and Tip
#
# The fields `template` and `tip` are subject to parameter substitution. When
@ -31,24 +34,31 @@
AsciiControlCharacter:
template: "The control character #unicode can only be used in strings and comments."
dart2jsCode: BAD_INPUT_CHARACTER
expresssion: "\x1b 1"
NonAsciiIdentifier:
template: "The non-ASCII character '#character' (#unicode) can't be used in identifiers, only in strings and comments."
tip: "Try using an US-ASCII letter, a digit, '_' (an underscore), or '$' (a dollar sign)."
analyzerCode: ILLEGAL_CHARACTER
dart2jsCode: BAD_INPUT_CHARACTER
expresssion: "å"
NonAsciiWhitespace:
template: "The non-ASCII space character #unicode can only be used in strings and comments."
analyzerCode: ILLEGAL_CHARACTER
dart2jsCode: BAD_INPUT_CHARACTER
expresssion: "\u2028 1"
Encoding:
template: "Unable to decode bytes as UTF-8."
dart2jsCode: FASTA_FATAL
bytes: [255]
EmptyNamedParameterList:
template: "Named parameter lists cannot be empty."
tip: "Try adding a named parameter to the list."
dart2jsCode: EMPTY_NAMED_PARAMETER_LIST
script: >
foo({}) {}
@ -59,6 +69,7 @@ EmptyNamedParameterList:
EmptyOptionalParameterList:
template: "Optional parameter lists cannot be empty."
tip: "Try adding an optional parameter to the list."
dart2jsCode: EMPTY_OPTIONAL_PARAMETER_LIST
script: >
foo([]) {}
@ -66,41 +77,54 @@ EmptyOptionalParameterList:
foo();
}
ExpectedBlockToSkip: ExpectedBody
ExpectedBlockToSkip:
template: "Expected a function body or '=>'."
# TODO(ahe): In some scenarios, we can suggest removing the 'static' keyword.
tip: "Try adding {}."
dart2jsCode: NATIVE_OR_BODY_EXPECTED
script: "main();"
ExpectedBody:
template: "Expected a function body or '=>'."
# TODO(ahe): In some scenarios, we can suggest removing the 'static' keyword.
tip: "Try adding {}."
dart2jsCode: BODY_EXPECTED
script: "main();"
ExpectedButGot:
template: "Expected '#lexeme' before this."
template: "Expected '#string' before this."
# Consider the second example below: the parser expects a ')' before 'y', but
# a ',' would also have worked. We don't have enough information to give a
# good suggestion.
tip: DONT_KNOW_HOW_TO_FIX,
dart2jsCode: MISSING_TOKEN_BEFORE_THIS
script:
- "main() => true ? 1;"
- "main() => foo(x: 1 y: 2);"
ExpectedClassBody:
template: "Expected a class body, but got '#lexeme'."
dart2jsCode: FASTA_FATAL
ExpectedClassBodyToSkip: ExpectedClassBody
ExpectedDeclaration:
template: "Expected a declaration, but got '#lexeme'."
dart2jsCode: FASTA_FATAL
ExpectedExpression:
template: "Expected an expression, but got '#lexeme'."
dart2jsCode: FASTA_FATAL
ExpectedFunctionBody:
template: "Expected a function body, but got '#lexeme'."
dart2jsCode: NATIVE_OR_FATAL
ExpectedHexDigit:
template: "A hex digit (0-9 or A-F) must follow '0x'."
# No tip, seems obvious from the error message.
analyzerCode: MISSING_HEX_DIGIT
dart2jsCode: HEX_DIGIT_EXPECTED
script: >
main() {
var i = 0x;
@ -109,20 +133,25 @@ ExpectedHexDigit:
ExpectedIdentifier:
template: "'#lexeme' is a reserved word and can't be used here."
tip: "Try using a different name."
dart2jsCode: EXPECTED_IDENTIFIER
script: "do() {} main() {}"
ExpectedOpenParens:
template: "Expected '('."
dart2jsCode: GENERIC
ExpectedString:
template: "Expected a String, but got '#lexeme'."
dart2jsCode: FASTA_FATAL
ExpectedType:
template: "Expected a type, but got '#lexeme'."
dart2jsCode: FASTA_FATAL
ExtraneousModifier:
template: "Can't have modifier '#lexeme' here."
tip: "Try removing '#lexeme'."
dart2jsCode: EXTRANEOUS_MODIFIER
script:
- "var String foo; main(){}"
- "var set foo; main(){}"
@ -144,6 +173,7 @@ ExtraneousModifier:
ExtraneousModifierReplace:
template: "Can't have modifier '#lexeme' here."
tip: "Try replacing modifier '#lexeme' with 'var', 'final', or a type."
dart2jsCode: EXTRANEOUS_MODIFIER_REPLACE
script:
- "set foo; main(){}"
- "abstract foo; main(){}"
@ -153,6 +183,7 @@ ExtraneousModifierReplace:
InvalidAwaitFor:
template: "'await' is only supported in methods with an 'async' or 'async*' body modifier."
tip: "Try adding 'async' or 'async*' to the method body or removing the 'await' keyword."
dart2jsCode: INVALID_AWAIT_FOR
script: >
main(o) sync* {
await for (var e in o) {}
@ -161,11 +192,13 @@ InvalidAwaitFor:
InvalidSyncModifier:
template: "Invalid modifier 'sync'."
tip: "Try replacing 'sync' with 'sync*'."
dart2jsCode: INVALID_SYNC_MODIFIER
script: "main() sync {}"
InvalidVoid:
template: "Type 'void' can't be used here because it isn't a return type."
tip: "Try removing 'void' keyword or replace it with 'var', 'final', or a type."
dart2jsCode: VOID_NOT_ALLOWED
script:
- "void x; main() {}"
- "foo(void x) {} main() { foo(null); }"
@ -173,6 +206,8 @@ InvalidVoid:
MissingExponent:
template: "Numbers in exponential notation should always contain an exponent (an integer number with an optional sign)."
tip: "Make sure there is an exponent, and remove any whitespace before it."
analyzerCode: MISSING_DIGIT
dart2jsCode: EXPONENT_MISSING
script: >
main() {
var i = 1e;
@ -181,6 +216,7 @@ MissingExponent:
PositionalParameterWithEquals:
template: "Positional optional parameters can't use ':' to specify a default value."
tip: "Try replacing ':' with '='."
dart2jsCode: POSITIONAL_PARAMETER_WITH_EQUALS
script: >
main() {
foo([a: 1]) => print(a);
@ -190,6 +226,7 @@ PositionalParameterWithEquals:
RequiredParameterWithDefault:
template: "Non-optional parameters can't have a default value."
tip: "Try removing the default value or making the parameter optional."
dart2jsCode: REQUIRED_PARAMETER_WITH_DEFAULT
script:
- >
main() {
@ -204,10 +241,12 @@ RequiredParameterWithDefault:
StackOverflow:
template: "Stack overflow."
dart2jsCode: GENERIC
UnexpectedDollarInString:
template: "A '$' has special meaning inside a string, and must be followed by an identifier or an expression in curly braces ({})."
tip: "Try adding a backslash (\\) to escape the '$'."
dart2jsCode: MALFORMED_STRING_LITERAL
script:
- >
main() {
@ -228,9 +267,11 @@ UnexpectedDollarInString:
UnexpectedToken:
template: "Unexpected token '#lexeme'."
dart2jsCode: FASTA_FATAL
UnmatchedToken:
template: "Can't find '#string' to match '#lexeme'."
dart2jsCode: UNMATCHED_TOKEN
script:
- "main("
- "main(){"
@ -239,10 +280,13 @@ UnmatchedToken:
UnsupportedPrefixPlus:
template: "'+' is not a prefix operator. "
tip: "Try removing '+'."
dart2jsCode: UNSUPPORTED_PREFIX_PLUS
script: "main() => +2; // No longer a valid way to write '2'"
UnterminatedComment:
template: "Comment starting with '/*' must end with '*/'."
analyzerCode: UNTERMINATED_MULTI_LINE_COMMENT
dart2jsCode: UNTERMINATED_COMMENT
script:
main() {
}
@ -250,6 +294,8 @@ UnterminatedComment:
UnterminatedString:
template: "String must end with #string."
analyzerCode: UNTERMINATED_STRING_LITERAL
dart2jsCode: UNTERMINATED_STRING
script:
- >
main() {
@ -283,52 +329,69 @@ UnterminatedString:
UnterminatedToken:
# This is a fall-back message that shouldn't happen.
template: "Incomplete token."
dart2jsCode: UNTERMINATED_TOKEN
Unspecified:
template: "#string"
dart2jsCode: GENERIC
AbstractNotSync:
template: "Abstract methods can't use 'async', 'async*', or 'sync*'."
dart2jsCode: FASTA_IGNORED
AsyncAsIdentifier:
analyzerCode: ASYNC_KEYWORD_USED_AS_IDENTIFIER
template: "'async' can't be used as an identifier in 'async', 'async*', or 'sync*' methods."
dart2jsCode: GENERIC
AwaitAsIdentifier:
template: "'await' can't be used as an identifier in 'async', 'async*', or 'sync*' methods."
dart2jsCode: FASTA_IGNORED
AwaitNotAsync:
template: "'await' can only be used in 'async' or 'async*' methods."
dart2jsCode: FASTA_IGNORED
BuiltInIdentifierAsType:
template: "Can't use '#lexeme' as a type."
dart2jsCode: GENERIC
BuiltInIdentifierInDeclaration:
template: "Can't use '#lexeme' as a name here."
dart2jsCode: GENERIC
AwaitForNotAsync:
template: "Asynchronous for-loop can only be used in 'async' or 'async*' methods."
dart2jsCode: FASTA_IGNORED
FactoryNotSync:
template: "Factories can't use 'async', 'async*', or 'sync*'."
dart2jsCode: FASTA_IGNORED
GeneratorReturnsValue:
template: "'sync*' and 'async*' can't return a value."
dart2jsCode: FASTA_IGNORED
InvalidInlineFunctionType:
template: "Invalid inline function type."
tip: "Try changing the inline function type (as in 'int f()') to a prefixed function type using the `Function` keyword (as in 'int Function() f')."
dart2jsCode: INVALID_INLINE_FUNCTION_TYPE
declaration: "typedef F = Function(int f(String x)); main() { F f; }"
SetterNotSync:
template: "Setters can't use 'async', 'async*', or 'sync*'."
dart2jsCode: FASTA_IGNORED
YieldAsIdentifier:
template: "'yield' can't be used as an identifier in 'async', 'async*', or 'sync*' methods."
dart2jsCode: FASTA_IGNORED
YieldNotGenerator:
template: "'yield' can only be used in 'sync*' or 'async*' methods."
dart2jsCode: FASTA_IGNORED
OnlyTry:
template: "Try block should be followed by 'on', 'catch', or 'finally' block."
tip: "Did you forget to add a 'finally' block?"
statement: "try {}"
dart2jsCode: FASTA_IGNORED

View file

@ -77,7 +77,6 @@ final subpackageRules = {
]),
'lib/src/fasta/scanner': new SubpackageRules(allowedDependencies: [
'lib/src/fasta',
'lib/src/fasta/parser',
// fasta scanner produces analyzer scanner tokens
'lib/src/scanner',
'lib/src/fasta/util',
@ -102,6 +101,8 @@ final subpackageRules = {
'lib/src/fasta/util': new SubpackageRules(),
'lib/src/scanner': new SubpackageRules(allowedDependencies: [
'lib/src/base',
// For error codes.
'lib/src/fasta',
// fasta scanner produces analyzer scanner tokens
'lib/src/fasta/scanner',
]),

View file

@ -8,25 +8,12 @@ import 'dart:isolate';
import 'package:yaml/yaml.dart' show loadYaml;
import 'package:front_end/src/fasta/parser/error_kind.dart' show ErrorKind;
import 'package:dart_style/dart_style.dart' show DartFormatter;
main(List<String> arguments) async {
var port = new ReceivePort();
Uri messagesFile = Platform.script.resolve("../../messages.yaml");
Map yaml = loadYaml(await new File.fromUri(messagesFile).readAsStringSync());
Set<String> names =
new Set<String>.from(yaml.keys.map((String s) => "ErrorKind.$s"));
Set<String> kinds =
new Set<String>.from(ErrorKind.values.map((kind) => "$kind"));
Set<String> difference = kinds.difference(names);
if (difference.isNotEmpty) {
Uri errorKindFile = await Isolate.resolvePackageUri(
Uri.parse('package:front_end/src/fasta/parser/error_kind.dart'));
throw "Mismatch between '${errorKindFile.toFilePath()}' and"
" '${messagesFile.toFilePath()}': ${difference.join(' ')}.";
}
StringBuffer sb = new StringBuffer();
sb.writeln("""
@ -39,11 +26,7 @@ main(List<String> arguments) async {
// Instead modify 'pkg/front_end/messages.yaml' and run
// 'pkg/front_end/tool/_fasta/generate_messages.dart' to update.
library fasta.problems;
import 'package:front_end/src/fasta/scanner/token.dart' show Token;
import 'package:front_end/src/fasta/parser/error_kind.dart' show ErrorKind;
part of fasta.codes;
""");
yaml.forEach((String name, description) {
@ -51,13 +34,14 @@ import 'package:front_end/src/fasta/parser/error_kind.dart' show ErrorKind;
description = yaml[description];
}
Map map = description;
sb.writeln(compileTemplate(name, map['template'], map['tip']));
sb.writeln(compileTemplate(name, map['template'], map['tip'],
map['analyzerCode'], map['dart2jsCode']));
});
String dartfmtedText = new DartFormatter().format("$sb");
Uri problemsFile = await Isolate.resolvePackageUri(
Uri.parse('package:front_end/src/fasta/problems.dart'));
Uri.parse('package:front_end/src/fasta/fasta_codes_generated.dart'));
await new File.fromUri(problemsFile)
.writeAsString(dartfmtedText, flush: true);
port.close();
@ -65,38 +49,41 @@ import 'package:front_end/src/fasta/parser/error_kind.dart' show ErrorKind;
final RegExp placeholderPattern = new RegExp("#[a-zA-Z0-9_]+");
String compileTemplate(String name, String template, String tip) {
String compileTemplate(String name, String template, String tip,
String analyzerCode, String dart2jsCode) {
var parameters = new Set<String>();
var conversions = new Set<String>();
var arguments = new Set<String>();
parameters.add("Uri uri");
parameters.add("int charOffset");
for (Match match in placeholderPattern.allMatches("$template${tip ?? ''}")) {
switch (match[0]) {
case "#character":
parameters.add("String character");
arguments.add("'character': character,");
arguments.add("'character': character");
break;
case "#unicode":
parameters.add("int codePoint");
conversions.add("String unicode = "
"\"(U+\${codePoint.toRadixString(16).padLeft(4, '0')})\";");
arguments.add("'codePoint': codePoint,");
arguments.add("'codePoint': codePoint");
break;
case "#name":
parameters.add("String name");
arguments.add("'name': name,");
arguments.add("'name': name");
break;
case "#lexeme":
parameters.add("Token token");
conversions.add("String lexeme = token.lexeme;");
arguments.add("'token': token,");
arguments.add("'token': token");
break;
case "#string":
parameters.add("String string");
arguments.add("'string': string,");
arguments.add("'string': string");
break;
default:
@ -105,23 +92,48 @@ String compileTemplate(String name, String template, String tip) {
}
String interpolate(String name, String text) {
if (text == null) return "";
return " '$name': "
"\"${text.replaceAll(r'$', r'\$').replaceAll('#', '\$')}\",";
return "$name: "
"\"${text.replaceAll(r'$', r'\$').replaceAll('#', '\$')}\"";
}
List<String> codeArguments = <String>[];
if (template != null) {
codeArguments.add('template: r"$template"');
}
if (tip != null) {
codeArguments.add('tip: r"$tip"');
}
if (analyzerCode != null) {
codeArguments.add('analyzerCode: "$analyzerCode"');
}
if (dart2jsCode != null) {
codeArguments.add('dart2jsCode: "$dart2jsCode"');
}
codeArguments.add("format: _format$name");
List<String> messageArguments = <String>[];
messageArguments.add(interpolate("message", template));
if (tip != null) {
messageArguments.add(interpolate("tip", tip));
}
messageArguments.add("arguments: { ${arguments.join(', ')} }");
return """
problem$name(${parameters.join(', ')}) {
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const FastaCode<_$name> code$name =
const FastaCode<_$name>(${codeArguments.join(', ')});
typedef FastaMessage _$name(${parameters.join(', ')});
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
FastaMessage _format$name(${parameters.join(', ')}) {
${conversions.join('\n ')}
return {
${interpolate('message', template)}
${interpolate('tip', tip)}
'code': ErrorKind.$name,
'arguments': {
${arguments.join('\n ')}
},
};
return new FastaMessage(
uri,
charOffset,
code$name,
${messageArguments.join(', ')});
}
""";
}