Chromium Code Reviews| Index: runtime/vm/ast.cc |
| =================================================================== |
| --- runtime/vm/ast.cc (revision 45315) |
| +++ runtime/vm/ast.cc (working copy) |
| @@ -561,34 +561,116 @@ |
| AstNode* StaticGetterNode::MakeAssignmentNode(AstNode* rhs) { |
| if (is_super_getter()) { |
| ASSERT(receiver() != NULL); |
| - // If the static setter is not found in the superclass, noSuchMethod will be |
| - // called at runtime. |
| + const String& setter_name = |
| + String::ZoneHandle(Field::SetterSymbol(field_name_)); |
| + Function& setter = Function::ZoneHandle( |
| + Resolver::ResolveDynamicAnyArgs(cls(), setter_name)); |
| + if (setter.IsNull() || setter.is_abstract()) { |
| + // No instance setter found in super class chain, |
| + // noSuchMethod will be called at runtime. |
| + return new StaticSetterNode(token_pos(), |
| + receiver(), |
| + cls(), |
| + field_name_, |
| + rhs); |
| + } |
| return new StaticSetterNode(token_pos(), |
| receiver(), |
| - cls(), |
| - field_name(), |
| + field_name_, |
| + setter, |
| rhs); |
| } |
| + if (owner().IsLibraryPrefix()) { |
| + const LibraryPrefix& prefix = LibraryPrefix::Cast(owner_); |
| + // The parser has already dealt with the pathological case where a |
| + // library imports itself. See Parser::ResolveIdentInPrefixScope() |
| + ASSERT(field_name_.CharAt(0) != Library::kPrivateIdentifierStart); |
| + |
| + // If the prefix is not yet loaded, the getter doesn't exist. Return a |
| + // setter that will throw a NSME at runtime. |
| + if (!prefix.is_loaded()) { |
| + return new StaticSetterNode(token_pos(), NULL, cls(), field_name_, rhs); |
| + } |
| + |
| + Object& obj = Object::Handle(prefix.LookupObject(field_name_)); |
| + if (obj.IsField()) { |
| + const Field& field = Field::ZoneHandle(Field::Cast(obj).raw()); |
| + if (!field.is_final()) { |
| + if (Isolate::Current()->TypeChecksEnabled()) { |
| + rhs = new AssignableNode(field.token_pos(), |
| + rhs, |
| + AbstractType::ZoneHandle(field.type()), |
| + field_name_); |
| + } |
| + return new StoreStaticFieldNode(token_pos(), field, rhs); |
|
regis
2015/04/21 17:30:30
Indent lines 600-606.
hausner
2015/04/21 17:40:11
Done.
|
| + } |
| + } |
| + |
| + // No field found in prefix. Look for a setter function. |
| + const String& setter_name = String::Handle(Field::SetterName(field_name_)); |
| + obj = prefix.LookupObject(setter_name); |
| + if (obj.IsFunction()) { |
| + const Function& setter = Function::ZoneHandle(Function::Cast(obj).raw()); |
| + ASSERT(setter.is_static() && setter.IsSetterFunction()); |
| + return new StaticSetterNode( |
| + token_pos(), NULL, field_name_, setter, rhs); |
| + } |
| + |
| + // No writeable field and no setter found in the prefix. Return a |
| + // non-existing setter that will throw an NSM error. |
| + return new StaticSetterNode(token_pos(), NULL, cls(), field_name_, rhs); |
| + } |
| + |
| + if (owner().IsLibrary()) { |
| + const Library& library = Library::Cast(owner()); |
| + Object& obj = Object::Handle(library.ResolveName(field_name_)); |
| + if (obj.IsField()) { |
| + const Field& field = Field::ZoneHandle(Field::Cast(obj).raw()); |
| + if (!field.is_final()) { |
| + if (Isolate::Current()->TypeChecksEnabled()) { |
| + rhs = new AssignableNode(field.token_pos(), |
| + rhs, |
| + AbstractType::ZoneHandle(field.type()), |
| + field_name_); |
| + } |
| + return new StoreStaticFieldNode(token_pos(), field, rhs); |
| + } |
| + } |
| + |
| + // No field found in library. Look for a setter function. |
| + const String& setter_name = String::Handle(Field::SetterName(field_name_)); |
| + obj = library.ResolveName(setter_name); |
| + if (obj.IsFunction()) { |
| + const Function& setter = Function::ZoneHandle(Function::Cast(obj).raw()); |
| + ASSERT(setter.is_static() && setter.IsSetterFunction()); |
| + return new StaticSetterNode(token_pos(), NULL, field_name_, setter, rhs); |
| + } |
| + |
| + // No writeable field and no setter found in the library. Return a |
| + // non-existing setter that will throw an NSM error. |
| + return new StaticSetterNode(token_pos(), NULL, cls(), field_name_, rhs); |
| + } |
| + |
| const Function& setter = |
| - Function::Handle(cls().LookupSetterFunction(field_name())); |
| + Function::ZoneHandle(cls().LookupSetterFunction(field_name_)); |
| if (!setter.IsNull() && setter.IsStaticFunction()) { |
| - return new StaticSetterNode(token_pos(), NULL, cls(), field_name(), rhs); |
| + return new StaticSetterNode(token_pos(), NULL, field_name_, setter, rhs); |
| } |
| // Could not find a static setter. Look for a field. |
| // Access to a lazily initialized static field that has not yet been |
| // initialized is compiled to a static implicit getter. |
| // A setter may not exist for such a field. |
| - const Field& field = Field::ZoneHandle(cls().LookupStaticField(field_name())); |
| + const Field& field = Field::ZoneHandle(cls().LookupStaticField(field_name_)); |
| if (!field.IsNull()) { |
| if (field.is_final()) { |
| // Attempting to assign to a final variable will cause a NoSuchMethodError |
| // to be thrown. Change static getter to non-existent static setter in |
| // order to trigger the throw at runtime. |
| - return new StaticSetterNode(token_pos(), NULL, cls(), field_name(), rhs); |
| + return new StaticSetterNode(token_pos(), NULL, cls(), field_name_, rhs); |
| } |
| #if defined(DEBUG) |
| - const String& getter_name = String::Handle(Field::GetterName(field_name())); |
| + const String& getter_name = String::Handle(Field::GetterName(field_name_)); |
| const Function& getter = |
| Function::Handle(cls().LookupStaticFunction(getter_name)); |
| ASSERT(!getter.IsNull() && |
| @@ -605,7 +687,7 @@ |
| } |
| // Didn't find a static setter or a static field. Make a call to |
| // the non-existent setter to trigger a NoSuchMethodError at runtime. |
| - return new StaticSetterNode(token_pos(), NULL, cls(), field_name(), rhs); |
| + return new StaticSetterNode(token_pos(), NULL, cls(), field_name_, rhs); |
| } |