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); |
} |
} |