| Index: runtime/vm/parser.cc
|
| ===================================================================
|
| --- runtime/vm/parser.cc (revision 14582)
|
| +++ runtime/vm/parser.cc (working copy)
|
| @@ -584,46 +584,63 @@
|
|
|
| bool FunctionNameExists(const String& name, RawFunction::Kind kind) const {
|
| // First check if a function or field of same name exists.
|
| - if (NameExists<Function>(functions_, name) ||
|
| - NameExists<Field>(fields_, name)) {
|
| + if (FunctionExists(name)) {
|
| return true;
|
| }
|
| - String& accessor_name = String::Handle();
|
| - if (kind != RawFunction::kSetterFunction) {
|
| - // Check if a getter function of same name exists.
|
| - accessor_name = Field::GetterName(name);
|
| - if (NameExists<Function>(functions_, accessor_name)) {
|
| + // Now check whether there is a field and whether its implicit getter
|
| + // or setter collides with the name.
|
| + Field* field = LookupField(name);
|
| + if (field != NULL) {
|
| + if (kind == RawFunction::kSetterFunction) {
|
| + // It's ok to have an implicit getter, it does not collide with
|
| + // this setter function.
|
| + if (!field->is_final()) {
|
| + return true;
|
| + }
|
| + } else {
|
| + // The implicit getter of the field collides with the name.
|
| return true;
|
| }
|
| }
|
| - if (kind != RawFunction::kGetterFunction) {
|
| +
|
| + String& accessor_name = String::Handle();
|
| + if (kind == RawFunction::kSetterFunction) {
|
| // Check if a setter function of same name exists.
|
| accessor_name = Field::SetterName(name);
|
| - if (NameExists<Function>(functions_, accessor_name)) {
|
| + if (FunctionExists(accessor_name)) {
|
| return true;
|
| }
|
| + } else {
|
| + // Check if a getter function of same name exists.
|
| + accessor_name = Field::GetterName(name);
|
| + if (FunctionExists(accessor_name)) {
|
| + return true;
|
| + }
|
| }
|
| return false;
|
| }
|
|
|
| - bool FieldNameExists(const String& name) const {
|
| + bool FieldNameExists(const String& name, bool check_setter) const {
|
| // First check if a function or field of same name exists.
|
| - if (NameExists<Function>(functions_, name) ||
|
| - NameExists<Field>(fields_, name)) {
|
| + if (FunctionExists(name) || FieldExists(name)) {
|
| return true;
|
| }
|
| // Now check if a getter/setter function of same name exists.
|
| String& getter_name = String::Handle(Field::GetterName(name));
|
| - String& setter_name = String::Handle(Field::SetterName(name));
|
| - if (NameExists<Function>(functions_, getter_name) ||
|
| - NameExists<Function>(functions_, setter_name)) {
|
| + if (FunctionExists(getter_name)) {
|
| return true;
|
| }
|
| + if (check_setter) {
|
| + String& setter_name = String::Handle(Field::SetterName(name));
|
| + if (FunctionExists(setter_name)) {
|
| + return true;
|
| + }
|
| + }
|
| return false;
|
| }
|
|
|
| void AddFunction(const Function& function) {
|
| - ASSERT(!NameExists<Function>(functions_, String::Handle(function.name())));
|
| + ASSERT(!FunctionExists(String::Handle(function.name())));
|
| functions_.Add(function);
|
| }
|
|
|
| @@ -632,7 +649,7 @@
|
| }
|
|
|
| void AddField(const Field& field) {
|
| - ASSERT(!NameExists<Field>(fields_, String::Handle(field.name())));
|
| + ASSERT(!FieldExists(String::Handle(field.name())));
|
| fields_.Add(field);
|
| }
|
|
|
| @@ -685,20 +702,40 @@
|
| }
|
|
|
| private:
|
| - template<typename T>
|
| - bool NameExists(const GrowableObjectArray& list, const String& name) const {
|
| + Field* LookupField(const String& name) const {
|
| String& test_name = String::Handle();
|
| - T& obj = T::Handle();
|
| - for (int i = 0; i < list.Length(); i++) {
|
| - obj ^= list.At(i);
|
| - test_name = obj.name();
|
| + Field& field = Field::Handle();
|
| + for (int i = 0; i < fields_.Length(); i++) {
|
| + field ^= fields_.At(i);
|
| + test_name = field.name();
|
| if (name.Equals(test_name)) {
|
| - return true;
|
| + return &field;
|
| }
|
| }
|
| - return false;
|
| + return NULL;
|
| }
|
|
|
| + bool FieldExists(const String& name) const {
|
| + return LookupField(name) != NULL;
|
| + }
|
| +
|
| + Function* LookupFunction(const String& name) const {
|
| + String& test_name = String::Handle();
|
| + Function& func = Function::Handle();
|
| + for (int i = 0; i < functions_.Length(); i++) {
|
| + func ^= functions_.At(i);
|
| + test_name = func.name();
|
| + if (name.Equals(test_name)) {
|
| + return &func;
|
| + }
|
| + }
|
| + return NULL;
|
| + }
|
| +
|
| + bool FunctionExists(const String& name) const {
|
| + return LookupFunction(name) != NULL;
|
| + }
|
| +
|
| const Class& clazz_;
|
| const String& class_name_;
|
| const bool is_interface_;
|
| @@ -2738,6 +2775,7 @@
|
| ASSERT(field->type != NULL);
|
| ASSERT(field->name_pos > 0);
|
| ASSERT(current_member_ == field);
|
| + // All const fields are also final.
|
| ASSERT(!field->has_const || field->has_final);
|
|
|
| if (field->has_abstract) {
|
| @@ -2749,7 +2787,7 @@
|
| if (field->has_factory) {
|
| ErrorMsg("keyword 'factory' not allowed in field declaration");
|
| }
|
| - if (members->FieldNameExists(*field->name)) {
|
| + if (members->FieldNameExists(*field->name, !field->has_final)) {
|
| ErrorMsg(field->name_pos,
|
| "'%s' field/method already defined\n", field->name->ToCString());
|
| }
|
| @@ -3866,10 +3904,14 @@
|
| ErrorMsg(name_pos, "getter for '%s' is already defined",
|
| var_name.ToCString());
|
| }
|
| - accessor_name = Field::SetterName(var_name);
|
| - if (library_.LookupLocalObject(accessor_name) != Object::null()) {
|
| - ErrorMsg(name_pos, "setter for '%s' is already defined",
|
| - var_name.ToCString());
|
| + // A const or final variable does not define an implicit setter,
|
| + // so we only check setters for non-final variables.
|
| + if (!is_final) {
|
| + accessor_name = Field::SetterName(var_name);
|
| + if (library_.LookupLocalObject(accessor_name) != Object::null()) {
|
| + ErrorMsg(name_pos, "setter for '%s' is already defined",
|
| + var_name.ToCString());
|
| + }
|
| }
|
|
|
| field = Field::New(var_name, is_static, is_final, is_const,
|
| @@ -3957,11 +3999,8 @@
|
| ErrorMsg(name_pos, "'%s' is already defined as getter",
|
| func_name.ToCString());
|
| }
|
| - accessor_name = Field::SetterName(func_name);
|
| - if (library_.LookupLocalObject(accessor_name) != Object::null()) {
|
| - ErrorMsg(name_pos, "'%s' is already defined as setter",
|
| - func_name.ToCString());
|
| - }
|
| + // A setter named x= may co-exist with a function named x, thus we do
|
| + // not need to check setters.
|
|
|
| if (CurrentToken() != Token::kLPAREN) {
|
| ErrorMsg("'(' expected");
|
| @@ -4071,10 +4110,19 @@
|
| is_getter ? "getter" : "setter");
|
| }
|
|
|
| - if (library_.LookupLocalObject(*field_name) != Object::null()) {
|
| + if (is_getter && library_.LookupLocalObject(*field_name) != Object::null()) {
|
| ErrorMsg(name_pos, "'%s' is already defined in this library",
|
| field_name->ToCString());
|
| }
|
| + if (!is_getter) {
|
| + // Check whether there is a field with the same name that has an implicit
|
| + // setter.
|
| + const Field& field = Field::Handle(library_.LookupLocalField(*field_name));
|
| + if (!field.IsNull() && !field.is_final()) {
|
| + ErrorMsg(name_pos, "Variable '%s' is already defined in this library",
|
| + field_name->ToCString());
|
| + }
|
| + }
|
| bool found = library_.LookupLocalObject(accessor_name) != Object::null();
|
| if (found && !is_patch) {
|
| ErrorMsg(name_pos, "%s for '%s' is already defined",
|
|
|