This source file includes following definitions.
- mode_flags_
- mode_flags_
- mode_flags_
- GetValue
- GetMutableValue
- GetValueForcedToCurrentScope
- GetValue
- SetValue
- AddTemplate
- GetTemplate
- MarkUsed
- MarkUnused
- IsSetButUnused
- CheckForUnusedVars
- GetCurrentScopeValues
- NonRecursiveMergeTo
- MakeClosure
- MakeTargetDefaults
- GetTargetDefaults
- GetSourcesAssignmentFilter
- SetProcessingBuildConfig
- ClearProcessingBuildConfig
- IsProcessingBuildConfig
- SetProcessingImport
- ClearProcessingImport
- IsProcessingImport
- GetSourceDir
- SetProperty
- GetProperty
- AddProvider
- RemoveProvider
#include "tools/gn/scope.h"
#include "base/logging.h"
#include "base/stl_util.h"
#include "tools/gn/parse_tree.h"
#include "tools/gn/template.h"
namespace {
const unsigned kProcessingBuildConfigFlag = 1;
const unsigned kProcessingImportFlag = 2;
}
Scope::Scope(const Settings* settings)
: const_containing_(NULL),
mutable_containing_(NULL),
settings_(settings),
mode_flags_(0) {
}
Scope::Scope(Scope* parent)
: const_containing_(NULL),
mutable_containing_(parent),
settings_(parent->settings()),
mode_flags_(0) {
}
Scope::Scope(const Scope* parent)
: const_containing_(parent),
mutable_containing_(NULL),
settings_(parent->settings()),
mode_flags_(0) {
}
Scope::~Scope() {
STLDeleteContainerPairSecondPointers(target_defaults_.begin(),
target_defaults_.end());
STLDeleteContainerPairSecondPointers(templates_.begin(), templates_.end());
}
const Value* Scope::GetValue(const base::StringPiece& ident,
bool counts_as_used) {
for (ProviderSet::const_iterator i = programmatic_providers_.begin();
i != programmatic_providers_.end(); ++i) {
const Value* v = (*i)->GetProgrammaticValue(ident);
if (v)
return v;
}
RecordMap::iterator found = values_.find(ident);
if (found != values_.end()) {
if (counts_as_used)
found->second.used = true;
return &found->second.value;
}
if (const_containing_)
return const_containing_->GetValue(ident);
if (mutable_containing_)
return mutable_containing_->GetValue(ident, counts_as_used);
return NULL;
}
Value* Scope::GetMutableValue(const base::StringPiece& ident,
bool counts_as_used) {
RecordMap::iterator found = values_.find(ident);
if (found != values_.end()) {
if (counts_as_used)
found->second.used = true;
return &found->second.value;
}
if (mutable_containing_)
return mutable_containing_->GetMutableValue(ident, counts_as_used);
return NULL;
}
Value* Scope::GetValueForcedToCurrentScope(const base::StringPiece& ident,
const ParseNode* set_node) {
RecordMap::iterator found = values_.find(ident);
if (found != values_.end())
return &found->second.value;
if (containing()) {
const Value* in_containing = containing()->GetValue(ident);
if (in_containing) {
return SetValue(ident, *in_containing, set_node);
}
}
return NULL;
}
const Value* Scope::GetValue(const base::StringPiece& ident) const {
RecordMap::const_iterator found = values_.find(ident);
if (found != values_.end())
return &found->second.value;
if (containing())
return containing()->GetValue(ident);
return NULL;
}
Value* Scope::SetValue(const base::StringPiece& ident,
const Value& v,
const ParseNode* set_node) {
Record& r = values_[ident];
r.value = v;
r.value.set_origin(set_node);
return &r.value;
}
bool Scope::AddTemplate(const std::string& name, scoped_ptr<Template> templ) {
if (GetTemplate(name))
return false;
templates_[name] = templ.release();
return true;
}
const Template* Scope::GetTemplate(const std::string& name) const {
TemplateMap::const_iterator found = templates_.find(name);
if (found != templates_.end())
return found->second;
if (containing())
return containing()->GetTemplate(name);
return NULL;
}
void Scope::MarkUsed(const base::StringPiece& ident) {
RecordMap::iterator found = values_.find(ident);
if (found == values_.end()) {
NOTREACHED();
return;
}
found->second.used = true;
}
void Scope::MarkUnused(const base::StringPiece& ident) {
RecordMap::iterator found = values_.find(ident);
if (found == values_.end()) {
NOTREACHED();
return;
}
found->second.used = false;
}
bool Scope::IsSetButUnused(const base::StringPiece& ident) const {
RecordMap::const_iterator found = values_.find(ident);
if (found != values_.end()) {
if (!found->second.used) {
return true;
}
}
return false;
}
bool Scope::CheckForUnusedVars(Err* err) const {
for (RecordMap::const_iterator i = values_.begin();
i != values_.end(); ++i) {
if (!i->second.used) {
std::string help = "You set the variable \"" + i->first.as_string() +
"\" here and it was unused before it went\nout of scope.";
const BinaryOpNode* binary = i->second.value.origin()->AsBinaryOp();
if (binary && binary->op().type() == Token::EQUAL) {
*err = Err(binary->left()->GetRange(), "Assignment had no effect.",
help);
} else {
*err = Err(i->second.value.origin(), "Assignment had no effect.", help);
}
return false;
}
}
return true;
}
void Scope::GetCurrentScopeValues(KeyValueMap* output) const {
for (RecordMap::const_iterator i = values_.begin(); i != values_.end(); ++i)
(*output)[i->first] = i->second.value;
}
bool Scope::NonRecursiveMergeTo(Scope* dest,
bool clobber_existing,
const ParseNode* node_for_err,
const char* desc_for_err,
Err* err) const {
for (RecordMap::const_iterator i = values_.begin(); i != values_.end(); ++i) {
const Value& new_value = i->second.value;
if (!clobber_existing) {
const Value* existing_value = dest->GetValue(i->first);
if (existing_value && new_value != *existing_value) {
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;
}
for (NamedScopeMap::const_iterator i = target_defaults_.begin();
i != target_defaults_.end(); ++i) {
if (!clobber_existing) {
if (dest->GetTargetDefaults(i->first)) {
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** 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);
}
if (sources_assignment_filter_) {
if (!clobber_existing) {
if (dest->GetSourcesAssignmentFilter()) {
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_));
}
for (TemplateMap::const_iterator i = templates_.begin();
i != templates_.end(); ++i) {
if (!clobber_existing) {
const Template* existing_template = dest->GetTemplate(i->first);
if (existing_template) {
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;
}
}
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_) {
result.reset(new Scope(const_containing_));
} else if (mutable_containing_) {
result = mutable_containing_->MakeClosure();
} else {
result.reset(new Scope(settings_));
}
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;
Scope** dest = &target_defaults_[target_type];
if (*dest) {
NOTREACHED();
return *dest;
}
*dest = new Scope(settings_);
return *dest;
}
const Scope* Scope::GetTargetDefaults(const std::string& target_type) const {
NamedScopeMap::const_iterator found = target_defaults_.find(target_type);
if (found != target_defaults_.end())
return found->second;
if (containing())
return containing()->GetTargetDefaults(target_type);
return NULL;
}
const PatternList* Scope::GetSourcesAssignmentFilter() const {
if (sources_assignment_filter_)
return sources_assignment_filter_.get();
if (containing())
return containing()->GetSourcesAssignmentFilter();
return NULL;
}
void Scope::SetProcessingBuildConfig() {
DCHECK((mode_flags_ & kProcessingBuildConfigFlag) == 0);
mode_flags_ |= kProcessingBuildConfigFlag;
}
void Scope::ClearProcessingBuildConfig() {
DCHECK(mode_flags_ & kProcessingBuildConfigFlag);
mode_flags_ &= ~(kProcessingBuildConfigFlag);
}
bool Scope::IsProcessingBuildConfig() const {
if (mode_flags_ & kProcessingBuildConfigFlag)
return true;
if (containing())
return containing()->IsProcessingBuildConfig();
return false;
}
void Scope::SetProcessingImport() {
DCHECK((mode_flags_ & kProcessingImportFlag) == 0);
mode_flags_ |= kProcessingImportFlag;
}
void Scope::ClearProcessingImport() {
DCHECK(mode_flags_ & kProcessingImportFlag);
mode_flags_ &= ~(kProcessingImportFlag);
}
bool Scope::IsProcessingImport() const {
if (mode_flags_ & kProcessingImportFlag)
return true;
if (containing())
return containing()->IsProcessingImport();
return false;
}
const SourceDir& Scope::GetSourceDir() const {
if (!source_dir_.is_null())
return source_dir_;
if (containing())
return containing()->GetSourceDir();
return source_dir_;
}
void Scope::SetProperty(const void* key, void* value) {
if (!value) {
DCHECK(properties_.find(key) != properties_.end());
properties_.erase(key);
} else {
properties_[key] = value;
}
}
void* Scope::GetProperty(const void* key, const Scope** found_on_scope) const {
PropertyMap::const_iterator found = properties_.find(key);
if (found != properties_.end()) {
if (found_on_scope)
*found_on_scope = this;
return found->second;
}
if (containing())
return containing()->GetProperty(key, found_on_scope);
return NULL;
}
void Scope::AddProvider(ProgrammaticProvider* p) {
programmatic_providers_.insert(p);
}
void Scope::RemoveProvider(ProgrammaticProvider* p) {
DCHECK(programmatic_providers_.find(p) != programmatic_providers_.end());
programmatic_providers_.erase(p);
}