Escape `+` characters in rule names

When adding an `action()` in buildtools/third_party/libc++/BUILD.gn,
we get

    ninja: error: toolchain.ninja:629: expected newline, got lexing error
    rule __buildtools_third_party_libc++_write_libcxx_modulemap___build_tool...
                                      ^ near here

without this.

Bug: chromium:1430964
Change-Id: I4fe30182565ac2114319c4fb79bb9b8442407f0d
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/15500
Reviewed-by: Sylvain Defresne <sdefresne@chromium.org>
Commit-Queue: Nico Weber <thakis@chromium.org>
diff --git a/src/gn/ninja_action_target_writer.cc b/src/gn/ninja_action_target_writer.cc
index 644b845..336a9f7 100644
--- a/src/gn/ninja_action_target_writer.cc
+++ b/src/gn/ninja_action_target_writer.cc
@@ -112,7 +112,7 @@
   // there will be only one invocation so we can use a simple name.
   std::string target_label = target_->label().GetUserVisibleName(true);
   std::string custom_rule_name(target_label);
-  base::ReplaceChars(custom_rule_name, ":/()", "_", &custom_rule_name);
+  base::ReplaceChars(custom_rule_name, ":/()+", "_", &custom_rule_name);
   custom_rule_name.append("_rule");
 
   const SubstitutionList& args = target_->action_values().args();
diff --git a/src/gn/ninja_action_target_writer_unittest.cc b/src/gn/ninja_action_target_writer_unittest.cc
index 8fcddb6..d291dc8 100644
--- a/src/gn/ninja_action_target_writer_unittest.cc
+++ b/src/gn/ninja_action_target_writer_unittest.cc
@@ -42,11 +42,11 @@
   Err err;
   TestWithScope setup;
 
-  Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
+  Target target(setup.settings(), Label(SourceDir("//foo++/"), "bar"));
   target.set_output_type(Target::ACTION);
 
-  target.action_values().set_script(SourceFile("//foo/script.py"));
-  target.config_values().inputs().push_back(SourceFile("//foo/included.txt"));
+  target.action_values().set_script(SourceFile("//foo++/script.py"));
+  target.config_values().inputs().push_back(SourceFile("//foo++/included.txt"));
 
   target.action_values().outputs() =
       SubstitutionList::MakeForTest("//out/Debug/foo.out");
@@ -61,14 +61,14 @@
   NinjaActionTargetWriter writer(&target, out);
   writer.Run();
 
-  const char* expected = R"(rule __foo_bar___rule
-  command = /usr/bin/python ../../foo/script.py
-  description = ACTION //foo:bar()
+  const char* expected = R"(rule __foo___bar___rule
+  command = /usr/bin/python ../../foo++/script.py
+  description = ACTION //foo++:bar()
   restat = 1
 
-build foo.out: __foo_bar___rule | ../../foo/script.py ../../foo/included.txt
+build foo.out: __foo___bar___rule | ../../foo++/script.py ../../foo++/included.txt
 
-build obj/foo/bar.stamp: stamp foo.out
+build obj/foo++/bar.stamp: stamp foo.out
 )";
   EXPECT_EQ(expected, out.str()) << expected << "--" << out.str();
 }