Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(436)

Side by Side Diff: trunk/src/tools/gn/header_checker.cc

Issue 231293003: Revert 262747 "Improve GN public header file checking" (Closed) Base URL: svn://svn.chromium.org/chrome/
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « trunk/src/tools/gn/header_checker.h ('k') | trunk/src/tools/gn/header_checker_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
11 #include "base/message_loop/message_loop.h" 11 #include "base/message_loop/message_loop.h"
12 #include "base/threading/sequenced_worker_pool.h" 12 #include "base/threading/sequenced_worker_pool.h"
13 #include "tools/gn/build_settings.h" 13 #include "tools/gn/build_settings.h"
14 #include "tools/gn/builder.h" 14 #include "tools/gn/builder.h"
15 #include "tools/gn/c_include_iterator.h" 15 #include "tools/gn/c_include_iterator.h"
16 #include "tools/gn/err.h" 16 #include "tools/gn/err.h"
17 #include "tools/gn/filesystem_utils.h" 17 #include "tools/gn/filesystem_utils.h"
18 #include "tools/gn/scheduler.h" 18 #include "tools/gn/scheduler.h"
19 #include "tools/gn/target.h" 19 #include "tools/gn/target.h"
20 #include "tools/gn/trace.h" 20 #include "tools/gn/trace.h"
21 21
22 namespace {
23
24 // This class makes InputFiles on the stack as it reads files to check. When
25 // we throw an error, the Err indicates a locatin which has a pointer to
26 // an InputFile that must persist as long as the Err does.
27 //
28 // To make this work, this function creates a clone of the InputFile managed
29 // by the InputFileManager so the error can refer to something that
30 // persists. This means that the current file contents will live as long as
31 // the program, but this is OK since we're erroring out anyway.
32 LocationRange CreatePersistentRange(const InputFile& input_file,
33 const LocationRange& range) {
34 InputFile* clone_input_file;
35 std::vector<Token>* tokens; // Don't care about this.
36 scoped_ptr<ParseNode>* parse_root; // Don't care about this.
37
38 g_scheduler->input_file_manager()->AddDynamicInput(
39 input_file.name(), &clone_input_file, &tokens, &parse_root);
40 clone_input_file->SetContents(input_file.contents());
41
42 return LocationRange(
43 Location(clone_input_file, range.begin().line_number(),
44 range.begin().char_offset()),
45 Location(clone_input_file, range.end().line_number(),
46 range.end().char_offset()));
47 }
48
49 } // namespace
50
51 HeaderChecker::HeaderChecker(const BuildSettings* build_settings, 22 HeaderChecker::HeaderChecker(const BuildSettings* build_settings,
52 const std::vector<const Target*>& targets) 23 const std::vector<const Target*>& targets)
53 : main_loop_(base::MessageLoop::current()), 24 : main_loop_(base::MessageLoop::current()),
54 build_settings_(build_settings) { 25 build_settings_(build_settings) {
55 for (size_t i = 0; i < targets.size(); i++) 26 for (size_t i = 0; i < targets.size(); i++)
56 AddTargetToFileMap(targets[i]); 27 AddTargetToFileMap(targets[i]);
57 } 28 }
58 29
59 HeaderChecker::~HeaderChecker() { 30 HeaderChecker::~HeaderChecker() {
60 } 31 }
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 130
160 base::FilePath path = build_settings_->GetFullPath(file); 131 base::FilePath path = build_settings_->GetFullPath(file);
161 std::string contents; 132 std::string contents;
162 if (!base::ReadFileToString(path, &contents)) { 133 if (!base::ReadFileToString(path, &contents)) {
163 *err = Err(from_target->defined_from(), "Source file not found.", 134 *err = Err(from_target->defined_from(), "Source file not found.",
164 "This target includes as a source:\n " + file.value() + 135 "This target includes as a source:\n " + file.value() +
165 "\nwhich was not found."); 136 "\nwhich was not found.");
166 return false; 137 return false;
167 } 138 }
168 139
169 InputFile input_file(file); 140 CIncludeIterator iter(contents);
170 input_file.SetContents(contents);
171
172 CIncludeIterator iter(&input_file);
173 base::StringPiece current_include; 141 base::StringPiece current_include;
174 LocationRange range; 142 while (iter.GetNextIncludeString(&current_include)) {
175 while (iter.GetNextIncludeString(&current_include, &range)) {
176 SourceFile include = SourceFileForInclude(current_include); 143 SourceFile include = SourceFileForInclude(current_include);
177 if (!CheckInclude(from_target, input_file, include, range, err)) 144 if (!CheckInclude(from_target, file, include, err))
178 return false; 145 return false;
179 } 146 }
180 147
181 return true; 148 return true;
182 } 149 }
183 150
184 // If the file exists, it must be in a dependency of the given target, and it 151 // If the file exists, it must be in a dependency of the given target, and it
185 // must be public in that dependency. 152 // must be public in that dependency.
186 bool HeaderChecker::CheckInclude(const Target* from_target, 153 bool HeaderChecker::CheckInclude(const Target* from_target,
187 const InputFile& source_file, 154 const SourceFile& source_file,
188 const SourceFile& include_file, 155 const SourceFile& include_file,
189 const LocationRange& range,
190 Err* err) const { 156 Err* err) const {
191 // Assume if the file isn't declared in our sources that we don't need to 157 // Assume if the file isn't declared in our sources that we don't need to
192 // check it. It would be nice if we could give an error if this happens, but 158 // check it. It would be nice if we could give an error if this happens, but
193 // our include finder is too primitive and returns all includes, even if 159 // our include finder is too primitive and returns all includes, even if
194 // they're in a #if not executed in the current build. In that case, it's 160 // they're in a #if not executed in the current build. In that case, it's
195 // not unusual for the buildfiles to not specify that header at all. 161 // not unusual for the buildfiles to not specify that header at all.
196 FileMap::const_iterator found = file_map_.find(include_file); 162 FileMap::const_iterator found = file_map_.find(include_file);
197 if (found == file_map_.end()) 163 if (found == file_map_.end())
198 return true; 164 return true;
199 165
200 const TargetVector& targets = found->second; 166 const TargetVector& targets = found->second;
201 167
202 // For all targets containing this file, we require that at least one be 168 // For all targets containing this file, we require that at least one be
203 // a dependency of the current target, and all targets that are dependencies 169 // a dependency of the current target, and all targets that are dependencies
204 // must have the file listed in the public section. 170 // must have the file listed in the public section.
205 bool found_dependency = false; 171 bool found_dependency = false;
206 for (size_t i = 0; i < targets.size(); i++) { 172 for (size_t i = 0; i < targets.size(); i++) {
207 // We always allow source files in a target to include headers also in that 173 // We always allow source files in a target to include headers also in that
208 // target. 174 // target.
209 if (targets[i].target == from_target) 175 if (targets[i].target == from_target)
210 return true; 176 return true;
211 177
212 if (IsDependencyOf(targets[i].target, from_target)) { 178 if (IsDependencyOf(targets[i].target, from_target)) {
213 // The include is in a target that's a proper dependency. Verify that 179 // The include is in a target that's a proper dependency. Now verify
214 // the including target has visibility. 180 // that the include is a public file.
215 if (!targets[i].target->visibility().CanSeeMe(from_target->label())) { 181 if (!targets[i].is_public) {
216 std::string msg = "The included file is in " + 182 // Depending on a private header.
217 targets[i].target->label().GetUserVisibleName(false) + 183 std::string msg = "The file " + source_file.value() +
218 "\nwhich is not visible from " + 184 "\nincludes " + include_file.value() +
219 from_target->label().GetUserVisibleName(false) + 185 "\nwhich is private to the target " +
220 "\n(see \"gn help visibility\")."; 186 targets[i].target->label().GetUserVisibleName(false);
221 187
222 // Danger: must call CreatePersistentRange to put in Err. 188 // TODO(brettw) blame the including file.
223 *err = Err(CreatePersistentRange(source_file, range), 189 *err = Err(NULL, "Including a private header.", msg);
224 "Including a header from non-visible target.", msg);
225 return false;
226 }
227
228 // The file must also be public in the target.
229 if (!targets[i].is_public) {
230 // Danger: must call CreatePersistentRange to put in Err.
231 *err = Err(CreatePersistentRange(source_file, range),
232 "Including a private header.",
233 "This file is private to the target " +
234 targets[i].target->label().GetUserVisibleName(false));
235 return false; 190 return false;
236 } 191 }
237 found_dependency = true; 192 found_dependency = true;
238 } 193 }
239 } 194 }
240 195
241 if (!found_dependency) { 196 if (!found_dependency) {
242 std::string msg = "It is not in any dependency of " + 197 std::string msg =
198 source_file.value() + " includes the header\n" +
199 include_file.value() + " which is not in any dependency of\n" +
243 from_target->label().GetUserVisibleName(false); 200 from_target->label().GetUserVisibleName(false);
244 msg += "\nThe include file is in the target(s):\n"; 201 msg += "\n\nThe include file is in the target(s):\n";
245 for (size_t i = 0; i < targets.size(); i++) 202 for (size_t i = 0; i < targets.size(); i++)
246 msg += " " + targets[i].target->label().GetUserVisibleName(false) + "\n"; 203 msg += " " + targets[i].target->label().GetUserVisibleName(false) + "\n";
247 if (targets.size() > 1)
248 msg += "at least one of ";
249 msg += "which should somehow be reachable from " +
250 from_target->label().GetUserVisibleName(false);
251 204
252 // Danger: must call CreatePersistentRange to put in Err. 205 msg += "\nMake sure one of these is a direct or indirect dependency\n"
253 *err = Err(CreatePersistentRange(source_file, range), 206 "of " + from_target->label().GetUserVisibleName(false);
254 "Include not allowed.", msg); 207
208 // TODO(brettw) blame the including file.
209 // Probably this means making and leaking an input file for it, and also
210 // tracking the locations for each include.
211 *err = Err(NULL, "Include not allowed.", msg);
255 return false; 212 return false;
256 } 213 }
257 214
258 return true; 215 return true;
259 } 216 }
260 217
261 bool HeaderChecker::IsDependencyOf(const Target* search_for, 218 bool HeaderChecker::IsDependencyOf(const Target* search_for,
262 const Target* search_from) const { 219 const Target* search_from) const {
263 std::set<const Target*> checked; 220 std::set<const Target*> checked;
264 return IsDependencyOf(search_for, search_from, &checked); 221 return IsDependencyOf(search_for, search_from, &checked);
(...skipping 11 matching lines...) Expand all
276 return true; // Found it. 233 return true; // Found it.
277 234
278 // Recursive search. 235 // Recursive search.
279 checked->insert(deps[i].ptr); 236 checked->insert(deps[i].ptr);
280 if (IsDependencyOf(search_for, deps[i].ptr, checked)) 237 if (IsDependencyOf(search_for, deps[i].ptr, checked))
281 return true; 238 return true;
282 } 239 }
283 240
284 return false; 241 return false;
285 } 242 }
OLDNEW
« no previous file with comments | « trunk/src/tools/gn/header_checker.h ('k') | trunk/src/tools/gn/header_checker_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698