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 | 11 |
11 namespace { | 12 namespace { |
12 | 13 |
13 // 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 |
14 // recursively to all dependent scopes. | 15 // recursively to all dependent scopes. |
15 const unsigned kProcessingBuildConfigFlag = 1; | 16 const unsigned kProcessingBuildConfigFlag = 1; |
16 const unsigned kProcessingImportFlag = 2; | 17 const unsigned kProcessingImportFlag = 2; |
17 | 18 |
18 } // namespace | 19 } // namespace |
19 | 20 |
(...skipping 14 matching lines...) Expand all Loading... |
34 Scope::Scope(const Scope* parent) | 35 Scope::Scope(const Scope* parent) |
35 : const_containing_(parent), | 36 : const_containing_(parent), |
36 mutable_containing_(NULL), | 37 mutable_containing_(NULL), |
37 settings_(parent->settings()), | 38 settings_(parent->settings()), |
38 mode_flags_(0) { | 39 mode_flags_(0) { |
39 } | 40 } |
40 | 41 |
41 Scope::~Scope() { | 42 Scope::~Scope() { |
42 STLDeleteContainerPairSecondPointers(target_defaults_.begin(), | 43 STLDeleteContainerPairSecondPointers(target_defaults_.begin(), |
43 target_defaults_.end()); | 44 target_defaults_.end()); |
| 45 STLDeleteContainerPairSecondPointers(templates_.begin(), templates_.end()); |
44 } | 46 } |
45 | 47 |
46 const Value* Scope::GetValue(const base::StringPiece& ident, | 48 const Value* Scope::GetValue(const base::StringPiece& ident, |
47 bool counts_as_used) { | 49 bool counts_as_used) { |
48 // First check for programatically-provided values. | 50 // First check for programatically-provided values. |
49 for (ProviderSet::const_iterator i = programmatic_providers_.begin(); | 51 for (ProviderSet::const_iterator i = programmatic_providers_.begin(); |
50 i != programmatic_providers_.end(); ++i) { | 52 i != programmatic_providers_.end(); ++i) { |
51 const Value* v = (*i)->GetProgrammaticValue(ident); | 53 const Value* v = (*i)->GetProgrammaticValue(ident); |
52 if (v) | 54 if (v) |
53 return v; | 55 return v; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
112 | 114 |
113 Value* Scope::SetValue(const base::StringPiece& ident, | 115 Value* Scope::SetValue(const base::StringPiece& ident, |
114 const Value& v, | 116 const Value& v, |
115 const ParseNode* set_node) { | 117 const ParseNode* set_node) { |
116 Record& r = values_[ident]; // Clears any existing value. | 118 Record& r = values_[ident]; // Clears any existing value. |
117 r.value = v; | 119 r.value = v; |
118 r.value.set_origin(set_node); | 120 r.value.set_origin(set_node); |
119 return &r.value; | 121 return &r.value; |
120 } | 122 } |
121 | 123 |
122 bool Scope::AddTemplate(const std::string& name, const FunctionCallNode* decl) { | 124 bool Scope::AddTemplate(const std::string& name, scoped_ptr<Template> templ) { |
123 if (GetTemplate(name)) | 125 if (GetTemplate(name)) |
124 return false; | 126 return false; |
125 templates_[name] = decl; | 127 templates_[name] = templ.release(); |
126 return true; | 128 return true; |
127 } | 129 } |
128 | 130 |
129 const FunctionCallNode* Scope::GetTemplate(const std::string& name) const { | 131 const Template* Scope::GetTemplate(const std::string& name) const { |
130 TemplateMap::const_iterator found = templates_.find(name); | 132 TemplateMap::const_iterator found = templates_.find(name); |
131 if (found != templates_.end()) | 133 if (found != templates_.end()) |
132 return found->second; | 134 return found->second; |
133 if (containing()) | 135 if (containing()) |
134 return containing()->GetTemplate(name); | 136 return containing()->GetTemplate(name); |
135 return NULL; | 137 return NULL; |
136 } | 138 } |
137 | 139 |
138 void Scope::MarkUsed(const base::StringPiece& ident) { | 140 void Scope::MarkUsed(const base::StringPiece& ident) { |
139 RecordMap::iterator found = values_.find(ident); | 141 RecordMap::iterator found = values_.find(ident); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
184 } | 186 } |
185 return true; | 187 return true; |
186 } | 188 } |
187 | 189 |
188 void Scope::GetCurrentScopeValues(KeyValueMap* output) const { | 190 void Scope::GetCurrentScopeValues(KeyValueMap* output) const { |
189 for (RecordMap::const_iterator i = values_.begin(); i != values_.end(); ++i) | 191 for (RecordMap::const_iterator i = values_.begin(); i != values_.end(); ++i) |
190 (*output)[i->first] = i->second.value; | 192 (*output)[i->first] = i->second.value; |
191 } | 193 } |
192 | 194 |
193 bool Scope::NonRecursiveMergeTo(Scope* dest, | 195 bool Scope::NonRecursiveMergeTo(Scope* dest, |
| 196 bool clobber_existing, |
194 const ParseNode* node_for_err, | 197 const ParseNode* node_for_err, |
195 const char* desc_for_err, | 198 const char* desc_for_err, |
196 Err* err) const { | 199 Err* err) const { |
197 // Values. | 200 // Values. |
198 for (RecordMap::const_iterator i = values_.begin(); i != values_.end(); ++i) { | 201 for (RecordMap::const_iterator i = values_.begin(); i != values_.end(); ++i) { |
199 const Value& new_value = i->second.value; | 202 const Value& new_value = i->second.value; |
200 const Value* existing_value = dest->GetValue(i->first); | 203 if (!clobber_existing) { |
201 if (existing_value && new_value != *existing_value) { | 204 const Value* existing_value = dest->GetValue(i->first); |
202 // Value present in both the source and the dest. | 205 if (existing_value && new_value != *existing_value) { |
203 std::string desc_string(desc_for_err); | 206 // Value present in both the source and the dest. |
204 *err = Err(node_for_err, "Value collision.", | 207 std::string desc_string(desc_for_err); |
205 "This " + desc_string + " contains \"" + i->first.as_string() + "\""); | 208 *err = Err(node_for_err, "Value collision.", |
206 err->AppendSubErr(Err(i->second.value, "defined here.", | 209 "This " + desc_string + " contains \"" + i->first.as_string() + |
207 "Which would clobber the one in your current scope")); | 210 "\""); |
208 err->AppendSubErr(Err(*existing_value, "defined here.", | 211 err->AppendSubErr(Err(i->second.value, "defined here.", |
209 "Executing " + desc_string + " should not conflict with anything " | 212 "Which would clobber the one in your current scope")); |
210 "in the current\nscope unless the values are identical.")); | 213 err->AppendSubErr(Err(*existing_value, "defined here.", |
211 return false; | 214 "Executing " + desc_string + " should not conflict with anything " |
| 215 "in the current\nscope unless the values are identical.")); |
| 216 return false; |
| 217 } |
212 } | 218 } |
213 dest->values_[i->first] = i->second; | 219 dest->values_[i->first] = i->second; |
214 } | 220 } |
215 | 221 |
216 // Target defaults are owning pointers. | 222 // Target defaults are owning pointers. |
217 for (NamedScopeMap::const_iterator i = target_defaults_.begin(); | 223 for (NamedScopeMap::const_iterator i = target_defaults_.begin(); |
218 i != target_defaults_.end(); ++i) { | 224 i != target_defaults_.end(); ++i) { |
219 if (dest->GetTargetDefaults(i->first)) { | 225 if (!clobber_existing) { |
220 // TODO(brettw) it would be nice to know the origin of a | 226 if (dest->GetTargetDefaults(i->first)) { |
221 // set_target_defaults so we can give locations for the colliding target | 227 // TODO(brettw) it would be nice to know the origin of a |
222 // defaults. | 228 // set_target_defaults so we can give locations for the colliding target |
223 std::string desc_string(desc_for_err); | 229 // defaults. |
224 *err = Err(node_for_err, "Target defaults collision.", | 230 std::string desc_string(desc_for_err); |
225 "This " + desc_string + " contains target defaults for\n" | 231 *err = Err(node_for_err, "Target defaults collision.", |
226 "\"" + i->first + "\" which would clobber one for the\n" | 232 "This " + desc_string + " contains target defaults for\n" |
227 "same target type in your current scope. It's unfortunate that I'm " | 233 "\"" + i->first + "\" which would clobber one for the\n" |
228 "too stupid\nto tell you the location of where the target defaults " | 234 "same target type in your current scope. It's unfortunate that I'm " |
229 "were set. Usually\nthis happens in the BUILDCONFIG.gn file."); | 235 "too stupid\nto tell you the location of where the target defaults " |
230 return false; | 236 "were set. Usually\nthis happens in the BUILDCONFIG.gn file."); |
| 237 return false; |
| 238 } |
231 } | 239 } |
232 | 240 |
233 Scope* s = new Scope(settings_); | 241 // Be careful to delete any pointer we're about to clobber. |
234 i->second->NonRecursiveMergeTo(s, node_for_err, "<SHOULDN'T HAPPEN>", err); | 242 Scope** dest_scope = &dest->target_defaults_[i->first]; |
235 dest->target_defaults_[i->first] = s; | 243 if (*dest_scope) |
| 244 delete *dest_scope; |
| 245 *dest_scope = new Scope(settings_); |
| 246 i->second->NonRecursiveMergeTo(*dest_scope, clobber_existing, node_for_err, |
| 247 "<SHOULDN'T HAPPEN>", err); |
236 } | 248 } |
237 | 249 |
238 // Sources assignment filter. | 250 // Sources assignment filter. |
239 if (sources_assignment_filter_) { | 251 if (sources_assignment_filter_) { |
240 if (dest->GetSourcesAssignmentFilter()) { | 252 if (!clobber_existing) { |
241 // Sources assignment filter present in both the source and the dest. | 253 if (dest->GetSourcesAssignmentFilter()) { |
242 std::string desc_string(desc_for_err); | 254 // Sources assignment filter present in both the source and the dest. |
243 *err = Err(node_for_err, "Assignment filter collision.", | 255 std::string desc_string(desc_for_err); |
244 "The " + desc_string + " contains a sources_assignment_filter which\n" | 256 *err = Err(node_for_err, "Assignment filter collision.", |
245 "would clobber the one in your current scope."); | 257 "The " + desc_string + " contains a sources_assignment_filter " |
246 return false; | 258 "which\nwould clobber the one in your current scope."); |
| 259 return false; |
| 260 } |
247 } | 261 } |
248 dest->sources_assignment_filter_.reset( | 262 dest->sources_assignment_filter_.reset( |
249 new PatternList(*sources_assignment_filter_)); | 263 new PatternList(*sources_assignment_filter_)); |
250 } | 264 } |
251 | 265 |
252 // Templates. | 266 // Templates. |
253 for (TemplateMap::const_iterator i = templates_.begin(); | 267 for (TemplateMap::const_iterator i = templates_.begin(); |
254 i != templates_.end(); ++i) { | 268 i != templates_.end(); ++i) { |
255 const FunctionCallNode* existing_template = dest->GetTemplate(i->first); | 269 if (!clobber_existing) { |
256 if (existing_template) { | 270 const Template* existing_template = dest->GetTemplate(i->first); |
257 // Rule present in both the source and the dest. | 271 if (existing_template) { |
258 std::string desc_string(desc_for_err); | 272 // Rule present in both the source and the dest. |
259 *err = Err(node_for_err, "Template collision.", | 273 std::string desc_string(desc_for_err); |
260 "This " + desc_string + " contains a template \"" + i->first + "\""); | 274 *err = Err(node_for_err, "Template collision.", |
261 err->AppendSubErr(Err(i->second->function(), "defined here.", | 275 "This " + desc_string + " contains a template \"" + |
262 "Which would clobber the one in your current scope")); | 276 i->first + "\""); |
263 err->AppendSubErr(Err(existing_template->function(), "defined here.", | 277 err->AppendSubErr(Err(i->second->GetDefinitionRange(), "defined here.", |
264 "Executing " + desc_string + " should not conflict with anything " | 278 "Which would clobber the one in your current scope")); |
265 "in the current\nscope.")); | 279 err->AppendSubErr(Err(existing_template->GetDefinitionRange(), |
266 return false; | 280 "defined here.", |
| 281 "Executing " + desc_string + " should not conflict with anything " |
| 282 "in the current\nscope.")); |
| 283 return false; |
| 284 } |
267 } | 285 } |
268 dest->templates_.insert(*i); | 286 |
| 287 // Be careful to delete any pointer we're about to clobber. |
| 288 const Template** dest_template = &dest->templates_[i->first]; |
| 289 if (*dest_template) |
| 290 delete *dest_template; |
| 291 *dest_template = i->second; |
269 } | 292 } |
270 | 293 |
271 return true; | 294 return true; |
272 } | 295 } |
273 | 296 |
| 297 scoped_ptr<Scope> Scope::MakeClosure() const { |
| 298 scoped_ptr<Scope> result; |
| 299 if (const_containing_) { |
| 300 // We reached the top of the mutable scope stack. The result scope just |
| 301 // references the const scope (which will never change). |
| 302 result.reset(new Scope(const_containing_)); |
| 303 } else if (mutable_containing_) { |
| 304 // There are more nested mutable scopes. Recursively go up the stack to |
| 305 // get the closure. |
| 306 result = mutable_containing_->MakeClosure(); |
| 307 } else { |
| 308 // This is a standalone scope, just copy it. |
| 309 result.reset(new Scope(settings_)); |
| 310 } |
| 311 |
| 312 // Add in our variables and we're done. |
| 313 Err err; |
| 314 NonRecursiveMergeTo(result.get(), true, NULL, "<SHOULDN'T HAPPEN>", &err); |
| 315 DCHECK(!err.has_error()); |
| 316 return result.Pass(); |
| 317 } |
| 318 |
274 Scope* Scope::MakeTargetDefaults(const std::string& target_type) { | 319 Scope* Scope::MakeTargetDefaults(const std::string& target_type) { |
275 if (GetTargetDefaults(target_type)) | 320 if (GetTargetDefaults(target_type)) |
276 return NULL; | 321 return NULL; |
277 | 322 |
278 Scope** dest = &target_defaults_[target_type]; | 323 Scope** dest = &target_defaults_[target_type]; |
279 if (*dest) { | 324 if (*dest) { |
280 NOTREACHED(); // Already set. | 325 NOTREACHED(); // Already set. |
281 return *dest; | 326 return *dest; |
282 } | 327 } |
283 *dest = new Scope(settings_); | 328 *dest = new Scope(settings_); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
367 } | 412 } |
368 | 413 |
369 void Scope::AddProvider(ProgrammaticProvider* p) { | 414 void Scope::AddProvider(ProgrammaticProvider* p) { |
370 programmatic_providers_.insert(p); | 415 programmatic_providers_.insert(p); |
371 } | 416 } |
372 | 417 |
373 void Scope::RemoveProvider(ProgrammaticProvider* p) { | 418 void Scope::RemoveProvider(ProgrammaticProvider* p) { |
374 DCHECK(programmatic_providers_.find(p) != programmatic_providers_.end()); | 419 DCHECK(programmatic_providers_.find(p) != programmatic_providers_.end()); |
375 programmatic_providers_.erase(p); | 420 programmatic_providers_.erase(p); |
376 } | 421 } |
OLD | NEW |