| Index: runtime/vm/parser.cc
|
| diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
|
| index 832ddd9e2032039ea5592b4cd88353308dfd66e2..8626a5f91f2a31ff50b019d4a65dccb289b76b8c 100644
|
| --- a/runtime/vm/parser.cc
|
| +++ b/runtime/vm/parser.cc
|
| @@ -48,6 +48,8 @@ DEFINE_FLAG(bool, warn_mixin_typedef, true, "Warning on legacy mixin typedef.");
|
| // committed to the current version.
|
| DEFINE_FLAG(bool, conditional_directives, true,
|
| "Enable conditional directives");
|
| +DEFINE_FLAG(bool, initializing_formal_access, false,
|
| + "Make initializing formal parameters visible in initializer list.");
|
| DEFINE_FLAG(bool, warn_super, false,
|
| "Warning if super initializer not last in initializer list.");
|
| DEFINE_FLAG(bool, await_is_keyword, false,
|
| @@ -697,12 +699,23 @@ struct ParamList {
|
| for (int i = 0; i < num_params; i++) {
|
| ParamDesc& param = (*parameters)[i];
|
| ASSERT(param.var != NULL);
|
| - if (!param.is_field_initializer) {
|
| + if (FLAG_initializing_formal_access || !param.is_field_initializer) {
|
| param.var->set_invisible(invisible);
|
| }
|
| }
|
| }
|
|
|
| + void HideInitFormals() {
|
| + const intptr_t num_params = parameters->length();
|
| + for (int i = 0; i < num_params; i++) {
|
| + ParamDesc& param = (*parameters)[i];
|
| + if (param.is_field_initializer) {
|
| + ASSERT(param.var != NULL);
|
| + param.var->set_invisible(true);
|
| + }
|
| + }
|
| + }
|
| +
|
| void SetImplicitlyFinal() {
|
| implicitly_final = true;
|
| }
|
| @@ -1948,6 +1961,7 @@ void Parser::ParseFormalParameter(bool allow_explicit_default_value,
|
| TRACE_PARSER("ParseFormalParameter");
|
| ParamDesc parameter;
|
| bool var_seen = false;
|
| + bool final_seen = false;
|
| bool this_seen = false;
|
|
|
| if (evaluate_metadata && (CurrentToken() == Token::kAT)) {
|
| @@ -1958,6 +1972,7 @@ void Parser::ParseFormalParameter(bool allow_explicit_default_value,
|
|
|
| if (CurrentToken() == Token::kFINAL) {
|
| ConsumeToken();
|
| + final_seen = true;
|
| parameter.is_final = true;
|
| } else if (CurrentToken() == Token::kVAR) {
|
| ConsumeToken();
|
| @@ -1972,6 +1987,9 @@ void Parser::ParseFormalParameter(bool allow_explicit_default_value,
|
| ExpectToken(Token::kPERIOD);
|
| this_seen = true;
|
| parameter.is_field_initializer = true;
|
| + if (FLAG_initializing_formal_access) {
|
| + parameter.is_final = true;
|
| + }
|
| }
|
| if ((parameter.type == NULL) && (CurrentToken() == Token::kVOID)) {
|
| ConsumeToken();
|
| @@ -2013,6 +2031,9 @@ void Parser::ParseFormalParameter(bool allow_explicit_default_value,
|
| ExpectToken(Token::kPERIOD);
|
| this_seen = true;
|
| parameter.is_field_initializer = true;
|
| + if (FLAG_initializing_formal_access) {
|
| + parameter.is_final = true;
|
| + }
|
| }
|
|
|
| // At this point, we must see an identifier for the parameter name.
|
| @@ -2042,7 +2063,11 @@ void Parser::ParseFormalParameter(bool allow_explicit_default_value,
|
| // This parameter is probably a closure. If we saw the keyword 'var'
|
| // or 'final', a closure is not legal here and we ignore the
|
| // opening parens.
|
| - if (!var_seen && !parameter.is_final) {
|
| + // TODO(hausner): The language spec appears to allow var and final
|
| + // in signature types when used with initializing formals:
|
| + // fieldFormalParameter:
|
| + // metadata finalConstVarOrType? this ‘.’ identifier formalParameterList? ;
|
| + if (!var_seen && !final_seen) {
|
| // The parsed parameter type is actually the function result type.
|
| const AbstractType& result_type =
|
| AbstractType::Handle(Z, parameter.type->raw());
|
| @@ -3248,7 +3273,6 @@ SequenceNode* Parser::ParseConstructor(const Function& func) {
|
| // Thus, they are set to be invisible when added to the scope.
|
| LocalVariable* p = param.var;
|
| ASSERT(p != NULL);
|
| - ASSERT(p->is_invisible());
|
| AstNode* value = new LoadLocalNode(param.name_pos, p);
|
| EnsureExpressionTemp();
|
| AstNode* initializer =
|
| @@ -3278,6 +3302,9 @@ SequenceNode* Parser::ParseConstructor(const Function& func) {
|
|
|
| // Parsing of initializers done. Now we parse the constructor body.
|
| OpenBlock(); // Block to collect constructor body nodes.
|
| + if (FLAG_initializing_formal_access) {
|
| + params.HideInitFormals();
|
| + }
|
| if (CurrentToken() == Token::kLBRACE) {
|
| // We checked in the top-level parse phase that a redirecting
|
| // constructor does not have a body.
|
| @@ -7468,7 +7495,10 @@ void Parser::AddFormalParamsToScope(const ParamList* params,
|
| if (param_desc.is_final) {
|
| parameter->set_is_final();
|
| }
|
| - if (param_desc.is_field_initializer) {
|
| + if (FLAG_initializing_formal_access) {
|
| + // Field initializer parameters are implicitly final.
|
| + ASSERT(!param_desc.is_field_initializer || param_desc.is_final);
|
| + } else if (param_desc.is_field_initializer) {
|
| parameter->set_invisible(true);
|
| }
|
| }
|
|
|