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 |