Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(569)

Side by Side Diff: tools/gn/analyzer.cc

Issue 2341683006: Fix various issues with `gn analyze`. (Closed)
Patch Set: update docs Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | tools/gn/analyzer_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "tools/gn/analyzer.h" 5 #include "tools/gn/analyzer.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <iterator> 8 #include <iterator>
9 #include <set> 9 #include <set>
10 #include <vector> 10 #include <vector>
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 strings = GetStringVector(*dict, "files", &err); 150 strings = GetStringVector(*dict, "files", &err);
151 if (err.has_error()) 151 if (err.has_error())
152 return err; 152 return err;
153 for (auto s : strings) { 153 for (auto s : strings) {
154 if (!IsPathSourceAbsolute(s) && !IsPathAbsolute(s)) 154 if (!IsPathSourceAbsolute(s) && !IsPathAbsolute(s))
155 return Err(Location(), 155 return Err(Location(),
156 "\"" + s + "\" is not a source-absolute or absolute path."); 156 "\"" + s + "\" is not a source-absolute or absolute path.");
157 inputs->source_vec.push_back(SourceFile(s)); 157 inputs->source_vec.push_back(SourceFile(s));
158 } 158 }
159 159
160 strings = GetStringVector(*dict, "compile_targets", &err); 160 strings = GetStringVector(*dict, "additional_compile_targets", &err);
161 if (err.has_error()) 161 if (err.has_error())
162 return err; 162 return err;
163 163
164 inputs->compile_included_all = false; 164 inputs->compile_included_all = false;
165 for (auto& s : strings) { 165 for (auto& s : strings) {
166 if (s == "all") { 166 if (s == "all") {
167 inputs->compile_included_all = true; 167 inputs->compile_included_all = true;
168 } else { 168 } else {
169 inputs->compile_vec.push_back( 169 inputs->compile_vec.push_back(
170 AbsoluteOrSourceAbsoluteStringToLabel(default_toolchain, s, &err)); 170 AbsoluteOrSourceAbsoluteStringToLabel(default_toolchain, s, &err));
(...skipping 15 matching lines...) Expand all
186 for (auto& s : inputs->source_vec) 186 for (auto& s : inputs->source_vec)
187 inputs->source_files.insert(&s); 187 inputs->source_files.insert(&s);
188 for (auto& l : inputs->compile_vec) 188 for (auto& l : inputs->compile_vec)
189 inputs->compile_labels.insert(l); 189 inputs->compile_labels.insert(l);
190 for (auto& l : inputs->test_vec) 190 for (auto& l : inputs->test_vec)
191 inputs->test_labels.insert(l); 191 inputs->test_labels.insert(l);
192 return Err(); 192 return Err();
193 } 193 }
194 194
195 std::string OutputsToJSON(const Outputs& outputs, 195 std::string OutputsToJSON(const Outputs& outputs,
196 const Label& default_toolchain) { 196 const Label& default_toolchain, Err *err) {
197 std::string output; 197 std::string output;
198 auto value = base::MakeUnique<base::DictionaryValue>(); 198 auto value = base::MakeUnique<base::DictionaryValue>();
199 199
200 if (outputs.error.size()) { 200 if (outputs.error.size()) {
201 WriteString(*value, "error", outputs.error); 201 WriteString(*value, "error", outputs.error);
202 WriteLabels(default_toolchain, *value, "invalid_targets", 202 WriteLabels(default_toolchain, *value, "invalid_targets",
203 outputs.invalid_labels); 203 outputs.invalid_labels);
204 } else { 204 } else {
205 WriteString(*value, "status", outputs.status); 205 WriteString(*value, "status", outputs.status);
206 WriteLabels(default_toolchain, *value, "compile_targets", 206 WriteLabels(default_toolchain, *value, "compile_targets",
207 outputs.compile_labels); 207 outputs.compile_labels);
208 WriteLabels(default_toolchain, *value, "test_targets", outputs.test_labels); 208 WriteLabels(default_toolchain, *value, "test_targets", outputs.test_labels);
209 } 209 }
210 210
211 base::JSONWriter::Write(*value.get(), &output); 211 if (!base::JSONWriter::Write(*value.get(), &output))
212 *err = Err(Location(), "Failed to marshal JSON value for output");
212 return output; 213 return output;
213 } 214 }
214 215
215 } // namespace 216 } // namespace
216 217
217 Analyzer::Analyzer(const Builder& builder) 218 Analyzer::Analyzer(const Builder& builder)
218 : all_targets_(builder.GetAllResolvedTargets()), 219 : all_targets_(builder.GetAllResolvedTargets()),
219 default_toolchain_(builder.loader()->GetDefaultToolchain()) { 220 default_toolchain_(builder.loader()->GetDefaultToolchain()) {
220 for (const auto* target : all_targets_) { 221 for (const auto* target : all_targets_) {
221 labels_to_targets_[target->label()] = target; 222 labels_to_targets_[target->label()] = target;
222 for (const auto& dep_pair : target->GetDeps(Target::DEPS_ALL)) 223 for (const auto& dep_pair : target->GetDeps(Target::DEPS_ALL))
223 dep_map_.insert(std::make_pair(dep_pair.ptr, target)); 224 dep_map_.insert(std::make_pair(dep_pair.ptr, target));
224 } 225 }
225 for (const auto* target : all_targets_) { 226 for (const auto* target : all_targets_) {
226 if (dep_map_.find(target) == dep_map_.end()) 227 if (dep_map_.find(target) == dep_map_.end())
227 roots_.insert(target); 228 roots_.insert(target);
228 } 229 }
229 } 230 }
230 231
231 Analyzer::~Analyzer() {} 232 Analyzer::~Analyzer() {}
232 233
233 std::string Analyzer::Analyze(const std::string& input, Err* err) const { 234 std::string Analyzer::Analyze(const std::string& input, Err* err) const {
234 Inputs inputs; 235 Inputs inputs;
235 Outputs outputs; 236 Outputs outputs;
236 237
237 Err local_err = JSONToInputs(default_toolchain_, input, &inputs); 238 Err local_err = JSONToInputs(default_toolchain_, input, &inputs);
238 if (local_err.has_error()) { 239 if (local_err.has_error()) {
239 outputs.error = local_err.message(); 240 outputs.error = local_err.message();
240 if (err) 241 return OutputsToJSON(outputs, default_toolchain_, err);
241 *err = Err();
242 return "";
243 } 242 }
244 243
245 LabelSet invalid_labels; 244 LabelSet invalid_labels;
246 for (const auto& label : InvalidLabels(inputs.compile_labels)) 245 for (const auto& label : InvalidLabels(inputs.compile_labels))
247 invalid_labels.insert(label); 246 invalid_labels.insert(label);
248 for (const auto& label : InvalidLabels(inputs.test_labels)) 247 for (const auto& label : InvalidLabels(inputs.test_labels))
249 invalid_labels.insert(label); 248 invalid_labels.insert(label);
250 if (!invalid_labels.empty()) { 249 if (!invalid_labels.empty()) {
251 outputs.error = "Invalid targets"; 250 outputs.error = "Invalid targets";
252 outputs.invalid_labels = invalid_labels; 251 outputs.invalid_labels = invalid_labels;
253 if (err) 252 return OutputsToJSON(outputs, default_toolchain_, err);
254 *err = Err();
255 return OutputsToJSON(outputs, default_toolchain_);
256 } 253 }
257 254
258 TargetSet affected_targets = AllAffectedTargets(inputs.source_files); 255 TargetSet affected_targets = AllAffectedTargets(inputs.source_files);
259 if (affected_targets.empty()) { 256 if (affected_targets.empty()) {
260 outputs.status = "No dependency"; 257 outputs.status = "No dependency";
261 if (err) 258 return OutputsToJSON(outputs, default_toolchain_, err);
262 *err = Err();
263 return OutputsToJSON(outputs, default_toolchain_);
264 } 259 }
265 260
266 // TODO: We can do smarter things when we detect changes to build files. 261 // TODO: We can do smarter things when we detect changes to build files.
267 // For example, if all of the ninja files are unchanged, we know that we 262 // For example, if all of the ninja files are unchanged, we know that we
268 // can ignore changes to these files. Also, for most .gn files, we can 263 // can ignore changes to these files. Also, for most .gn files, we can
269 // treat a change as simply affecting every target, config, or toolchain 264 // treat a change as simply affecting every target, config, or toolchain
270 // defined in that file. 265 // defined in that file.
271 if (AnyBuildFilesWereModified(inputs.source_files)) { 266 if (AnyBuildFilesWereModified(inputs.source_files)) {
272 outputs.status = "Found dependency (all)"; 267 outputs.status = "Found dependency (all)";
273 outputs.compile_labels = inputs.compile_labels; 268 outputs.compile_labels = inputs.compile_labels;
274 outputs.test_labels = inputs.test_labels; 269 outputs.test_labels = inputs.test_labels;
275 if (err) 270 return OutputsToJSON(outputs, default_toolchain_, err);
276 *err = Err();
277 return OutputsToJSON(outputs, default_toolchain_);
278 } 271 }
279 272
280 TargetSet compile_targets = TargetsFor(inputs.compile_labels); 273 TargetSet compile_targets = TargetsFor(inputs.compile_labels);
281 if (inputs.compile_included_all) { 274 if (inputs.compile_included_all) {
282 for (auto& root : roots_) 275 for (auto& root : roots_)
283 compile_targets.insert(root); 276 compile_targets.insert(root);
284 } 277 }
285 TargetSet filtered_targets = Filter(compile_targets); 278 TargetSet filtered_targets = Filter(compile_targets);
286 outputs.compile_labels = 279 outputs.compile_labels =
287 LabelsFor(Intersect(filtered_targets, affected_targets)); 280 LabelsFor(Intersect(filtered_targets, affected_targets));
288 281
289 TargetSet test_targets = TargetsFor(inputs.test_labels); 282 TargetSet test_targets = TargetsFor(inputs.test_labels);
290 outputs.test_labels = LabelsFor(Intersect(test_targets, affected_targets)); 283 outputs.test_labels = LabelsFor(Intersect(test_targets, affected_targets));
291 284
292 if (outputs.compile_labels.empty() && outputs.test_labels.empty()) 285 if (outputs.compile_labels.empty() && outputs.test_labels.empty())
293 outputs.status = "No dependency"; 286 outputs.status = "No dependency";
294 else 287 else
295 outputs.status = "Found dependency"; 288 outputs.status = "Found dependency";
296 *err = Err(); 289 return OutputsToJSON(outputs, default_toolchain_, err);
297 return OutputsToJSON(outputs, default_toolchain_);
298 } 290 }
299 291
300 TargetSet Analyzer::AllAffectedTargets( 292 TargetSet Analyzer::AllAffectedTargets(
301 const SourceFileSet& source_files) const { 293 const SourceFileSet& source_files) const {
302 TargetSet direct_matches; 294 TargetSet direct_matches;
303 for (const auto& source_file : source_files) 295 for (const auto& source_file : source_files)
304 AddTargetsDirectlyReferringToFileTo(source_file, &direct_matches); 296 AddTargetsDirectlyReferringToFileTo(source_file, &direct_matches);
305 TargetSet all_matches; 297 TargetSet all_matches;
306 for (const auto& match : direct_matches) 298 for (const auto& match : direct_matches)
307 AddAllRefsTo(match, &all_matches); 299 AddAllRefsTo(match, &all_matches);
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
396 void Analyzer::AddAllRefsTo(const Target* target, TargetSet* results) const { 388 void Analyzer::AddAllRefsTo(const Target* target, TargetSet* results) const {
397 if (results->find(target) != results->end()) 389 if (results->find(target) != results->end())
398 return; // Already found this target. 390 return; // Already found this target.
399 results->insert(target); 391 results->insert(target);
400 392
401 auto dep_begin = dep_map_.lower_bound(target); 393 auto dep_begin = dep_map_.lower_bound(target);
402 auto dep_end = dep_map_.upper_bound(target); 394 auto dep_end = dep_map_.upper_bound(target);
403 for (auto cur_dep = dep_begin; cur_dep != dep_end; cur_dep++) 395 for (auto cur_dep = dep_begin; cur_dep != dep_end; cur_dep++)
404 AddAllRefsTo(cur_dep->second, results); 396 AddAllRefsTo(cur_dep->second, results);
405 } 397 }
OLDNEW
« no previous file with comments | « no previous file | tools/gn/analyzer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698