Change "gn check" to report all incorrect include

Backport of
https://chromium-review.googlesource.com/c/chromium/src/+/1107992 which
was landed after fork to standalone repo.

Change-Id: I940ab8451758f1ef77e4c66361f956a88fe2e2c4
Reviewed-on: https://gn-review.googlesource.com/1842
Commit-Queue: Scott Graham <scottmg@chromium.org>
Reviewed-by: Dirk Pranke <dpranke@chromium.org>
diff --git a/tools/gn/header_checker.cc b/tools/gn/header_checker.cc
index a2958d5..03afc46 100644
--- a/tools/gn/header_checker.cc
+++ b/tools/gn/header_checker.cc
@@ -180,10 +180,10 @@
 }
 
 void HeaderChecker::DoWork(const Target* target, const SourceFile& file) {
-  Err err;
-  if (!CheckFile(target, file, &err)) {
+  std::vector<Err> errors;
+  if (!CheckFile(target, file, &errors)) {
     std::lock_guard<std::mutex> lock(lock_);
-    errors_.push_back(err);
+    errors_.insert(errors_.end(), errors.begin(), errors.end());
   }
 
   if (!task_count_.Decrement()) {
@@ -262,7 +262,7 @@
 
 bool HeaderChecker::CheckFile(const Target* from_target,
                               const SourceFile& file,
-                              Err* err) const {
+                              std::vector<Err>* errors) const {
   ScopedTrace trace(TraceItem::TRACE_CHECK_HEADER, file.value());
 
   // Sometimes you have generated source files included as sources in another
@@ -275,11 +275,11 @@
   base::FilePath path = build_settings_->GetFullPath(file);
   std::string contents;
   if (!base::ReadFileToString(path, &contents)) {
-    *err =
-        Err(from_target->defined_from(), "Source file not found.",
-            "The target:\n  " + from_target->label().GetUserVisibleName(false) +
-                "\nhas a source file:\n  " + file.value() +
-                "\nwhich was not found.");
+    errors->emplace_back(from_target->defined_from(), "Source file not found.",
+                         "The target:\n  " +
+                             from_target->label().GetUserVisibleName(false) +
+                             "\nhas a source file:\n  " + file.value() +
+                             "\nwhich was not found.");
     return false;
   }
 
@@ -295,19 +295,23 @@
                         target_include_dirs.end());
   }
 
+  bool has_errors = false;
   CIncludeIterator iter(&input_file);
   base::StringPiece current_include;
   LocationRange range;
   while (iter.GetNextIncludeString(&current_include, &range)) {
+    Err err;
     SourceFile include = SourceFileForInclude(current_include, include_dirs,
-                                              input_file, range, err);
+                                              input_file, range, &err);
     if (!include.is_null()) {
-      if (!CheckInclude(from_target, input_file, include, range, err))
-        return false;
+      if (!CheckInclude(from_target, input_file, include, range, &err)) {
+        errors->emplace_back(std::move(err));
+        has_errors = true;
+      }
     }
   }
 
-  return true;
+  return !has_errors;
 }
 
 // If the file exists:
diff --git a/tools/gn/header_checker.h b/tools/gn/header_checker.h
index 9fde97c..ef14729 100644
--- a/tools/gn/header_checker.h
+++ b/tools/gn/header_checker.h
@@ -117,7 +117,7 @@
   // error messages.
   bool CheckFile(const Target* from_target,
                  const SourceFile& file,
-                 Err* err) const;
+                 std::vector<Err>* err) const;
 
   // Checks that the given file in the given target can include the given
   // include file. If disallowed, returns false and sets the error. The