[rust-project] switch cfgs to new list schema

The `key_vlaue_cfgs: {}` schema used before didn't allow for a key
being present multiple times.  This aligns with new support in
rust-analyzer to take in the set of cfgs in the same format as
rustc produces them, as a series of key="value" pairs.

Change-Id: I1d486a670f1e2669805a55084b725798414fe5ed
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/8441
Commit-Queue: Petr Hosek <phosek@google.com>
Reviewed-by: Petr Hosek <phosek@google.com>
Reviewed-by: Benjamin Brittain <bwb@google.com>
diff --git a/src/gn/rust_project_writer.cc b/src/gn/rust_project_writer.cc
index 0c238ce..8452dae 100644
--- a/src/gn/rust_project_writer.cc
+++ b/src/gn/rust_project_writer.cc
@@ -30,7 +30,6 @@
 //    "roots": [] // always empty for GN. To be deprecated.
 //    "crates": [
 //        {
-//            "atom_cfgs": [], // atom config options
 //            "deps": [
 //                {
 //                    "crate": 1, // index into crate array
@@ -38,9 +37,10 @@
 //                },
 //            ],
 //            "edition": "2018", // edition of crate
-//            "key_value_cfgs": {
-//              "rust_panic": "abort" // key value config options
-//            },
+//            "cfg": [
+//              "unix", // "atomic" value config options
+//              "rust_panic=\"abort\""", // key="value" config options
+//            ]
 //            "root_module": "absolute path to crate"
 //        },
 // }
@@ -224,8 +224,8 @@
   }
   rust_project << NEWLINE "      ]," NEWLINE;
 
-  rust_project << "      \"atom_cfgs\": []," NEWLINE
-                  "      \"key_value_cfgs\": {}" NEWLINE;
+  rust_project << "      \"cfg\": []" NEWLINE;
+
   rust_project << "    }";
 }
 
@@ -286,8 +286,7 @@
 
   std::string cfg_prefix("--cfg=");
   std::string edition_prefix("--edition=");
-  std::vector<std::string> atoms;
-  std::vector<std::tuple<std::string, std::string>> kvs;
+  std::vector<std::string> cfgs;
 
   bool edition_set = false;
   for (ConfigValuesIterator iter(target); !iter.done(); iter.Next()) {
@@ -298,50 +297,31 @@
         rust_project << "      \"edition\": \"" << edition << "\"," NEWLINE;
         edition_set = true;
       }
-      // Can't directly print cfgs since they come in any order.
-      // If they have an = they are a k/v cfg, otherwise an atom cfg.
       if (!flag.compare(0, cfg_prefix.size(), cfg_prefix)) {
         auto cfg = flag.substr(cfg_prefix.size());
-        auto idx = cfg.rfind("=");
-        if (idx == std::string::npos) {
-          atoms.push_back(cfg);
-        } else {
-          std::string key = cfg.substr(0, idx);
-          std::string value = cfg.substr(idx + 1);
-          kvs.push_back(std::make_pair(key, value));
-        }
+        std::string escaped_config;
+        base::EscapeJSONString(cfg, false, &escaped_config);
+        cfgs.push_back(escaped_config);
       }
     }
   }
 
-  if (!edition_set)
+if (!edition_set)
     rust_project << "      \"edition\": \"2015\"," NEWLINE;
 
