cc: Remove noisy UpdateTiles traces.
[chromium-blink-merge.git] / tools / gn / value_extractors.cc
blob9e6a37edc95c6c27478b0434ddc7f49d6ad9d645
1 // Copyright (c) 2013 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.
5 #include "tools/gn/value_extractors.h"
7 #include "tools/gn/build_settings.h"
8 #include "tools/gn/err.h"
9 #include "tools/gn/label.h"
10 #include "tools/gn/source_dir.h"
11 #include "tools/gn/source_file.h"
12 #include "tools/gn/target.h"
13 #include "tools/gn/value.h"
15 namespace {
17 // Sets the error and returns false on failure.
18 template<typename T, class Converter>
19 bool ListValueExtractor(const Value& value,
20 std::vector<T>* dest,
21 Err* err,
22 const Converter& converter) {
23 if (!value.VerifyTypeIs(Value::LIST, err))
24 return false;
25 const std::vector<Value>& input_list = value.list_value();
26 dest->resize(input_list.size());
27 for (size_t i = 0; i < input_list.size(); i++) {
28 if (!converter(input_list[i], &(*dest)[i], err))
29 return false;
31 return true;
34 // Like the above version but extracts to a UniqueVector and sets the error if
35 // there are duplicates.
36 template<typename T, class Converter>
37 bool ListValueUniqueExtractor(const Value& value,
38 UniqueVector<T>* dest,
39 Err* err,
40 const Converter& converter) {
41 if (!value.VerifyTypeIs(Value::LIST, err))
42 return false;
43 const std::vector<Value>& input_list = value.list_value();
45 for (const auto& item : input_list) {
46 T new_one;
47 if (!converter(item, &new_one, err))
48 return false;
49 if (!dest->push_back(new_one)) {
50 // Already in the list, throw error.
51 *err = Err(item, "Duplicate item in list");
52 size_t previous_index = dest->IndexOf(new_one);
53 err->AppendSubErr(Err(input_list[previous_index],
54 "This was the previous definition."));
55 return false;
58 return true;
61 // This extractor rejects files with system-absolute file paths. If we need
62 // that in the future, we'll have to add some flag to control this.
63 struct RelativeFileConverter {
64 RelativeFileConverter(const BuildSettings* build_settings_in,
65 const SourceDir& current_dir_in)
66 : build_settings(build_settings_in),
67 current_dir(current_dir_in) {
69 bool operator()(const Value& v, SourceFile* out, Err* err) const {
70 if (!v.VerifyTypeIs(Value::STRING, err))
71 return false;
72 *out = current_dir.ResolveRelativeFile(v.string_value(),
73 build_settings->root_path_utf8());
74 if (out->is_system_absolute()) {
75 *err = Err(v, "System-absolute file path.",
76 "You can't list a system-absolute file path here. Please include "
77 "only files in\nthe source tree. Maybe you meant to begin with two "
78 "slashes to indicate an\nabsolute path in the source tree?");
79 return false;
81 return true;
83 const BuildSettings* build_settings;
84 const SourceDir& current_dir;
87 struct RelativeDirConverter {
88 RelativeDirConverter(const BuildSettings* build_settings_in,
89 const SourceDir& current_dir_in)
90 : build_settings(build_settings_in),
91 current_dir(current_dir_in) {
93 bool operator()(const Value& v, SourceDir* out, Err* err) const {
94 if (!v.VerifyTypeIs(Value::STRING, err))
95 return false;
96 *out = current_dir.ResolveRelativeDir(v.string_value(),
97 build_settings->root_path_utf8());
98 return true;
100 const BuildSettings* build_settings;
101 const SourceDir& current_dir;
104 // Fills in a label.
105 template<typename T> struct LabelResolver {
106 LabelResolver(const SourceDir& current_dir_in,
107 const Label& current_toolchain_in)
108 : current_dir(current_dir_in),
109 current_toolchain(current_toolchain_in) {}
110 bool operator()(const Value& v, Label* out, Err* err) const {
111 if (!v.VerifyTypeIs(Value::STRING, err))
112 return false;
113 *out = Label::Resolve(current_dir, current_toolchain, v, err);
114 return !err->has_error();
116 const SourceDir& current_dir;
117 const Label& current_toolchain;
120 // Fills the label part of a LabelPtrPair, leaving the pointer null.
121 template<typename T> struct LabelPtrResolver {
122 LabelPtrResolver(const SourceDir& current_dir_in,
123 const Label& current_toolchain_in)
124 : current_dir(current_dir_in),
125 current_toolchain(current_toolchain_in) {}
126 bool operator()(const Value& v, LabelPtrPair<T>* out, Err* err) const {
127 if (!v.VerifyTypeIs(Value::STRING, err))
128 return false;
129 out->label = Label::Resolve(current_dir, current_toolchain, v, err);
130 out->origin = v.origin();
131 return !err->has_error();
133 const SourceDir& current_dir;
134 const Label& current_toolchain;
137 } // namespace
139 bool ExtractListOfStringValues(const Value& value,
140 std::vector<std::string>* dest,
141 Err* err) {
142 if (!value.VerifyTypeIs(Value::LIST, err))
143 return false;
144 const std::vector<Value>& input_list = value.list_value();
145 dest->reserve(input_list.size());
146 for (const auto& item : input_list) {
147 if (!item.VerifyTypeIs(Value::STRING, err))
148 return false;
149 dest->push_back(item.string_value());
151 return true;
154 bool ExtractListOfRelativeFiles(const BuildSettings* build_settings,
155 const Value& value,
156 const SourceDir& current_dir,
157 std::vector<SourceFile>* files,
158 Err* err) {
159 return ListValueExtractor(value, files, err,
160 RelativeFileConverter(build_settings, current_dir));
163 bool ExtractListOfRelativeDirs(const BuildSettings* build_settings,
164 const Value& value,
165 const SourceDir& current_dir,
166 std::vector<SourceDir>* dest,
167 Err* err) {
168 return ListValueExtractor(value, dest, err,
169 RelativeDirConverter(build_settings, current_dir));
172 bool ExtractListOfLabels(const Value& value,
173 const SourceDir& current_dir,
174 const Label& current_toolchain,
175 LabelTargetVector* dest,
176 Err* err) {
177 return ListValueExtractor(value, dest, err,
178 LabelPtrResolver<Target>(current_dir,
179 current_toolchain));
182 bool ExtractListOfUniqueLabels(const Value& value,
183 const SourceDir& current_dir,
184 const Label& current_toolchain,
185 UniqueVector<Label>* dest,
186 Err* err) {
187 return ListValueUniqueExtractor(value, dest, err,
188 LabelResolver<Config>(current_dir,
189 current_toolchain));
192 bool ExtractListOfUniqueLabels(const Value& value,
193 const SourceDir& current_dir,
194 const Label& current_toolchain,
195 UniqueVector<LabelConfigPair>* dest,
196 Err* err) {
197 return ListValueUniqueExtractor(value, dest, err,
198 LabelPtrResolver<Config>(current_dir,
199 current_toolchain));
202 bool ExtractListOfUniqueLabels(const Value& value,
203 const SourceDir& current_dir,
204 const Label& current_toolchain,
205 UniqueVector<LabelTargetPair>* dest,
206 Err* err) {
207 return ListValueUniqueExtractor(value, dest, err,
208 LabelPtrResolver<Target>(current_dir,
209 current_toolchain));
212 bool ExtractRelativeFile(const BuildSettings* build_settings,
213 const Value& value,
214 const SourceDir& current_dir,
215 SourceFile* file,
216 Err* err) {
217 RelativeFileConverter converter(build_settings, current_dir);
218 return converter(value, file, err);