Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(182)

Side by Side Diff: tools/gn/scope.cc

Issue 21114002: Add initial prototype for the GN meta-buildsystem. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: add owners and readme Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « tools/gn/scope.h ('k') | tools/gn/scope_per_file_provider.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 }
OLDNEW
« no previous file with comments | « tools/gn/scope.h ('k') | tools/gn/scope_per_file_provider.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698