rust-project: Represent source roots properly

The current structure of a rust-project.json is documented here:
https://rust-analyzer.github.io/manual.html#non-cargo-based-projects

There are a couple of differences from what gn previously generated:
* There is no longer a 'roots' section
* Each crate has its own set of source includes and exclude directories.

This difference has prevented rust-analyzer from correctly spotting and
including Rust files pulled into a crate using the include! macro. With
the current change, 'gen' dirs are included such that such generated
files can be identified and correctly included by rust-analyzer.

Bug: chromium/1293933
Change-Id: I108dd20114274dc0b2112aefa5990af6381b5466
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/13420
Reviewed-by: Brett Wilson <brettw@chromium.org>
Commit-Queue: Tyler Mandry <tmandry@google.com>
diff --git a/src/gn/rust_project_writer.cc b/src/gn/rust_project_writer.cc
index eea527c..8c73d57 100644
--- a/src/gn/rust_project_writer.cc
+++ b/src/gn/rust_project_writer.cc
@@ -29,9 +29,6 @@
 // Current structure of rust-project.json output file
 //
 // {
-//    "roots": [
-//      "some/source/root"  // each crate's source root
-//    ],
 //    "crates": [
 //        {
 //            "deps": [
@@ -40,6 +37,13 @@
 //                    "name": "alloc" // extern name of dependency
 //                },
 //            ],
+//            "source": [
+//                "include_dirs": [
+//                     "some/source/root",
+//                     "some/gen/dir",
+//                ],
+//                "exclude_dirs": []
+//            },
 //            "edition": "2018", // edition of crate
 //            "cfg": [
 //              "unix", // "atomic" value config options
@@ -204,8 +208,8 @@
       FilePathToUTF8(rebased_out_dir) + std::string(current_sysroot) +
       "/lib/rustlib/src/rust/library/" + std::string(crate) + "/src/lib.rs";
 
-  Crate sysroot_crate =
-      Crate(SourceFile(crate_path), crate_index, std::string(crate), "2018");
+  Crate sysroot_crate = Crate(SourceFile(crate_path), std::nullopt, crate_index,
+                              std::string(crate), "2018");
 
   sysroot_crate.AddConfigItem("debug_assertions");
 
@@ -290,8 +294,10 @@
     edition = FindArgValue("--edition", compiler_args);
   }
 
-  Crate crate =
-      Crate(crate_root, crate_id, crate_label, edition.value_or("2015"));
+  auto gen_dir = GetBuildDirForTargetAsOutputFile(target, BuildDirType::GEN);
+
+  Crate crate = Crate(crate_root, gen_dir, crate_id, crate_label,
+                      edition.value_or("2015"));
 
   crate.SetCompilerArgs(compiler_args);
   if (compiler_target.has_value())
