| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "tools/gn/scope.h" | |
| 6 | |
| 7 #include "base/logging.h" | |
| 8 #include "base/stl_util.h" | |
| 9 #include "tools/gn/parse_tree.h" | |
| 10 | |
| 11 namespace { | |
| 12 | |
| 13 // FLags set in the mode_flags_ of a scope. If a bit is set, it applies | |
| 14 // recursively to all dependent scopes. | |
| 15 const unsigned kProcessingBuildConfigFlag = 1; | |
| 16 const unsigned kProcessingDefaultBuildConfigFlag = 2; | |
| 17 const unsigned kProcessingImportFlag = 4; | |
| 18 | |
| 19 } // namespace | |
| 20 | |
| 21 Scope::Scope(const Settings* settings) | |
| 22 : const_containing_(NULL), | |
| 23 mutable_containing_(NULL), | |
| 24 settings_(settings), | |
| 25 mode_flags_(0) { | |
| 26 } | |
| 27 | |
| 28 Scope::Scope(Scope* parent) | |
| 29 : const_containing_(NULL), | |
| 30 mutable_containing_(parent), | |
| 31 settings_(parent->settings()), | |
| 32 mode_flags_(0) { | |
| 33 } | |
| 34 | |
| 35 Scope::Scope(const Scope* parent) | |
| 36 : const_containing_(parent), | |
| 37 mutable_containing_(NULL), | |
| 38 settings_(parent->settings()), | |
| 39 mode_flags_(0) { | |
| 40 } | |
| 41 | |
| 42 Scope::~Scope() { | |
| 43 STLDeleteContainerPairSecondPointers(target_defaults_.begin(), | |
| 44 target_defaults_.end()); | |
| 45 } | |
| 46 | |
| 47 const Value* Scope::GetValue(const base::StringPiece& ident, | |
| 48 bool counts_as_used) { | |
| 49 // First check for programatically-provided values. | |
| 50 for (ProviderSet::const_iterator i = programmatic_providers_.begin(); | |
| 51 i != programmatic_providers_.end(); ++i) { | |
| 52 const Value* v = (*i)->GetProgrammaticValue(ident); | |
| 53 if (v) | |
| 54 return v; | |
| 55 } | |
| 56 | |
| 57 RecordMap::iterator found = values_.find(ident); | |
| 58 if (found != values_.end()) { | |
| 59 if (counts_as_used) | |
| 60 found->second.used = true; | |
| 61 return &found->second.value; | |
| 62 } | |
| 63 | |
| 64 // Search in the parent scope. | |
| 65 if (const_containing_) | |
| 66 return const_containing_->GetValue(ident); | |
| 67 if (mutable_containing_) | |
| 68 return mutable_containing_->GetValue(ident, counts_as_used); | |
| 69 return NULL; | |
| 70 } | |
| 71 | |
| 72 Value* Scope::GetValueForcedToCurrentScope(const base::StringPiece& ident, | |
| 73 const ParseNode* set_node) { | |
| 74 RecordMap::iterator found = values_.find(ident); | |
| 75 if (found != values_.end()) | |
| 76 return &found->second.value; // Already have in the current scope. | |
| 77 | |
| 78 // Search in the parent scope. | |
| 79 if (containing()) { | |
| 80 const Value* in_containing = containing()->GetValue(ident); | |
| 81 if (in_containing) { | |
| 82 // Promote to current scope. | |
| 83 return SetValue(ident, *in_containing, set_node); | |
| 84 } | |
| 85 } | |
| 86 return NULL; | |
| 87 } | |
| 88 | |
| 89 const Value* Scope::GetValue(const base::StringPiece& ident) const { | |
| 90 RecordMap::const_iterator found = values_.find(ident); | |
| 91 if (found != values_.end()) | |
| 92 return &found->second.value; | |
| 93 if (containing()) | |
| 94 return containing()->GetValue(ident); | |
| 95 return NULL; | |
| 96 } | |
| 97 | |
| 98 Value* Scope::SetValue(const base::StringPiece& ident, | |
| 99 const Value& v, | |
| 100 const ParseNode* set_node) { | |
| 101 Record& r = values_[ident]; // Clears any existing value. | |
| 102 r.value = v; | |
| 103 r.value.set_origin(set_node); | |
| 104 return &r.value; | |
| 105 } | |
| 106 | |
| 107 bool Scope::AddTemplate(const std::string& name, const FunctionCallNode* decl) { | |
| 108 if (GetTemplate(name)) | |
| 109 return false; | |
| 110 templates_[name] = decl; | |
| 111 return true; | |
| 112 } | |
| 113 | |
| 114 const FunctionCallNode* Scope::GetTemplate(const std::string& name) const { | |
| 115 TemplateMap::const_iterator found = templates_.find(name); | |
| 116 if (found != templates_.end()) | |
| 117 return found->second; | |
| 118 if (containing()) | |
| 119 return containing()->GetTemplate(name); | |
| 120 return NULL; | |
| 121 } | |
| 122 | |
| 123 void Scope::MarkUsed(const base::StringPiece& ident) { | |
| 124 RecordMap::iterator found = values_.find(ident); | |
| 125 if (found == values_.end()) { | |
| 126 NOTREACHED(); | |
| 127 return; | |
| 128 } | |
| 129 found->second.used = true; | |
| 130 } | |
| 131 | |
| 132 void Scope::MarkUnused(const base::StringPiece& ident) { | |
| 133 RecordMap::iterator found = values_.find(ident); | |
| 134 if (found == values_.end()) { | |
| 135 NOTREACHED(); | |
| 136 return; | |
| 137 } | |
| 138 found->second.used = false; | |
| 139 } | |
| 140 | |
| 141 bool Scope::IsSetButUnused(const base::StringPiece& ident) const { | |
| 142 RecordMap::const_iterator found = values_.find(ident); | |
| 143 if (found != values_.end()) { | |
| 144 if (!found->second.used) { | |
| 145 return true; | |
| 146 } | |
| 147 } | |
| 148 return false; | |
| 149 } | |
| 150 | |
| 151 bool Scope::CheckForUnusedVars(Err* err) const { | |
| 152 for (RecordMap::const_iterator i = values_.begin(); | |
| 153 i != values_.end(); ++i) { | |
| 154 if (!i->second.used) { | |
| 155 std::string help = "You set the variable \"" + i->first.as_string() + | |
| 156 "\" here and it was unused before it went\nout of scope."; | |
| 157 | |
| 158 const BinaryOpNode* binary = i->second.value.origin()->AsBinaryOp(); | |
| 159 if (binary) { | |
| 160 // Make a nicer error message for normal var sets. | |
| 161 *err = Err(binary->left()->GetRange(), "Assignment had no effect.", | |
| 162 help); | |
| 163 } else { | |
| 164 // This will happen for internally-generated variables. | |
| 165 *err = Err(i->second.value.origin(), "Assignment had no effect.", help); | |
| 166 } | |
| 167 return false; | |
| 168 } | |
| 169 } | |
| 170 return true; | |
| 171 } | |
| 172 | |
| 173 void Scope::GetCurrentScopeValues(KeyValueVector* output) const { | |
| 174 output->reserve(values_.size()); | |
| 175 for (RecordMap::const_iterator i = values_.begin(); i != values_.end(); ++i) { | |
| 176 output->push_back(std::make_pair(i->first, i->second.value)); | |
| 177 } | |
| 178 } | |
| 179 | |
| 180 bool Scope::NonRecursiveMergeTo(Scope* dest, | |
| 181 const ParseNode* node_for_err, | |
| 182 const char* desc_for_err, | |
| 183 Err* err) const { | |
| 184 // Values. | |
| 185 for (RecordMap::const_iterator i = values_.begin(); i != values_.end(); ++i) { | |
| 186 const Value* existing_value = dest->GetValue(i->first); | |
| 187 if (existing_value) { | |
| 188 // Value present in both the source and the dest. | |
| 189 std::string desc_string(desc_for_err); | |
| 190 *err = Err(node_for_err, "Value collision.", | |
| 191 "This " + desc_string + " contains \"" + i->first.as_string() + "\""); | |
| 192 err->AppendSubErr(Err(i->second.value, "defined here.", | |
| 193 "Which would clobber the one in your current scope")); | |
| 194 err->AppendSubErr(Err(*existing_value, "defined here.", | |
| 195 "Executing " + desc_string + " should not conflict with anything " | |
| 196 "in the current\nscope.")); | |
| 197 return false; | |
| 198 } | |
| 199 dest->values_[i->first] = i->second; | |
| 200 } | |
| 201 | |
| 202 // Target defaults are owning pointers. | |
| 203 for (NamedScopeMap::const_iterator i = target_defaults_.begin(); | |
| 204 i != target_defaults_.end(); ++i) { | |
| 205 if (dest->GetTargetDefaults(i->first)) { | |
| 206 // TODO(brettw) it would be nice to know the origin of a | |
| 207 // set_target_defaults so we can give locations for the colliding target | |
| 208 // defaults. | |
| 209 std::string desc_string(desc_for_err); | |
| 210 *err = Err(node_for_err, "Target defaults collision.", | |
| 211 "This " + desc_string + " contains target defaults for\n" | |
| 212 "\"" + i->first + "\" which would clobber one for the\n" | |
| 213 "same target type in your current scope. It's unfortunate that I'm " | |
| 214 "too stupid\nto tell you the location of where the target defaults " | |
| 215 "were set. Usually\nthis happens in the BUILDCONFIG.gn file."); | |
| 216 return false; | |
| 217 } | |
| 218 | |
| 219 Scope* s = new Scope(settings_); | |
| 220 i->second->NonRecursiveMergeTo(s, node_for_err, "<SHOULDN'T HAPPEN>", err); | |
| 221 dest->target_defaults_[i->first] = s; | |
| 222 } | |
| 223 | |
| 224 // Sources assignment filter. | |
| 225 if (sources_assignment_filter_) { | |
| 226 if (dest->GetSourcesAssignmentFilter()) { | |
| 227 // Sources assignment filter present in both the source and the dest. | |
| 228 std::string desc_string(desc_for_err); | |
| 229 *err = Err(node_for_err, "Assignment filter collision.", | |
| 230 "The " + desc_string + " contains a sources_assignment_filter which\n" | |
| 231 "would clobber the one in your current scope."); | |
| 232 return false; | |
| 233 } | |
| 234 dest->sources_assignment_filter_.reset( | |
| 235 new PatternList(*sources_assignment_filter_)); | |
| 236 } | |
| 237 | |
| 238 // Templates. | |
| 239 for (TemplateMap::const_iterator i = templates_.begin(); | |
| 240 i != templates_.end(); ++i) { | |
| 241 const FunctionCallNode* existing_template = dest->GetTemplate(i->first); | |
| 242 if (existing_template) { | |
| 243 // Rule present in both the source and the dest. | |
| 244 std::string desc_string(desc_for_err); | |
| 245 *err = Err(node_for_err, "Template collision.", | |
| 246 "This " + desc_string + " contains a template \"" + i->first + "\""); | |
| 247 err->AppendSubErr(Err(i->second->function(), "defined here.", | |
| 248 "Which would clobber the one in your current scope")); | |
| 249 err->AppendSubErr(Err(existing_template->function(), "defined here.", | |
| 250 "Executing " + desc_string + " should not conflict with anything " | |
| 251 "in the current\nscope.")); | |
| 252 return false; | |
| 253 } | |
| 254 dest->templates_.insert(*i); | |
| 255 } | |
| 256 | |
| 257 return true; | |
| 258 } | |
| 259 | |
| 260 Scope* Scope::MakeTargetDefaults(const std::string& target_type) { | |
| 261 if (GetTargetDefaults(target_type)) | |
| 262 return NULL; | |
| 263 | |
| 264 Scope** dest = &target_defaults_[target_type]; | |
| 265 if (*dest) { | |
| 266 NOTREACHED(); // Already set. | |
| 267 return *dest; | |
| 268 } | |
| 269 *dest = new Scope(settings_); | |
| 270 return *dest; | |
| 271 } | |
| 272 | |
| 273 const Scope* Scope::GetTargetDefaults(const std::string& target_type) const { | |
| 274 NamedScopeMap::const_iterator found = target_defaults_.find(target_type); | |
| 275 if (found != target_defaults_.end()) | |
| 276 return found->second; | |
| 277 if (containing()) | |
| 278 return containing()->GetTargetDefaults(target_type); | |
| 279 return NULL; | |
| 280 } | |
| 281 | |
| 282 const PatternList* Scope::GetSourcesAssignmentFilter() const { | |
| 283 if (sources_assignment_filter_) | |
| 284 return sources_assignment_filter_.get(); | |
| 285 if (containing()) | |
| 286 return containing()->GetSourcesAssignmentFilter(); | |
| 287 return NULL; | |
| 288 } | |
| 289 | |
| 290 void Scope::SetProcessingBuildConfig() { | |
| 291 DCHECK((mode_flags_ & kProcessingBuildConfigFlag) == 0); | |
| 292 mode_flags_ |= kProcessingBuildConfigFlag; | |
| 293 } | |
| 294 | |
| 295 void Scope::ClearProcessingBuildConfig() { | |
| 296 DCHECK(mode_flags_ & kProcessingBuildConfigFlag); | |
| 297 mode_flags_ &= ~(kProcessingBuildConfigFlag); | |
| 298 } | |
| 299 | |
| 300 bool Scope::IsProcessingBuildConfig() const { | |
| 301 if (mode_flags_ & kProcessingBuildConfigFlag) | |
| 302 return true; | |
| 303 if (containing()) | |
| 304 return containing()->IsProcessingBuildConfig(); | |
| 305 return false; | |
| 306 } | |
| 307 | |
| 308 void Scope::SetProcessingDefaultBuildConfig() { | |
| 309 DCHECK((mode_flags_ & kProcessingDefaultBuildConfigFlag) == 0); | |
| 310 mode_flags_ |= kProcessingDefaultBuildConfigFlag; | |
| 311 } | |
| 312 | |
| 313 void Scope::ClearProcessingDefaultBuildConfig() { | |
| 314 DCHECK(mode_flags_ & kProcessingDefaultBuildConfigFlag); | |
| 315 mode_flags_ &= ~(kProcessingDefaultBuildConfigFlag); | |
| 316 } | |
| 317 | |
| 318 bool Scope::IsProcessingDefaultBuildConfig() const { | |
| 319 if (mode_flags_ & kProcessingDefaultBuildConfigFlag) | |
| 320 return true; | |
| 321 if (containing()) | |
| 322 return containing()->IsProcessingDefaultBuildConfig(); | |
| 323 return false; | |
| 324 } | |
| 325 | |
| 326 void Scope::SetProcessingImport() { | |
| 327 DCHECK((mode_flags_ & kProcessingImportFlag) == 0); | |
| 328 mode_flags_ |= kProcessingImportFlag; | |
| 329 } | |
| 330 | |
| 331 void Scope::ClearProcessingImport() { | |
| 332 DCHECK(mode_flags_ & kProcessingImportFlag); | |
| 333 mode_flags_ &= ~(kProcessingImportFlag); | |
| 334 } | |
| 335 | |
| 336 bool Scope::IsProcessingImport() const { | |
| 337 if (mode_flags_ & kProcessingImportFlag) | |
| 338 return true; | |
| 339 if (containing()) | |
| 340 return containing()->IsProcessingImport(); | |
| 341 return false; | |
| 342 } | |
| 343 | |
| 344 void Scope::SetProperty(const void* key, void* value) { | |
| 345 if (!value) { | |
| 346 DCHECK(properties_.find(key) != properties_.end()); | |
| 347 properties_.erase(key); | |
| 348 } else { | |
| 349 properties_[key] = value; | |
| 350 } | |
| 351 } | |
| 352 | |
| 353 void* Scope::GetProperty(const void* key, const Scope** found_on_scope) const { | |
| 354 PropertyMap::const_iterator found = properties_.find(key); | |
| 355 if (found != properties_.end()) { | |
| 356 if (found_on_scope) | |
| 357 *found_on_scope = this; | |
| 358 return found->second; | |
| 359 } | |
| 360 if (containing()) | |
| 361 return containing()->GetProperty(key, found_on_scope); | |
| 362 return NULL; | |
| 363 } | |
| 364 | |
| 365 void Scope::AddProvider(ProgrammaticProvider* p) { | |
| 366 programmatic_providers_.insert(p); | |
| 367 } | |
| 368 | |
| 369 void Scope::RemoveProvider(ProgrammaticProvider* p) { | |
| 370 DCHECK(programmatic_providers_.find(p) != programmatic_providers_.end()); | |
| 371 programmatic_providers_.erase(p); | |
| 372 } | |
| OLD | NEW |