| 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 #include "tools/gn/template.h" |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 116 | 116 |
| 117 Value* Scope::SetValue(const base::StringPiece& ident, | 117 Value* Scope::SetValue(const base::StringPiece& ident, |
| 118 const Value& v, | 118 const Value& v, |
| 119 const ParseNode* set_node) { | 119 const ParseNode* set_node) { |
| 120 Record& r = values_[ident]; // Clears any existing value. | 120 Record& r = values_[ident]; // Clears any existing value. |
| 121 r.value = v; | 121 r.value = v; |
| 122 r.value.set_origin(set_node); | 122 r.value.set_origin(set_node); |
| 123 return &r.value; | 123 return &r.value; |
| 124 } | 124 } |
| 125 | 125 |
| 126 void Scope::DeleteValue(const base::StringPiece& ident) { |
| 127 RecordMap::iterator found = values_.find(ident); |
| 128 if (found != values_.end()) |
| 129 values_.erase(found); |
| 130 } |
| 131 |
| 126 bool Scope::AddTemplate(const std::string& name, const Template* templ) { | 132 bool Scope::AddTemplate(const std::string& name, const Template* templ) { |
| 127 if (GetTemplate(name)) | 133 if (GetTemplate(name)) |
| 128 return false; | 134 return false; |
| 129 templates_[name] = templ; | 135 templates_[name] = templ; |
| 130 return true; | 136 return true; |
| 131 } | 137 } |
| 132 | 138 |
| 133 const Template* Scope::GetTemplate(const std::string& name) const { | 139 const Template* Scope::GetTemplate(const std::string& name) const { |
| 134 TemplateMap::const_iterator found = templates_.find(name); | 140 TemplateMap::const_iterator found = templates_.find(name); |
| 135 if (found != templates_.end()) | 141 if (found != templates_.end()) |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 } | 193 } |
| 188 } | 194 } |
| 189 return true; | 195 return true; |
| 190 } | 196 } |
| 191 | 197 |
| 192 void Scope::GetCurrentScopeValues(KeyValueMap* output) const { | 198 void Scope::GetCurrentScopeValues(KeyValueMap* output) const { |
| 193 for (RecordMap::const_iterator i = values_.begin(); i != values_.end(); ++i) | 199 for (RecordMap::const_iterator i = values_.begin(); i != values_.end(); ++i) |
| 194 (*output)[i->first] = i->second.value; | 200 (*output)[i->first] = i->second.value; |
| 195 } | 201 } |
| 196 | 202 |
| 203 void Scope::GetCurrentScopeVariables( |
| 204 std::vector<base::StringPiece>* output) const { |
| 205 output->reserve(values_.size()); |
| 206 for (RecordMap::const_iterator i = values_.begin(); i != values_.end(); ++i) |
| 207 output->push_back(i->first); |
| 208 } |
| 209 |
| 197 bool Scope::NonRecursiveMergeTo(Scope* dest, | 210 bool Scope::NonRecursiveMergeTo(Scope* dest, |
| 198 bool clobber_existing, | 211 const MergeOptions& options, |
| 199 const ParseNode* node_for_err, | 212 const ParseNode* node_for_err, |
| 200 const char* desc_for_err, | 213 const char* desc_for_err, |
| 201 Err* err) const { | 214 Err* err) const { |
| 202 // Values. | 215 // Values. |
| 203 for (RecordMap::const_iterator i = values_.begin(); i != values_.end(); ++i) { | 216 for (RecordMap::const_iterator i = values_.begin(); i != values_.end(); ++i) { |
| 217 if (!options.copy_private_vars && IsPrivateVar(i->first)) |
| 218 continue; // Skip this private var. |
| 219 |
| 204 const Value& new_value = i->second.value; | 220 const Value& new_value = i->second.value; |
| 205 if (!clobber_existing) { | 221 if (!options.clobber_existing) { |
| 206 const Value* existing_value = dest->GetValue(i->first); | 222 const Value* existing_value = dest->GetValue(i->first); |
| 207 if (existing_value && new_value != *existing_value) { | 223 if (existing_value && new_value != *existing_value) { |
| 208 // Value present in both the source and the dest. | 224 // Value present in both the source and the dest. |
| 209 std::string desc_string(desc_for_err); | 225 std::string desc_string(desc_for_err); |
| 210 *err = Err(node_for_err, "Value collision.", | 226 *err = Err(node_for_err, "Value collision.", |
| 211 "This " + desc_string + " contains \"" + i->first.as_string() + | 227 "This " + desc_string + " contains \"" + i->first.as_string() + |
| 212 "\""); | 228 "\""); |
| 213 err->AppendSubErr(Err(i->second.value, "defined here.", | 229 err->AppendSubErr(Err(i->second.value, "defined here.", |
| 214 "Which would clobber the one in your current scope")); | 230 "Which would clobber the one in your current scope")); |
| 215 err->AppendSubErr(Err(*existing_value, "defined here.", | 231 err->AppendSubErr(Err(*existing_value, "defined here.", |
| 216 "Executing " + desc_string + " should not conflict with anything " | 232 "Executing " + desc_string + " should not conflict with anything " |
| 217 "in the current\nscope unless the values are identical.")); | 233 "in the current\nscope unless the values are identical.")); |
| 218 return false; | 234 return false; |
| 219 } | 235 } |
| 220 } | 236 } |
| 221 dest->values_[i->first] = i->second; | 237 dest->values_[i->first] = i->second; |
| 238 |
| 239 if (options.mark_used) |
| 240 dest->MarkUsed(i->first); |
| 222 } | 241 } |
| 223 | 242 |
| 224 // Target defaults are owning pointers. | 243 // Target defaults are owning pointers. |
| 225 for (NamedScopeMap::const_iterator i = target_defaults_.begin(); | 244 for (NamedScopeMap::const_iterator i = target_defaults_.begin(); |
| 226 i != target_defaults_.end(); ++i) { | 245 i != target_defaults_.end(); ++i) { |
| 227 if (!clobber_existing) { | 246 if (!options.clobber_existing) { |
| 228 if (dest->GetTargetDefaults(i->first)) { | 247 if (dest->GetTargetDefaults(i->first)) { |
| 229 // TODO(brettw) it would be nice to know the origin of a | 248 // TODO(brettw) it would be nice to know the origin of a |
| 230 // set_target_defaults so we can give locations for the colliding target | 249 // set_target_defaults so we can give locations for the colliding target |
| 231 // defaults. | 250 // defaults. |
| 232 std::string desc_string(desc_for_err); | 251 std::string desc_string(desc_for_err); |
| 233 *err = Err(node_for_err, "Target defaults collision.", | 252 *err = Err(node_for_err, "Target defaults collision.", |
| 234 "This " + desc_string + " contains target defaults for\n" | 253 "This " + desc_string + " contains target defaults for\n" |
| 235 "\"" + i->first + "\" which would clobber one for the\n" | 254 "\"" + i->first + "\" which would clobber one for the\n" |
| 236 "same target type in your current scope. It's unfortunate that I'm " | 255 "same target type in your current scope. It's unfortunate that I'm " |
| 237 "too stupid\nto tell you the location of where the target defaults " | 256 "too stupid\nto tell you the location of where the target defaults " |
| 238 "were set. Usually\nthis happens in the BUILDCONFIG.gn file."); | 257 "were set. Usually\nthis happens in the BUILDCONFIG.gn file."); |
| 239 return false; | 258 return false; |
| 240 } | 259 } |
| 241 } | 260 } |
| 242 | 261 |
| 243 // Be careful to delete any pointer we're about to clobber. | 262 // Be careful to delete any pointer we're about to clobber. |
| 244 Scope** dest_scope = &dest->target_defaults_[i->first]; | 263 Scope** dest_scope = &dest->target_defaults_[i->first]; |
| 245 if (*dest_scope) | 264 if (*dest_scope) |
| 246 delete *dest_scope; | 265 delete *dest_scope; |
| 247 *dest_scope = new Scope(settings_); | 266 *dest_scope = new Scope(settings_); |
| 248 i->second->NonRecursiveMergeTo(*dest_scope, clobber_existing, node_for_err, | 267 i->second->NonRecursiveMergeTo(*dest_scope, options, node_for_err, |
| 249 "<SHOULDN'T HAPPEN>", err); | 268 "<SHOULDN'T HAPPEN>", err); |
| 250 } | 269 } |
| 251 | 270 |
| 252 // Sources assignment filter. | 271 // Sources assignment filter. |
| 253 if (sources_assignment_filter_) { | 272 if (sources_assignment_filter_) { |
| 254 if (!clobber_existing) { | 273 if (!options.clobber_existing) { |
| 255 if (dest->GetSourcesAssignmentFilter()) { | 274 if (dest->GetSourcesAssignmentFilter()) { |
| 256 // Sources assignment filter present in both the source and the dest. | 275 // Sources assignment filter present in both the source and the dest. |
| 257 std::string desc_string(desc_for_err); | 276 std::string desc_string(desc_for_err); |
| 258 *err = Err(node_for_err, "Assignment filter collision.", | 277 *err = Err(node_for_err, "Assignment filter collision.", |
| 259 "The " + desc_string + " contains a sources_assignment_filter " | 278 "The " + desc_string + " contains a sources_assignment_filter " |
| 260 "which\nwould clobber the one in your current scope."); | 279 "which\nwould clobber the one in your current scope."); |
| 261 return false; | 280 return false; |
| 262 } | 281 } |
| 263 } | 282 } |
| 264 dest->sources_assignment_filter_.reset( | 283 dest->sources_assignment_filter_.reset( |
| 265 new PatternList(*sources_assignment_filter_)); | 284 new PatternList(*sources_assignment_filter_)); |
| 266 } | 285 } |
| 267 | 286 |
| 268 // Templates. | 287 // Templates. |
| 269 for (TemplateMap::const_iterator i = templates_.begin(); | 288 for (TemplateMap::const_iterator i = templates_.begin(); |
| 270 i != templates_.end(); ++i) { | 289 i != templates_.end(); ++i) { |
| 271 if (!clobber_existing) { | 290 if (!options.copy_private_vars && IsPrivateVar(i->first)) |
| 291 continue; // Skip this private template. |
| 292 |
| 293 if (!options.clobber_existing) { |
| 272 const Template* existing_template = dest->GetTemplate(i->first); | 294 const Template* existing_template = dest->GetTemplate(i->first); |
| 273 if (existing_template) { | 295 if (existing_template) { |
| 274 // Rule present in both the source and the dest. | 296 // Rule present in both the source and the dest. |
| 275 std::string desc_string(desc_for_err); | 297 std::string desc_string(desc_for_err); |
| 276 *err = Err(node_for_err, "Template collision.", | 298 *err = Err(node_for_err, "Template collision.", |
| 277 "This " + desc_string + " contains a template \"" + | 299 "This " + desc_string + " contains a template \"" + |
| 278 i->first + "\""); | 300 i->first + "\""); |
| 279 err->AppendSubErr(Err(i->second->GetDefinitionRange(), "defined here.", | 301 err->AppendSubErr(Err(i->second->GetDefinitionRange(), "defined here.", |
| 280 "Which would clobber the one in your current scope")); | 302 "Which would clobber the one in your current scope")); |
| 281 err->AppendSubErr(Err(existing_template->GetDefinitionRange(), | 303 err->AppendSubErr(Err(existing_template->GetDefinitionRange(), |
| (...skipping 19 matching lines...) Expand all Loading... |
| 301 result.reset(new Scope(const_containing_)); | 323 result.reset(new Scope(const_containing_)); |
| 302 } else if (mutable_containing_) { | 324 } else if (mutable_containing_) { |
| 303 // There are more nested mutable scopes. Recursively go up the stack to | 325 // There are more nested mutable scopes. Recursively go up the stack to |
| 304 // get the closure. | 326 // get the closure. |
| 305 result = mutable_containing_->MakeClosure(); | 327 result = mutable_containing_->MakeClosure(); |
| 306 } else { | 328 } else { |
| 307 // This is a standalone scope, just copy it. | 329 // This is a standalone scope, just copy it. |
| 308 result.reset(new Scope(settings_)); | 330 result.reset(new Scope(settings_)); |
| 309 } | 331 } |
| 310 | 332 |
| 333 // Want to clobber since we've flattened some nested scopes, and our parent |
| 334 // scope may have a duplicate value set. |
| 335 MergeOptions options; |
| 336 options.clobber_existing = true; |
| 337 |
| 311 // Add in our variables and we're done. | 338 // Add in our variables and we're done. |
| 312 Err err; | 339 Err err; |
| 313 NonRecursiveMergeTo(result.get(), true, NULL, "<SHOULDN'T HAPPEN>", &err); | 340 NonRecursiveMergeTo(result.get(), options, NULL, "<SHOULDN'T HAPPEN>", &err); |
| 314 DCHECK(!err.has_error()); | 341 DCHECK(!err.has_error()); |
| 315 return result.Pass(); | 342 return result.Pass(); |
| 316 } | 343 } |
| 317 | 344 |
| 318 Scope* Scope::MakeTargetDefaults(const std::string& target_type) { | 345 Scope* Scope::MakeTargetDefaults(const std::string& target_type) { |
| 319 if (GetTargetDefaults(target_type)) | 346 if (GetTargetDefaults(target_type)) |
| 320 return NULL; | 347 return NULL; |
| 321 | 348 |
| 322 Scope** dest = &target_defaults_[target_type]; | 349 Scope** dest = &target_defaults_[target_type]; |
| 323 if (*dest) { | 350 if (*dest) { |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 411 if (found != properties_.end()) { | 438 if (found != properties_.end()) { |
| 412 if (found_on_scope) | 439 if (found_on_scope) |
| 413 *found_on_scope = this; | 440 *found_on_scope = this; |
| 414 return found->second; | 441 return found->second; |
| 415 } | 442 } |
| 416 if (containing()) | 443 if (containing()) |
| 417 return containing()->GetProperty(key, found_on_scope); | 444 return containing()->GetProperty(key, found_on_scope); |
| 418 return NULL; | 445 return NULL; |
| 419 } | 446 } |
| 420 | 447 |
| 448 // static |
| 449 bool Scope::IsPrivateVar(const base::StringPiece& name) { |
| 450 return name.empty() || name[0] == '_'; |
| 451 } |
| 452 |
| 421 void Scope::AddProvider(ProgrammaticProvider* p) { | 453 void Scope::AddProvider(ProgrammaticProvider* p) { |
| 422 programmatic_providers_.insert(p); | 454 programmatic_providers_.insert(p); |
| 423 } | 455 } |
| 424 | 456 |
| 425 void Scope::RemoveProvider(ProgrammaticProvider* p) { | 457 void Scope::RemoveProvider(ProgrammaticProvider* p) { |
| 426 DCHECK(programmatic_providers_.find(p) != programmatic_providers_.end()); | 458 DCHECK(programmatic_providers_.find(p) != programmatic_providers_.end()); |
| 427 programmatic_providers_.erase(p); | 459 programmatic_providers_.erase(p); |
| 428 } | 460 } |
| OLD | NEW |