| Index: runtime/vm/parser.cc
|
| ===================================================================
|
| --- runtime/vm/parser.cc (revision 2391)
|
| +++ runtime/vm/parser.cc (working copy)
|
| @@ -31,9 +31,10 @@
|
| static const char* kAssertionErrorName = "AssertionError";
|
| static const char* kFallThroughErrorName = "FallThroughError";
|
| static const char* kThrowNewName = "_throwNew";
|
| -static const char* kLiteralFactoryClassName = "_LiteralFactory";
|
| -static const char* kLiteralFactoryListFromLiteralName = "List.fromLiteral";
|
| -static const char* kLiteralFactoryMapFromLiteralName = "Map.fromLiteral";
|
| +static const char* kListLiteralFactoryClassName = "_ListLiteralFactory";
|
| +static const char* kListLiteralFactoryName = "List.fromLiteral";
|
| +static const char* kMapLiteralFactoryClassName = "_MapLiteralFactory";
|
| +static const char* kMapLiteralFactoryName = "Map.fromLiteral";
|
| static const char* kImmutableMapName = "ImmutableMap";
|
| static const char* kImmutableMapConstructorName = "ImmutableMap._create";
|
| static const char* kStringClassName = "StringBase";
|
| @@ -566,7 +567,6 @@
|
| case RawFunction::kGetterFunction:
|
| case RawFunction::kSetterFunction:
|
| case RawFunction::kConstructor:
|
| - ASSERT(!func.IsFactory() || (func.signature_class() != Class::null()));
|
| node_sequence = parser.ParseFunc(func, default_parameter_values);
|
| break;
|
| case RawFunction::kImplicitGetter:
|
| @@ -2326,9 +2326,6 @@
|
| member.name = CurrentLiteral();
|
| member.name_pos = this->token_index_;
|
| ConsumeToken();
|
| - // Resolution of the factory result type is always postponed until class
|
| - // finalization, so that the list of type parameters in the factory
|
| - // signature can be checked at the same time.
|
| if (member.has_factory) {
|
| String& qualifier = String::Handle();
|
| if (CurrentToken() == Token::kPERIOD) {
|
| @@ -2341,6 +2338,9 @@
|
| member.name = ExpectIdentifier("identifier expected");
|
| }
|
| }
|
| + // TODO(regis): Remove support for type parameters on factories.
|
| + // Once done, stop postponing resolution of the factory result type until
|
| + // class finalization.
|
| const UnresolvedClass& unresolved_factory_class =
|
| UnresolvedClass::Handle(UnresolvedClass::New(member.name_pos,
|
| qualifier,
|
| @@ -2356,6 +2356,13 @@
|
| member.type = &Type::ZoneHandle(
|
| Type::NewParameterizedType(unresolved_factory_class, args));
|
| ParseTypeParameters(signature_class);
|
| + if (signature_class.NumTypeParameters() > 0) {
|
| + Warning("factory method '%s' should not declare type parameters.\n",
|
| + member.name->ToCString());
|
| + } else {
|
| + // Remove factory signature class, since no type parameters declared.
|
| + unresolved_factory_class.set_factory_signature_class(Class::Handle());
|
| + }
|
| }
|
| // We must be dealing with a constructor or named constructor.
|
| member.kind = RawFunction::kConstructor;
|
| @@ -2746,7 +2753,12 @@
|
| AddInterfaces(interfaces_pos, interface, interfaces);
|
| }
|
|
|
| - if (CurrentToken() == Token::kFACTORY) {
|
| + // TODO(regis): Remove support for "factory" keyword.
|
| + if ((CurrentToken() == Token::kDEFAULT) ||
|
| + (CurrentToken() == Token::kFACTORY)) {
|
| + if (CurrentToken() == Token::kFACTORY) {
|
| + Warning("'factory' is obsolete, use 'default' instead.");
|
| + }
|
| ConsumeToken();
|
| const intptr_t factory_pos = token_index_;
|
| QualIdent factory_name;
|
| @@ -2762,14 +2774,53 @@
|
| }
|
| const UnresolvedClass& unresolved_factory_class = UnresolvedClass::Handle(
|
| UnresolvedClass::New(factory_pos, qualifier, *(factory_name.ident)));
|
| - const Class& signature_class = Class::Handle(
|
| + const Class& factory_class = Class::Handle(
|
| Class::New(String::Handle(String::NewSymbol(":factory_signature")),
|
| script_));
|
| - signature_class.set_library(library_);
|
| - signature_class.set_is_finalized();
|
| - ParseTypeParameters(signature_class);
|
| - unresolved_factory_class.set_factory_signature_class(signature_class);
|
| + factory_class.set_library(library_);
|
| + factory_class.set_is_finalized();
|
| + ParseTypeParameters(factory_class);
|
| + unresolved_factory_class.set_factory_signature_class(factory_class);
|
| interface.set_factory_class(unresolved_factory_class);
|
| + // Verify that the type parameters of the factory class and of the interface
|
| + // have identical names.
|
| + const intptr_t num_type_params = factory_class.NumTypeParameters();
|
| + bool mismatch = interface.NumTypeParameters() != num_type_params;
|
| + if (mismatch && (num_type_params == 0)) {
|
| + // TODO(regis): For now, and until the core lib is fixed, we accept a
|
| + // factory clause with a class missing its list of type parameters.
|
| + // See bug 5408808.
|
| + const String& interface_name = String::Handle(interface.Name());
|
| + const String& factory_name = String::Handle(factory_class.Name());
|
| + Warning(factory_pos,
|
| + "class '%s' in default clause of interface '%s' is "
|
| + "missing its type parameter list.\n",
|
| + factory_name.ToCString(),
|
| + interface_name.ToCString());
|
| + } else {
|
| + String& interface_type_param_name = String::Handle();
|
| + String& factory_type_param_name = String::Handle();
|
| + const Array& interface_type_param_names =
|
| + Array::Handle(interface.type_parameters());
|
| + const Array& factory_type_param_names =
|
| + Array::Handle(factory_class.type_parameters());
|
| + for (intptr_t i = 0; !mismatch && (i < num_type_params); i++) {
|
| + interface_type_param_name ^= interface_type_param_names.At(i);
|
| + factory_type_param_name ^= factory_type_param_names.At(i);
|
| + if (!interface_type_param_name.Equals(factory_type_param_name)) {
|
| + mismatch = true;
|
| + }
|
| + }
|
| + if (mismatch) {
|
| + const String& interface_name = String::Handle(interface.Name());
|
| + const String& factory_name = String::Handle(factory_class.Name());
|
| + ErrorMsg(factory_pos,
|
| + "mismatch in number or names of type parameters between "
|
| + "interface '%s' and default factory class '%s'.\n",
|
| + interface_name.ToCString(),
|
| + factory_name.ToCString());
|
| + }
|
| + }
|
| }
|
|
|
| ExpectToken(Token::kLBRACE);
|
| @@ -6162,20 +6213,12 @@
|
| ASSERT(!factory_result_type.IsNull());
|
| const UnresolvedClass& unresolved_factory_class =
|
| UnresolvedClass::Handle(factory_result_type.unresolved_class());
|
| - // TODO(regis): For now, and until the core lib is fixed, we accept a
|
| - // factory method with missing list of type parameters and use the
|
| - // list of the enclosing class.
|
| - // See bug 5408808.
|
| - // Therefore, we temporarily return the current class instead of the
|
| - // factory signature class if the latter one does not declare any type
|
| - // parameters.
|
| - const Class& factory_signature_class =
|
| - Class::Handle(unresolved_factory_class.factory_signature_class());
|
| - if (factory_signature_class.NumTypeParameters() == 0) {
|
| - return current_class().raw();
|
| - } else {
|
| - return factory_signature_class.raw();
|
| + // TODO(regis): Remove support for type parameters declared by factory
|
| + // methods.
|
| + if (unresolved_factory_class.factory_signature_class() != Class::null()) {
|
| + return unresolved_factory_class.factory_signature_class();
|
| }
|
| + return current_class().raw();
|
| }
|
| if ((current_member_ == NULL) || !current_member_->has_static) {
|
| return current_class().raw();
|
| @@ -6187,7 +6230,12 @@
|
| outer_function = outer_function.parent_function();
|
| }
|
| if (outer_function.IsFactory()) {
|
| - return outer_function.signature_class();
|
| + // TODO(regis): Remove support for type parameters declared by factory
|
| + // methods.
|
| + if (outer_function.signature_class() != Class::null()) {
|
| + return outer_function.signature_class();
|
| + }
|
| + return current_class().raw();
|
| }
|
| if (!outer_function.is_static()) {
|
| return current_class().raw();
|
| @@ -6205,8 +6253,11 @@
|
| outer_function = outer_function.parent_function();
|
| }
|
| if (outer_function.IsFactory()) {
|
| - const Class& signature_class =
|
| - Class::Handle(outer_function.signature_class());
|
| + // TODO(regis): Remove support for type parameters on factories.
|
| + Class& signature_class = Class::Handle(outer_function.signature_class());
|
| + if (signature_class.IsNull()) {
|
| + return current_class().NumTypeParameters() > 0;
|
| + }
|
| return signature_class.NumTypeParameters() > 0;
|
| }
|
| if (!outer_function.is_static()) {
|
| @@ -6619,8 +6670,10 @@
|
| intptr_t pos, Function& constructor,
|
| const AbstractTypeArguments& type_arguments) {
|
| if (!type_arguments.IsNull()) {
|
| + // TODO(regis): Remove support for type parameters on factories.
|
| Class& signature_class = Class::Handle();
|
| - if (constructor.IsFactory()) {
|
| + if (constructor.IsFactory() &&
|
| + (constructor.signature_class() != Class::null())) {
|
| signature_class = constructor.signature_class();
|
| } else {
|
| signature_class = constructor.owner();
|
| @@ -6735,16 +6788,16 @@
|
| return new LiteralNode(literal_pos, const_list);
|
| } else {
|
| // Factory call at runtime.
|
| - String& literal_factory_class_name = String::Handle(
|
| - String::NewSymbol(kLiteralFactoryClassName));
|
| - const Class& literal_factory_class =
|
| - Class::Handle(LookupCoreClass(literal_factory_class_name));
|
| - ASSERT(!literal_factory_class.IsNull());
|
| - const String& literal_list_factory_name =
|
| - String::Handle(String::NewSymbol(kLiteralFactoryListFromLiteralName));
|
| - const Function& literal_list_factory = Function::ZoneHandle(
|
| - literal_factory_class.LookupFactory(literal_list_factory_name));
|
| - ASSERT(!literal_list_factory.IsNull());
|
| + String& list_literal_factory_class_name = String::Handle(
|
| + String::NewSymbol(kListLiteralFactoryClassName));
|
| + const Class& list_literal_factory_class =
|
| + Class::Handle(LookupCoreClass(list_literal_factory_class_name));
|
| + ASSERT(!list_literal_factory_class.IsNull());
|
| + const String& list_literal_factory_name =
|
| + String::Handle(String::NewSymbol(kListLiteralFactoryName));
|
| + const Function& list_literal_factory = Function::ZoneHandle(
|
| + list_literal_factory_class.LookupFactory(list_literal_factory_name));
|
| + ASSERT(!list_literal_factory.IsNull());
|
| if (!type_arguments.IsNull() &&
|
| !type_arguments.IsInstantiated() &&
|
| (current_block_->scope->function_level() > 0)) {
|
| @@ -6757,7 +6810,7 @@
|
| AbstractTypeArguments::ZoneHandle(type_arguments.Canonicalize());
|
| return new ConstructorCallNode(literal_pos,
|
| canonical_type_arguments,
|
| - literal_list_factory,
|
| + list_literal_factory,
|
| factory_param);
|
| }
|
| }
|
| @@ -6938,16 +6991,16 @@
|
| }
|
| } else {
|
| // Factory call at runtime.
|
| - String& literal_factory_class_name = String::Handle(
|
| - String::NewSymbol(kLiteralFactoryClassName));
|
| - const Class& literal_factory_class =
|
| - Class::Handle(LookupCoreClass(literal_factory_class_name));
|
| - ASSERT(!literal_factory_class.IsNull());
|
| - const String& literal_map_factory_name =
|
| - String::Handle(String::NewSymbol(kLiteralFactoryMapFromLiteralName));
|
| - const Function& literal_map_factory = Function::ZoneHandle(
|
| - literal_factory_class.LookupFactory(literal_map_factory_name));
|
| - ASSERT(!literal_map_factory.IsNull());
|
| + String& map_literal_factory_class_name = String::Handle(
|
| + String::NewSymbol(kMapLiteralFactoryClassName));
|
| + const Class& map_literal_factory_class =
|
| + Class::Handle(LookupCoreClass(map_literal_factory_class_name));
|
| + ASSERT(!map_literal_factory_class.IsNull());
|
| + const String& map_literal_factory_name =
|
| + String::Handle(String::NewSymbol(kMapLiteralFactoryName));
|
| + const Function& map_literal_factory = Function::ZoneHandle(
|
| + map_literal_factory_class.LookupFactory(map_literal_factory_name));
|
| + ASSERT(!map_literal_factory.IsNull());
|
| if (!map_type_arguments.IsNull() &&
|
| !map_type_arguments.IsInstantiated() &&
|
| (current_block_->scope->function_level() > 0)) {
|
| @@ -6958,7 +7011,7 @@
|
| factory_param->Add(kv_pairs);
|
| return new ConstructorCallNode(literal_pos,
|
| map_type_arguments,
|
| - literal_map_factory,
|
| + map_literal_factory,
|
| factory_param);
|
| }
|
| }
|
| @@ -7146,8 +7199,10 @@
|
| // Now that the constructor to be called is identified, finalize the type
|
| // argument vector to be passed.
|
| {
|
| + // TODO(regis): Remove support for type parameters on factories.
|
| Class& signature_class = Class::Handle();
|
| - if (constructor.IsFactory()) {
|
| + if (constructor.IsFactory() &&
|
| + (constructor.signature_class() != Class::null())) {
|
| signature_class = constructor.signature_class();
|
| } else {
|
| signature_class = constructor.owner();
|
|
|