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

Unified Diff: tools/gn/scope.cc

Issue 212933008: Don't dynamically scope GN templates. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 9 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/gn/scope.h ('k') | tools/gn/scope_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/gn/scope.cc
diff --git a/tools/gn/scope.cc b/tools/gn/scope.cc
index 86f82beb804c87fcc17dc6def47d77ce77e5b17c..78612f2c64b555c241cd11979231f8e8494f4220 100644
--- a/tools/gn/scope.cc
+++ b/tools/gn/scope.cc
@@ -7,6 +7,7 @@
#include "base/logging.h"
#include "base/stl_util.h"
#include "tools/gn/parse_tree.h"
+#include "tools/gn/template.h"
namespace {
@@ -41,6 +42,7 @@ Scope::Scope(const Scope* parent)
Scope::~Scope() {
STLDeleteContainerPairSecondPointers(target_defaults_.begin(),
target_defaults_.end());
+ STLDeleteContainerPairSecondPointers(templates_.begin(), templates_.end());
}
const Value* Scope::GetValue(const base::StringPiece& ident,
@@ -119,14 +121,14 @@ Value* Scope::SetValue(const base::StringPiece& ident,
return &r.value;
}
-bool Scope::AddTemplate(const std::string& name, const FunctionCallNode* decl) {
+bool Scope::AddTemplate(const std::string& name, scoped_ptr<Template> templ) {
if (GetTemplate(name))
return false;
- templates_[name] = decl;
+ templates_[name] = templ.release();
return true;
}
-const FunctionCallNode* Scope::GetTemplate(const std::string& name) const {
+const Template* Scope::GetTemplate(const std::string& name) const {
TemplateMap::const_iterator found = templates_.find(name);
if (found != templates_.end())
return found->second;
@@ -191,24 +193,28 @@ void Scope::GetCurrentScopeValues(KeyValueMap* output) const {
}
bool Scope::NonRecursiveMergeTo(Scope* dest,
+ bool clobber_existing,
const ParseNode* node_for_err,
const char* desc_for_err,
Err* err) const {
// Values.
for (RecordMap::const_iterator i = values_.begin(); i != values_.end(); ++i) {
const Value& new_value = i->second.value;
- const Value* existing_value = dest->GetValue(i->first);
- if (existing_value && new_value != *existing_value) {
- // Value present in both the source and the dest.
- std::string desc_string(desc_for_err);
- *err = Err(node_for_err, "Value collision.",
- "This " + desc_string + " contains \"" + i->first.as_string() + "\"");
- err->AppendSubErr(Err(i->second.value, "defined here.",
- "Which would clobber the one in your current scope"));
- err->AppendSubErr(Err(*existing_value, "defined here.",
- "Executing " + desc_string + " should not conflict with anything "
- "in the current\nscope unless the values are identical."));
- return false;
+ if (!clobber_existing) {
+ const Value* existing_value = dest->GetValue(i->first);
+ if (existing_value && new_value != *existing_value) {
+ // Value present in both the source and the dest.
+ std::string desc_string(desc_for_err);
+ *err = Err(node_for_err, "Value collision.",
+ "This " + desc_string + " contains \"" + i->first.as_string() +
+ "\"");
+ err->AppendSubErr(Err(i->second.value, "defined here.",
+ "Which would clobber the one in your current scope"));
+ err->AppendSubErr(Err(*existing_value, "defined here.",
+ "Executing " + desc_string + " should not conflict with anything "
+ "in the current\nscope unless the values are identical."));
+ return false;
+ }
}
dest->values_[i->first] = i->second;
}
@@ -216,34 +222,42 @@ bool Scope::NonRecursiveMergeTo(Scope* dest,
// Target defaults are owning pointers.
for (NamedScopeMap::const_iterator i = target_defaults_.begin();
i != target_defaults_.end(); ++i) {
- if (dest->GetTargetDefaults(i->first)) {
- // TODO(brettw) it would be nice to know the origin of a
- // set_target_defaults so we can give locations for the colliding target
- // defaults.
- std::string desc_string(desc_for_err);
- *err = Err(node_for_err, "Target defaults collision.",
- "This " + desc_string + " contains target defaults for\n"
- "\"" + i->first + "\" which would clobber one for the\n"
- "same target type in your current scope. It's unfortunate that I'm "
- "too stupid\nto tell you the location of where the target defaults "
- "were set. Usually\nthis happens in the BUILDCONFIG.gn file.");
- return false;
+ if (!clobber_existing) {
+ if (dest->GetTargetDefaults(i->first)) {
+ // TODO(brettw) it would be nice to know the origin of a
+ // set_target_defaults so we can give locations for the colliding target
+ // defaults.
+ std::string desc_string(desc_for_err);
+ *err = Err(node_for_err, "Target defaults collision.",
+ "This " + desc_string + " contains target defaults for\n"
+ "\"" + i->first + "\" which would clobber one for the\n"
+ "same target type in your current scope. It's unfortunate that I'm "
+ "too stupid\nto tell you the location of where the target defaults "
+ "were set. Usually\nthis happens in the BUILDCONFIG.gn file.");
+ return false;
+ }
}
- Scope* s = new Scope(settings_);
- i->second->NonRecursiveMergeTo(s, node_for_err, "<SHOULDN'T HAPPEN>", err);
- dest->target_defaults_[i->first] = s;
+ // Be careful to delete any pointer we're about to clobber.
+ Scope** dest_scope = &dest->target_defaults_[i->first];
+ if (*dest_scope)
+ delete *dest_scope;
+ *dest_scope = new Scope(settings_);
+ i->second->NonRecursiveMergeTo(*dest_scope, clobber_existing, node_for_err,
+ "<SHOULDN'T HAPPEN>", err);
}
// Sources assignment filter.
if (sources_assignment_filter_) {
- if (dest->GetSourcesAssignmentFilter()) {
- // Sources assignment filter present in both the source and the dest.
- std::string desc_string(desc_for_err);
- *err = Err(node_for_err, "Assignment filter collision.",
- "The " + desc_string + " contains a sources_assignment_filter which\n"
- "would clobber the one in your current scope.");
- return false;
+ if (!clobber_existing) {
+ if (dest->GetSourcesAssignmentFilter()) {
+ // Sources assignment filter present in both the source and the dest.
+ std::string desc_string(desc_for_err);
+ *err = Err(node_for_err, "Assignment filter collision.",
+ "The " + desc_string + " contains a sources_assignment_filter "
+ "which\nwould clobber the one in your current scope.");
+ return false;
+ }
}
dest->sources_assignment_filter_.reset(
new PatternList(*sources_assignment_filter_));
@@ -252,25 +266,56 @@ bool Scope::NonRecursiveMergeTo(Scope* dest,
// Templates.
for (TemplateMap::const_iterator i = templates_.begin();
i != templates_.end(); ++i) {
- const FunctionCallNode* existing_template = dest->GetTemplate(i->first);
- if (existing_template) {
- // Rule present in both the source and the dest.
- std::string desc_string(desc_for_err);
- *err = Err(node_for_err, "Template collision.",
- "This " + desc_string + " contains a template \"" + i->first + "\"");
- err->AppendSubErr(Err(i->second->function(), "defined here.",
- "Which would clobber the one in your current scope"));
- err->AppendSubErr(Err(existing_template->function(), "defined here.",
- "Executing " + desc_string + " should not conflict with anything "
- "in the current\nscope."));
- return false;
+ if (!clobber_existing) {
+ const Template* existing_template = dest->GetTemplate(i->first);
+ if (existing_template) {
+ // Rule present in both the source and the dest.
+ std::string desc_string(desc_for_err);
+ *err = Err(node_for_err, "Template collision.",
+ "This " + desc_string + " contains a template \"" +
+ i->first + "\"");
+ err->AppendSubErr(Err(i->second->GetDefinitionRange(), "defined here.",
+ "Which would clobber the one in your current scope"));
+ err->AppendSubErr(Err(existing_template->GetDefinitionRange(),
+ "defined here.",
+ "Executing " + desc_string + " should not conflict with anything "
+ "in the current\nscope."));
+ return false;
+ }
}
- dest->templates_.insert(*i);
+
+ // Be careful to delete any pointer we're about to clobber.
+ const Template** dest_template = &dest->templates_[i->first];
+ if (*dest_template)
+ delete *dest_template;
+ *dest_template = i->second;
}
return true;
}
+scoped_ptr<Scope> Scope::MakeClosure() const {
+ scoped_ptr<Scope> result;
+ if (const_containing_) {
+ // We reached the top of the mutable scope stack. The result scope just
+ // references the const scope (which will never change).
+ result.reset(new Scope(const_containing_));
+ } else if (mutable_containing_) {
+ // There are more nested mutable scopes. Recursively go up the stack to
+ // get the closure.
+ result = mutable_containing_->MakeClosure();
+ } else {
+ // This is a standalone scope, just copy it.
+ result.reset(new Scope(settings_));
+ }
+
+ // Add in our variables and we're done.
+ Err err;
+ NonRecursiveMergeTo(result.get(), true, NULL, "<SHOULDN'T HAPPEN>", &err);
+ DCHECK(!err.has_error());
+ return result.Pass();
+}
+
Scope* Scope::MakeTargetDefaults(const std::string& target_type) {
if (GetTargetDefaults(target_type))
return NULL;
« no previous file with comments | « tools/gn/scope.h ('k') | tools/gn/scope_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698