Fix more Analyzer tests

* Add "usingFastaParser" accessor for Analyzer engine tests
* Update Analyzer compile time error code tests
* Add additional checks for async/await/yield as identifiers
* Update built-in as type variable error message
* Check for "this." in local declaration parameters
* Remove unnecessary asserts

and address comment in https://dart-review.googlesource.com/c/sdk/+/57022

Change-Id: I54b5ac22f912289dad6360646fae7eca717bbd98
Reviewed-on: https://dart-review.googlesource.com/57220
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Dan Rubel <danrubel@google.com>
This commit is contained in:
danrubel 2018-05-31 00:25:03 +00:00 committed by commit-bot@chromium.org
parent fa9ff9a061
commit a53b585498
5 changed files with 151 additions and 32 deletions

View file

@ -1603,7 +1603,6 @@ class AstBuilder extends ScopeListener {
List<Configuration> configurations = pop();
StringLiteral uri = pop();
List<Annotation> metadata = pop();
assert(metadata == null); // TODO(paulberry): fix.
Comment comment = _findComment(metadata, importKeyword);
directives.add(ast.importDirective(
@ -1654,7 +1653,6 @@ class AstBuilder extends ScopeListener {
List<Configuration> configurations = pop();
StringLiteral uri = pop();
List<Annotation> metadata = pop();
assert(metadata == null);
Comment comment = _findComment(metadata, exportKeyword);
directives.add(ast.exportDirective(comment, metadata, exportKeyword, uri,
configurations, combinators, semicolon));
@ -2155,6 +2153,7 @@ class AstBuilder extends ScopeListener {
pop(); // separator before constructor initializers
}
FormalParameterList parameters = pop();
checkFieldFormalParameters(parameters);
SimpleIdentifier name = pop();
TypeAnnotation returnType = pop();
TypeParameterList typeParameters = pop();
@ -2342,15 +2341,7 @@ class AstBuilder extends ScopeListener {
handleRecoverableError(
messageConstMethod, modifiers.constKeyword, modifiers.constKeyword);
}
if (parameters?.parameters != null) {
parameters.parameters.forEach((FormalParameter param) {
if (param is FieldFormalParameter) {
// This error is reported in the BodyBuilder.endFormalParameter.
handleRecoverableError(messageFieldInitializerOutsideConstructor,
param.thisKeyword, param.thisKeyword);
}
});
}
checkFieldFormalParameters(parameters);
classDeclaration.members.add(ast.methodDeclaration(
comment,
metadata,
@ -2382,6 +2373,18 @@ class AstBuilder extends ScopeListener {
}
}
void checkFieldFormalParameters(FormalParameterList parameters) {
if (parameters?.parameters != null) {
parameters.parameters.forEach((FormalParameter param) {
if (param is FieldFormalParameter) {
// This error is reported in the BodyBuilder.endFormalParameter.
handleRecoverableError(messageFieldInitializerOutsideConstructor,
param.thisKeyword, param.thisKeyword);
}
});
}
}
@override
void handleInvalidMember(Token endToken) {
debugEvent("InvalidMember");

View file

@ -628,7 +628,11 @@ class A {
A(static this.x);
}''');
await computeAnalysisResult(source);
assertErrors(source, [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE]);
assertErrors(
source,
usingFastaParser
? [ParserErrorCode.EXTRANEOUS_MODIFIER]
: [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE]);
verify([source]);
}
@ -637,7 +641,11 @@ class A {
f(static x) {
}''');
await computeAnalysisResult(source);
assertErrors(source, [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE]);
assertErrors(
source,
usingFastaParser
? [ParserErrorCode.EXTRANEOUS_MODIFIER]
: [CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE]);
verify([source]);
}
@ -1350,14 +1358,28 @@ class A {
A(const this.x) {}
}''');
await computeAnalysisResult(source);
assertErrors(source, [CompileTimeErrorCode.CONST_FORMAL_PARAMETER]);
assertErrors(
source,
usingFastaParser
? [
CompileTimeErrorCode.CONST_FORMAL_PARAMETER,
ParserErrorCode.EXTRANEOUS_MODIFIER
]
: [CompileTimeErrorCode.CONST_FORMAL_PARAMETER]);
verify([source]);
}
test_constFormalParameter_simpleFormalParameter() async {
Source source = addSource("f(const x) {}");
await computeAnalysisResult(source);
assertErrors(source, [CompileTimeErrorCode.CONST_FORMAL_PARAMETER]);
assertErrors(
source,
usingFastaParser
? [
CompileTimeErrorCode.CONST_FORMAL_PARAMETER,
ParserErrorCode.EXTRANEOUS_MODIFIER
]
: [CompileTimeErrorCode.CONST_FORMAL_PARAMETER]);
verify([source]);
}
@ -1706,7 +1728,13 @@ typedef F = int Function([Map<String, String> m = const {}]);
Source source = addSource("typedef F([x = 0]);");
await computeAnalysisResult(source);
assertErrors(
source, [CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS]);
source,
usingFastaParser
? [
CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS,
ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE
]
: [CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS]);
verify([source]);
}
@ -1714,23 +1742,41 @@ typedef F = int Function([Map<String, String> m = const {}]);
Source source = addSource("typedef F([x = 0]);");
await computeAnalysisResult(source);
assertErrors(
source, [CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS]);
source,
usingFastaParser
? [
CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS,
ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE
]
: [CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS]);
verify([source]);
}
test_defaultValueInFunctionTypedParameter_named() async {
Source source = addSource("f(g({p: null})) {}");
await computeAnalysisResult(source);
assertErrors(source,
[CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER]);
assertErrors(
source,
usingFastaParser
? [
CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER,
ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE
]
: [CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER]);
verify([source]);
}
test_defaultValueInFunctionTypedParameter_optional() async {
Source source = addSource("f(g([p = null])) {}");
await computeAnalysisResult(source);
assertErrors(source,
[CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER]);
assertErrors(
source,
usingFastaParser
? [
CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER,
ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE
]
: [CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER]);
verify([source]);
}
@ -3589,7 +3635,16 @@ class A {
set x(v) async {}
}''');
await computeAnalysisResult(source);
assertErrors(source, [CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER]);
// TODO(danrubel): Investigate why error message is duplicated when
// using fasta parser.
assertErrors(
source,
usingFastaParser
? [
CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER,
CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER
]
: [CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER]);
verify([source]);
}
@ -3599,7 +3654,14 @@ class A {
set x(v) async* {}
}''');
await computeAnalysisResult(source);
assertErrors(source, [CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER]);
assertErrors(
source,
usingFastaParser
? [
CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER,
CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER
]
: [CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER]);
verify([source]);
}
@ -3609,28 +3671,56 @@ class A {
set x(v) sync* {}
}''');
await computeAnalysisResult(source);
assertErrors(source, [CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER]);
assertErrors(
source,
usingFastaParser
? [
CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER,
CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER
]
: [CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER]);
verify([source]);
}
test_invalidModifierOnSetter_topLevel_async() async {
Source source = addSource("set x(v) async {}");
await computeAnalysisResult(source);
assertErrors(source, [CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER]);
assertErrors(
source,
usingFastaParser
? [
CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER,
CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER
]
: [CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER]);
verify([source]);
}
test_invalidModifierOnSetter_topLevel_asyncStar() async {
Source source = addSource("set x(v) async* {}");
await computeAnalysisResult(source);
assertErrors(source, [CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER]);
assertErrors(
source,
usingFastaParser
? [
CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER,
CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER
]
: [CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER]);
verify([source]);
}
test_invalidModifierOnSetter_topLevel_syncStar() async {
Source source = addSource("set x(v) sync* {}");
await computeAnalysisResult(source);
assertErrors(source, [CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER]);
assertErrors(
source,
usingFastaParser
? [
CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER,
CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER
]
: [CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER]);
verify([source]);
}