-  rust_project << "      \"atom_cfgs\": [";
-  bool first_atom = true;
-  for (const auto& cfg : atoms) {
-    if (!first_atom) {
+  rust_project << "      \"cfg\": [";
+  bool first_cfg = true;
+  for (const auto& cfg : cfgs) {
+    if (!first_cfg) {
       rust_project << ",";
     }
-    first_atom = false;
+    first_cfg = false;
     rust_project << NEWLINE;
     rust_project << "        \"" << cfg << "\"";
   }
   rust_project << NEWLINE;
-  rust_project << "      ]," NEWLINE;
+  rust_project << "      ]" NEWLINE;
 
-  rust_project << "      \"key_value_cfgs\": {";
-  bool first_kv = true;
-  for (const auto& cfg : kvs) {
-    if (!first_kv) {
-      rust_project << ",";
-    }
-    first_kv = false;
-    rust_project << NEWLINE << "        \"" << std::get<0>(cfg)
-                 << "\" : " << std::get<1>(cfg);
-  }
-  rust_project << NEWLINE;
-  rust_project << "      }" NEWLINE;
   rust_project << "    }";
 }
 
diff --git a/src/gn/rust_project_writer_unittest.cc b/src/gn/rust_project_writer_unittest.cc
index e43641d..fb7200e 100644
--- a/src/gn/rust_project_writer_unittest.cc
+++ b/src/gn/rust_project_writer_unittest.cc
@@ -25,6 +25,7 @@
   target.source_types_used().Set(SourceFile::SOURCE_RS);
   target.rust_values().set_crate_root(lib);
   target.rust_values().crate_name() = "foo";
+  target.config_values().rustflags().push_back("--cfg=feature=\"foo_enabled\"");
   target.SetToolchain(setup.toolchain());
   ASSERT_TRUE(target.OnResolved(&err));
 
@@ -47,10 +48,9 @@
       "      \"deps\": [\n"
       "      ],\n"
       "      \"edition\": \"2015\",\n"
-      "      \"atom_cfgs\": [\n"
-      "      ],\n"
-      "      \"key_value_cfgs\": {\n"
-      "      }\n"
+      "      \"cfg\": [\n"
+      "        \"feature=\\\"foo_enabled\\\"\"\n"
+      "      ]\n"
       "    }\n"
       "  ]\n"
       "}\n";
@@ -103,10 +103,8 @@
       "      \"deps\": [\n"
       "      ],\n"
       "      \"edition\": \"2015\",\n"
-      "      \"atom_cfgs\": [\n"
-      "      ],\n"
-      "      \"key_value_cfgs\": {\n"
-      "      }\n"
+      "      \"cfg\": [\n"
+      "      ]\n"
       "    },\n"
       "    {\n"
       "      \"crate_id\": 1,\n"
@@ -119,10 +117,8 @@
       "        }\n"
       "      ],\n"
       "      \"edition\": \"2015\",\n"
-      "      \"atom_cfgs\": [\n"
-      "      ],\n"
-      "      \"key_value_cfgs\": {\n"
-      "      }\n"
+      "      \"cfg\": [\n"
+      "      ]\n"
       "    }\n"
       "  ]\n"
       "}\n";
@@ -186,10 +182,8 @@
       "      \"deps\": [\n"
       "      ],\n"
       "      \"edition\": \"2015\",\n"
-      "      \"atom_cfgs\": [\n"
-      "      ],\n"
-      "      \"key_value_cfgs\": {\n"
-      "      }\n"
+      "      \"cfg\": [\n"
+      "      ]\n"
       "    },\n"
       "    {\n"
       "      \"crate_id\": 1,\n"
@@ -198,10 +192,8 @@
       "      \"deps\": [\n"
       "      ],\n"
       "      \"edition\": \"2015\",\n"
-      "      \"atom_cfgs\": [\n"
-      "      ],\n"
-      "      \"key_value_cfgs\": {\n"
-      "      }\n"
+      "      \"cfg\": [\n"
+      "      ]\n"
       "    },\n"
       "    {\n"
       "      \"crate_id\": 2,\n"
@@ -218,10 +210,8 @@
       "        }\n"
       "      ],\n"
       "      \"edition\": \"2015\",\n"
-      "      \"atom_cfgs\": [\n"
-      "      ],\n"
-      "      \"key_value_cfgs\": {\n"
-      "      }\n"
+      "      \"cfg\": [\n"
+      "      ]\n"
       "    }\n"
       "  ]\n"
       "}\n";
@@ -299,10 +289,8 @@
       "      \"deps\": [\n"
       "      ],\n"
       "      \"edition\": \"2015\",\n"
-      "      \"atom_cfgs\": [\n"
-      "      ],\n"
-      "      \"key_value_cfgs\": {\n"
-      "      }\n"
+      "      \"cfg\": [\n"
+      "      ]\n"
       "    },\n"
       "    {\n"
       "      \"crate_id\": 1,\n"
@@ -311,10 +299,8 @@
       "      \"deps\": [\n"
       "      ],\n"
       "      \"edition\": \"2015\",\n"
-      "      \"atom_cfgs\": [\n"
-      "      ],\n"
-      "      \"key_value_cfgs\": {\n"
-      "      }\n"
+      "      \"cfg\": [\n"
+      "      ]\n"
       "    },\n"
       "    {\n"
       "      \"crate_id\": 2,\n"
@@ -331,10 +317,8 @@
       "        }\n"
       "      ],\n"
       "      \"edition\": \"2015\",\n"
-      "      \"atom_cfgs\": [\n"
-      "      ],\n"
-      "      \"key_value_cfgs\": {\n"
-      "      }\n"
+      "      \"cfg\": [\n"
+      "      ]\n"
       "    }\n"
       "  ]\n"
       "}\n";