| // Copyright 2014 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 "gn/visibility.h" | |
| #include <memory> | |
| #include <string_view> | |
| #include "base/strings/string_util.h" | |
| #include "base/values.h" | |
| #include "gn/err.h" | |
| #include "gn/filesystem_utils.h" | |
| #include "gn/item.h" | |
| #include "gn/label.h" | |
| #include "gn/scope.h" | |
| #include "gn/value.h" | |
| #include "gn/variables.h" | |
| Visibility::Visibility() = default; | |
| Visibility::~Visibility() = default; | |
| bool Visibility::Set(const SourceDir& current_dir, | |
| std::string_view source_root, | |
| const Value& value, | |
| Err* err) { | |
| patterns_.clear(); | |
| if (!value.VerifyTypeIs(Value::LIST, err)) { | |
| CHECK(err->has_error()); | |
| return false; | |
| } | |
| for (const auto& item : value.list_value()) { | |
| patterns_.push_back( | |
| LabelPattern::GetPattern(current_dir, source_root, item, err)); | |
| if (err->has_error()) | |
| return false; | |
| } | |
| return true; | |
| } | |
| void Visibility::SetPublic() { | |
| patterns_.clear(); | |
| patterns_.push_back(LabelPattern(LabelPattern::RECURSIVE_DIRECTORY, | |
| SourceDir(), std::string(), Label())); | |
| } | |
| void Visibility::SetPrivate(const SourceDir& current_dir) { | |
| patterns_.clear(); | |
| patterns_.push_back(LabelPattern(LabelPattern::DIRECTORY, current_dir, | |
| std::string(), Label())); | |
| } | |
| bool Visibility::CanSeeMe(const Label& label) const { | |
| return LabelPattern::VectorMatches(patterns_, label); | |
| } | |
| std::string Visibility::Describe(int indent, bool include_brackets) const { | |
| std::string outer_indent_string(indent, ' '); | |
| if (patterns_.empty()) | |
| return outer_indent_string + "[] (no visibility)\n"; | |
| std::string result; | |
| std::string inner_indent_string = outer_indent_string; | |
| if (include_brackets) { | |
| result += outer_indent_string + "[\n"; | |
| // Indent the insides more if brackets are requested. | |
| inner_indent_string += " "; | |
| } | |
| for (const auto& pattern : patterns_) | |
| result += inner_indent_string + pattern.Describe() + "\n"; | |
| if (include_brackets) | |
| result += outer_indent_string + "]\n"; | |
| return result; | |
| } | |
| std::unique_ptr<base::Value> Visibility::AsValue() const { | |
| auto res = std::make_unique<base::ListValue>(); | |
| for (const auto& pattern : patterns_) | |
| res->AppendString(pattern.Describe()); | |
| return std::move(res); | |
| } | |
| // static | |
| bool Visibility::CheckItemVisibility(const Item* from, | |
| const Item* to, | |
| Err* err) { | |
| if (!to->visibility().CanSeeMe(from->label())) { | |
| std::string to_label = to->label().GetUserVisibleName(false); | |
| *err = Err(from->defined_from(), "Dependency not allowed.", | |
| "The item " + from->label().GetUserVisibleName(false) + | |
| "\n" | |
| "can not depend on " + | |
| to_label + | |
| "\n" | |
| "because it is not in " + | |
| to_label + | |
| "'s visibility list: " + to->visibility().Describe(0, true)); | |
| return false; | |
| } | |
| return true; | |
| } | |
| // static | |
| bool Visibility::FillItemVisibility(Item* item, Scope* scope, Err* err) { | |
| const Value* vis_value = scope->GetValue(variables::kVisibility, true); | |
| if (vis_value) | |
| item->visibility().Set( | |
| scope->GetSourceDir(), | |
| scope->settings()->build_settings()->root_path_utf8(), *vis_value, err); | |
| else // Default to public. | |
| item->visibility().SetPublic(); | |
| return !err->has_error(); | |
| } |