Home | History | Annotate | Download | only in gn
      1 // Copyright 2014 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/visibility.h"
      6 
      7 #include "base/strings/string_piece.h"
      8 #include "base/strings/string_util.h"
      9 #include "tools/gn/err.h"
     10 #include "tools/gn/filesystem_utils.h"
     11 #include "tools/gn/item.h"
     12 #include "tools/gn/label.h"
     13 #include "tools/gn/scope.h"
     14 #include "tools/gn/value.h"
     15 #include "tools/gn/variables.h"
     16 
     17 Visibility::Visibility() {
     18 }
     19 
     20 Visibility::~Visibility() {
     21 }
     22 
     23 bool Visibility::Set(const SourceDir& current_dir,
     24                      const Value& value,
     25                      Err* err) {
     26   patterns_.clear();
     27 
     28   if (!value.VerifyTypeIs(Value::LIST, err)) {
     29     CHECK(err->has_error());
     30     return false;
     31   }
     32 
     33   const std::vector<Value>& list = value.list_value();
     34   for (size_t i = 0; i < list.size(); i++) {
     35     patterns_.push_back(LabelPattern::GetPattern(current_dir, list[i], err));
     36     if (err->has_error())
     37       return false;
     38   }
     39   return true;
     40 }
     41 
     42 void Visibility::SetPublic() {
     43   patterns_.clear();
     44   patterns_.push_back(
     45       LabelPattern(LabelPattern::RECURSIVE_DIRECTORY, SourceDir(),
     46       std::string(), Label()));
     47 }
     48 
     49 void Visibility::SetPrivate(const SourceDir& current_dir) {
     50   patterns_.clear();
     51   patterns_.push_back(
     52       LabelPattern(LabelPattern::DIRECTORY, current_dir, std::string(),
     53       Label()));
     54 }
     55 
     56 bool Visibility::CanSeeMe(const Label& label) const {
     57   for (size_t i = 0; i < patterns_.size(); i++) {
     58     if (patterns_[i].Matches(label))
     59       return true;
     60   }
     61   return false;
     62 }
     63 
     64 std::string Visibility::Describe(int indent, bool include_brackets) const {
     65   std::string outer_indent_string(indent, ' ');
     66 
     67   if (patterns_.empty())
     68     return outer_indent_string + "[] (no visibility)\n";
     69 
     70   std::string result;
     71 
     72   std::string inner_indent_string = outer_indent_string;
     73   if (include_brackets) {
     74     result += outer_indent_string + "[\n";
     75     // Indent the insides more if brackets are requested.
     76     inner_indent_string += "  ";
     77   }
     78 
     79   for (size_t i = 0; i < patterns_.size(); i++)
     80     result += inner_indent_string + patterns_[i].Describe() + "\n";
     81 
     82   if (include_brackets)
     83     result += outer_indent_string + "]\n";
     84   return result;
     85 }
     86 
     87 // static
     88 bool Visibility::CheckItemVisibility(const Item* from,
     89                                      const Item* to,
     90                                      Err* err) {
     91   if (!to->visibility().CanSeeMe(from->label())) {
     92     std::string to_label = to->label().GetUserVisibleName(false);
     93     *err = Err(from->defined_from(), "Dependency not allowed.",
     94         "The item " + from->label().GetUserVisibleName(false) + "\n"
     95         "can not depend on " + to_label + "\n"
     96         "because it is not in " + to_label + "'s visibility list: " +
     97         to->visibility().Describe(0, true));
     98     return false;
     99   }
    100   return true;
    101 }
    102 
    103 // static
    104 bool Visibility::FillItemVisibility(Item* item, Scope* scope, Err* err) {
    105   const Value* vis_value = scope->GetValue(variables::kVisibility, true);
    106   if (vis_value)
    107     item->visibility().Set(scope->GetSourceDir(), *vis_value, err);
    108   else  // Default to public.
    109     item->visibility().SetPublic();
    110   return !err->has_error();
    111 }
    112