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 |