diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart index 996e96596c4..f62baf874f3 100644 --- a/pkg/analyzer/test/generated/parser_fasta_test.dart +++ b/pkg/analyzer/test/generated/parser_fasta_test.dart @@ -333,20 +333,19 @@ class FastaParserTestCase extends Object @override FormalParameter parseFormalParameter(String code, ParameterKind kind, {List errorCodes: const []}) { - 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() { diff --git a/pkg/compiler/lib/src/parser/node_listener.dart b/pkg/compiler/lib/src/parser/node_listener.dart index f5336291009..0cd290a50fd 100644 --- a/pkg/compiler/lib/src/parser/node_listener.dart +++ b/pkg/compiler/lib/src/parser/node_listener.dart @@ -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; diff --git a/pkg/front_end/lib/src/fasta/analyzer/ast_builder.dart b/pkg/front_end/lib/src/fasta/analyzer/ast_builder.dart index 119629b9add..e357b9cd89b 100644 --- a/pkg/front_end/lib/src/fasta/analyzer/ast_builder.dart +++ b/pkg/front_end/lib/src/fasta/analyzer/ast_builder.dart @@ -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 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); +} diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart index f6d25058190..67c49ed80e6 100644 --- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart +++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart @@ -1277,7 +1277,7 @@ class BodyBuilder extends ScopeListener 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 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"); diff --git a/pkg/front_end/lib/src/fasta/parser/listener.dart b/pkg/front_end/lib/src/fasta/parser/listener.dart index c819aaace1e..9e0427436db 100644 --- a/pkg/front_end/lib/src/fasta/parser/listener.dart +++ b/pkg/front_end/lib/src/fasta/parser/listener.dart @@ -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"); } diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart index f7d33a5bcf6..65f41aed105 100644 --- a/pkg/front_end/lib/src/fasta/parser/parser.dart +++ b/pkg/front_end/lib/src/fasta/parser/parser.dart @@ -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; } diff --git a/pkg/front_end/lib/src/fasta/source/outline_builder.dart b/pkg/front_end/lib/src/fasta/source/outline_builder.dart index 94738758aaf..557a9e56968 100644 --- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart +++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart @@ -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"); diff --git a/pkg/front_end/lib/src/fasta/source/stack_listener.dart b/pkg/front_end/lib/src/fasta/source/stack_listener.dart index 0e77bb63dc9..e4367f52b07 100644 --- a/pkg/front_end/lib/src/fasta/source/stack_listener.dart +++ b/pkg/front_end/lib/src/fasta/source/stack_listener.dart @@ -35,6 +35,7 @@ enum NullValue { Initializers, Metadata, Modifiers, + ParameterDefaultValue, SwitchScope, Type, TypeArguments,