| 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 | 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 | 20 // values start with an underscore, and are not imported from "gni" files | 
| 21 // when processing an import. | 21 // when processing an import. | 
| 22 bool IsPrivateVar(const base::StringPiece& name) { | 22 bool IsPrivateVar(const base::StringPiece& name) { | 
| 23   return name.empty() || name[0] == '_'; | 23   return name.empty() || name[0] == '_'; | 
| 24 } | 24 } | 
| 25 | 25 | 
| 26 }  // namespace | 26 }  // namespace | 
| 27 | 27 | 
|  | 28 // Defaults to all false, which are the things least likely to cause errors. | 
|  | 29 Scope::MergeOptions::MergeOptions() | 
|  | 30     : clobber_existing(false), | 
|  | 31       skip_private_vars(false), | 
|  | 32       mark_dest_used(false) { | 
|  | 33 } | 
|  | 34 | 
|  | 35 Scope::MergeOptions::~MergeOptions() { | 
|  | 36 } | 
| 28 | 37 | 
| 29 Scope::ProgrammaticProvider::~ProgrammaticProvider() { | 38 Scope::ProgrammaticProvider::~ProgrammaticProvider() { | 
| 30   scope_->RemoveProvider(this); | 39   scope_->RemoveProvider(this); | 
| 31 } | 40 } | 
| 32 | 41 | 
| 33 Scope::Scope(const Settings* settings) | 42 Scope::Scope(const Settings* settings) | 
| 34     : const_containing_(nullptr), | 43     : const_containing_(nullptr), | 
| 35       mutable_containing_(nullptr), | 44       mutable_containing_(nullptr), | 
| 36       settings_(settings), | 45       settings_(settings), | 
| 37       mode_flags_(0), | 46       mode_flags_(0), | 
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 242     (*output)[pair.first] = pair.second.value; | 251     (*output)[pair.first] = pair.second.value; | 
| 243 } | 252 } | 
| 244 | 253 | 
| 245 bool Scope::NonRecursiveMergeTo(Scope* dest, | 254 bool Scope::NonRecursiveMergeTo(Scope* dest, | 
| 246                                 const MergeOptions& options, | 255                                 const MergeOptions& options, | 
| 247                                 const ParseNode* node_for_err, | 256                                 const ParseNode* node_for_err, | 
| 248                                 const char* desc_for_err, | 257                                 const char* desc_for_err, | 
| 249                                 Err* err) const { | 258                                 Err* err) const { | 
| 250   // Values. | 259   // Values. | 
| 251   for (const auto& pair : values_) { | 260   for (const auto& pair : values_) { | 
| 252     if (options.skip_private_vars && IsPrivateVar(pair.first)) | 261     const base::StringPiece& current_name = pair.first; | 
|  | 262     if (options.skip_private_vars && IsPrivateVar(current_name)) | 
| 253       continue;  // Skip this private var. | 263       continue;  // Skip this private var. | 
|  | 264     if (!options.excluded_values.empty() && | 
|  | 265         options.excluded_values.find(current_name.as_string()) != | 
|  | 266             options.excluded_values.end()) { | 
|  | 267       continue;  // Skip this excluded value. | 
|  | 268     } | 
| 254 | 269 | 
| 255     const Value& new_value = pair.second.value; | 270     const Value& new_value = pair.second.value; | 
| 256     if (!options.clobber_existing) { | 271     if (!options.clobber_existing) { | 
| 257       const Value* existing_value = dest->GetValue(pair.first); | 272       const Value* existing_value = dest->GetValue(current_name); | 
| 258       if (existing_value && new_value != *existing_value) { | 273       if (existing_value && new_value != *existing_value) { | 
| 259         // Value present in both the source and the dest. | 274         // Value present in both the source and the dest. | 
| 260         std::string desc_string(desc_for_err); | 275         std::string desc_string(desc_for_err); | 
| 261         *err = Err(node_for_err, "Value collision.", | 276         *err = Err(node_for_err, "Value collision.", | 
| 262             "This " + desc_string + " contains \"" + pair.first.as_string() + | 277             "This " + desc_string + " contains \"" + current_name.as_string() + | 
| 263             "\""); | 278             "\""); | 
| 264         err->AppendSubErr(Err(pair.second.value, "defined here.", | 279         err->AppendSubErr(Err(pair.second.value, "defined here.", | 
| 265             "Which would clobber the one in your current scope")); | 280             "Which would clobber the one in your current scope")); | 
| 266         err->AppendSubErr(Err(*existing_value, "defined here.", | 281         err->AppendSubErr(Err(*existing_value, "defined here.", | 
| 267             "Executing " + desc_string + " should not conflict with anything " | 282             "Executing " + desc_string + " should not conflict with anything " | 
| 268             "in the current\nscope unless the values are identical.")); | 283             "in the current\nscope unless the values are identical.")); | 
| 269         return false; | 284         return false; | 
| 270       } | 285       } | 
| 271     } | 286     } | 
| 272     dest->values_[pair.first] = pair.second; | 287     dest->values_[current_name] = pair.second; | 
| 273 | 288 | 
| 274     if (options.mark_dest_used) | 289     if (options.mark_dest_used) | 
| 275       dest->MarkUsed(pair.first); | 290       dest->MarkUsed(current_name); | 
| 276   } | 291   } | 
| 277 | 292 | 
| 278   // Target defaults are owning pointers. | 293   // Target defaults are owning pointers. | 
| 279   for (const auto& pair : target_defaults_) { | 294   for (const auto& pair : target_defaults_) { | 
|  | 295     const std::string& current_name = pair.first; | 
|  | 296     if (!options.excluded_values.empty() && | 
|  | 297         options.excluded_values.find(current_name) != | 
|  | 298             options.excluded_values.end()) { | 
|  | 299       continue;  // Skip the excluded value. | 
|  | 300     } | 
|  | 301 | 
| 280     if (!options.clobber_existing) { | 302     if (!options.clobber_existing) { | 
| 281       if (dest->GetTargetDefaults(pair.first)) { | 303       if (dest->GetTargetDefaults(current_name)) { | 
| 282         // TODO(brettw) it would be nice to know the origin of a | 304         // TODO(brettw) it would be nice to know the origin of a | 
| 283         // set_target_defaults so we can give locations for the colliding target | 305         // set_target_defaults so we can give locations for the colliding target | 
| 284         // defaults. | 306         // defaults. | 
| 285         std::string desc_string(desc_for_err); | 307         std::string desc_string(desc_for_err); | 
| 286         *err = Err(node_for_err, "Target defaults collision.", | 308         *err = Err(node_for_err, "Target defaults collision.", | 
| 287             "This " + desc_string + " contains target defaults for\n" | 309             "This " + desc_string + " contains target defaults for\n" | 
| 288             "\"" + pair.first + "\" which would clobber one for the\n" | 310             "\"" + current_name + "\" which would clobber one for the\n" | 
| 289             "same target type in your current scope. It's unfortunate that I'm " | 311             "same target type in your current scope. It's unfortunate that I'm " | 
| 290             "too stupid\nto tell you the location of where the target defaults " | 312             "too stupid\nto tell you the location of where the target defaults " | 
| 291             "were set. Usually\nthis happens in the BUILDCONFIG.gn file."); | 313             "were set. Usually\nthis happens in the BUILDCONFIG.gn file."); | 
| 292         return false; | 314         return false; | 
| 293       } | 315       } | 
| 294     } | 316     } | 
| 295 | 317 | 
| 296     // Be careful to delete any pointer we're about to clobber. | 318     // Be careful to delete any pointer we're about to clobber. | 
| 297     Scope** dest_scope = &dest->target_defaults_[pair.first]; | 319     Scope** dest_scope = &dest->target_defaults_[current_name]; | 
| 298     if (*dest_scope) | 320     if (*dest_scope) | 
| 299       delete *dest_scope; | 321       delete *dest_scope; | 
| 300     *dest_scope = new Scope(settings_); | 322     *dest_scope = new Scope(settings_); | 
| 301     pair.second->NonRecursiveMergeTo(*dest_scope, options, node_for_err, | 323     pair.second->NonRecursiveMergeTo(*dest_scope, options, node_for_err, | 
| 302                                      "<SHOULDN'T HAPPEN>", err); | 324                                      "<SHOULDN'T HAPPEN>", err); | 
| 303   } | 325   } | 
| 304 | 326 | 
| 305   // Sources assignment filter. | 327   // Sources assignment filter. | 
| 306   if (sources_assignment_filter_) { | 328   if (sources_assignment_filter_) { | 
| 307     if (!options.clobber_existing) { | 329     if (!options.clobber_existing) { | 
| 308       if (dest->GetSourcesAssignmentFilter()) { | 330       if (dest->GetSourcesAssignmentFilter()) { | 
| 309         // Sources assignment filter present in both the source and the dest. | 331         // Sources assignment filter present in both the source and the dest. | 
| 310         std::string desc_string(desc_for_err); | 332         std::string desc_string(desc_for_err); | 
| 311         *err = Err(node_for_err, "Assignment filter collision.", | 333         *err = Err(node_for_err, "Assignment filter collision.", | 
| 312             "The " + desc_string + " contains a sources_assignment_filter " | 334             "The " + desc_string + " contains a sources_assignment_filter " | 
| 313             "which\nwould clobber the one in your current scope."); | 335             "which\nwould clobber the one in your current scope."); | 
| 314         return false; | 336         return false; | 
| 315       } | 337       } | 
| 316     } | 338     } | 
| 317     dest->sources_assignment_filter_.reset( | 339     dest->sources_assignment_filter_.reset( | 
| 318         new PatternList(*sources_assignment_filter_)); | 340         new PatternList(*sources_assignment_filter_)); | 
| 319   } | 341   } | 
| 320 | 342 | 
| 321   // Templates. | 343   // Templates. | 
| 322   for (const auto& pair : templates_) { | 344   for (const auto& pair : templates_) { | 
| 323     if (options.skip_private_vars && IsPrivateVar(pair.first)) | 345     const std::string& current_name = pair.first; | 
|  | 346     if (options.skip_private_vars && IsPrivateVar(current_name)) | 
| 324       continue;  // Skip this private template. | 347       continue;  // Skip this private template. | 
|  | 348     if (!options.excluded_values.empty() && | 
|  | 349         options.excluded_values.find(current_name) != | 
|  | 350             options.excluded_values.end()) { | 
|  | 351       continue;  // Skip the excluded value. | 
|  | 352     } | 
| 325 | 353 | 
| 326     if (!options.clobber_existing) { | 354     if (!options.clobber_existing) { | 
| 327       const Template* existing_template = dest->GetTemplate(pair.first); | 355       const Template* existing_template = dest->GetTemplate(current_name); | 
| 328       // Since templates are refcounted, we can check if it's the same one by | 356       // Since templates are refcounted, we can check if it's the same one by | 
| 329       // comparing pointers. | 357       // comparing pointers. | 
| 330       if (existing_template && pair.second.get() != existing_template) { | 358       if (existing_template && pair.second.get() != existing_template) { | 
| 331         // Rule present in both the source and the dest, and they're not the | 359         // Rule present in both the source and the dest, and they're not the | 
| 332         // same one. | 360         // same one. | 
| 333         std::string desc_string(desc_for_err); | 361         std::string desc_string(desc_for_err); | 
| 334         *err = Err(node_for_err, "Template collision.", | 362         *err = Err(node_for_err, "Template collision.", | 
| 335             "This " + desc_string + " contains a template \"" + | 363             "This " + desc_string + " contains a template \"" + | 
| 336             pair.first + "\""); | 364             current_name + "\""); | 
| 337         err->AppendSubErr(Err(pair.second->GetDefinitionRange(), | 365         err->AppendSubErr(Err(pair.second->GetDefinitionRange(), | 
| 338             "defined here.", | 366             "defined here.", | 
| 339             "Which would clobber the one in your current scope")); | 367             "Which would clobber the one in your current scope")); | 
| 340         err->AppendSubErr(Err(existing_template->GetDefinitionRange(), | 368         err->AppendSubErr(Err(existing_template->GetDefinitionRange(), | 
| 341             "defined here.", | 369             "defined here.", | 
| 342             "Executing " + desc_string + " should not conflict with anything " | 370             "Executing " + desc_string + " should not conflict with anything " | 
| 343             "in the current\nscope.")); | 371             "in the current\nscope.")); | 
| 344         return false; | 372         return false; | 
| 345       } | 373       } | 
| 346     } | 374     } | 
| 347 | 375 | 
| 348     // Be careful to delete any pointer we're about to clobber. | 376     // Be careful to delete any pointer we're about to clobber. | 
| 349     dest->templates_[pair.first] = pair.second; | 377     dest->templates_[current_name] = pair.second; | 
| 350   } | 378   } | 
| 351 | 379 | 
| 352   return true; | 380   return true; | 
| 353 } | 381 } | 
| 354 | 382 | 
| 355 scoped_ptr<Scope> Scope::MakeClosure() const { | 383 scoped_ptr<Scope> Scope::MakeClosure() const { | 
| 356   scoped_ptr<Scope> result; | 384   scoped_ptr<Scope> result; | 
| 357   if (const_containing_) { | 385   if (const_containing_) { | 
| 358     // We reached the top of the mutable scope stack. The result scope just | 386     // We reached the top of the mutable scope stack. The result scope just | 
| 359     // references the const scope (which will never change). | 387     // references the const scope (which will never change). | 
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 484 } | 512 } | 
| 485 | 513 | 
| 486 void Scope::AddProvider(ProgrammaticProvider* p) { | 514 void Scope::AddProvider(ProgrammaticProvider* p) { | 
| 487   programmatic_providers_.insert(p); | 515   programmatic_providers_.insert(p); | 
| 488 } | 516 } | 
| 489 | 517 | 
| 490 void Scope::RemoveProvider(ProgrammaticProvider* p) { | 518 void Scope::RemoveProvider(ProgrammaticProvider* p) { | 
| 491   DCHECK(programmatic_providers_.find(p) != programmatic_providers_.end()); | 519   DCHECK(programmatic_providers_.find(p) != programmatic_providers_.end()); | 
| 492   programmatic_providers_.erase(p); | 520   programmatic_providers_.erase(p); | 
| 493 } | 521 } | 
| OLD | NEW | 
|---|