Generate VS projects also for target dependencies.

This changes the way the --filters argument to
`gn gen --ide=vs --filters=X;Y;...` works so that
the information for all the dependents of X and Y will be generated
along with the information for X and Y.

This CL is based on tmoniuszko@opera.com's patch from
issue 2027733004 at patchset 1 (http://crrev.com/2027733004#ps1),
just updated w/ the review feedback, so we can land it.

R=brettw@chromium.org, pkasting@chromium.org, tmoniuszko@opera.com
BUG=589099

Review-Url: https://codereview.chromium.org/2060613002
Cr-Original-Commit-Position: refs/heads/master@{#399402}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: 4ed6b5594a150bd4de269ab71dfc36d812aa6161
diff --git a/tools/gn/command_gen.cc b/tools/gn/command_gen.cc
index 7bdb6d8..3d44274 100644
--- a/tools/gn/command_gen.cc
+++ b/tools/gn/command_gen.cc
@@ -263,8 +263,8 @@
     "  --filters=<path_prefixes>\n"
     "      Semicolon-separated list of label patterns used to limit the set\n"
     "      of generated projects (see \"gn help label_pattern\"). Only\n"
-    "      matching targets will be included to the solution. Only used for\n"
-    "      Visual Studio and Xcode.\n"
+    "      matching targets and their dependencies will be included in the\n"
+    "      solution. Only used for Visual Studio and Xcode.\n"
     "\n"
     "Visual Studio Flags\n"
     "\n"
diff --git a/tools/gn/docs/reference.md b/tools/gn/docs/reference.md
index c29b24f..4071fd9 100644
--- a/tools/gn/docs/reference.md
+++ b/tools/gn/docs/reference.md
@@ -697,8 +697,8 @@
   --filters=<path_prefixes>
       Semicolon-separated list of label patterns used to limit the set
       of generated projects (see "gn help label_pattern"). Only
-      matching targets will be included to the solution. Only used for
-      Visual Studio and Xcode.
+      matching targets and their dependencies will be included in the
+      solution. Only used for Visual Studio and Xcode.
 
 ```
 
@@ -864,8 +864,8 @@
 ```
   Finds paths of dependencies between two targets. Each unique path
   will be printed in one group, and groups will be separate by newlines.
-  The two targets can appear in either order: paths will be found going
-  in either direction.
+  The two targets can appear in either order (paths will be found going
+  in either direction).
 
   By default, a single path will be printed. If there is a path with
   only public dependencies, the shortest public path will be printed.
@@ -876,13 +876,23 @@
 
 ```
 
+### **Interesting paths**
+
+```
+  In a large project, there can be 100's of millions of unique paths
+  between a very high level and a common low-level target. To make the
+  output more useful (and terminate in a reasonable time), GN will not
+  revisit sub-paths previously known to lead to the target.
+
+```
+
 ### **Options**
 
 ```
   --all
-     Prints all paths found rather than just the first one. Public paths
-     will be printed first in order of increasing length, followed by
-     non-public paths in order of increasing length.
+     Prints all "interesting" paths found rather than just the first
+     one. Public paths will be printed first in order of increasing
+     length, followed by non-public paths in order of increasing length.
 
   --public
      Considers only public paths. Can't be used with --with-data.
@@ -3611,13 +3621,13 @@
 ```
   This value should be used to indicate the desired architecture for
   the primary objects of the build. It will match the cpu architecture
-  of the default toolchain.
+  of the default toolchain, but not necessarily the current toolchain.
 
   In many cases, this is the same as "host_cpu", but in the case
-  of cross-compiles, this can be set to something different. This 
-  value is different from "current_cpu" in that it can be referenced
-  from inside any toolchain. This value can also be ignored if it is
-  not needed or meaningful for a project.
+  of cross-compiles, this can be set to something different. This
+  value is different from "current_cpu" in that it does not change
+  based on the current toolchain. When writing rules, "current_cpu"
+  should be used rather than "target_cpu" most of the time.
 
   This value is not used internally by GN for any purpose, so it
   may be set to whatever value is needed for the build.
@@ -5949,8 +5959,8 @@
   When a tool produces more than one output, only the first output
   is considered. For example, a shared library target may produce a
   .dll and a .lib file on Windows. Only the .dll file will be considered
-  a runtime dependency. This applies only to linker tools, scripts and
-  copy steps with multiple outputs will also get all outputs listed.
+  a runtime dependency. This applies only to linker tools. Scripts and
+  copy steps with multiple outputs will get all outputs listed.
 
 
 ```
diff --git a/tools/gn/visual_studio_writer.cc b/tools/gn/visual_studio_writer.cc
index 7dedd4d..401782f 100644
--- a/tools/gn/visual_studio_writer.cc
+++ b/tools/gn/visual_studio_writer.cc
@@ -8,6 +8,7 @@
 #include <iterator>
 #include <map>
 #include <memory>
+#include <queue>
 #include <set>
 #include <string>
 
@@ -18,6 +19,7 @@
 #include "tools/gn/commands.h"
 #include "tools/gn/config.h"
 #include "tools/gn/config_values_extractors.h"
+#include "tools/gn/deps_iterator.h"
 #include "tools/gn/filesystem_utils.h"
 #include "tools/gn/label_pattern.h"
 #include "tools/gn/parse_tree.h"
@@ -163,6 +165,46 @@
   return base::StringPiece();
 }
 
+bool FilterTargets(const BuildSettings* build_settings,
+                   Builder* builder,
+                   const std::string& dir_filters,
+                   std::vector<const Target*>* targets,
+                   Err* err) {
+  if (dir_filters.empty()) {
+    *targets = builder->GetAllResolvedTargets();
+    return true;
+  }
+
+  std::vector<LabelPattern> filters;
+  if (!commands::FilterPatternsFromString(build_settings, dir_filters, &filters,
+                                          err))
+    return false;
+
+  commands::FilterTargetsByPatterns(builder->GetAllResolvedTargets(), filters,
+                                    targets);
+
+  std::set<Label> labels;
+  std::queue<const Target*> to_process;
+  for (const Target* target : *targets) {
+    labels.insert(target->label());
+    to_process.push(target);
+  }
+
+  while (!to_process.empty()) {
+    const Target* target = to_process.front();
+    to_process.pop();
+    for (const auto& pair : target->GetDeps(Target::DEPS_ALL)) {
+      if (labels.find(pair.label) == labels.end()) {
+        targets->push_back(pair.ptr);
+        to_process.push(pair.ptr);
+        labels.insert(pair.label);
+      }
+    }
+  }
+
+  return true;
+}
+
 }  // namespace
 
 VisualStudioWriter::SolutionEntry::SolutionEntry(const std::string& _name,
@@ -233,18 +275,8 @@
                                           const std::string& dir_filters,
                                           Err* err) {
   std::vector<const Target*> targets;
-  if (dir_filters.empty()) {
-    targets = builder->GetAllResolvedTargets();
-  } else {
-    std::vector<LabelPattern> filters;
-    if (!commands::FilterPatternsFromString(build_settings, dir_filters,
-                                            &filters, err)) {
-      return false;
-    }
-
-    commands::FilterTargetsByPatterns(builder->GetAllResolvedTargets(), filters,
-                                      &targets);
-  }
+  if (!FilterTargets(build_settings, builder, dir_filters, &targets, err))
+    return false;
 
   const char* config_platform = "Win32";