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 3 // found in the LICENSE file. 4 5 #ifndef TOOLS_GN_HEADER_CHECKER_H_ 6 #define TOOLS_GN_HEADER_CHECKER_H_ 7 8 #include <map> 9 #include <set> 10 #include <vector> 11 12 #include "base/basictypes.h" 13 #include "base/gtest_prod_util.h" 14 #include "base/memory/ref_counted.h" 15 #include "base/run_loop.h" 16 #include "base/strings/string_piece.h" 17 #include "base/synchronization/lock.h" 18 #include "tools/gn/err.h" 19 20 class BuildSettings; 21 class InputFile; 22 class Label; 23 class LocationRange; 24 class SourceFile; 25 class Target; 26 27 namespace base { 28 class MessageLoop; 29 } 30 31 class HeaderChecker : public base::RefCountedThreadSafe<HeaderChecker> { 32 public: 33 // Represents a dependency chain. 34 struct ChainLink { ChainLinkChainLink35 ChainLink() : target(NULL), is_public(false) {} ChainLinkChainLink36 ChainLink(const Target* t, bool p) : target(t), is_public(p) {} 37 38 const Target* target; 39 40 // True when the dependency on this target is public. 41 bool is_public; 42 43 // Used for testing. 44 bool operator==(const ChainLink& other) const { 45 return target == other.target && is_public == other.is_public; 46 } 47 }; 48 typedef std::vector<ChainLink> Chain; 49 50 HeaderChecker(const BuildSettings* build_settings, 51 const std::vector<const Target*>& targets); 52 53 // Runs the check. The targets in to_check will be checked. If this list is 54 // empty, all targets will be checked. 55 // 56 // This assumes that the current thread already has a message loop. On 57 // error, fills the given vector with the errors and returns false. Returns 58 // true on success. 59 // 60 // force_check, if true, will override targets opting out of header checking 61 // with "check_includes = false" and will check them anyway. 62 bool Run(const std::vector<const Target*>& to_check, 63 bool force_check, 64 std::vector<Err>* errors); 65 66 private: 67 friend class base::RefCountedThreadSafe<HeaderChecker>; 68 FRIEND_TEST_ALL_PREFIXES(HeaderCheckerTest, IsDependencyOf); 69 FRIEND_TEST_ALL_PREFIXES(HeaderCheckerTest, CheckInclude); 70 FRIEND_TEST_ALL_PREFIXES(HeaderCheckerTest, PublicFirst); 71 FRIEND_TEST_ALL_PREFIXES(HeaderCheckerTest, CheckIncludeAllowCircular); 72 ~HeaderChecker(); 73 74 struct TargetInfo { TargetInfoTargetInfo75 TargetInfo() : target(NULL), is_public(false), is_generated(false) {} TargetInfoTargetInfo76 TargetInfo(const Target* t, bool is_pub, bool is_gen) 77 : target(t), 78 is_public(is_pub), 79 is_generated(is_gen) { 80 } 81 82 const Target* target; 83 84 // True if the file is public in the given target. 85 bool is_public; 86 87 // True if this file is generated and won't actually exist on disk. 88 bool is_generated; 89 }; 90 91 typedef std::vector<TargetInfo> TargetVector; 92 typedef std::map<SourceFile, TargetVector> FileMap; 93 94 // Backend for Run() that takes the list of files to check. The errors_ list 95 // will be populate on failure. 96 void RunCheckOverFiles(const FileMap& flies, bool force_check); 97 98 void DoWork(const Target* target, const SourceFile& file); 99 100 // Adds the sources and public files from the given target to the given map. 101 static void AddTargetToFileMap(const Target* target, FileMap* dest); 102 103 // Returns true if the given file is in the output directory. 104 bool IsFileInOuputDir(const SourceFile& file) const; 105 106 // Resolves the contents of an include to a SourceFile. 107 SourceFile SourceFileForInclude(const base::StringPiece& input) const; 108 109 // from_target is the target the file was defined from. It will be used in 110 // error messages. 111 bool CheckFile(const Target* from_target, 112 const SourceFile& file, 113 Err* err) const; 114 115 // Checks that the given file in the given target can include the given 116 // include file. If disallowed, returns false and sets the error. The 117 // range indicates the location of the include in the file for error 118 // reporting. 119 bool CheckInclude(const Target* from_target, 120 const InputFile& source_file, 121 const SourceFile& include_file, 122 const LocationRange& range, 123 Err* err) const; 124 125 // Returns true if the given search_for target is a dependency of 126 // search_from. 127 // 128 // If found, the vector given in "chain" will be filled with the reverse 129 // dependency chain from the dest target (chain[0] = search_for) to the src 130 // target (chain[chain.size() - 1] = search_from). 131 // 132 // Chains with permitted dependencies will be considered first. If a 133 // permitted match is found, *is_permitted will be set to true. A chain with 134 // indirect, non-public dependencies will only be considered if there are no 135 // public or direct chains. In this case, *is_permitted will be false. 136 // 137 // A permitted dependency is a sequence of public dependencies. The first 138 // one may be private, since a direct dependency always allows headers to be 139 // included. 140 bool IsDependencyOf(const Target* search_for, 141 const Target* search_from, 142 Chain* chain, 143 bool* is_permitted) const; 144 145 // For internal use by the previous override of IsDependencyOf. If 146 // require_public is true, only public dependency chains are searched. 147 bool IsDependencyOf(const Target* search_for, 148 const Target* search_from, 149 bool require_permitted, 150 Chain* chain) const; 151 152 // Non-locked variables ------------------------------------------------------ 153 // 154 // These are initialized during construction (which happens on one thread) 155 // and are not modified after, so any thread can read these without locking. 156 157 base::MessageLoop* main_loop_; 158 base::RunLoop main_thread_runner_; 159 160 const BuildSettings* build_settings_; 161 162 // Maps source files to targets it appears in (usually just one target). 163 FileMap file_map_; 164 165 // Locked variables ---------------------------------------------------------- 166 // 167 // These are mutable during runtime and require locking. 168 169 base::Lock lock_; 170 171 std::vector<Err> errors_; 172 173 DISALLOW_COPY_AND_ASSIGN(HeaderChecker); 174 }; 175 176 #endif // TOOLS_GN_HEADER_CHECKER_H_ 177