Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(113)

Unified Diff: runtime/vm/ast.cc

Issue 1090373006: Properly resolve top-level setters (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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);
}
« no previous file with comments | « runtime/vm/ast.h ('k') | runtime/vm/ast_transformer.cc » ('j') | runtime/vm/ast_transformer.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698