Parse optional and named parameters.

I'm not a big fan of the currentParameterKind stack, this information is
almost accessible from parseFormalParameter(), but we don't pass the type
to the listener.

R=ahe@google.com, paulberry@google.com
BUG=

Review-Url: https://codereview.chromium.org/2709783003 .
This commit is contained in:
Konstantin Shcheglov 2017-02-23 09:55:15 -08:00
parent 86c1ef03ee
commit 4500bb0920
8 changed files with 91 additions and 74 deletions

View file

@ -333,20 +333,19 @@ class FastaParserTestCase extends Object
@override
FormalParameter parseFormalParameter(String code, ParameterKind kind,
{List<ErrorCode> errorCodes: const <ErrorCode>[]}) {
fasta.FormalParameterType type;
String parametersCode;
if (kind == ParameterKind.REQUIRED) {
type = fasta.FormalParameterType.REQUIRED;
parametersCode = '($code)';
} else if (kind == ParameterKind.POSITIONAL) {
type = fasta.FormalParameterType.POSITIONAL;
parametersCode = '([$code])';
} else if (kind == ParameterKind.NAMED) {
type = fasta.FormalParameterType.NAMED;
parametersCode = '({$code})';
} else {
fail('$kind');
}
return _runParser(
code,
(parser) => (token) => parser.parseFormalParameter(token, type),
errorCodes) as FormalParameter;
FormalParameterList list = parseFormalParameterList(parametersCode,
inFunctionType: false, errorCodes: errorCodes);
return list.parameters.single;
}
@override
@ -496,34 +495,6 @@ class FormalParameterParserTest_Fasta extends FastaParserTestCase
super.test_parseFormalParameter_covariant_var_positional();
}
@override
@failingTest
void test_parseFormalParameter_final_named() {
// TODO(scheglov): Unhandled event: ValuedFormalParameter
super.test_parseFormalParameter_final_named();
}
@override
@failingTest
void test_parseFormalParameter_final_positional() {
// TODO(scheglov): Unhandled event: ValuedFormalParameter
super.test_parseFormalParameter_final_positional();
}
@override
@failingTest
void test_parseFormalParameter_final_type_named() {
// TODO(scheglov): Unhandled event: ValuedFormalParameter
super.test_parseFormalParameter_final_type_named();
}
@override
@failingTest
void test_parseFormalParameter_final_type_positional() {
// TODO(scheglov): Unhandled event: ValuedFormalParameter
super.test_parseFormalParameter_final_type_positional();
}
@override
@failingTest
void test_parseFormalParameter_type_function() {
@ -531,34 +502,6 @@ class FormalParameterParserTest_Fasta extends FastaParserTestCase
super.test_parseFormalParameter_type_function();
}
@override
@failingTest
void test_parseFormalParameter_type_named() {
// TODO(scheglov): Unhandled event: ValuedFormalParameter
super.test_parseFormalParameter_type_named();
}
@override
@failingTest
void test_parseFormalParameter_type_positional() {
// TODO(scheglov): Unhandled event: ValuedFormalParameter
super.test_parseFormalParameter_type_positional();
}
@override
@failingTest
void test_parseFormalParameter_var_named() {
// TODO(scheglov): Unhandled event: ValuedFormalParameter
super.test_parseFormalParameter_var_named();
}
@override
@failingTest
void test_parseFormalParameter_var_positional() {
// TODO(scheglov): Unhandled event: ValuedFormalParameter
super.test_parseFormalParameter_var_positional();
}
@override
@failingTest
void test_parseFormalParameterList_named_multiple() {

View file

@ -6,6 +6,8 @@ library dart2js.parser.node_listener;
import '../common.dart';
import '../elements/elements.dart' show CompilationUnitElement;
import 'package:front_end/src/fasta/parser/parser.dart'
show FormalParameterType;
import 'package:front_end/src/fasta/scanner/precedence.dart' as Precedence
show INDEX_INFO;
import 'package:front_end/src/fasta/scanner.dart' show StringToken, Token;
@ -229,7 +231,7 @@ class NodeListener extends ElementListener {
}
@override
void endFormalParameter(Token thisKeyword) {
void endFormalParameter(Token thisKeyword, FormalParameterType kind) {
Expression name = popNode();
if (thisKeyword != null) {
Identifier thisIdentifier = new Identifier(thisKeyword);
@ -769,6 +771,10 @@ class NodeListener extends ElementListener {
new NodeList.singleton(defaultValue)));
}
@override
void handleFormalParameterWithoutValue(Token token) {
}
@override
void endTryStatement(int catchCount, Token tryKeyword, Token finallyKeyword) {
Block finallyBlock = null;

View file

@ -9,6 +9,8 @@ import 'package:analyzer/dart/ast/ast_factory.dart' show AstFactory;
import 'package:analyzer/dart/ast/standard_ast_factory.dart' as standard;
import 'package:analyzer/dart/ast/token.dart' as analyzer show Token;
import 'package:analyzer/dart/element/element.dart' show Element;
import 'package:front_end/src/fasta/parser/parser.dart'
show FormalParameterType;
import 'package:front_end/src/fasta/scanner/token.dart'
show BeginGroupToken, Token;
import 'package:kernel/ast.dart' show AsyncMarker;
@ -42,6 +44,11 @@ class AstBuilder extends ScopeListener {
@override
final Uri uri;
/// If `true`, the first call to [handleIdentifier] should push a
/// List<SimpleIdentifier> on the stack, and [handleQualified] should append
/// to the list.
var accumulateIdentifierComponents = false;
AstBuilder(this.library, this.member, this.elementStore, Scope scope,
[Uri uri])
: uri = uri ?? library.fileUri,
@ -470,8 +477,26 @@ class AstBuilder extends ScopeListener {
push(ast.throwExpression(toAnalyzerToken(throwToken), pop()));
}
void endFormalParameter(Token thisKeyword) {
@override
void endOptionalFormalParameters(
int count, Token beginToken, Token endToken) {
debugEvent("OptionalFormalParameters");
}
void handleValuedFormalParameter(Token equals, Token token) {
debugEvent("ValuedFormalParameter");
Expression value = pop();
push(new _ParameterDefaultValue(equals, value));
}
void handleFormalParameterWithoutValue(Token token) {
debugEvent("FormalParameterWithoutValue");
push(NullValue.ParameterDefaultValue);
}
void endFormalParameter(Token thisKeyword, FormalParameterType kind) {
debugEvent("FormalParameter");
_ParameterDefaultValue defaultValue = pop();
SimpleIdentifier name = pop();
TypeName type = pop();
Token keyword = _popOptionalSingleModifier();
@ -501,6 +526,11 @@ class AstBuilder extends ScopeListener {
formalParameters);
}
if (defaultValue != null) {
node = ast.defaultFormalParameter(node, _toAnalyzerParameterKind(kind),
toAnalyzerToken(defaultValue.separator), defaultValue.value);
}
scope[name.name] = name.staticElement = new AnalyzerParameterElement(node);
push(node);
}
@ -1177,6 +1207,16 @@ class AstBuilder extends ScopeListener {
return null;
}
}
ParameterKind _toAnalyzerParameterKind(FormalParameterType type) {
if (type == FormalParameterType.POSITIONAL) {
return ParameterKind.POSITIONAL;
} else if (type == FormalParameterType.NAMED) {
return ParameterKind.NAMED;
} else {
return ParameterKind.REQUIRED;
}
}
}
/// Data structure placed on the stack to represent a class body.
@ -1209,3 +1249,12 @@ class _MixinApplication {
_MixinApplication(this.supertype, this.withKeyword, this.mixinTypes);
}
/// Data structure placed on the stack to represent the default parameter
/// value with the separator token.
class _ParameterDefaultValue {
final Token separator;
final Expression value;
_ParameterDefaultValue(this.separator, this.value);
}

View file

@ -1277,7 +1277,7 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
}
@override
void endFormalParameter(Token thisKeyword) {
void endFormalParameter(Token thisKeyword, FormalParameterType kind) {
debugEvent("FormalParameter");
// TODO(ahe): Need beginToken here.
int charOffset = thisKeyword?.charOffset;
@ -1363,6 +1363,11 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
push(new InitializedIdentifier(name.name, initializer));
}
@override
void handleFormalParameterWithoutValue(Token token) {
debugEvent("FormalParameterWithoutValue");
}
@override
void endFormalParameters(int count, Token beginToken, Token endToken) {
debugEvent("FormalParameters");

View file

@ -9,6 +9,7 @@ import '../scanner/token.dart' show BeginGroupToken, Token;
import '../util/link.dart' show Link;
import 'error_kind.dart' show ErrorKind;
import 'parser.dart' show FormalParameterType;
import 'identifier_context.dart' show IdentifierContext;
@ -163,7 +164,7 @@ class Listener {
void beginFormalParameter(Token token) {}
void endFormalParameter(Token thisKeyword) {
void endFormalParameter(Token thisKeyword, FormalParameterType kind) {
logEvent("FormalParameter");
}
@ -901,6 +902,10 @@ class Listener {
logEvent("ValuedFormalParameter");
}
void handleFormalParameterWithoutValue(Token token) {
logEvent("FormalParameterWithoutValue");
}
void handleVoidKeyword(Token token) {
logEvent("VoidKeyword");
}

View file

@ -490,7 +490,7 @@ class Parser {
return expect(')', token);
}
Token parseFormalParameter(Token token, FormalParameterType type,
Token parseFormalParameter(Token token, FormalParameterType kind,
{bool inFunctionType: false}) {
token = parseMetadataStar(token, forParameter: true);
listener.beginFormalParameter(token);
@ -504,7 +504,7 @@ class Parser {
token = token.next;
}
token = parseModifiers(token);
bool isNamedParameter = type == FormalParameterType.NAMED;
bool isNamedParameter = kind == FormalParameterType.NAMED;
Token thisKeyword = null;
if (inFunctionType && isNamedParameter) {
@ -564,15 +564,17 @@ class Parser {
Token equal = token;
token = parseExpression(token.next);
listener.handleValuedFormalParameter(equal, token);
if (type.isRequired) {
if (kind.isRequired) {
reportRecoverableError(
equal, ErrorKind.RequiredParameterWithDefault);
} else if (type.isPositional && identical(':', value)) {
} else if (kind.isPositional && identical(':', value)) {
reportRecoverableError(
equal, ErrorKind.PositionalParameterWithEquals);
}
} else {
listener.handleFormalParameterWithoutValue(token);
}
listener.endFormalParameter(thisKeyword);
listener.endFormalParameter(thisKeyword, kind);
return token;
}

View file

@ -372,7 +372,7 @@ class OutlineBuilder extends UnhandledListener {
}
@override
void endFormalParameter(Token thisKeyword) {
void endFormalParameter(Token thisKeyword, FormalParameterType kind) {
debugEvent("FormalParameter");
String name = pop();
TypeBuilder type = pop();
@ -389,6 +389,12 @@ class OutlineBuilder extends UnhandledListener {
// Ignored for now.
}
@override
void handleFormalParameterWithoutValue(Token token) {
debugEvent("FormalParameterWithoutValue");
// Ignored for now.
}
@override
void endFunctionTypedFormalParameter(Token token) {
debugEvent("FunctionTypedFormalParameter");

View file

@ -35,6 +35,7 @@ enum NullValue {
Initializers,
Metadata,
Modifiers,
ParameterDefaultValue,
SwitchScope,
Type,
TypeArguments,