blob: 5091645d2d8e7546f3289a11e08ec50e3ca91183 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "tools/gn/metadata.h"
#include "tools/gn/filesystem_utils.h"
bool Metadata::WalkStep(const BuildSettings* settings,
const std::vector<std::string>& keys_to_extract,
const std::vector<std::string>& keys_to_walk,
const SourceDir& rebase_dir,
std::vector<Value>* next_walk_keys,
std::vector<Value>* result,
Err* err) const {
// If there's no metadata, there's nothing to find, so quick exit.
if (contents_.empty()) {
next_walk_keys->emplace_back(nullptr, "");
return true;
}
// Pull the data from each specified key.
for (const auto& key : keys_to_extract) {
auto iter = contents_.find(key);
if (iter == contents_.end())
continue;
assert(iter->second.type() == Value::LIST);
if (!rebase_dir.is_null()) {
for (const auto& val : iter->second.list_value()) {
std::pair<Value, bool> pair =
this->RebaseValue(settings, rebase_dir, val, err);
if (!pair.second)
return false;
result->push_back(pair.first);
}
} else {
result->insert(result->end(), iter->second.list_value().begin(),
iter->second.list_value().end());
}
}
// Get the targets to look at next. If no keys_to_walk are present, we push
// the empty string to the list so that the target knows to include its deps
// and data_deps. The values used here must be lists of strings.
bool found_walk_key = false;
for (const auto& key : keys_to_walk) {
auto iter = contents_.find(key);
if (iter != contents_.end()) {
found_walk_key = true;
assert(iter->second.type() == Value::LIST);
for (const auto& val : iter->second.list_value()) {
if (!val.VerifyTypeIs(Value::STRING, err))
return false;
next_walk_keys->emplace_back(val);
}
}
}
if (!found_walk_key)
next_walk_keys->emplace_back(nullptr, "");
return true;
}
std::pair<Value, bool> Metadata::RebaseValue(const BuildSettings* settings,
const SourceDir& rebase_dir,
const Value& value,
Err* err) const {
switch (value.type()) {
case Value::STRING:
return this->RebaseStringValue(settings, rebase_dir, value, err);
case Value::LIST:
return this->RebaseListValue(settings, rebase_dir, value, err);
case Value::SCOPE:
return this->RebaseScopeValue(settings, rebase_dir, value, err);
default:
return std::make_pair(value, true);
}
}
std::pair<Value, bool> Metadata::RebaseStringValue(
const BuildSettings* settings,
const SourceDir& rebase_dir,
const Value& value,
Err* err) const {
if (!value.VerifyTypeIs(Value::STRING, err))
return std::make_pair(value, false);
std::string filename = source_dir_.ResolveRelativeAs(
/*as_file = */ true, value, err, settings->root_path_utf8());
if (err->has_error())
return std::make_pair(value, false);
Value rebased_value(value.origin(), RebasePath(filename, rebase_dir,
settings->root_path_utf8()));
return std::make_pair(rebased_value, true);
}
std::pair<Value, bool> Metadata::RebaseListValue(const BuildSettings* settings,
const SourceDir& rebase_dir,
const Value& value,
Err* err) const {
if (!value.VerifyTypeIs(Value::LIST, err))
return std::make_pair(value, false);
Value rebased_list_value(value.origin(), Value::LIST);
for (auto& val : value.list_value()) {
std::pair<Value, bool> pair = RebaseValue(settings, rebase_dir, val, err);
if (!pair.second)
return std::make_pair(value, false);
rebased_list_value.list_value().push_back(pair.first);
}
return std::make_pair(rebased_list_value, true);
}
std::pair<Value, bool> Metadata::RebaseScopeValue(const BuildSettings* settings,
const SourceDir& rebase_dir,
const Value& value,
Err* err) const {
if (!value.VerifyTypeIs(Value::SCOPE, err))
return std::make_pair(value, false);
Value rebased_scope_value(value);
Scope::KeyValueMap scope_values;
value.scope_value()->GetCurrentScopeValues(&scope_values);
for (auto& value_pair : scope_values) {
std::pair<Value, bool> pair =
RebaseValue(settings, rebase_dir, value_pair.second, err);
if (!pair.second)
return std::make_pair(value, false);
rebased_scope_value.scope_value()->SetValue(value_pair.first, pair.first,
value.origin());
}
return std::make_pair(rebased_scope_value, true);
}