[format] Sort visibility like deps

Bug: 189
Change-Id: I7e35b6811444c0656de8dc452d105cc92afa2c0d
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/9780
Commit-Queue: Petr Hosek <phosek@google.com>
Reviewed-by: Scott Graham <scottmg@chromium.org>
Reviewed-by: Petr Hosek <phosek@google.com>
Reviewed-by: Brett Wilson <brettw@chromium.org>
diff --git a/src/gn/command_format.cc b/src/gn/command_format.cc
index 67cd78b..7219131 100644
--- a/src/gn/command_format.cc
+++ b/src/gn/command_format.cc
@@ -156,11 +156,12 @@
   // Whether there's a blank separator line at the current position.
   bool HaveBlankLine();
 
-  // Sort a list on the RHS if the LHS is 'sources', 'deps' or 'public_deps'.
-  // The 'sources' are sorted alphabetically while the 'deps' and 'public_deps'
-  // are sorted putting first the relative targets and then the global ones
-  // (both sorted alphabetically).
-  void SortIfSourcesOrDeps(const BinaryOpNode* binop);
+  // Sort a list on the RHS if the LHS is one of the following:
+  // 'sources': sorted alphabetically.
+  // 'deps' or ends in 'deps': sorted such that relative targets are first,
+  //   followed by global targets, each internally sorted alphabetically.
+  // 'visibility': same as 'deps'.
+  void SortIfApplicable(const BinaryOpNode* binop);
 
   // Sort contiguous import() function calls in the given ordered list of
   // statements (the body of a block or scope).
@@ -383,7 +384,7 @@
   return n > 2 && output_[n - 1] == '\n' && output_[n - 2] == '\n';
 }
 
-void Printer::SortIfSourcesOrDeps(const BinaryOpNode* binop) {
+void Printer::SortIfApplicable(const BinaryOpNode* binop) {
   if (const Comments* comments = binop->comments()) {
     const std::vector<Token>& before = comments->before();
     if (!before.empty() && (before.front().value() == "# NOSORT" ||
@@ -402,8 +403,9 @@
     if (base::EndsWith(lhs, "sources", base::CompareCase::SENSITIVE) ||
         lhs == "public")
       const_cast<ListNode*>(list)->SortAsStringsList();
-    else if (base::EndsWith(lhs, "deps", base::CompareCase::SENSITIVE))
-      const_cast<ListNode*>(list)->SortAsDepsList();
+    else if (base::EndsWith(lhs, "deps", base::CompareCase::SENSITIVE) ||
+        lhs == "visibility")
+      const_cast<ListNode*>(list)->SortAsTargetsList();
   }
 }
 
@@ -725,7 +727,7 @@
   } else if (const BinaryOpNode* binop = root->AsBinaryOp()) {
     CHECK(precedence_.find(binop->op().value()) != precedence_.end());
 
-    SortIfSourcesOrDeps(binop);
+    SortIfApplicable(binop);
 
     Precedence prec = precedence_[binop->op().value()];
 
diff --git a/src/gn/format_test_data/063.gn b/src/gn/format_test_data/063.gn
index 418d90f..de5002e 100644
--- a/src/gn/format_test_data/063.gn
+++ b/src/gn/format_test_data/063.gn
@@ -39,4 +39,12 @@
     "//a",
     ":z",
   ]
+
+  # Likewise for visibility
+  visibility = [
+    "//b:*",
+    "//a",
+    "//b/*",
+    ":z",
+  ]
 }
diff --git a/src/gn/format_test_data/063.golden b/src/gn/format_test_data/063.golden
index 3ae77b2..8972886 100644
--- a/src/gn/format_test_data/063.golden
+++ b/src/gn/format_test_data/063.golden
@@ -39,4 +39,12 @@
     ":z",
     "//a",
   ]
+
+  # Likewise for visibility
+  visibility = [
+    ":z",
+    "//a",
+    "//b:*",
+    "//b/*",
+  ]
 }
diff --git a/src/gn/parse_tree.cc b/src/gn/parse_tree.cc
index d4c6290..e62b87e 100644
--- a/src/gn/parse_tree.cc
+++ b/src/gn/parse_tree.cc
@@ -748,7 +748,7 @@
   });
 }
 
-void ListNode::SortAsDepsList() {
+void ListNode::SortAsTargetsList() {
   // Sorts first relative targets, then absolute, each group is sorted
   // alphabetically.
   SortList([](const ParseNode* a, const ParseNode* b) {
diff --git a/src/gn/parse_tree.h b/src/gn/parse_tree.h
index 13fa7d1..cb64661 100644
--- a/src/gn/parse_tree.h
+++ b/src/gn/parse_tree.h
@@ -425,7 +425,7 @@
   }
 
   void SortAsStringsList();
-  void SortAsDepsList();
+  void SortAsTargetsList();
 
   struct SortRange {
     size_t begin;