Fix bug in analyze related to sub-configs.

Analyze had a bug where if you modified a build file containing
a config that was only used as a sub-config, analyze wouldn't
thing changes to the file would matter.

This apparently is due to sub-configs not being treated as fully
defined items in the builder (which is sensible), which led to
the analyze code not seeing them directly.

A fix for this is to walk any configs that *are* defined as part
of analyze and explicitly check them for subconfigs that might
be relevant.

Bug: 131
Change-Id: I0323c2340ccda58b341699ed221d2fd54d9d261c
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/11000
Commit-Queue: Dirk Pranke <dpranke@google.com>
Reviewed-by: Brett Wilson <brettw@chromium.org>
diff --git a/src/gn/analyzer.cc b/src/gn/analyzer.cc
index 47b0a6d..a42779a 100644
--- a/src/gn/analyzer.cc
+++ b/src/gn/analyzer.cc
@@ -404,6 +404,13 @@
       return true;
   }
 
+  if (const Config* config = item->AsConfig()) {
+    for (const auto& config_pair: config->configs()) {
+      if (ItemRefersToFile(config_pair.ptr, file))
+        return true;
+    }
+  }
+
   if (!item->AsTarget())
     return false;
 
diff --git a/src/gn/analyzer_unittest.cc b/src/gn/analyzer_unittest.cc
index 9f7d897..558700e 100644
--- a/src/gn/analyzer_unittest.cc
+++ b/src/gn/analyzer_unittest.cc
@@ -226,6 +226,40 @@
       "}");
 }
 
+// Tests that a target is marked as affected if a sub-config is modified.
+//
+// This test uses two levels of sub-configs to ensure the config hierarchy
+// is completely traversed.
+TEST_F(AnalyzerTest, SubConfigIsModified) {
+  std::unique_ptr<Config> ssc = MakeConfig("//dir3", "subsubconfig_name");
+  ssc->build_dependency_files().insert(SourceFile("//dir3/BUILD.gn"));
+
+  std::unique_ptr<Config> sc = MakeConfig("//dir2", "subconfig_name");
+  sc->configs().push_back(LabelConfigPair(ssc->label()));
+
+  std::unique_ptr<Config> c = MakeConfig("//dir", "config_name");
+  c->configs().push_back(LabelConfigPair(sc->label()));
+
+  std::unique_ptr<Target> t = MakeTarget("//dir", "target_name");
+  t->configs().push_back(LabelConfigPair(c.get()));
+
+  builder_.ItemDefined(std::move(ssc));
+  builder_.ItemDefined(std::move(sc));
+  builder_.ItemDefined(std::move(c));
+  builder_.ItemDefined(std::move(t));
+  RunAnalyzerTest(
+      R"({
+       "files": [ "//dir3/BUILD.gn" ],
+       "additional_compile_targets": [],
+       "test_targets": [ "//dir:target_name" ]
+       })",
+      "{"
+      R"("compile_targets":[],)"
+      R"/("status":"Found dependency",)/"
+      R"("test_targets":["//dir:target_name"])"
+      "}");
+}
+
 // Tests that a target is marked as affected if its data are modified.
 TEST_F(AnalyzerTest, TargetRefersToData) {
   std::unique_ptr<Target> t = MakeTarget("//dir", "target_name");