// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef TOOLS_GN_HEADER_CHECKER_H_ #define TOOLS_GN_HEADER_CHECKER_H_ #include <map> #include <set> #include <vector> #include "base/basictypes.h" #include "base/gtest_prod_util.h" #include "base/memory/ref_counted.h" #include "base/run_loop.h" #include "base/strings/string_piece.h" #include "base/synchronization/lock.h" #include "tools/gn/err.h" class BuildSettings; class InputFile; class Label; class LocationRange; class SourceFile; class Target; namespace base { class MessageLoop; } class HeaderChecker : public base::RefCountedThreadSafe<HeaderChecker> { public: HeaderChecker(const BuildSettings* build_settings, const std::vector<const Target*>& targets); // This assumes that the current thread already has a message loop. On // error, fills the given vector with the errors and returns false. Returns // true on success. bool Run(std::vector<Err>* errors); private: friend class base::RefCountedThreadSafe<HeaderChecker>; FRIEND_TEST_ALL_PREFIXES(HeaderCheckerTest, IsDependencyOf); FRIEND_TEST_ALL_PREFIXES(HeaderCheckerTest, CheckInclude); FRIEND_TEST_ALL_PREFIXES(HeaderCheckerTest, DoDirectDependentConfigsApply); ~HeaderChecker(); struct TargetInfo { TargetInfo() : target(NULL), is_public(false) {} TargetInfo(const Target* t, bool p) : target(t), is_public(p) {} const Target* target; bool is_public; }; typedef std::vector<TargetInfo> TargetVector; void DoWork(const Target* target, const SourceFile& file); // Adds the sources and public files from the given target to the file_map_. // Not threadsafe! Called only during init. void AddTargetToFileMap(const Target* target); // Returns true if the given file is in the output directory. bool IsFileInOuputDir(const SourceFile& file) const; // Resolves the contents of an include to a SourceFile. SourceFile SourceFileForInclude(const base::StringPiece& input) const; // from_target is the target the file was defined from. It will be used in // error messages. bool CheckFile(const Target* from_target, const SourceFile& file, 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 // range indicates the location of the include in the file for error // reporting. bool CheckInclude(const Target* from_target, const InputFile& source_file, const SourceFile& include_file, const LocationRange& range, Err* err) const; // Returns true if the given search_for target is a dependency of // search_from. Many subtrees are duplicated so this function avoids // duplicate checking across recursive calls by keeping track of checked // targets in the given set. It should point to an empty set for the first // call. A target is not considered to be a dependency of itself. // // If found, the vector given in "chain" will be filled with the reverse // dependency chain from the dest target (chain[0] = search_for) to the src // target (chain[chain.size() - 1] = search_from). bool IsDependencyOf(const Target* search_for, const Target* search_from, std::vector<const Target*>* chain) const; bool IsDependencyOf(const Target* search_for, const Target* search_from, std::vector<const Target*>* chain, std::set<const Target*>* checked) const; // Given a reverse dependency chain (chain[0] is the lower-level target, // chain[end] is the higher-level target), determines if all direct dependent // configs on the lower-level target would apply to the higher-level one. // // If configs do not apply, this function returns false and indicates the // index of the target that caused the config to not apply by putting it in // problematic_index. static bool DoDirectDependentConfigsApply( const std::vector<const Target*>& chain, size_t* problematic_index); // Non-locked variables ------------------------------------------------------ // // These are initialized during construction (which happens on one thread) // and are not modified after, so any thread can read these without locking. base::MessageLoop* main_loop_; base::RunLoop main_thread_runner_; const BuildSettings* build_settings_; // Maps source files to targets it appears in (usually just one target). typedef std::map<SourceFile, TargetVector> FileMap; FileMap file_map_; // Locked variables ---------------------------------------------------------- // // These are mutable during runtime and require locking. base::Lock lock_; std::vector<Err> errors_; DISALLOW_COPY_AND_ASSIGN(HeaderChecker); }; #endif // TOOLS_GN_HEADER_CHECKER_H_