[errors] Print label toolchains more often

Adds the toolchain to labels in error messages in many
more cases than in the past.

Change-Id: Ib098bf1902f64fc8c27015dee1a3c3abc786ca5b
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/14720
Reviewed-by: Brett Wilson <brettw@chromium.org>
Commit-Queue: Aaron Wood <aaronwood@google.com>
diff --git a/src/gn/binary_target_generator.cc b/src/gn/binary_target_generator.cc
index 5796cfe..07df7bf 100644
--- a/src/gn/binary_target_generator.cc
+++ b/src/gn/binary_target_generator.cc
@@ -218,8 +218,12 @@
       }
     }
     if (!found_dep) {
+      bool with_toolchain = scope_->settings()->ShouldShowToolchain({
+        &target_->label(),
+        &cur
+      });
       *err_ = Err(*value, "Label not in deps.",
-                  "The label \"" + cur.GetUserVisibleName(false) +
+                  "The label \"" + cur.GetUserVisibleName(with_toolchain) +
                       "\"\nwas not in the deps of this target. "
                       "allow_circular_includes_from only allows\ntargets "
                       "present in the "
diff --git a/src/gn/builder.cc b/src/gn/builder.cc
index 1522a36..81335f8 100644
--- a/src/gn/builder.cc
+++ b/src/gn/builder.cc
@@ -75,8 +75,9 @@
 
   // Check that it's not been already defined.
   if (record->item()) {
+    bool with_toolchain = item->settings()->ShouldShowToolchain({&item->label()});
     err = Err(item->defined_from(), "Duplicate definition.",
-              "The item\n  " + item->label().GetUserVisibleName(false) +
+              "The item\n  " + item->label().GetUserVisibleName(with_toolchain) +
                   "\nwas already defined.");
     err.AppendSubErr(
         Err(record->item()->defined_from(), "Previous definition:"));
@@ -232,7 +233,7 @@
           "possibly due to an\ninternal error:";
       for (auto* bad_record : bad_records) {
         depstring +=
-            "\n\"" + bad_record->label().GetUserVisibleName(false) + "\"";
+            "\n\"" + bad_record->label().GetUserVisibleName(true) + "\"";
       }
       *err = Err(Location(), "", depstring);
     } else {
@@ -330,7 +331,7 @@
   // Check types, if the record was not just created.
   if (!pair.first && record->type() != type) {
     std::string msg =
-        "The type of " + label.GetUserVisibleName(false) + "\nhere is a " +
+        "The type of " + label.GetUserVisibleName(true) + "\nhere is a " +
         BuilderRecord::GetNameForType(type) + " but was previously seen as a " +
         BuilderRecord::GetNameForType(record->type()) +
         ".\n\n"
@@ -354,7 +355,7 @@
   BuilderRecord* record = GetRecord(label);
   if (!record) {
     *err = Err(origin, "Item not found",
-               "\"" + label.GetUserVisibleName(false) +
+               "\"" + label.GetUserVisibleName(true) +
                    "\" doesn't\n"
                    "refer to an existent thing.");
     return nullptr;
@@ -364,7 +365,7 @@
   if (!item) {
     *err = Err(
         origin, "Item not resolved.",
-        "\"" + label.GetUserVisibleName(false) + "\" hasn't been resolved.\n");
+        "\"" + label.GetUserVisibleName(true) + "\" hasn't been resolved.\n");
     return nullptr;
   }
 
@@ -372,7 +373,7 @@
     *err =
         Err(origin,
             std::string("This is not a ") + BuilderRecord::GetNameForType(type),
-            "\"" + label.GetUserVisibleName(false) + "\" refers to a " +
+            "\"" + label.GetUserVisibleName(true) + "\" refers to a " +
                 item->GetItemTypeName() + " instead of a " +
                 BuilderRecord::GetNameForType(type) + ".");
     return nullptr;
diff --git a/src/gn/function_get_target_outputs.cc b/src/gn/function_get_target_outputs.cc
index fa851f3..c9f10c0 100644
--- a/src/gn/function_get_target_outputs.cc
+++ b/src/gn/function_get_target_outputs.cc
@@ -105,8 +105,9 @@
   }
 
   if (!target) {
+    bool with_toolchain = !scope->settings()->is_default();
     *err = Err(function, "Target not found in this context.",
-               label.GetUserVisibleName(false) +
+               label.GetUserVisibleName(with_toolchain) +
                    "\nwas not found. get_target_outputs() can only be used for "
                    "targets\n"
                    "previously defined in the current file.");
diff --git a/src/gn/target.cc b/src/gn/target.cc
index 7b545b5..2cebcf7 100644
--- a/src/gn/target.cc
+++ b/src/gn/target.cc
@@ -44,12 +44,16 @@
 }
 
 Err MakeTestOnlyError(const Item* from, const Item* to) {
+  bool with_toolchain = from->settings()->ShouldShowToolchain({
+    &from->label(),
+    &to->label(),
+  });
   return Err(
       from->defined_from(), "Test-only dependency not allowed.",
-      from->label().GetUserVisibleName(false) +
+      from->label().GetUserVisibleName(with_toolchain) +
           "\n"
           "which is NOT marked testonly can't depend on\n" +
-          to->label().GetUserVisibleName(false) +
+          to->label().GetUserVisibleName(with_toolchain) +
           "\n"
           "which is marked testonly. Only targets with \"testonly = true\"\n"
           "can depend on other test-only targets.\n"
@@ -1082,19 +1086,24 @@
       // Already have a precompiled header values, the settings must match.
       if (config_values_->precompiled_header() != cur.precompiled_header() ||
           config_values_->precompiled_source() != cur.precompiled_source()) {
+        bool with_toolchain = settings()->ShouldShowToolchain({
+          &label(),
+          pch_header_settings_from,
+          &config->label(),
+        });
         *err = Err(
             defined_from(), "Precompiled header setting conflict.",
-            "The target " + label().GetUserVisibleName(false) +
+            "The target " + label().GetUserVisibleName(with_toolchain) +
                 "\n"
                 "has conflicting precompiled header settings.\n"
                 "\n"
                 "From " +
-                pch_header_settings_from->GetUserVisibleName(false) +
+                pch_header_settings_from->GetUserVisibleName(with_toolchain) +
                 "\n  header: " + config_values_->precompiled_header() +
                 "\n  source: " + config_values_->precompiled_source().value() +
                 "\n\n"
                 "From " +
-                config->label().GetUserVisibleName(false) +
+                config->label().GetUserVisibleName(with_toolchain) +
                 "\n  header: " + cur.precompiled_header() +
                 "\n  source: " + cur.precompiled_source().value());
         return false;
@@ -1131,7 +1140,7 @@
   if (output_type() == Target::SOURCE_SET &&
       source_types_used().RustSourceUsed()) {
     *err = Err(defined_from(), "source_set contained Rust code.",
-               label().GetUserVisibleName(false) +
+               label().GetUserVisibleName(!settings()->is_default()) +
                    " has Rust code. Only C/C++ source_sets are supported.");
     return false;
   }
@@ -1177,7 +1186,7 @@
                                   &failure_path_str, &failure_pattern)) {
     *err = Err(
         defined_from(), "assert_no_deps failed.",
-        label().GetUserVisibleName(false) +
+        label().GetUserVisibleName(!settings()->is_default()) +
             " has an assert_no_deps entry:\n  " + failure_pattern->Describe() +
             "\nwhich fails for the dependency path:\n" + failure_path_str);
     return false;
diff --git a/src/gn/target_unittest.cc b/src/gn/target_unittest.cc
index b4ea699..005335d 100644
--- a/src/gn/target_unittest.cc
+++ b/src/gn/target_unittest.cc
@@ -926,7 +926,7 @@
                                              &computed_outputs, &err));
   ASSERT_EQ(1u, computed_outputs.size());
   EXPECT_EQ("//out/Debug/obj/a/a.stamp", computed_outputs[0].value())
-    << "was instead: " << computed_outputs[0].value();
+      << "was instead: " << computed_outputs[0].value();
 }
 
 // Tests Target::GetOutputFilesForSource for action_foreach targets (these, like
@@ -1219,13 +1219,16 @@
   TestWithScope setup;
   Err err;
 
-  Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
+  Target target(setup.settings(), Label(SourceDir("//foo/"), "bar",
+                                        SourceDir("//toolchain/"), "default"));
 
   // Target with no settings, no configs, should be a no-op.
   EXPECT_TRUE(target.ResolvePrecompiledHeaders(&err));
 
   // Config with PCH values.
-  Config config_1(setup.settings(), Label(SourceDir("//foo/"), "c1"));
+  Config config_1(
+      setup.settings(),
+      Label(SourceDir("//foo/"), "c1", SourceDir("//toolchain/"), "default"));
   std::string pch_1("pch.h");
   SourceFile pcs_1("//pcs.cc");
   config_1.own_values().set_precompiled_header(pch_1);
@@ -1246,7 +1249,9 @@
   EXPECT_TRUE(target.config_values().precompiled_source() == pcs_1);
 
   // Second config with different PCH values.
-  Config config_2(setup.settings(), Label(SourceDir("//foo/"), "c2"));
+  Config config_2(
+      setup.settings(),
+      Label(SourceDir("//foo/"), "c2", SourceDir("//toolchain/"), "default"));
   std::string pch_2("pch2.h");
   SourceFile pcs_2("//pcs2.cc");
   config_2.own_values().set_precompiled_header(pch_2);