| 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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 } | 50 } |
| 51 | 51 |
| 52 Scope::~Scope() { | 52 Scope::~Scope() { |
| 53 STLDeleteContainerPairSecondPointers(target_defaults_.begin(), | 53 STLDeleteContainerPairSecondPointers(target_defaults_.begin(), |
| 54 target_defaults_.end()); | 54 target_defaults_.end()); |
| 55 } | 55 } |
| 56 | 56 |
| 57 const Value* Scope::GetValue(const base::StringPiece& ident, | 57 const Value* Scope::GetValue(const base::StringPiece& ident, |
| 58 bool counts_as_used) { | 58 bool counts_as_used) { |
| 59 // First check for programatically-provided values. | 59 // First check for programatically-provided values. |
| 60 for (ProviderSet::const_iterator i = programmatic_providers_.begin(); | 60 for (const auto& provider : programmatic_providers_) { |
| 61 i != programmatic_providers_.end(); ++i) { | 61 const Value* v = provider->GetProgrammaticValue(ident); |
| 62 const Value* v = (*i)->GetProgrammaticValue(ident); | |
| 63 if (v) | 62 if (v) |
| 64 return v; | 63 return v; |
| 65 } | 64 } |
| 66 | 65 |
| 67 RecordMap::iterator found = values_.find(ident); | 66 RecordMap::iterator found = values_.find(ident); |
| 68 if (found != values_.end()) { | 67 if (found != values_.end()) { |
| 69 if (counts_as_used) | 68 if (counts_as_used) |
| 70 found->second.used = true; | 69 found->second.used = true; |
| 71 return &found->second.value; | 70 return &found->second.value; |
| 72 } | 71 } |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 135 if (found != values_.end()) | 134 if (found != values_.end()) |
| 136 values_.erase(found); | 135 values_.erase(found); |
| 137 } | 136 } |
| 138 | 137 |
| 139 void Scope::RemovePrivateIdentifiers() { | 138 void Scope::RemovePrivateIdentifiers() { |
| 140 // Do it in two phases to avoid mutating while iterating. Our hash map is | 139 // Do it in two phases to avoid mutating while iterating. Our hash map is |
| 141 // currently backed by several different vendor-specific implementations and | 140 // currently backed by several different vendor-specific implementations and |
| 142 // I'm not sure if all of them support mutating while iterating. Since this | 141 // I'm not sure if all of them support mutating while iterating. Since this |
| 143 // is not perf-critical, do the safe thing. | 142 // is not perf-critical, do the safe thing. |
| 144 std::vector<base::StringPiece> to_remove; | 143 std::vector<base::StringPiece> to_remove; |
| 145 for (RecordMap::const_iterator i = values_.begin(); i != values_.end(); ++i) { | 144 for (const auto& cur : values_) { |
| 146 if (IsPrivateVar(i->first)) | 145 if (IsPrivateVar(cur.first)) |
| 147 to_remove.push_back(i->first); | 146 to_remove.push_back(cur.first); |
| 148 } | 147 } |
| 149 | 148 |
| 150 for (size_t i = 0; i < to_remove.size(); i++) | 149 for (const auto& cur : to_remove) |
| 151 values_.erase(to_remove[i]); | 150 values_.erase(cur); |
| 152 } | 151 } |
| 153 | 152 |
| 154 bool Scope::AddTemplate(const std::string& name, const Template* templ) { | 153 bool Scope::AddTemplate(const std::string& name, const Template* templ) { |
| 155 if (GetTemplate(name)) | 154 if (GetTemplate(name)) |
| 156 return false; | 155 return false; |
| 157 templates_[name] = templ; | 156 templates_[name] = templ; |
| 158 return true; | 157 return true; |
| 159 } | 158 } |
| 160 | 159 |
| 161 const Template* Scope::GetTemplate(const std::string& name) const { | 160 const Template* Scope::GetTemplate(const std::string& name) const { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 189 RecordMap::const_iterator found = values_.find(ident); | 188 RecordMap::const_iterator found = values_.find(ident); |
| 190 if (found != values_.end()) { | 189 if (found != values_.end()) { |
| 191 if (!found->second.used) { | 190 if (!found->second.used) { |
| 192 return true; | 191 return true; |
| 193 } | 192 } |
| 194 } | 193 } |
| 195 return false; | 194 return false; |
| 196 } | 195 } |
| 197 | 196 |
| 198 bool Scope::CheckForUnusedVars(Err* err) const { | 197 bool Scope::CheckForUnusedVars(Err* err) const { |
| 199 for (RecordMap::const_iterator i = values_.begin(); | 198 for (const auto& pair : values_) { |
| 200 i != values_.end(); ++i) { | 199 if (!pair.second.used) { |
| 201 if (!i->second.used) { | 200 std::string help = "You set the variable \"" + pair.first.as_string() + |
| 202 std::string help = "You set the variable \"" + i->first.as_string() + | |
| 203 "\" here and it was unused before it went\nout of scope."; | 201 "\" here and it was unused before it went\nout of scope."; |
| 204 | 202 |
| 205 const BinaryOpNode* binary = i->second.value.origin()->AsBinaryOp(); | 203 const BinaryOpNode* binary = pair.second.value.origin()->AsBinaryOp(); |
| 206 if (binary && binary->op().type() == Token::EQUAL) { | 204 if (binary && binary->op().type() == Token::EQUAL) { |
| 207 // Make a nicer error message for normal var sets. | 205 // Make a nicer error message for normal var sets. |
| 208 *err = Err(binary->left()->GetRange(), "Assignment had no effect.", | 206 *err = Err(binary->left()->GetRange(), "Assignment had no effect.", |
| 209 help); | 207 help); |
| 210 } else { | 208 } else { |
| 211 // This will happen for internally-generated variables. | 209 // This will happen for internally-generated variables. |
| 212 *err = Err(i->second.value.origin(), "Assignment had no effect.", help); | 210 *err = Err(pair.second.value.origin(), "Assignment had no effect.", |
| 211 help); |
| 213 } | 212 } |
| 214 return false; | 213 return false; |
| 215 } | 214 } |
| 216 } | 215 } |
| 217 return true; | 216 return true; |
| 218 } | 217 } |
| 219 | 218 |
| 220 void Scope::GetCurrentScopeValues(KeyValueMap* output) const { | 219 void Scope::GetCurrentScopeValues(KeyValueMap* output) const { |
| 221 for (RecordMap::const_iterator i = values_.begin(); i != values_.end(); ++i) | 220 for (const auto& pair : values_) |
| 222 (*output)[i->first] = i->second.value; | 221 (*output)[pair.first] = pair.second.value; |
| 223 } | 222 } |
| 224 | 223 |
| 225 bool Scope::NonRecursiveMergeTo(Scope* dest, | 224 bool Scope::NonRecursiveMergeTo(Scope* dest, |
| 226 const MergeOptions& options, | 225 const MergeOptions& options, |
| 227 const ParseNode* node_for_err, | 226 const ParseNode* node_for_err, |
| 228 const char* desc_for_err, | 227 const char* desc_for_err, |
| 229 Err* err) const { | 228 Err* err) const { |
| 230 // Values. | 229 // Values. |
| 231 for (RecordMap::const_iterator i = values_.begin(); i != values_.end(); ++i) { | 230 for (const auto& pair : values_) { |
| 232 if (options.skip_private_vars && IsPrivateVar(i->first)) | 231 if (options.skip_private_vars && IsPrivateVar(pair.first)) |
| 233 continue; // Skip this private var. | 232 continue; // Skip this private var. |
| 234 | 233 |
| 235 const Value& new_value = i->second.value; | 234 const Value& new_value = pair.second.value; |
| 236 if (!options.clobber_existing) { | 235 if (!options.clobber_existing) { |
| 237 const Value* existing_value = dest->GetValue(i->first); | 236 const Value* existing_value = dest->GetValue(pair.first); |
| 238 if (existing_value && new_value != *existing_value) { | 237 if (existing_value && new_value != *existing_value) { |
| 239 // Value present in both the source and the dest. | 238 // Value present in both the source and the dest. |
| 240 std::string desc_string(desc_for_err); | 239 std::string desc_string(desc_for_err); |
| 241 *err = Err(node_for_err, "Value collision.", | 240 *err = Err(node_for_err, "Value collision.", |
| 242 "This " + desc_string + " contains \"" + i->first.as_string() + | 241 "This " + desc_string + " contains \"" + pair.first.as_string() + |
| 243 "\""); | 242 "\""); |
| 244 err->AppendSubErr(Err(i->second.value, "defined here.", | 243 err->AppendSubErr(Err(pair.second.value, "defined here.", |
| 245 "Which would clobber the one in your current scope")); | 244 "Which would clobber the one in your current scope")); |
| 246 err->AppendSubErr(Err(*existing_value, "defined here.", | 245 err->AppendSubErr(Err(*existing_value, "defined here.", |
| 247 "Executing " + desc_string + " should not conflict with anything " | 246 "Executing " + desc_string + " should not conflict with anything " |
| 248 "in the current\nscope unless the values are identical.")); | 247 "in the current\nscope unless the values are identical.")); |
| 249 return false; | 248 return false; |
| 250 } | 249 } |
| 251 } | 250 } |
| 252 dest->values_[i->first] = i->second; | 251 dest->values_[pair.first] = pair.second; |
| 253 | 252 |
| 254 if (options.mark_used) | 253 if (options.mark_used) |
| 255 dest->MarkUsed(i->first); | 254 dest->MarkUsed(pair.first); |
| 256 } | 255 } |
| 257 | 256 |
| 258 // Target defaults are owning pointers. | 257 // Target defaults are owning pointers. |
| 259 for (NamedScopeMap::const_iterator i = target_defaults_.begin(); | 258 for (const auto& pair : target_defaults_) { |
| 260 i != target_defaults_.end(); ++i) { | |
| 261 if (!options.clobber_existing) { | 259 if (!options.clobber_existing) { |
| 262 if (dest->GetTargetDefaults(i->first)) { | 260 if (dest->GetTargetDefaults(pair.first)) { |
| 263 // TODO(brettw) it would be nice to know the origin of a | 261 // TODO(brettw) it would be nice to know the origin of a |
| 264 // set_target_defaults so we can give locations for the colliding target | 262 // set_target_defaults so we can give locations for the colliding target |
| 265 // defaults. | 263 // defaults. |
| 266 std::string desc_string(desc_for_err); | 264 std::string desc_string(desc_for_err); |
| 267 *err = Err(node_for_err, "Target defaults collision.", | 265 *err = Err(node_for_err, "Target defaults collision.", |
| 268 "This " + desc_string + " contains target defaults for\n" | 266 "This " + desc_string + " contains target defaults for\n" |
| 269 "\"" + i->first + "\" which would clobber one for the\n" | 267 "\"" + pair.first + "\" which would clobber one for the\n" |
| 270 "same target type in your current scope. It's unfortunate that I'm " | 268 "same target type in your current scope. It's unfortunate that I'm " |
| 271 "too stupid\nto tell you the location of where the target defaults " | 269 "too stupid\nto tell you the location of where the target defaults " |
| 272 "were set. Usually\nthis happens in the BUILDCONFIG.gn file."); | 270 "were set. Usually\nthis happens in the BUILDCONFIG.gn file."); |
| 273 return false; | 271 return false; |
| 274 } | 272 } |
| 275 } | 273 } |
| 276 | 274 |
| 277 // Be careful to delete any pointer we're about to clobber. | 275 // Be careful to delete any pointer we're about to clobber. |
| 278 Scope** dest_scope = &dest->target_defaults_[i->first]; | 276 Scope** dest_scope = &dest->target_defaults_[pair.first]; |
| 279 if (*dest_scope) | 277 if (*dest_scope) |
| 280 delete *dest_scope; | 278 delete *dest_scope; |
| 281 *dest_scope = new Scope(settings_); | 279 *dest_scope = new Scope(settings_); |
| 282 i->second->NonRecursiveMergeTo(*dest_scope, options, node_for_err, | 280 pair.second->NonRecursiveMergeTo(*dest_scope, options, node_for_err, |
| 283 "<SHOULDN'T HAPPEN>", err); | 281 "<SHOULDN'T HAPPEN>", err); |
| 284 } | 282 } |
| 285 | 283 |
| 286 // Sources assignment filter. | 284 // Sources assignment filter. |
| 287 if (sources_assignment_filter_) { | 285 if (sources_assignment_filter_) { |
| 288 if (!options.clobber_existing) { | 286 if (!options.clobber_existing) { |
| 289 if (dest->GetSourcesAssignmentFilter()) { | 287 if (dest->GetSourcesAssignmentFilter()) { |
| 290 // Sources assignment filter present in both the source and the dest. | 288 // Sources assignment filter present in both the source and the dest. |
| 291 std::string desc_string(desc_for_err); | 289 std::string desc_string(desc_for_err); |
| 292 *err = Err(node_for_err, "Assignment filter collision.", | 290 *err = Err(node_for_err, "Assignment filter collision.", |
| 293 "The " + desc_string + " contains a sources_assignment_filter " | 291 "The " + desc_string + " contains a sources_assignment_filter " |
| 294 "which\nwould clobber the one in your current scope."); | 292 "which\nwould clobber the one in your current scope."); |
| 295 return false; | 293 return false; |
| 296 } | 294 } |
| 297 } | 295 } |
| 298 dest->sources_assignment_filter_.reset( | 296 dest->sources_assignment_filter_.reset( |
| 299 new PatternList(*sources_assignment_filter_)); | 297 new PatternList(*sources_assignment_filter_)); |
| 300 } | 298 } |
| 301 | 299 |
| 302 // Templates. | 300 // Templates. |
| 303 for (TemplateMap::const_iterator i = templates_.begin(); | 301 for (const auto& pair : templates_) { |
| 304 i != templates_.end(); ++i) { | 302 if (options.skip_private_vars && IsPrivateVar(pair.first)) |
| 305 if (options.skip_private_vars && IsPrivateVar(i->first)) | |
| 306 continue; // Skip this private template. | 303 continue; // Skip this private template. |
| 307 | 304 |
| 308 if (!options.clobber_existing) { | 305 if (!options.clobber_existing) { |
| 309 const Template* existing_template = dest->GetTemplate(i->first); | 306 const Template* existing_template = dest->GetTemplate(pair.first); |
| 310 // Since templates are refcounted, we can check if it's the same one by | 307 // Since templates are refcounted, we can check if it's the same one by |
| 311 // comparing pointers. | 308 // comparing pointers. |
| 312 if (existing_template && i->second.get() != existing_template) { | 309 if (existing_template && pair.second.get() != existing_template) { |
| 313 // Rule present in both the source and the dest, and they're not the | 310 // Rule present in both the source and the dest, and they're not the |
| 314 // same one. | 311 // same one. |
| 315 std::string desc_string(desc_for_err); | 312 std::string desc_string(desc_for_err); |
| 316 *err = Err(node_for_err, "Template collision.", | 313 *err = Err(node_for_err, "Template collision.", |
| 317 "This " + desc_string + " contains a template \"" + | 314 "This " + desc_string + " contains a template \"" + |
| 318 i->first + "\""); | 315 pair.first + "\""); |
| 319 err->AppendSubErr(Err(i->second->GetDefinitionRange(), "defined here.", | 316 err->AppendSubErr(Err(pair.second->GetDefinitionRange(), |
| 317 "defined here.", |
| 320 "Which would clobber the one in your current scope")); | 318 "Which would clobber the one in your current scope")); |
| 321 err->AppendSubErr(Err(existing_template->GetDefinitionRange(), | 319 err->AppendSubErr(Err(existing_template->GetDefinitionRange(), |
| 322 "defined here.", | 320 "defined here.", |
| 323 "Executing " + desc_string + " should not conflict with anything " | 321 "Executing " + desc_string + " should not conflict with anything " |
| 324 "in the current\nscope.")); | 322 "in the current\nscope.")); |
| 325 return false; | 323 return false; |
| 326 } | 324 } |
| 327 } | 325 } |
| 328 | 326 |
| 329 // Be careful to delete any pointer we're about to clobber. | 327 // Be careful to delete any pointer we're about to clobber. |
| 330 dest->templates_[i->first] = i->second; | 328 dest->templates_[pair.first] = pair.second; |
| 331 } | 329 } |
| 332 | 330 |
| 333 return true; | 331 return true; |
| 334 } | 332 } |
| 335 | 333 |
| 336 scoped_ptr<Scope> Scope::MakeClosure() const { | 334 scoped_ptr<Scope> Scope::MakeClosure() const { |
| 337 scoped_ptr<Scope> result; | 335 scoped_ptr<Scope> result; |
| 338 if (const_containing_) { | 336 if (const_containing_) { |
| 339 // We reached the top of the mutable scope stack. The result scope just | 337 // We reached the top of the mutable scope stack. The result scope just |
| 340 // references the const scope (which will never change). | 338 // references the const scope (which will never change). |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 464 } | 462 } |
| 465 | 463 |
| 466 void Scope::AddProvider(ProgrammaticProvider* p) { | 464 void Scope::AddProvider(ProgrammaticProvider* p) { |
| 467 programmatic_providers_.insert(p); | 465 programmatic_providers_.insert(p); |
| 468 } | 466 } |
| 469 | 467 |
| 470 void Scope::RemoveProvider(ProgrammaticProvider* p) { | 468 void Scope::RemoveProvider(ProgrammaticProvider* p) { |
| 471 DCHECK(programmatic_providers_.find(p) != programmatic_providers_.end()); | 469 DCHECK(programmatic_providers_.find(p) != programmatic_providers_.end()); |
| 472 programmatic_providers_.erase(p); | 470 programmatic_providers_.erase(p); |
| 473 } | 471 } |
| OLD | NEW |