OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "tools/gn/header_checker.h" | 5 #include "tools/gn/header_checker.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
123 : main_loop_(base::MessageLoop::current()), | 123 : main_loop_(base::MessageLoop::current()), |
124 build_settings_(build_settings) { | 124 build_settings_(build_settings) { |
125 for (size_t i = 0; i < targets.size(); i++) | 125 for (size_t i = 0; i < targets.size(); i++) |
126 AddTargetToFileMap(targets[i], &file_map_); | 126 AddTargetToFileMap(targets[i], &file_map_); |
127 } | 127 } |
128 | 128 |
129 HeaderChecker::~HeaderChecker() { | 129 HeaderChecker::~HeaderChecker() { |
130 } | 130 } |
131 | 131 |
132 bool HeaderChecker::Run(const std::vector<const Target*>& to_check, | 132 bool HeaderChecker::Run(const std::vector<const Target*>& to_check, |
| 133 bool force_check, |
133 std::vector<Err>* errors) { | 134 std::vector<Err>* errors) { |
134 if (to_check.empty()) { | 135 if (to_check.empty()) { |
135 // Check all files. | 136 // Check all files. |
136 RunCheckOverFiles(file_map_); | 137 RunCheckOverFiles(file_map_, force_check); |
137 } else { | 138 } else { |
138 // Run only over the files in the given targets. | 139 // Run only over the files in the given targets. |
139 FileMap files_to_check; | 140 FileMap files_to_check; |
140 for (size_t i = 0; i < to_check.size(); i++) | 141 for (size_t i = 0; i < to_check.size(); i++) |
141 AddTargetToFileMap(to_check[i], &files_to_check); | 142 AddTargetToFileMap(to_check[i], &files_to_check); |
142 RunCheckOverFiles(files_to_check); | 143 RunCheckOverFiles(files_to_check, force_check); |
143 } | 144 } |
144 | 145 |
145 if (errors_.empty()) | 146 if (errors_.empty()) |
146 return true; | 147 return true; |
147 *errors = errors_; | 148 *errors = errors_; |
148 return false; | 149 return false; |
149 } | 150 } |
150 | 151 |
151 void HeaderChecker::RunCheckOverFiles(const FileMap& files) { | 152 void HeaderChecker::RunCheckOverFiles(const FileMap& files, bool force_check) { |
152 if (files.empty()) | 153 if (files.empty()) |
153 return; | 154 return; |
154 | 155 |
155 scoped_refptr<base::SequencedWorkerPool> pool( | 156 scoped_refptr<base::SequencedWorkerPool> pool( |
156 new base::SequencedWorkerPool(16, "HeaderChecker")); | 157 new base::SequencedWorkerPool(16, "HeaderChecker")); |
157 for (FileMap::const_iterator file_i = files.begin(); | 158 for (FileMap::const_iterator file_i = files.begin(); |
158 file_i != files.end(); ++file_i) { | 159 file_i != files.end(); ++file_i) { |
159 const TargetVector& vect = file_i->second; | 160 const TargetVector& vect = file_i->second; |
160 | 161 |
161 // Only check C-like source files (RC files also have includes). | 162 // Only check C-like source files (RC files also have includes). |
162 SourceFileType type = GetSourceFileType(file_i->first); | 163 SourceFileType type = GetSourceFileType(file_i->first); |
163 if (type != SOURCE_CC && type != SOURCE_H && type != SOURCE_C && | 164 if (type != SOURCE_CC && type != SOURCE_H && type != SOURCE_C && |
164 type != SOURCE_M && type != SOURCE_MM && type != SOURCE_RC) | 165 type != SOURCE_M && type != SOURCE_MM && type != SOURCE_RC) |
165 continue; | 166 continue; |
166 | 167 |
| 168 // Do a first pass to find if this should be skipped. All targets including |
| 169 // this source file must exclude it from checking. |
| 170 if (!force_check) { |
| 171 bool check_includes = false; |
| 172 for (size_t vect_i = 0; vect_i < vect.size(); ++vect_i) |
| 173 check_includes |= vect[vect_i].target->check_includes(); |
| 174 if (!check_includes) |
| 175 continue; |
| 176 } |
| 177 |
167 for (size_t vect_i = 0; vect_i < vect.size(); ++vect_i) { | 178 for (size_t vect_i = 0; vect_i < vect.size(); ++vect_i) { |
168 pool->PostWorkerTaskWithShutdownBehavior( | 179 pool->PostWorkerTaskWithShutdownBehavior( |
169 FROM_HERE, | 180 FROM_HERE, |
170 base::Bind(&HeaderChecker::DoWork, this, | 181 base::Bind(&HeaderChecker::DoWork, this, |
171 vect[vect_i].target, file_i->first), | 182 vect[vect_i].target, file_i->first), |
172 base::SequencedWorkerPool::BLOCK_SHUTDOWN); | 183 base::SequencedWorkerPool::BLOCK_SHUTDOWN); |
173 } | 184 } |
174 } | 185 } |
175 | 186 |
176 // After this call we're single-threaded again. | 187 // After this call we're single-threaded again. |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
343 if (has_direct_dependent_compiler_settings && | 354 if (has_direct_dependent_compiler_settings && |
344 !direct_dependent_configs_apply) { | 355 !direct_dependent_configs_apply) { |
345 size_t problematic_index = GetDependentConfigChainProblemIndex(chain); | 356 size_t problematic_index = GetDependentConfigChainProblemIndex(chain); |
346 *err = Err(CreatePersistentRange(source_file, range), | 357 *err = Err(CreatePersistentRange(source_file, range), |
347 "Can't include this header from here.", | 358 "Can't include this header from here.", |
348 GetDependentConfigChainError(chain, problematic_index)); | 359 GetDependentConfigChainError(chain, problematic_index)); |
349 return false; | 360 return false; |
350 } | 361 } |
351 | 362 |
352 found_dependency = true; | 363 found_dependency = true; |
| 364 } else if ( |
| 365 to_target->allow_circular_includes_from().find(from_target->label()) != |
| 366 to_target->allow_circular_includes_from().end()) { |
| 367 // Not a dependency, but this include is whitelisted from the destination. |
| 368 found_dependency = true; |
353 } | 369 } |
354 } | 370 } |
355 | 371 |
356 if (!found_dependency) { | 372 if (!found_dependency) { |
357 std::string msg = "It is not in any dependency of " + | 373 std::string msg = "It is not in any dependency of " + |
358 from_target->label().GetUserVisibleName(false); | 374 from_target->label().GetUserVisibleName(false); |
359 msg += "\nThe include file is in the target(s):\n"; | 375 msg += "\nThe include file is in the target(s):\n"; |
360 for (size_t i = 0; i < targets.size(); i++) | 376 for (size_t i = 0; i < targets.size(); i++) |
361 msg += " " + targets[i].target->label().GetUserVisibleName(false) + "\n"; | 377 msg += " " + targets[i].target->label().GetUserVisibleName(false) + "\n"; |
362 if (targets.size() > 1) | 378 if (targets.size() > 1) |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
497 chain[i]->forward_dependent_configs(); | 513 chain[i]->forward_dependent_configs(); |
498 if (std::find_if(forwarded.begin(), forwarded.end(), | 514 if (std::find_if(forwarded.begin(), forwarded.end(), |
499 LabelPtrPtrEquals<Target>(chain[i - 1])) == | 515 LabelPtrPtrEquals<Target>(chain[i - 1])) == |
500 forwarded.end()) | 516 forwarded.end()) |
501 return i; | 517 return i; |
502 } | 518 } |
503 | 519 |
504 CHECK(false) << "Unable to diagnose dependent config chain problem."; | 520 CHECK(false) << "Unable to diagnose dependent config chain problem."; |
505 return 0; | 521 return 0; |
506 } | 522 } |
OLD | NEW |