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 20class BuildSettings; 21class InputFile; 22class Label; 23class LocationRange; 24class SourceFile; 25class Target; 26 27namespace base { 28class MessageLoop; 29} 30 31class HeaderChecker : public base::RefCountedThreadSafe<HeaderChecker> { 32 public: 33 HeaderChecker(const BuildSettings* build_settings, 34 const std::vector<const Target*>& targets); 35 36 // This assumes that the current thread already has a message loop. On 37 // error, fills the given vector with the errors and returns false. Returns 38 // true on success. 39 bool Run(std::vector<Err>* errors); 40 41 private: 42 friend class base::RefCountedThreadSafe<HeaderChecker>; 43 FRIEND_TEST_ALL_PREFIXES(HeaderCheckerTest, IsDependencyOf); 44 FRIEND_TEST_ALL_PREFIXES(HeaderCheckerTest, CheckInclude); 45 FRIEND_TEST_ALL_PREFIXES(HeaderCheckerTest, DoDirectDependentConfigsApply); 46 ~HeaderChecker(); 47 48 struct TargetInfo { 49 TargetInfo() : target(NULL), is_public(false) {} 50 TargetInfo(const Target* t, bool p) : target(t), is_public(p) {} 51 52 const Target* target; 53 bool is_public; 54 }; 55 56 typedef std::vector<TargetInfo> TargetVector; 57 58 void DoWork(const Target* target, const SourceFile& file); 59 60 // Adds the sources and public files from the given target to the file_map_. 61 // Not threadsafe! Called only during init. 62 void AddTargetToFileMap(const Target* target); 63 64 // Returns true if the given file is in the output directory. 65 bool IsFileInOuputDir(const SourceFile& file) const; 66 67 // Resolves the contents of an include to a SourceFile. 68 SourceFile SourceFileForInclude(const base::StringPiece& input) const; 69 70 // from_target is the target the file was defined from. It will be used in 71 // error messages. 72 bool CheckFile(const Target* from_target, 73 const SourceFile& file, 74 Err* err) const; 75 76 // Checks that the given file in the given target can include the given 77 // include file. If disallowed, returns false and sets the error. The 78 // range indicates the location of the include in the file for error 79 // reporting. 80 bool CheckInclude(const Target* from_target, 81 const InputFile& source_file, 82 const SourceFile& include_file, 83 const LocationRange& range, 84 Err* err) const; 85 86 // Returns true if the given search_for target is a dependency of 87 // search_from. Many subtrees are duplicated so this function avoids 88 // duplicate checking across recursive calls by keeping track of checked 89 // targets in the given set. It should point to an empty set for the first 90 // call. A target is not considered to be a dependency of itself. 91 // 92 // If found, the vector given in "chain" will be filled with the reverse 93 // dependency chain from the dest target (chain[0] = search_for) to the src 94 // target (chain[chain.size() - 1] = search_from). 95 bool IsDependencyOf(const Target* search_for, 96 const Target* search_from, 97 std::vector<const Target*>* chain) const; 98 bool IsDependencyOf(const Target* search_for, 99 const Target* search_from, 100 std::vector<const Target*>* chain, 101 std::set<const Target*>* checked) const; 102 103 // Given a reverse dependency chain (chain[0] is the lower-level target, 104 // chain[end] is the higher-level target), determines if all direct dependent 105 // configs on the lower-level target would apply to the higher-level one. 106 // 107 // If configs do not apply, this function returns false and indicates the 108 // index of the target that caused the config to not apply by putting it in 109 // problematic_index. 110 static bool DoDirectDependentConfigsApply( 111 const std::vector<const Target*>& chain, 112 size_t* problematic_index); 113 114 // Non-locked variables ------------------------------------------------------ 115 // 116 // These are initialized during construction (which happens on one thread) 117 // and are not modified after, so any thread can read these without locking. 118 119 base::MessageLoop* main_loop_; 120 base::RunLoop main_thread_runner_; 121 122 const BuildSettings* build_settings_; 123 124 // Maps source files to targets it appears in (usually just one target). 125 typedef std::map<SourceFile, TargetVector> FileMap; 126 FileMap file_map_; 127 128 // Locked variables ---------------------------------------------------------- 129 // 130 // These are mutable during runtime and require locking. 131 132 base::Lock lock_; 133 134 std::vector<Err> errors_; 135 136 DISALLOW_COPY_AND_ASSIGN(HeaderChecker); 137}; 138 139#endif // TOOLS_GN_HEADER_CHECKER_H_ 140