| 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" |
| 11 | 11 |
| 12 namespace { | 12 namespace { |
| 13 | 13 |
| 14 // 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 |
| 15 // recursively to all dependent scopes. | 15 // recursively to all dependent scopes. |
| 16 const unsigned kProcessingBuildConfigFlag = 1; | 16 const unsigned kProcessingBuildConfigFlag = 1; |
| 17 const unsigned kProcessingImportFlag = 2; | 17 const unsigned kProcessingImportFlag = 2; |
| 18 | 18 |
| 19 // Returns true if this variable name should be considered private. Private |
| 20 // values start with an underscore, and are not imported from "gni" files |
| 21 // when processing an import. |
| 22 bool IsPrivateVar(const base::StringPiece& name) { |
| 23 return name.empty() || name[0] == '_'; |
| 24 } |
| 25 |
| 19 } // namespace | 26 } // namespace |
| 20 | 27 |
| 21 Scope::Scope(const Settings* settings) | 28 Scope::Scope(const Settings* settings) |
| 22 : const_containing_(NULL), | 29 : const_containing_(NULL), |
| 23 mutable_containing_(NULL), | 30 mutable_containing_(NULL), |
| 24 settings_(settings), | 31 settings_(settings), |
| 25 mode_flags_(0), | 32 mode_flags_(0), |
| 26 item_collector_(NULL) { | 33 item_collector_(NULL) { |
| 27 } | 34 } |
| 28 | 35 |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 122 r.value.set_origin(set_node); | 129 r.value.set_origin(set_node); |
| 123 return &r.value; | 130 return &r.value; |
| 124 } | 131 } |
| 125 | 132 |
| 126 void Scope::RemoveIdentifier(const base::StringPiece& ident) { | 133 void Scope::RemoveIdentifier(const base::StringPiece& ident) { |
| 127 RecordMap::iterator found = values_.find(ident); | 134 RecordMap::iterator found = values_.find(ident); |
| 128 if (found != values_.end()) | 135 if (found != values_.end()) |
| 129 values_.erase(found); | 136 values_.erase(found); |
| 130 } | 137 } |
| 131 | 138 |
| 139 void Scope::RemovePrivateIdentifiers() { |
| 140 // Do it in two phases to avoid mutating while iterating. Our hash map is |
| 141 // currently backed by several different vendor-specific implementations and |
| 142 // I'm not sure if all of them support mutating while iterating. Since this |
| 143 // is not perf-critical, do the safe thing. |
| 144 std::vector<base::StringPiece> to_remove; |
| 145 for (RecordMap::const_iterator i = values_.begin(); i != values_.end(); ++i) { |
| 146 if (IsPrivateVar(i->first)) |
| 147 to_remove.push_back(i->first); |
| 148 } |
| 149 |
| 150 for (size_t i = 0; i < to_remove.size(); i++) |
| 151 values_.erase(to_remove[i]); |
| 152 } |
| 153 |
| 132 bool Scope::AddTemplate(const std::string& name, const Template* templ) { | 154 bool Scope::AddTemplate(const std::string& name, const Template* templ) { |
| 133 if (GetTemplate(name)) | 155 if (GetTemplate(name)) |
| 134 return false; | 156 return false; |
| 135 templates_[name] = templ; | 157 templates_[name] = templ; |
| 136 return true; | 158 return true; |
| 137 } | 159 } |
| 138 | 160 |
| 139 const Template* Scope::GetTemplate(const std::string& name) const { | 161 const Template* Scope::GetTemplate(const std::string& name) const { |
| 140 TemplateMap::const_iterator found = templates_.find(name); | 162 TemplateMap::const_iterator found = templates_.find(name); |
| 141 if (found != templates_.end()) | 163 if (found != templates_.end()) |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 } | 216 } |
| 195 return true; | 217 return true; |
| 196 } | 218 } |
| 197 | 219 |
| 198 void Scope::GetCurrentScopeValues(KeyValueMap* output) const { | 220 void Scope::GetCurrentScopeValues(KeyValueMap* output) const { |
| 199 for (RecordMap::const_iterator i = values_.begin(); i != values_.end(); ++i) | 221 for (RecordMap::const_iterator i = values_.begin(); i != values_.end(); ++i) |
| 200 (*output)[i->first] = i->second.value; | 222 (*output)[i->first] = i->second.value; |
| 201 } | 223 } |
| 202 | 224 |
| 203 bool Scope::NonRecursiveMergeTo(Scope* dest, | 225 bool Scope::NonRecursiveMergeTo(Scope* dest, |
| 204 bool clobber_existing, | 226 const MergeOptions& options, |
| 205 const ParseNode* node_for_err, | 227 const ParseNode* node_for_err, |
| 206 const char* desc_for_err, | 228 const char* desc_for_err, |
| 207 Err* err) const { | 229 Err* err) const { |
| 208 // Values. | 230 // Values. |
| 209 for (RecordMap::const_iterator i = values_.begin(); i != values_.end(); ++i) { | 231 for (RecordMap::const_iterator i = values_.begin(); i != values_.end(); ++i) { |
| 232 if (options.skip_private_vars && IsPrivateVar(i->first)) |
| 233 continue; // Skip this private var. |
| 234 |
| 210 const Value& new_value = i->second.value; | 235 const Value& new_value = i->second.value; |
| 211 if (!clobber_existing) { | 236 if (!options.clobber_existing) { |
| 212 const Value* existing_value = dest->GetValue(i->first); | 237 const Value* existing_value = dest->GetValue(i->first); |
| 213 if (existing_value && new_value != *existing_value) { | 238 if (existing_value && new_value != *existing_value) { |
| 214 // Value present in both the source and the dest. | 239 // Value present in both the source and the dest. |
| 215 std::string desc_string(desc_for_err); | 240 std::string desc_string(desc_for_err); |
| 216 *err = Err(node_for_err, "Value collision.", | 241 *err = Err(node_for_err, "Value collision.", |
| 217 "This " + desc_string + " contains \"" + i->first.as_string() + | 242 "This " + desc_string + " contains \"" + i->first.as_string() + |
| 218 "\""); | 243 "\""); |
| 219 err->AppendSubErr(Err(i->second.value, "defined here.", | 244 err->AppendSubErr(Err(i->second.value, "defined here.", |
| 220 "Which would clobber the one in your current scope")); | 245 "Which would clobber the one in your current scope")); |
| 221 err->AppendSubErr(Err(*existing_value, "defined here.", | 246 err->AppendSubErr(Err(*existing_value, "defined here.", |
| 222 "Executing " + desc_string + " should not conflict with anything " | 247 "Executing " + desc_string + " should not conflict with anything " |
| 223 "in the current\nscope unless the values are identical.")); | 248 "in the current\nscope unless the values are identical.")); |
| 224 return false; | 249 return false; |
| 225 } | 250 } |
| 226 } | 251 } |
| 227 dest->values_[i->first] = i->second; | 252 dest->values_[i->first] = i->second; |
| 253 |
| 254 if (options.mark_used) |
| 255 dest->MarkUsed(i->first); |
| 228 } | 256 } |
| 229 | 257 |
| 230 // Target defaults are owning pointers. | 258 // Target defaults are owning pointers. |
| 231 for (NamedScopeMap::const_iterator i = target_defaults_.begin(); | 259 for (NamedScopeMap::const_iterator i = target_defaults_.begin(); |
| 232 i != target_defaults_.end(); ++i) { | 260 i != target_defaults_.end(); ++i) { |
| 233 if (!clobber_existing) { | 261 if (!options.clobber_existing) { |
| 234 if (dest->GetTargetDefaults(i->first)) { | 262 if (dest->GetTargetDefaults(i->first)) { |
| 235 // TODO(brettw) it would be nice to know the origin of a | 263 // TODO(brettw) it would be nice to know the origin of a |
| 236 // set_target_defaults so we can give locations for the colliding target | 264 // set_target_defaults so we can give locations for the colliding target |
| 237 // defaults. | 265 // defaults. |
| 238 std::string desc_string(desc_for_err); | 266 std::string desc_string(desc_for_err); |
| 239 *err = Err(node_for_err, "Target defaults collision.", | 267 *err = Err(node_for_err, "Target defaults collision.", |
| 240 "This " + desc_string + " contains target defaults for\n" | 268 "This " + desc_string + " contains target defaults for\n" |
| 241 "\"" + i->first + "\" which would clobber one for the\n" | 269 "\"" + i->first + "\" which would clobber one for the\n" |
| 242 "same target type in your current scope. It's unfortunate that I'm " | 270 "same target type in your current scope. It's unfortunate that I'm " |
| 243 "too stupid\nto tell you the location of where the target defaults " | 271 "too stupid\nto tell you the location of where the target defaults " |
| 244 "were set. Usually\nthis happens in the BUILDCONFIG.gn file."); | 272 "were set. Usually\nthis happens in the BUILDCONFIG.gn file."); |
| 245 return false; | 273 return false; |
| 246 } | 274 } |
| 247 } | 275 } |
| 248 | 276 |
| 249 // Be careful to delete any pointer we're about to clobber. | 277 // Be careful to delete any pointer we're about to clobber. |
| 250 Scope** dest_scope = &dest->target_defaults_[i->first]; | 278 Scope** dest_scope = &dest->target_defaults_[i->first]; |
| 251 if (*dest_scope) | 279 if (*dest_scope) |
| 252 delete *dest_scope; | 280 delete *dest_scope; |
| 253 *dest_scope = new Scope(settings_); | 281 *dest_scope = new Scope(settings_); |
| 254 i->second->NonRecursiveMergeTo(*dest_scope, clobber_existing, node_for_err, | 282 i->second->NonRecursiveMergeTo(*dest_scope, options, node_for_err, |
| 255 "<SHOULDN'T HAPPEN>", err); | 283 "<SHOULDN'T HAPPEN>", err); |
| 256 } | 284 } |
| 257 | 285 |
| 258 // Sources assignment filter. | 286 // Sources assignment filter. |
| 259 if (sources_assignment_filter_) { | 287 if (sources_assignment_filter_) { |
| 260 if (!clobber_existing) { | 288 if (!options.clobber_existing) { |
| 261 if (dest->GetSourcesAssignmentFilter()) { | 289 if (dest->GetSourcesAssignmentFilter()) { |
| 262 // Sources assignment filter present in both the source and the dest. | 290 // Sources assignment filter present in both the source and the dest. |
| 263 std::string desc_string(desc_for_err); | 291 std::string desc_string(desc_for_err); |
| 264 *err = Err(node_for_err, "Assignment filter collision.", | 292 *err = Err(node_for_err, "Assignment filter collision.", |
| 265 "The " + desc_string + " contains a sources_assignment_filter " | 293 "The " + desc_string + " contains a sources_assignment_filter " |
| 266 "which\nwould clobber the one in your current scope."); | 294 "which\nwould clobber the one in your current scope."); |
| 267 return false; | 295 return false; |
| 268 } | 296 } |
| 269 } | 297 } |
| 270 dest->sources_assignment_filter_.reset( | 298 dest->sources_assignment_filter_.reset( |
| 271 new PatternList(*sources_assignment_filter_)); | 299 new PatternList(*sources_assignment_filter_)); |
| 272 } | 300 } |
| 273 | 301 |
| 274 // Templates. | 302 // Templates. |
| 275 for (TemplateMap::const_iterator i = templates_.begin(); | 303 for (TemplateMap::const_iterator i = templates_.begin(); |
| 276 i != templates_.end(); ++i) { | 304 i != templates_.end(); ++i) { |
| 277 if (!clobber_existing) { | 305 if (options.skip_private_vars && IsPrivateVar(i->first)) |
| 306 continue; // Skip this private template. |
| 307 |
| 308 if (!options.clobber_existing) { |
| 278 const Template* existing_template = dest->GetTemplate(i->first); | 309 const Template* existing_template = dest->GetTemplate(i->first); |
| 279 if (existing_template) { | 310 if (existing_template) { |
| 280 // Rule present in both the source and the dest. | 311 // Rule present in both the source and the dest. |
| 281 std::string desc_string(desc_for_err); | 312 std::string desc_string(desc_for_err); |
| 282 *err = Err(node_for_err, "Template collision.", | 313 *err = Err(node_for_err, "Template collision.", |
| 283 "This " + desc_string + " contains a template \"" + | 314 "This " + desc_string + " contains a template \"" + |
| 284 i->first + "\""); | 315 i->first + "\""); |
| 285 err->AppendSubErr(Err(i->second->GetDefinitionRange(), "defined here.", | 316 err->AppendSubErr(Err(i->second->GetDefinitionRange(), "defined here.", |
| 286 "Which would clobber the one in your current scope")); | 317 "Which would clobber the one in your current scope")); |
| 287 err->AppendSubErr(Err(existing_template->GetDefinitionRange(), | 318 err->AppendSubErr(Err(existing_template->GetDefinitionRange(), |
| (...skipping 19 matching lines...) Expand all Loading... |
| 307 result.reset(new Scope(const_containing_)); | 338 result.reset(new Scope(const_containing_)); |
| 308 } else if (mutable_containing_) { | 339 } else if (mutable_containing_) { |
| 309 // There are more nested mutable scopes. Recursively go up the stack to | 340 // There are more nested mutable scopes. Recursively go up the stack to |
| 310 // get the closure. | 341 // get the closure. |
| 311 result = mutable_containing_->MakeClosure(); | 342 result = mutable_containing_->MakeClosure(); |
| 312 } else { | 343 } else { |
| 313 // This is a standalone scope, just copy it. | 344 // This is a standalone scope, just copy it. |
| 314 result.reset(new Scope(settings_)); | 345 result.reset(new Scope(settings_)); |
| 315 } | 346 } |
| 316 | 347 |
| 348 // Want to clobber since we've flattened some nested scopes, and our parent |
| 349 // scope may have a duplicate value set. |
| 350 MergeOptions options; |
| 351 options.clobber_existing = true; |
| 352 |
| 317 // Add in our variables and we're done. | 353 // Add in our variables and we're done. |
| 318 Err err; | 354 Err err; |
| 319 NonRecursiveMergeTo(result.get(), true, NULL, "<SHOULDN'T HAPPEN>", &err); | 355 NonRecursiveMergeTo(result.get(), options, NULL, "<SHOULDN'T HAPPEN>", &err); |
| 320 DCHECK(!err.has_error()); | 356 DCHECK(!err.has_error()); |
| 321 return result.Pass(); | 357 return result.Pass(); |
| 322 } | 358 } |
| 323 | 359 |
| 324 Scope* Scope::MakeTargetDefaults(const std::string& target_type) { | 360 Scope* Scope::MakeTargetDefaults(const std::string& target_type) { |
| 325 if (GetTargetDefaults(target_type)) | 361 if (GetTargetDefaults(target_type)) |
| 326 return NULL; | 362 return NULL; |
| 327 | 363 |
| 328 Scope** dest = &target_defaults_[target_type]; | 364 Scope** dest = &target_defaults_[target_type]; |
| 329 if (*dest) { | 365 if (*dest) { |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 425 } | 461 } |
| 426 | 462 |
| 427 void Scope::AddProvider(ProgrammaticProvider* p) { | 463 void Scope::AddProvider(ProgrammaticProvider* p) { |
| 428 programmatic_providers_.insert(p); | 464 programmatic_providers_.insert(p); |
| 429 } | 465 } |
| 430 | 466 |
| 431 void Scope::RemoveProvider(ProgrammaticProvider* p) { | 467 void Scope::RemoveProvider(ProgrammaticProvider* p) { |
| 432 DCHECK(programmatic_providers_.find(p) != programmatic_providers_.end()); | 468 DCHECK(programmatic_providers_.find(p) != programmatic_providers_.end()); |
| 433 programmatic_providers_.erase(p); | 469 programmatic_providers_.erase(p); |
| 434 } | 470 } |
| OLD | NEW |