@@ -353,24 +359,7 @@
 void WriteCrates(const BuildSettings* build_settings,
                  CrateList& crate_list,
                  std::ostream& rust_project) {
-  // produce a de-duplicated set of source roots:
-  std::set<std::string> roots;
-  for (auto& crate : crate_list) {
-    roots.insert(
-        FilePathToUTF8(build_settings->GetFullPath(crate.root().GetDir())));
-  }
-
   rust_project << "{" NEWLINE;
-  rust_project << "  \"roots\": [";
-  bool first_root = true;
-  for (auto& root : roots) {
-    if (!first_root)
-      rust_project << ",";
-    first_root = false;
-
-    rust_project << NEWLINE "    \"" << root << "\"";
-  }
-  rust_project << NEWLINE "  ]," NEWLINE;
   rust_project << "  \"crates\": [";
   bool first_crate = true;
   for (auto& crate : crate_list) {
@@ -384,7 +373,25 @@
     rust_project << NEWLINE << "    {" NEWLINE
                  << "      \"crate_id\": " << crate.index() << "," NEWLINE
                  << "      \"root_module\": \"" << crate_module << "\"," NEWLINE
-                 << "      \"label\": \"" << crate.label() << "\"," NEWLINE;
+                 << "      \"label\": \"" << crate.label() << "\"," NEWLINE
+                 << "      \"source\": {" NEWLINE
+                 << "          \"include_dirs\": [" NEWLINE
+                 << "               \""
+                 << FilePathToUTF8(
+                        build_settings->GetFullPath(crate.root().GetDir()))
+                 << "\"";
+    auto gen_dir = crate.gen_dir();
+    if (gen_dir.has_value()) {
+      auto gen_dir_path = FilePathToUTF8(
+          build_settings->GetFullPath(gen_dir->AsSourceDir(build_settings)));
+      rust_project << "," NEWLINE << "               \"" << gen_dir_path
+                   << "\"" NEWLINE;
+    } else {
+      rust_project << NEWLINE;
+    }
+    rust_project << "          ]," NEWLINE
+                 << "          \"exclude_dirs\": []" NEWLINE
+                 << "      }," NEWLINE;
 
     auto compiler_target = crate.CompilerTarget();
     if (compiler_target.has_value()) {
diff --git a/src/gn/rust_project_writer_helpers.h b/src/gn/rust_project_writer_helpers.h
index 24b13d0..4ccf568 100644
--- a/src/gn/rust_project_writer_helpers.h
+++ b/src/gn/rust_project_writer_helpers.h
@@ -35,10 +35,15 @@
 class Crate {
  public:
   Crate(SourceFile root,
+        std::optional<OutputFile> gen_dir,
         CrateIndex index,
         std::string label,
         std::string edition)
-      : root_(root), index_(index), label_(label), edition_(edition) {}
+      : root_(root),
+        gen_dir_(gen_dir),
+        index_(index),
+        label_(label),
+        edition_(edition) {}
 
   ~Crate() = default;
 
@@ -69,6 +74,9 @@
   // Returns the root file for the crate.
   SourceFile& root() { return root_; }
 
+  // Returns the root file for the crate.
+  std::optional<OutputFile>& gen_dir() { return gen_dir_; }
+
   // Returns the crate index.
   CrateIndex index() { return index_; };
 
@@ -103,6 +111,7 @@
 
  private:
   SourceFile root_;
+  std::optional<OutputFile> gen_dir_;
   CrateIndex index_;
   std::string label_;
   std::string edition_;
diff --git a/src/gn/rust_project_writer_helpers_unittest.cc b/src/gn/rust_project_writer_helpers_unittest.cc
index 7ff3b48..ffdfcd8 100644
--- a/src/gn/rust_project_writer_helpers_unittest.cc
+++ b/src/gn/rust_project_writer_helpers_unittest.cc
@@ -27,10 +27,10 @@
   TestWithScope setup;
 
   CrateList crates;
-  Crate dep =
-      Crate(SourceFile("/root/tortoise/lib.rs"), 0, "//tortoise:bar", "2015");
-  Crate target =
-      Crate(SourceFile("/root/hare/lib.rs"), 1, "//hare:bar", "2015");
+  Crate dep = Crate(SourceFile("/root/tortoise/lib.rs"), std::nullopt, 0,
+                    "//tortoise:bar", "2015");
+  Crate target = Crate(SourceFile("/root/hare/lib.rs"),
+                       OutputFile("gendir/hare/"), 1, "//hare:bar", "2015");
   target.AddDependency(0, "tortoise");
   target.AddConfigItem("unix");
   target.AddConfigItem("feature=\"test\"");
@@ -46,15 +46,17 @@
 #endif
   const char expected_json[] =
       "{\n"
-      "  \"roots\": [\n"
-      "    \"/root/hare/\",\n"
-      "    \"/root/tortoise/\"\n"
-      "  ],\n"
       "  \"crates\": [\n"
       "    {\n"
       "      \"crate_id\": 0,\n"
       "      \"root_module\": \"/root/tortoise/lib.rs\",\n"
       "      \"label\": \"//tortoise:bar\",\n"
+      "      \"source\": {\n"
+      "          \"include_dirs\": [\n"
+      "               \"/root/tortoise/\"\n"
+      "          ],\n"
+      "          \"exclude_dirs\": []\n"
+      "      },\n"
       "      \"deps\": [\n"
       "      ],\n"
       "      \"edition\": \"2015\",\n"
@@ -65,6 +67,13 @@
       "      \"crate_id\": 1,\n"
       "      \"root_module\": \"/root/hare/lib.rs\",\n"
       "      \"label\": \"//hare:bar\",\n"
+      "      \"source\": {\n"
+      "          \"include_dirs\": [\n"
+      "               \"/root/hare/\",\n"
+      "               \"out/Debug/gendir/hare/\"\n"
+      "          ],\n"
+      "          \"exclude_dirs\": []\n"
+      "      },\n"
       "      \"deps\": [\n"
       "        {\n"
       "          \"crate\": 0,\n"
@@ -101,21 +110,20 @@
 
   const char expected_json[] =
       "{\n"
-      "  \"roots\": [\n"
-      "    \"/root/out/Debug/sysroot/lib/rustlib/src/rust/library/alloc/src/\",\n"
-      "    \"/root/out/Debug/sysroot/lib/rustlib/src/rust/library/core/src/\",\n"
-      "    \"/root/out/Debug/sysroot/lib/rustlib/src/rust/library/panic_abort/src/\",\n"
-      "    \"/root/out/Debug/sysroot/lib/rustlib/src/rust/library/panic_unwind/src/\",\n"
-      "    \"/root/out/Debug/sysroot/lib/rustlib/src/rust/library/proc_macro/src/\",\n"
-      "    \"/root/out/Debug/sysroot/lib/rustlib/src/rust/library/std/src/\",\n"
-      "    \"/root/out/Debug/sysroot/lib/rustlib/src/rust/library/test/src/\",\n"
-      "    \"/root/out/Debug/sysroot/lib/rustlib/src/rust/library/unwind/src/\"\n"
-      "  ],\n"
       "  \"crates\": [\n"
       "    {\n"
       "      \"crate_id\": 0,\n"
-      "      \"root_module\": \"/root/out/Debug/sysroot/lib/rustlib/src/rust/library/core/src/lib.rs\",\n"
+      "      \"root_module\": "
+      "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/library/core/src/"
+      "lib.rs\",\n"
       "      \"label\": \"core\",\n"
+      "      \"source\": {\n"
+      "          \"include_dirs\": [\n"
+      "               "
+      "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/library/core/src/\"\n"
+      "          ],\n"
+      "          \"exclude_dirs\": []\n"
+      "      },\n"
       "      \"deps\": [\n"
       "      ],\n"
       "      \"edition\": \"2018\",\n"
@@ -125,8 +133,17 @@
       "    },\n"
       "    {\n"
       "      \"crate_id\": 1,\n"
-      "      \"root_module\": \"/root/out/Debug/sysroot/lib/rustlib/src/rust/library/alloc/src/lib.rs\",\n"
+      "      \"root_module\": "
+      "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/library/alloc/src/"
+      "lib.rs\",\n"
       "      \"label\": \"alloc\",\n"
+      "      \"source\": {\n"
+      "          \"include_dirs\": [\n"
+      "               "
+      "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/library/alloc/src/\"\n"
+      "          ],\n"
+      "          \"exclude_dirs\": []\n"
+      "      },\n"
       "      \"deps\": [\n"
       "        {\n"
       "          \"crate\": 0,\n"
@@ -140,8 +157,18 @@
       "    },\n"
       "    {\n"
       "      \"crate_id\": 2,\n"
-      "      \"root_module\": \"/root/out/Debug/sysroot/lib/rustlib/src/rust/library/panic_abort/src/lib.rs\",\n"
+      "      \"root_module\": "
+      "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/library/panic_abort/src/"
+      "lib.rs\",\n"
       "      \"label\": \"panic_abort\",\n"
+      "      \"source\": {\n"
+      "          \"include_dirs\": [\n"
+      "               "
+      "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/library/panic_abort/src/"
+      "\"\n"
+      "          ],\n"
+      "          \"exclude_dirs\": []\n"
+      "      },\n"
       "      \"deps\": [\n"
       "      ],\n"
       "      \"edition\": \"2018\",\n"
@@ -151,8 +178,17 @@
       "    },\n"
       "    {\n"
       "      \"crate_id\": 3,\n"
-      "      \"root_module\": \"/root/out/Debug/sysroot/lib/rustlib/src/rust/library/unwind/src/lib.rs\",\n"
+      "      \"root_module\": "
+      "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/library/unwind/src/"
+      "lib.rs\",\n"
       "      \"label\": \"unwind\",\n"
+      "      \"source\": {\n"
+      "          \"include_dirs\": [\n"
+      "               "
+      "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/library/unwind/src/\"\n"
+      "          ],\n"
+      "          \"exclude_dirs\": []\n"
+      "      },\n"
       "      \"deps\": [\n"
       "      ],\n"
       "      \"edition\": \"2018\",\n"
@@ -162,8 +198,17 @@
       "    },\n"
       "    {\n"
       "      \"crate_id\": 4,\n"
-      "      \"root_module\": \"/root/out/Debug/sysroot/lib/rustlib/src/rust/library/std/src/lib.rs\",\n"
+      "      \"root_module\": "
+      "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/library/std/src/"
+      "lib.rs\",\n"
       "      \"label\": \"std\",\n"
+      "      \"source\": {\n"
+      "          \"include_dirs\": [\n"
+      "               "
+      "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/library/std/src/\"\n"
+      "          ],\n"
+      "          \"exclude_dirs\": []\n"
+      "      },\n"
       "      \"deps\": [\n"
       "        {\n"
       "          \"crate\": 1,\n"
@@ -189,8 +234,18 @@
       "    },\n"
       "    {\n"
       "      \"crate_id\": 5,\n"
-      "      \"root_module\": \"/root/out/Debug/sysroot/lib/rustlib/src/rust/library/panic_unwind/src/lib.rs\",\n"
+      "      \"root_module\": "
+      "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/library/panic_unwind/src/"
+      "lib.rs\",\n"
       "      \"label\": \"panic_unwind\",\n"
+      "      \"source\": {\n"
+      "          \"include_dirs\": [\n"
+      "               "
+      "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/library/panic_unwind/src/"
+      "\"\n"
+      "          ],\n"
+      "          \"exclude_dirs\": []\n"
+      "      },\n"
       "      \"deps\": [\n"
       "      ],\n"
       "      \"edition\": \"2018\",\n"
@@ -200,8 +255,18 @@
       "    },\n"
       "    {\n"
       "      \"crate_id\": 6,\n"
-      "      \"root_module\": \"/root/out/Debug/sysroot/lib/rustlib/src/rust/library/proc_macro/src/lib.rs\",\n"
+      "      \"root_module\": "
+      "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/library/proc_macro/src/"
+      "lib.rs\",\n"
       "      \"label\": \"proc_macro\",\n"
+      "      \"source\": {\n"
+      "          \"include_dirs\": [\n"
+      "               "
+      "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/library/proc_macro/src/"
+      "\"\n"
+      "          ],\n"
+      "          \"exclude_dirs\": []\n"
+      "      },\n"
       "      \"deps\": [\n"
       "      ],\n"
       "      \"edition\": \"2018\",\n"
@@ -211,8 +276,17 @@
       "    },\n"
       "    {\n"
       "      \"crate_id\": 7,\n"
-      "      \"root_module\": \"/root/out/Debug/sysroot/lib/rustlib/src/rust/library/test/src/lib.rs\",\n"
+      "      \"root_module\": "
+      "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/library/test/src/"
+      "lib.rs\",\n"
       "      \"label\": \"test\",\n"
+      "      \"source\": {\n"
+      "          \"include_dirs\": [\n"
+      "               "
+      "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/library/test/src/\"\n"
+      "          ],\n"
+      "          \"exclude_dirs\": []\n"
+      "      },\n"
       "      \"deps\": [\n"
       "      ],\n"
       "      \"edition\": \"2018\",\n"
diff --git a/src/gn/rust_project_writer_unittest.cc b/src/gn/rust_project_writer_unittest.cc
index 2d4f0dc..e57baf9 100644
--- a/src/gn/rust_project_writer_unittest.cc
+++ b/src/gn/rust_project_writer_unittest.cc
@@ -51,14 +51,18 @@
 #endif
   const char expected_json[] =
       "{\n"
-      "  \"roots\": [\n"
-      "    \"path/foo/\"\n"
-      "  ],\n"
       "  \"crates\": [\n"
       "    {\n"
       "      \"crate_id\": 0,\n"
       "      \"root_module\": \"path/foo/lib.rs\",\n"
       "      \"label\": \"//foo:bar\",\n"
+      "      \"source\": {\n"
+      "          \"include_dirs\": [\n"
+      "               \"path/foo/\",\n"
+      "               \"path/out/Debug/gen/foo/\"\n"
+      "          ],\n"
+      "          \"exclude_dirs\": []\n"
+      "      },\n"
       "      \"compiler_args\": [\"--cfg=feature=\\\"foo_enabled\\\"\"],\n"
       "      \"deps\": [\n"
       "      ],\n"
@@ -111,15 +115,18 @@
 #endif
   const char expected_json[] =
       "{\n"
-      "  \"roots\": [\n"
-      "    \"hare/\",\n"
-      "    \"tortoise/\"\n"
-      "  ],\n"
       "  \"crates\": [\n"
       "    {\n"
       "      \"crate_id\": 0,\n"
       "      \"root_module\": \"tortoise/lib.rs\",\n"
       "      \"label\": \"//tortoise:bar\",\n"
+      "      \"source\": {\n"
+      "          \"include_dirs\": [\n"
+      "               \"tortoise/\",\n"
+      "               \"out/Debug/gen/tortoise/\"\n"
+      "          ],\n"
+      "          \"exclude_dirs\": []\n"
+      "      },\n"
       "      \"deps\": [\n"
       "      ],\n"
       "      \"edition\": \"2015\",\n"
@@ -132,6 +139,13 @@
       "      \"crate_id\": 1,\n"
       "      \"root_module\": \"hare/lib.rs\",\n"
       "      \"label\": \"//hare:bar\",\n"
+      "      \"source\": {\n"
+      "          \"include_dirs\": [\n"
+      "               \"hare/\",\n"
+      "               \"out/Debug/gen/hare/\"\n"
+      "          ],\n"
+      "          \"exclude_dirs\": []\n"
+      "      },\n"
       "      \"deps\": [\n"
       "        {\n"
       "          \"crate\": 0,\n"
@@ -197,16 +211,18 @@
 #endif
   const char expected_json[] =
       "{\n"
-      "  \"roots\": [\n"
-      "    \"achilles/\",\n"
-      "    \"hare/\",\n"
-      "    \"tortoise/\"\n"
-      "  ],\n"
       "  \"crates\": [\n"
       "    {\n"
       "      \"crate_id\": 0,\n"
       "      \"root_module\": \"tortoise/lib.rs\",\n"
       "      \"label\": \"//tortoise:bar\",\n"
+      "      \"source\": {\n"
+      "          \"include_dirs\": [\n"
+      "               \"tortoise/\",\n"
+      "               \"out/Debug/gen/tortoise/\"\n"
+      "          ],\n"
+      "          \"exclude_dirs\": []\n"
+      "      },\n"
       "      \"deps\": [\n"
       "      ],\n"
       "      \"edition\": \"2015\",\n"
@@ -219,6 +235,13 @@
       "      \"crate_id\": 1,\n"
       "      \"root_module\": \"achilles/lib.rs\",\n"
       "      \"label\": \"//achilles:bar\",\n"
+      "      \"source\": {\n"
+      "          \"include_dirs\": [\n"
+      "               \"achilles/\",\n"
+      "               \"out/Debug/gen/achilles/\"\n"
+      "          ],\n"
+      "          \"exclude_dirs\": []\n"
+      "      },\n"
       "      \"deps\": [\n"
       "      ],\n"
       "      \"edition\": \"2015\",\n"
@@ -231,6 +254,13 @@
       "      \"crate_id\": 2,\n"
       "      \"root_module\": \"hare/lib.rs\",\n"
       "      \"label\": \"//hare:bar\",\n"
+      "      \"source\": {\n"
+      "          \"include_dirs\": [\n"
+      "               \"hare/\",\n"
+      "               \"out/Debug/gen/hare/\"\n"
+      "          ],\n"
+      "          \"exclude_dirs\": []\n"
+      "      },\n"
       "      \"deps\": [\n"
       "        {\n"
       "          \"crate\": 0,\n"
@@ -314,16 +344,18 @@
 #endif
   const char expected_json[] =
       "{\n"
-      "  \"roots\": [\n"
-      "    \"hare/\",\n"
-      "    \"tortoise/\",\n"
-      "    \"tortoise/macro/\"\n"
-      "  ],\n"
       "  \"crates\": [\n"
       "    {\n"
       "      \"crate_id\": 0,\n"
       "      \"root_module\": \"tortoise/lib.rs\",\n"
       "      \"label\": \"//tortoise:bar\",\n"
+      "      \"source\": {\n"
+      "          \"include_dirs\": [\n"
+      "               \"tortoise/\",\n"
+      "               \"out/Debug/gen/tortoise/\"\n"
+      "          ],\n"
+      "          \"exclude_dirs\": []\n"
+      "      },\n"
       "      \"deps\": [\n"
       "      ],\n"
       "      \"edition\": \"2015\",\n"
@@ -336,6 +368,13 @@
       "      \"crate_id\": 1,\n"
       "      \"root_module\": \"tortoise/macro/lib.rs\",\n"
       "      \"label\": \"//tortoise:macro\",\n"
+      "      \"source\": {\n"
+      "          \"include_dirs\": [\n"
+      "               \"tortoise/macro/\",\n"
+      "               \"out/Debug/gen/tortoise/\"\n"
+      "          ],\n"
+      "          \"exclude_dirs\": []\n"
+      "      },\n"
       "      \"deps\": [\n"
       "      ],\n"
       "      \"edition\": \"2015\",\n"
@@ -348,6 +387,13 @@
       "      \"crate_id\": 2,\n"
       "      \"root_module\": \"hare/lib.rs\",\n"
       "      \"label\": \"//hare:bar\",\n"
+      "      \"source\": {\n"
+      "          \"include_dirs\": [\n"
+      "               \"hare/\",\n"
+      "               \"out/Debug/gen/hare/\"\n"
+      "          ],\n"
+      "          \"exclude_dirs\": []\n"
+      "      },\n"
       "      \"deps\": [\n"
       "        {\n"
       "          \"crate\": 0,\n"
@@ -398,14 +444,18 @@
 #endif
   const char expected_json[] =
       "{\n"
-      "  \"roots\": [\n"
-      "    \"path/foo/\"\n"
-      "  ],\n"
       "  \"crates\": [\n"
       "    {\n"
       "      \"crate_id\": 0,\n"
       "      \"root_module\": \"path/foo/lib.rs\",\n"
       "      \"label\": \"//foo:bar\",\n"
+      "      \"source\": {\n"
+      "          \"include_dirs\": [\n"
+      "               \"path/foo/\",\n"
+      "               \"path/out/Debug/gen/foo/\"\n"
+      "          ],\n"
+      "          \"exclude_dirs\": []\n"
+      "      },\n"
       "      \"target\": \"x86-64_unknown\",\n"
       "      \"compiler_args\": [\"--target\", \"x86-64_unknown\"],\n"
       "      \"deps\": [\n"
@@ -449,14 +499,18 @@
 #endif
   const char expected_json[] =
       "{\n"
-      "  \"roots\": [\n"
-      "    \"path/foo/\"\n"
-      "  ],\n"
       "  \"crates\": [\n"
       "    {\n"
       "      \"crate_id\": 0,\n"
       "      \"root_module\": \"path/foo/lib.rs\",\n"
       "      \"label\": \"//foo:bar\",\n"
+      "      \"source\": {\n"
+      "          \"include_dirs\": [\n"
+      "               \"path/foo/\",\n"
+      "               \"path/out/Debug/gen/foo/\"\n"
+      "          ],\n"
+      "          \"exclude_dirs\": []\n"
+      "      },\n"
       "      \"compiler_args\": [\"--edition=2018\"],\n"
       "      \"deps\": [\n"
       "      ],\n"
@@ -500,14 +554,18 @@
 #endif
   const char expected_json[] =
       "{\n"
-      "  \"roots\": [\n"
-      "    \"path/foo/\"\n"
-      "  ],\n"
       "  \"crates\": [\n"
       "    {\n"
       "      \"crate_id\": 0,\n"
       "      \"root_module\": \"path/foo/lib.rs\",\n"
       "      \"label\": \"//foo:bar\",\n"
+      "      \"source\": {\n"
+      "          \"include_dirs\": [\n"
+      "               \"path/foo/\",\n"
+      "               \"path/out/Debug/gen/foo/\"\n"
+      "          ],\n"
+      "          \"exclude_dirs\": []\n"
+      "      },\n"
       "      \"compiler_args\": [\"--edition\", \"2018\"],\n"
       "      \"deps\": [\n"
       "      ],\n"
@@ -552,14 +610,18 @@
 #endif
   const char expected_json[] =
       "{\n"
-      "  \"roots\": [\n"
-      "    \"path/foo/\"\n"
-      "  ],\n"
       "  \"crates\": [\n"
       "    {\n"
       "      \"crate_id\": 0,\n"
       "      \"root_module\": \"path/foo/lib.rs\",\n"
       "      \"label\": \"//foo:bar\",\n"
+      "      \"source\": {\n"
+      "          \"include_dirs\": [\n"
+      "               \"path/foo/\",\n"
+      "               \"path/out/Debug/gen/foo/\"\n"
+      "          ],\n"
+      "          \"exclude_dirs\": []\n"
+      "      },\n"
       "      \"compiler_args\": [\"--cfg=feature=\\\"foo_enabled\\\"\"],\n"
       "      \"deps\": [\n"
       "      ],\n"