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 |