mirror of
https://github.com/dart-lang/sdk
synced 2024-09-18 22:21:18 +00:00
Report error on unsupported operators
Change-Id: Iea1469e1252c89c630e8bf646caf37051d78c84c Reviewed-on: https://dart-review.googlesource.com/67401 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Dan Rubel <danrubel@google.com>
This commit is contained in:
parent
00e3109368
commit
4734c55882
|
@ -538,6 +538,7 @@ const List<ErrorCode> errorCodeValues = const [
|
|||
ScannerErrorCode.MISSING_QUOTE,
|
||||
ScannerErrorCode.UNABLE_GET_CONTENT,
|
||||
ScannerErrorCode.UNEXPECTED_DOLLAR_IN_STRING,
|
||||
ScannerErrorCode.UNSUPPORTED_OPERATOR,
|
||||
ScannerErrorCode.UNTERMINATED_MULTI_LINE_COMMENT,
|
||||
ScannerErrorCode.UNTERMINATED_STRING_LITERAL,
|
||||
StaticTypeWarningCode.EXPECTED_ONE_LIST_TYPE_ARGUMENTS,
|
||||
|
|
|
@ -4103,11 +4103,15 @@ class Wrong<T> {
|
|||
}
|
||||
|
||||
void test_invalidOperator() {
|
||||
createParser('void operator ===(x) {}');
|
||||
ClassMember member = parser.parseClassMember('C');
|
||||
expectNotNullIfNoErrors(member);
|
||||
listener
|
||||
.assertErrors([expectedError(ParserErrorCode.INVALID_OPERATOR, 14, 3)]);
|
||||
CompilationUnit unit =
|
||||
parseCompilationUnit('class C { void operator ===(x) { } }',
|
||||
errors: usingFastaParser
|
||||
? [expectedError(ScannerErrorCode.UNSUPPORTED_OPERATOR, 24, 1)]
|
||||
: [
|
||||
expectedError(ScannerErrorCode.UNSUPPORTED_OPERATOR, 24, 1),
|
||||
expectedError(ParserErrorCode.INVALID_OPERATOR, 24, 3)
|
||||
]);
|
||||
expect(unit, isNotNull);
|
||||
}
|
||||
|
||||
void test_invalidOperator_unary() {
|
||||
|
|
|
@ -7168,6 +7168,26 @@ Message _withArgumentsUnspecified(String string) {
|
|||
message: """${string}""", arguments: {'string': string});
|
||||
}
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const Template<Message Function(Token token)> templateUnsupportedOperator =
|
||||
const Template<Message Function(Token token)>(
|
||||
messageTemplate: r"""The '#lexeme' operator is not supported.""",
|
||||
withArguments: _withArgumentsUnsupportedOperator);
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const Code<Message Function(Token token)> codeUnsupportedOperator =
|
||||
const Code<Message Function(Token token)>(
|
||||
"UnsupportedOperator", templateUnsupportedOperator,
|
||||
analyzerCode: "UNSUPPORTED_OPERATOR", dart2jsCode: "*ignored*");
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
Message _withArgumentsUnsupportedOperator(Token token) {
|
||||
String lexeme = token.lexeme;
|
||||
return new Message(codeUnsupportedOperator,
|
||||
message: """The '${lexeme}' operator is not supported.""",
|
||||
arguments: {'token': token});
|
||||
}
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||
const Code<Null> codeUnsupportedPrefixPlus = messageUnsupportedPrefixPlus;
|
||||
|
||||
|
|
|
@ -2700,6 +2700,7 @@ class Parser {
|
|||
listener.endMember();
|
||||
return token;
|
||||
} else if (optional('===', next2) ||
|
||||
optional('!==', next2) ||
|
||||
(next2.isOperator &&
|
||||
!optional('=', next2) &&
|
||||
!optional('<', next2))) {
|
||||
|
@ -2976,9 +2977,13 @@ class Parser {
|
|||
return next;
|
||||
} else {
|
||||
// Recovery
|
||||
// The user has specified an invalid operator name.
|
||||
// Report the error, accept the invalid operator name, and move on.
|
||||
reportRecoverableErrorWithToken(next, fasta.templateInvalidOperator);
|
||||
// Scanner reports an error for `===` and `!==`.
|
||||
if (next.type != TokenType.EQ_EQ_EQ &&
|
||||
next.type != TokenType.BANG_EQ_EQ) {
|
||||
// The user has specified an invalid operator name.
|
||||
// Report the error, accept the invalid operator name, and move on.
|
||||
reportRecoverableErrorWithToken(next, fasta.templateInvalidOperator);
|
||||
}
|
||||
listener.handleInvalidOperatorName(token, next);
|
||||
return next;
|
||||
}
|
||||
|
@ -5595,7 +5600,9 @@ class Parser {
|
|||
beforeName, new SyntheticToken(Keyword.OPERATOR, next.offset));
|
||||
}
|
||||
|
||||
assert((next.isOperator && next.endGroup == null) || optional('===', next));
|
||||
assert((next.isOperator && next.endGroup == null) ||
|
||||
optional('===', next) ||
|
||||
optional('!==', next));
|
||||
|
||||
Token token = parseMethod(
|
||||
beforeStart,
|
||||
|
|
|
@ -21,7 +21,8 @@ import '../fasta_codes.dart'
|
|||
import '../scanner.dart'
|
||||
show ErrorToken, Keyword, Scanner, buildUnexpectedCharacterToken;
|
||||
|
||||
import 'error_token.dart' show UnterminatedString, UnterminatedToken;
|
||||
import 'error_token.dart'
|
||||
show UnsupportedOperator, UnterminatedString, UnterminatedToken;
|
||||
|
||||
import 'keyword_state.dart' show KeywordState;
|
||||
|
||||
|
@ -599,7 +600,16 @@ abstract class AbstractScanner implements Scanner {
|
|||
|
||||
next = advance();
|
||||
if (identical(next, $EQ)) {
|
||||
return select($EQ, TokenType.BANG_EQ_EQ, TokenType.BANG_EQ);
|
||||
//was `return select($EQ, TokenType.BANG_EQ_EQ, TokenType.BANG_EQ);`
|
||||
int next = advance();
|
||||
if (identical(next, $EQ)) {
|
||||
appendPrecedenceToken(TokenType.BANG_EQ_EQ);
|
||||
appendErrorToken(new UnsupportedOperator(tail, tokenStart));
|
||||
return advance();
|
||||
} else {
|
||||
appendPrecedenceToken(TokenType.BANG_EQ);
|
||||
return next;
|
||||
}
|
||||
}
|
||||
appendPrecedenceToken(TokenType.BANG);
|
||||
return next;
|
||||
|
@ -615,7 +625,16 @@ abstract class AbstractScanner implements Scanner {
|
|||
|
||||
next = advance();
|
||||
if (identical(next, $EQ)) {
|
||||
return select($EQ, TokenType.EQ_EQ_EQ, TokenType.EQ_EQ);
|
||||
// was `return select($EQ, TokenType.EQ_EQ_EQ, TokenType.EQ_EQ);`
|
||||
int next = advance();
|
||||
if (identical(next, $EQ)) {
|
||||
appendPrecedenceToken(TokenType.EQ_EQ_EQ);
|
||||
appendErrorToken(new UnsupportedOperator(tail, tokenStart));
|
||||
return advance();
|
||||
} else {
|
||||
appendPrecedenceToken(TokenType.EQ_EQ);
|
||||
return next;
|
||||
}
|
||||
} else if (identical(next, $GT)) {
|
||||
appendPrecedenceToken(TokenType.FUNCTION);
|
||||
return advance();
|
||||
|
|
|
@ -15,6 +15,7 @@ import '../fasta_codes.dart'
|
|||
templateNonAsciiIdentifier,
|
||||
templateNonAsciiWhitespace,
|
||||
templateUnmatchedToken,
|
||||
templateUnsupportedOperator,
|
||||
templateUnterminatedString;
|
||||
|
||||
import '../scanner.dart' show Token, unicodeReplacementCharacter;
|
||||
|
@ -137,6 +138,20 @@ class AsciiControlCharacterToken extends ErrorToken {
|
|||
templateAsciiControlCharacter.withArguments(character);
|
||||
}
|
||||
|
||||
/// Denotes an operator that is not supported in the Dart language.
|
||||
class UnsupportedOperator extends ErrorToken {
|
||||
Token token;
|
||||
|
||||
UnsupportedOperator(this.token, int charOffset) : super(charOffset);
|
||||
|
||||
@override
|
||||
Message get assertionMessage =>
|
||||
templateUnsupportedOperator.withArguments(token);
|
||||
|
||||
@override
|
||||
String toString() => "UnsupportedOperator(${token.lexeme})";
|
||||
}
|
||||
|
||||
/// Represents an unterminated string.
|
||||
class UnterminatedString extends ErrorToken {
|
||||
final String start;
|
||||
|
@ -149,8 +164,8 @@ class UnterminatedString extends ErrorToken {
|
|||
|
||||
int get charCount => endOffset - charOffset;
|
||||
|
||||
Message get assertionMessage => templateUnterminatedString.withArguments(
|
||||
start, closeQuoteFor(start));
|
||||
Message get assertionMessage =>
|
||||
templateUnterminatedString.withArguments(start, closeQuoteFor(start));
|
||||
}
|
||||
|
||||
/// Represents an unterminated token.
|
||||
|
@ -179,6 +194,6 @@ class UnmatchedToken extends ErrorToken {
|
|||
|
||||
String toString() => "UnmatchedToken(${begin.lexeme})";
|
||||
|
||||
Message get assertionMessage => templateUnmatchedToken.withArguments(
|
||||
closeBraceFor(begin.lexeme), begin);
|
||||
Message get assertionMessage =>
|
||||
templateUnmatchedToken.withArguments(closeBraceFor(begin.lexeme), begin);
|
||||
}
|
||||
|
|
|
@ -52,6 +52,13 @@ class ScannerErrorCode extends ErrorCode {
|
|||
"an identifier or an expression in curly braces ({}).",
|
||||
correction: "Try adding a backslash (\\) to escape the '\$'.");
|
||||
|
||||
/**
|
||||
* Parameters:
|
||||
* 0: the unsupported operator
|
||||
*/
|
||||
static const ScannerErrorCode UNSUPPORTED_OPERATOR = const ScannerErrorCode(
|
||||
'UNSUPPORTED_OPERATOR', "The '{0}' operator is not supported.");
|
||||
|
||||
static const ScannerErrorCode UNTERMINATED_MULTI_LINE_COMMENT =
|
||||
const ScannerErrorCode(
|
||||
'UNTERMINATED_MULTI_LINE_COMMENT', "Unterminated multi-line comment.",
|
||||
|
@ -135,6 +142,10 @@ void translateErrorToken(ErrorToken token, ReportError reportError) {
|
|||
case "ILLEGAL_CHARACTER":
|
||||
return _makeError(ScannerErrorCode.ILLEGAL_CHARACTER, [token.character]);
|
||||
|
||||
case "UNSUPPORTED_OPERATOR":
|
||||
return _makeError(ScannerErrorCode.UNSUPPORTED_OPERATOR,
|
||||
[(token as UnsupportedOperator).token.lexeme]);
|
||||
|
||||
default:
|
||||
if (errorCode == codeUnmatchedToken) {
|
||||
charOffset = token.begin.endToken.charOffset;
|
||||
|
@ -155,7 +166,7 @@ void translateErrorToken(ErrorToken token, ReportError reportError) {
|
|||
} else if (errorCode == codeUnexpectedDollarInString) {
|
||||
return _makeError(ScannerErrorCode.MISSING_IDENTIFIER, null);
|
||||
}
|
||||
throw new UnimplementedError('$errorCode');
|
||||
throw new UnimplementedError('$errorCode "${errorCode.analyzerCode}"');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -948,6 +948,14 @@ UnmatchedToken:
|
|||
- "main(){"
|
||||
- "main(){[}"
|
||||
|
||||
UnsupportedOperator:
|
||||
template: "The '#lexeme' operator is not supported."
|
||||
analyzerCode: UNSUPPORTED_OPERATOR
|
||||
dart2jsCode: "*ignored*"
|
||||
script:
|
||||
- "class C { void operator ===(x) {} }"
|
||||
- "class C { void operator !==(x) {} }"
|
||||
|
||||
UnsupportedPrefixPlus:
|
||||
template: "'+' is not a prefix operator."
|
||||
tip: "Try removing '+'."
|
||||
|
@ -2130,7 +2138,7 @@ InvalidOperator:
|
|||
analyzerCode: INVALID_OPERATOR
|
||||
dart2jsCode: "*fatal*"
|
||||
script:
|
||||
- "class C { void operator ===(x) {} }"
|
||||
- "class C { void operator %=(x) {} }"
|
||||
|
||||
OperatorParameterMismatch0:
|
||||
template: "Operator '#name' shouldn't have any parameters."
|
||||
|
|
|
@ -18,10 +18,6 @@ multiline_newline_test/04r: Pass
|
|||
multiline_newline_test/05: Pass
|
||||
multiline_newline_test/05r: Pass
|
||||
regress_29349_test: Pass
|
||||
unsupported_operators_test/01: MissingCompileTimeError
|
||||
unsupported_operators_test/02: MissingCompileTimeError
|
||||
unsupported_operators_test/03: MissingCompileTimeError
|
||||
unsupported_operators_test/04: MissingCompileTimeError
|
||||
void_type_function_types_test/04: MissingCompileTimeError
|
||||
void_type_function_types_test/06: MissingCompileTimeError
|
||||
void_type_function_types_test/08: MissingCompileTimeError
|
||||
|
|
Loading…
Reference in a new issue