View file

@ -23,6 +23,11 @@ import 'analysis_context_factory.dart';
* The class `EngineTestCase` defines utility methods for making assertions.
*/
class EngineTestCase {
/**
* Flag indicating whether the fasta parser is being used.
*/
bool get usingFastaParser => Parser.useFasta;
/**
* Assert that the given collection has the same number of elements as the number of specified
* names, and that for each specified name, a corresponding element can be found in the given

View file

@ -136,6 +136,7 @@ class ConstructorReferenceIdentifierContext extends IdentifierContext {
Token identifier = token.next;
assert(identifier.kind != IDENTIFIER_TOKEN);
if (identifier.isIdentifier) {
checkAsyncAwaitYieldAsIdentifier(identifier, parser);
return identifier;
}
@ -369,6 +370,7 @@ class FormalParameterDeclarationIdentifierContext extends IdentifierContext {
Token identifier = token.next;
assert(identifier.kind != IDENTIFIER_TOKEN);
if (identifier.isIdentifier) {
checkAsyncAwaitYieldAsIdentifier(identifier, parser);
return identifier;
}
@ -732,6 +734,7 @@ class NamedArgumentReferenceIdentifierContext extends IdentifierContext {
Token identifier = token.next;
assert(identifier.kind != IDENTIFIER_TOKEN);
if (identifier.isIdentifier) {
checkAsyncAwaitYieldAsIdentifier(identifier, parser);
return identifier;
}
@ -902,18 +905,25 @@ class TypeVariableDeclarationIdentifierContext extends IdentifierContext {
}
// Recovery
parser.reportRecoverableErrorWithToken(
identifier, fasta.templateExpectedIdentifier);
const followingValues = const ['<', '>', ';', '}', 'extends', 'super'];
if (looksLikeStartOfNextTopLevelDeclaration(identifier) ||
looksLikeStartOfNextClassMember(identifier) ||
looksLikeStartOfNextStatement(identifier) ||
isOneOfOrEof(identifier, followingValues)) {
parser.reportRecoverableErrorWithToken(
identifier, fasta.templateExpectedIdentifier);
identifier = parser.rewriter.insertSyntheticIdentifier(token);
} else if (identifier.type.isBuiltIn) {
parser.reportRecoverableErrorWithToken(
identifier, fasta.templateBuiltInIdentifierInDeclaration);
} else {
// When in doubt, consume the token to ensure we make progress
// but insert a synthetic identifier to satisfy listeners.
identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
parser.reportRecoverableErrorWithToken(
identifier, fasta.templateExpectedIdentifier);
if (!identifier.isKeywordOrIdentifier) {
// When in doubt, consume the token to ensure we make progress
// but insert a synthetic identifier to satisfy listeners.
identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
}
}
return identifier;
}

View file

@ -5480,6 +5480,17 @@ class Parser {
if (!exceptionName.isSynthetic) {
reportRecoverableError(comma, fasta.messageCatchSyntax);
}
// TODO(danrubel): Consider inserting synthetic identifier if
// exceptionName is a non-synthetic identifier followed by `.`.
// Then this
// } catch (
// e.f();
// will recover to
// } catch (_s_) {}
// e.f();
// rather than
// } catch (e) {}
// _s_.f();
if (openParens.endGroup.isSynthetic) {
// The scanner did not place the synthetic ')' correctly.
rewriter.moveSynthetic(exceptionName, openParens.endGroup);