| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "tools/gn/scope.h" | 5 #include "tools/gn/scope.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/stl_util.h" | 8 #include "base/stl_util.h" |
| 9 #include "tools/gn/parse_tree.h" | 9 #include "tools/gn/parse_tree.h" |
| 10 #include "tools/gn/template.h" |
| 10 | 11 |
| 11 namespace { | 12 namespace { |
| 12 | 13 |
| 13 // FLags set in the mode_flags_ of a scope. If a bit is set, it applies | 14 // FLags set in the mode_flags_ of a scope. If a bit is set, it applies |
| 14 // recursively to all dependent scopes. | 15 // recursively to all dependent scopes. |
| 15 const unsigned kProcessingBuildConfigFlag = 1; | 16 const unsigned kProcessingBuildConfigFlag = 1; |
| 16 const unsigned kProcessingImportFlag = 2; | 17 const unsigned kProcessingImportFlag = 2; |
| 17 | 18 |
| 18 } // namespace | 19 } // namespace |
| 19 | 20 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 34 Scope::Scope(const Scope* parent) | 35 Scope::Scope(const Scope* parent) |
| 35 : const_containing_(parent), | 36 : const_containing_(parent), |
| 36 mutable_containing_(NULL), | 37 mutable_containing_(NULL), |
| 37 settings_(parent->settings()), | 38 settings_(parent->settings()), |
| 38 mode_flags_(0) { | 39 mode_flags_(0) { |
| 39 } | 40 } |
| 40 | 41 |
| 41 Scope::~Scope() { | 42 Scope::~Scope() { |
| 42 STLDeleteContainerPairSecondPointers(target_defaults_.begin(), | 43 STLDeleteContainerPairSecondPointers(target_defaults_.begin(), |
| 43 target_defaults_.end()); | 44 target_defaults_.end()); |
| 45 STLDeleteContainerPairSecondPointers(templates_.begin(), templates_.end()); |
| 44 } | 46 } |
| 45 | 47 |
| 46 const Value* Scope::GetValue(const base::StringPiece& ident, | 48 const Value* Scope::GetValue(const base::StringPiece& ident, |
| 47 bool counts_as_used) { | 49 bool counts_as_used) { |
| 48 // First check for programatically-provided values. | 50 // First check for programatically-provided values. |
| 49 for (ProviderSet::const_iterator i = programmatic_providers_.begin(); | 51 for (ProviderSet::const_iterator i = programmatic_providers_.begin(); |
| 50 i != programmatic_providers_.end(); ++i) { | 52 i != programmatic_providers_.end(); ++i) { |
| 51 const Value* v = (*i)->GetProgrammaticValue(ident); | 53 const Value* v = (*i)->GetProgrammaticValue(ident); |
| 52 if (v) | 54 if (v) |
| 53 return v; | 55 return v; |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 112 | 114 |
| 113 Value* Scope::SetValue(const base::StringPiece& ident, | 115 Value* Scope::SetValue(const base::StringPiece& ident, |
| 114 const Value& v, | 116 const Value& v, |
| 115 const ParseNode* set_node) { | 117 const ParseNode* set_node) { |
| 116 Record& r = values_[ident]; // Clears any existing value. | 118 Record& r = values_[ident]; // Clears any existing value. |
| 117 r.value = v; | 119 r.value = v; |
| 118 r.value.set_origin(set_node); | 120 r.value.set_origin(set_node); |
| 119 return &r.value; | 121 return &r.value; |
| 120 } | 122 } |
| 121 | 123 |
| 122 bool Scope::AddTemplate(const std::string& name, const FunctionCallNode* decl) { | 124 bool Scope::AddTemplate(const std::string& name, scoped_ptr<Template> templ) { |
| 123 if (GetTemplate(name)) | 125 if (GetTemplate(name)) |
| 124 return false; | 126 return false; |
| 125 templates_[name] = decl; | 127 templates_[name] = templ.release(); |
| 126 return true; | 128 return true; |
| 127 } | 129 } |
| 128 | 130 |
| 129 const FunctionCallNode* Scope::GetTemplate(const std::string& name) const { | 131 const Template* Scope::GetTemplate(const std::string& name) const { |
| 130 TemplateMap::const_iterator found = templates_.find(name); | 132 TemplateMap::const_iterator found = templates_.find(name); |
| 131 if (found != templates_.end()) | 133 if (found != templates_.end()) |
| 132 return found->second; | 134 return found->second; |
| 133 if (containing()) | 135 if (containing()) |
| 134 return containing()->GetTemplate(name); | 136 return containing()->GetTemplate(name); |
| 135 return NULL; | 137 return NULL; |
| 136 } | 138 } |
| 137 | 139 |
| 138 void Scope::MarkUsed(const base::StringPiece& ident) { | 140 void Scope::MarkUsed(const base::StringPiece& ident) { |
| 139 RecordMap::iterator found = values_.find(ident); | 141 RecordMap::iterator found = values_.find(ident); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 184 } | 186 } |
| 185 return true; | 187 return true; |
| 186 } | 188 } |
| 187 | 189 |
| 188 void Scope::GetCurrentScopeValues(KeyValueMap* output) const { | 190 void Scope::GetCurrentScopeValues(KeyValueMap* output) const { |
| 189 for (RecordMap::const_iterator i = values_.begin(); i != values_.end(); ++i) | 191 for (RecordMap::const_iterator i = values_.begin(); i != values_.end(); ++i) |
| 190 (*output)[i->first] = i->second.value; | 192 (*output)[i->first] = i->second.value; |
| 191 } | 193 } |
| 192 | 194 |
| 193 bool Scope::NonRecursiveMergeTo(Scope* dest, | 195 bool Scope::NonRecursiveMergeTo(Scope* dest, |
| 196 bool clobber_existing, |
| 194 const ParseNode* node_for_err, | 197 const ParseNode* node_for_err, |
| 195 const char* desc_for_err, | 198 const char* desc_for_err, |
| 196 Err* err) const { | 199 Err* err) const { |
| 197 // Values. | 200 // Values. |
| 198 for (RecordMap::const_iterator i = values_.begin(); i != values_.end(); ++i) { | 201 for (RecordMap::const_iterator i = values_.begin(); i != values_.end(); ++i) { |
| 199 const Value& new_value = i->second.value; | 202 const Value& new_value = i->second.value; |
| 200 const Value* existing_value = dest->GetValue(i->first); | 203 if (!clobber_existing) { |
| 201 if (existing_value && new_value != *existing_value) { | 204 const Value* existing_value = dest->GetValue(i->first); |
| 202 // Value present in both the source and the dest. | 205 if (existing_value && new_value != *existing_value) { |
| 203 std::string desc_string(desc_for_err); | 206 // Value present in both the source and the dest. |
| 204 *err = Err(node_for_err, "Value collision.", | 207 std::string desc_string(desc_for_err); |
| 205 "This " + desc_string + " contains \"" + i->first.as_string() + "\""); | 208 *err = Err(node_for_err, "Value collision.", |
| 206 err->AppendSubErr(Err(i->second.value, "defined here.", | 209 "This " + desc_string + " contains \"" + i->first.as_string() + |
| 207 "Which would clobber the one in your current scope")); | 210 "\""); |
| 208 err->AppendSubErr(Err(*existing_value, "defined here.", | 211 err->AppendSubErr(Err(i->second.value, "defined here.", |
| 209 "Executing " + desc_string + " should not conflict with anything " | 212 "Which would clobber the one in your current scope")); |
| 210 "in the current\nscope unless the values are identical.")); | 213 err->AppendSubErr(Err(*existing_value, "defined here.", |
| 211 return false; | 214 "Executing " + desc_string + " should not conflict with anything " |
| 215 "in the current\nscope unless the values are identical.")); |
| 216 return false; |
| 217 } |
| 212 } | 218 } |
| 213 dest->values_[i->first] = i->second; | 219 dest->values_[i->first] = i->second; |
| 214 } | 220 } |
| 215 | 221 |
| 216 // Target defaults are owning pointers. | 222 // Target defaults are owning pointers. |
| 217 for (NamedScopeMap::const_iterator i = target_defaults_.begin(); | 223 for (NamedScopeMap::const_iterator i = target_defaults_.begin(); |
| 218 i != target_defaults_.end(); ++i) { | 224 i != target_defaults_.end(); ++i) { |
| 219 if (dest->GetTargetDefaults(i->first)) { | 225 if (!clobber_existing) { |
| 220 // TODO(brettw) it would be nice to know the origin of a | 226 if (dest->GetTargetDefaults(i->first)) { |
| 221 // set_target_defaults so we can give locations for the colliding target | 227 // TODO(brettw) it would be nice to know the origin of a |
| 222 // defaults. | 228 // set_target_defaults so we can give locations for the colliding target |
| 223 std::string desc_string(desc_for_err); | 229 // defaults. |
| 224 *err = Err(node_for_err, "Target defaults collision.", | 230 std::string desc_string(desc_for_err); |
| 225 "This " + desc_string + " contains target defaults for\n" | 231 *err = Err(node_for_err, "Target defaults collision.", |
| 226 "\"" + i->first + "\" which would clobber one for the\n" | 232 "This " + desc_string + " contains target defaults for\n" |
| 227 "same target type in your current scope. It's unfortunate that I'm " | 233 "\"" + i->first + "\" which would clobber one for the\n" |
| 228 "too stupid\nto tell you the location of where the target defaults " | 234 "same target type in your current scope. It's unfortunate that I'm " |
| 229 "were set. Usually\nthis happens in the BUILDCONFIG.gn file."); | 235 "too stupid\nto tell you the location of where the target defaults " |
| 230 return false; | 236 "were set. Usually\nthis happens in the BUILDCONFIG.gn file."); |
| 237 return false; |
| 238 } |
| 231 } | 239 } |
| 232 | 240 |
| 233 Scope* s = new Scope(settings_); | 241 // Be careful to delete any pointer we're about to clobber. |
| 234 i->second->NonRecursiveMergeTo(s, node_for_err, "<SHOULDN'T HAPPEN>", err); | 242 Scope** dest_scope = &dest->target_defaults_[i->first]; |
| 235 dest->target_defaults_[i->first] = s; | 243 if (*dest_scope) |
| 244 delete *dest_scope; |
| 245 *dest_scope = new Scope(settings_); |
| 246 i->second->NonRecursiveMergeTo(*dest_scope, clobber_existing, node_for_err, |
| 247 "<SHOULDN'T HAPPEN>", err); |
| 236 } | 248 } |
| 237 | 249 |
| 238 // Sources assignment filter. | 250 // Sources assignment filter. |
| 239 if (sources_assignment_filter_) { | 251 if (sources_assignment_filter_) { |
| 240 if (dest->GetSourcesAssignmentFilter()) { | 252 if (!clobber_existing) { |
| 241 // Sources assignment filter present in both the source and the dest. | 253 if (dest->GetSourcesAssignmentFilter()) { |
| 242 std::string desc_string(desc_for_err); | 254 // Sources assignment filter present in both the source and the dest. |
| 243 *err = Err(node_for_err, "Assignment filter collision.", | 255 std::string desc_string(desc_for_err); |
| 244 "The " + desc_string + " contains a sources_assignment_filter which\n" | 256 *err = Err(node_for_err, "Assignment filter collision.", |
| 245 "would clobber the one in your current scope."); | 257 "The " + desc_string + " contains a sources_assignment_filter " |
| 246 return false; | 258 "which\nwould clobber the one in your current scope."); |
| 259 return false; |
| 260 } |
| 247 } | 261 } |
| 248 dest->sources_assignment_filter_.reset( | 262 dest->sources_assignment_filter_.reset( |
| 249 new PatternList(*sources_assignment_filter_)); | 263 new PatternList(*sources_assignment_filter_)); |
| 250 } | 264 } |
| 251 | 265 |
| 252 // Templates. | 266 // Templates. |
| 253 for (TemplateMap::const_iterator i = templates_.begin(); | 267 for (TemplateMap::const_iterator i = templates_.begin(); |
| 254 i != templates_.end(); ++i) { | 268 i != templates_.end(); ++i) { |
| 255 const FunctionCallNode* existing_template = dest->GetTemplate(i->first); | 269 if (!clobber_existing) { |
| 256 if (existing_template) { | 270 const Template* existing_template = dest->GetTemplate(i->first); |
| 257 // Rule present in both the source and the dest. | 271 if (existing_template) { |
| 258 std::string desc_string(desc_for_err); | 272 // Rule present in both the source and the dest. |
| 259 *err = Err(node_for_err, "Template collision.", | 273 std::string desc_string(desc_for_err); |
| 260 "This " + desc_string + " contains a template \"" + i->first + "\""); | 274 *err = Err(node_for_err, "Template collision.", |
| 261 err->AppendSubErr(Err(i->second->function(), "defined here.", | 275 "This " + desc_string + " contains a template \"" + |
| 262 "Which would clobber the one in your current scope")); | 276 i->first + "\""); |
| 263 err->AppendSubErr(Err(existing_template->function(), "defined here.", | 277 err->AppendSubErr(Err(i->second->GetDefinitionRange(), "defined here.", |
| 264 "Executing " + desc_string + " should not conflict with anything " | 278 "Which would clobber the one in your current scope")); |
| 265 "in the current\nscope.")); | 279 err->AppendSubErr(Err(existing_template->GetDefinitionRange(), |
| 266 return false; | 280 "defined here.", |
| 281 "Executing " + desc_string + " should not conflict with anything " |
| 282 "in the current\nscope.")); |
| 283 return false; |
| 284 } |
| 267 } | 285 } |
| 268 dest->templates_.insert(*i); | 286 |
| 287 // Be careful to delete any pointer we're about to clobber. |
| 288 const Template** dest_template = &dest->templates_[i->first]; |
| 289 if (*dest_template) |
| 290 delete *dest_template; |
| 291 *dest_template = i->second; |
| 269 } | 292 } |
| 270 | 293 |
| 271 return true; | 294 return true; |
| 272 } | 295 } |
| 273 | 296 |
| 297 scoped_ptr<Scope> Scope::MakeClosure() const { |
| 298 scoped_ptr<Scope> result; |
| 299 if (const_containing_) { |
| 300 // We reached the top of the mutable scope stack. The result scope just |
| 301 // references the const scope (which will never change). |
| 302 result.reset(new Scope(const_containing_)); |
| 303 } else if (mutable_containing_) { |
| 304 // There are more nested mutable scopes. Recursively go up the stack to |
| 305 // get the closure. |
| 306 result = mutable_containing_->MakeClosure(); |
| 307 } else { |
| 308 // This is a standalone scope, just copy it. |
| 309 result.reset(new Scope(settings_)); |
| 310 } |
| 311 |
| 312 // Add in our variables and we're done. |
| 313 Err err; |
| 314 NonRecursiveMergeTo(result.get(), true, NULL, "<SHOULDN'T HAPPEN>", &err); |
| 315 DCHECK(!err.has_error()); |
| 316 return result.Pass(); |
| 317 } |
| 318 |
| 274 Scope* Scope::MakeTargetDefaults(const std::string& target_type) { | 319 Scope* Scope::MakeTargetDefaults(const std::string& target_type) { |
| 275 if (GetTargetDefaults(target_type)) | 320 if (GetTargetDefaults(target_type)) |
| 276 return NULL; | 321 return NULL; |
| 277 | 322 |
| 278 Scope** dest = &target_defaults_[target_type]; | 323 Scope** dest = &target_defaults_[target_type]; |
| 279 if (*dest) { | 324 if (*dest) { |
| 280 NOTREACHED(); // Already set. | 325 NOTREACHED(); // Already set. |
| 281 return *dest; | 326 return *dest; |
| 282 } | 327 } |
| 283 *dest = new Scope(settings_); | 328 *dest = new Scope(settings_); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 367 } | 412 } |
| 368 | 413 |
| 369 void Scope::AddProvider(ProgrammaticProvider* p) { | 414 void Scope::AddProvider(ProgrammaticProvider* p) { |
| 370 programmatic_providers_.insert(p); | 415 programmatic_providers_.insert(p); |
| 371 } | 416 } |
| 372 | 417 |
| 373 void Scope::RemoveProvider(ProgrammaticProvider* p) { | 418 void Scope::RemoveProvider(ProgrammaticProvider* p) { |
| 374 DCHECK(programmatic_providers_.find(p) != programmatic_providers_.end()); | 419 DCHECK(programmatic_providers_.find(p) != programmatic_providers_.end()); |
| 375 programmatic_providers_.erase(p); | 420 programmatic_providers_.erase(p); |
| 376 } | 421 } |
| OLD | NEW |