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

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

Issue 2341683006: Fix various issues with `gn analyze`. (Closed)
Patch Set: 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();
brettw 2016/09/15 23:22:45 You don't need this, only write the error if it's
Dirk Pranke 2016/09/16 00:11:11 ok.
213 else
214 *err = Err(Location(), "Failed to marshal JSON value for output");
212 return output; 215 return output;
213 } 216 }
214 217
215 } // namespace 218 } // namespace
216 219
217 Analyzer::Analyzer(const Builder& builder) 220 Analyzer::Analyzer(const Builder& builder)
218 : all_targets_(builder.GetAllResolvedTargets()), 221 : all_targets_(builder.GetAllResolvedTargets()),
219 default_toolchain_(builder.loader()->GetDefaultToolchain()) { 222 default_toolchain_(builder.loader()->GetDefaultToolchain()) {
220 for (const auto* target : all_targets_) { 223 for (const auto* target : all_targets_) {
221 labels_to_targets_[target->label()] = target; 224 labels_to_targets_[target->label()] = target;
222 for (const auto& dep_pair : target->GetDeps(Target::DEPS_ALL)) 225 for (const auto& dep_pair : target->GetDeps(Target::DEPS_ALL))
223 dep_map_.insert(std::make_pair(dep_pair.ptr, target)); 226 dep_map_.insert(std::make_pair(dep_pair.ptr, target));
224 } 227 }
225 for (const auto* target : all_targets_) { 228 for (const auto* target : all_targets_) {
226 if (dep_map_.find(target) == dep_map_.end()) 229 if (dep_map_.find(target) == dep_map_.end())
227 roots_.insert(target); 230 roots_.insert(target);
228 } 231 }
229 } 232 }
230 233
231 Analyzer::~Analyzer() {} 234 Analyzer::~Analyzer() {}
232 235
233 std::string Analyzer::Analyze(const std::string& input, Err* err) const { 236 std::string Analyzer::Analyze(const std::string& input, Err* err) const {
234 Inputs inputs; 237 Inputs inputs;
235 Outputs outputs; 238 Outputs outputs;
236 239
237 Err local_err = JSONToInputs(default_toolchain_, input, &inputs); 240 Err local_err = JSONToInputs(default_toolchain_, input, &inputs);
238 if (local_err.has_error()) { 241 if (local_err.has_error()) {
239 outputs.error = local_err.message(); 242 outputs.error = local_err.message();
240 if (err) 243 return OutputsToJSON(outputs, default_toolchain_, err);
241 *err = Err();
242 return "";
243 } 244 }
244 245
245 LabelSet invalid_labels; 246 LabelSet invalid_labels;
246 for (const auto& label : InvalidLabels(inputs.compile_labels)) 247 for (const auto& label : InvalidLabels(inputs.compile_labels))
247 invalid_labels.insert(label); 248 invalid_labels.insert(label);
248 for (const auto& label : InvalidLabels(inputs.test_labels)) 249 for (const auto& label : InvalidLabels(inputs.test_labels))
249 invalid_labels.insert(label); 250 invalid_labels.insert(label);
250 if (!invalid_labels.empty()) { 251 if (!invalid_labels.empty()) {
251 outputs.error = "Invalid targets"; 252 outputs.error = "Invalid targets";
252 outputs.invalid_labels = invalid_labels; 253 outputs.invalid_labels = invalid_labels;
253 if (err) 254 return OutputsToJSON(outputs, default_toolchain_, err);
254 *err = Err();
255 return OutputsToJSON(outputs, default_toolchain_);
256 } 255 }
257 256
258 TargetSet affected_targets = AllAffectedTargets(inputs.source_files); 257 TargetSet affected_targets = AllAffectedTargets(inputs.source_files);
259 if (affected_targets.empty()) { 258 if (affected_targets.empty()) {
260 outputs.status = "No dependency"; 259 outputs.status = "No dependency";
261 if (err) 260 return OutputsToJSON(outputs, default_toolchain_, err);
262 *err = Err();
263 return OutputsToJSON(outputs, default_toolchain_);
264 } 261 }
265 262
266 // TODO: We can do smarter things when we detect changes to build files. 263 // 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 264 // 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 265 // 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 266 // treat a change as simply affecting every target, config, or toolchain
270 // defined in that file. 267 // defined in that file.
271 if (AnyBuildFilesWereModified(inputs.source_files)) { 268 if (AnyBuildFilesWereModified(inputs.source_files)) {
272 outputs.status = "Found dependency (all)"; 269 outputs.status = "Found dependency (all)";
273 outputs.compile_labels = inputs.compile_labels; 270 outputs.compile_labels = inputs.compile_labels;
274 outputs.test_labels = inputs.test_labels; 271 outputs.test_labels = inputs.test_labels;
275 if (err) 272 return OutputsToJSON(outputs, default_toolchain_, err);
276 *err = Err();
277 return OutputsToJSON(outputs, default_toolchain_);
278 } 273 }
279 274
280 TargetSet compile_targets = TargetsFor(inputs.compile_labels); 275 TargetSet compile_targets = TargetsFor(inputs.compile_labels);
281 if (inputs.compile_included_all) { 276 if (inputs.compile_included_all) {
282 for (auto& root : roots_) 277 for (auto& root : roots_)
283 compile_targets.insert(root); 278 compile_targets.insert(root);
284 } 279 }
285 TargetSet filtered_targets = Filter(compile_targets); 280 TargetSet filtered_targets = Filter(compile_targets);
286 outputs.compile_labels = 281 outputs.compile_labels =
287 LabelsFor(Intersect(filtered_targets, affected_targets)); 282 LabelsFor(Intersect(filtered_targets, affected_targets));
288 283
289 TargetSet test_targets = TargetsFor(inputs.test_labels); 284 TargetSet test_targets = TargetsFor(inputs.test_labels);
290 outputs.test_labels = LabelsFor(Intersect(test_targets, affected_targets)); 285 outputs.test_labels = LabelsFor(Intersect(test_targets, affected_targets));
291 286
292 if (outputs.compile_labels.empty() && outputs.test_labels.empty()) 287 if (outputs.compile_labels.empty() && outputs.test_labels.empty())
293 outputs.status = "No dependency"; 288 outputs.status = "No dependency";
294 else 289 else
295 outputs.status = "Found dependency"; 290 outputs.status = "Found dependency";
296 *err = Err(); 291 return OutputsToJSON(outputs, default_toolchain_, err);
297 return OutputsToJSON(outputs, default_toolchain_);
298 } 292 }
299 293
300 TargetSet Analyzer::AllAffectedTargets( 294 TargetSet Analyzer::AllAffectedTargets(
301 const SourceFileSet& source_files) const { 295 const SourceFileSet& source_files) const {
302 TargetSet direct_matches; 296 TargetSet direct_matches;
303 for (const auto& source_file : source_files) 297 for (const auto& source_file : source_files)
304 AddTargetsDirectlyReferringToFileTo(source_file, &direct_matches); 298 AddTargetsDirectlyReferringToFileTo(source_file, &direct_matches);
305 TargetSet all_matches; 299 TargetSet all_matches;
306 for (const auto& match : direct_matches) 300 for (const auto& match : direct_matches)
307 AddAllRefsTo(match, &all_matches); 301 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 { 390 void Analyzer::AddAllRefsTo(const Target* target, TargetSet* results) const {
397 if (results->find(target) != results->end()) 391 if (results->find(target) != results->end())
398 return; // Already found this target. 392 return; // Already found this target.
399 results->insert(target); 393 results->insert(target);
400 394
401 auto dep_begin = dep_map_.lower_bound(target); 395 auto dep_begin = dep_map_.lower_bound(target);
402 auto dep_end = dep_map_.upper_bound(target); 396 auto dep_end = dep_map_.upper_bound(target);
403 for (auto cur_dep = dep_begin; cur_dep != dep_end; cur_dep++) 397 for (auto cur_dep = dep_begin; cur_dep != dep_end; cur_dep++)
404 AddAllRefsTo(cur_dep->second, results); 398 AddAllRefsTo(cur_dep->second, results);
405 } 399 }
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