1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
// 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_
|