1 # Copyright (c) 2012 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.
6 """Results object and results formatters for checkdeps tool."""
12 class DependencyViolation(object):
13 """A single dependency violation."""
15 def __init__(self
, include_path
, violated_rule
, rules
):
16 # The include or import path that is in violation of a rule.
17 self
.include_path
= include_path
20 self
.violated_rule
= violated_rule
22 # The set of rules containing self.violated_rule.
26 class DependeeStatus(object):
27 """Results object for a dependee file."""
29 def __init__(self
, dependee_path
):
30 # Path of the file whose nonconforming dependencies are listed in
32 self
.dependee_path
= dependee_path
34 # List of DependencyViolation objects that apply to the dependee
38 def AddViolation(self
, violation
):
39 """Adds a violation."""
40 self
.violations
.append(violation
)
42 def HasViolations(self
):
43 """Returns True if this dependee is violating one or more rules."""
44 return not not self
.violations
47 class ResultsFormatter(object):
48 """Base class for results formatters."""
50 def AddError(self
, dependee_status
):
51 """Add a formatted result to |self.results| for |dependee_status|,
52 which is guaranteed to return True for
53 |dependee_status.HasViolations|.
55 raise NotImplementedError()
58 """Returns the results. May be overridden e.g. to process the
59 results that have been accumulated.
61 raise NotImplementedError()
63 def PrintResults(self
):
64 """Prints the results to stdout."""
65 raise NotImplementedError()
68 class NormalResultsFormatter(ResultsFormatter
):
69 """A results formatting object that produces the classical,
70 detailed, human-readable output of the checkdeps tool.
73 def __init__(self
, verbose
):
75 self
.verbose
= verbose
77 def AddError(self
, dependee_status
):
79 lines
.append('\nERROR in %s' % dependee_status
.dependee_path
)
80 for violation
in dependee_status
.violations
:
81 lines
.append(self
.FormatViolation(violation
, self
.verbose
))
82 self
.results
.append('\n'.join(lines
))
85 def FormatViolation(violation
, verbose
=False):
88 lines
.append(' For %s' % violation
.rules
)
90 ' Illegal include: "%s"\n Because of %s' %
91 (violation
.include_path
, str(violation
.violated_rule
)))
92 return '\n'.join(lines
)
97 def PrintResults(self
):
98 for result
in self
.results
:
104 class JSONResultsFormatter(ResultsFormatter
):
105 """A results formatter that outputs results to a file as JSON."""
107 def __init__(self
, output_path
, wrapped_formatter
=None):
108 self
.output_path
= output_path
109 self
.wrapped_formatter
= wrapped_formatter
113 def AddError(self
, dependee_status
):
114 self
.results
.append({
115 'dependee_path': dependee_status
.dependee_path
,
117 'include_path': violation
.include_path
,
118 'violated_rule': violation
.violated_rule
.AsDependencyTuple(),
119 } for violation
in dependee_status
.violations
]
122 if self
.wrapped_formatter
:
123 self
.wrapped_formatter
.AddError(dependee_status
)
125 def GetResults(self
):
126 with
open(self
.output_path
, 'w') as f
:
127 f
.write(json
.dumps(self
.results
))
131 def PrintResults(self
):
132 if self
.wrapped_formatter
:
133 self
.wrapped_formatter
.PrintResults()
139 class TemporaryRulesFormatter(ResultsFormatter
):
140 """A results formatter that produces a single line per nonconforming
141 include. The combined output is suitable for directly pasting into a
142 DEPS file as a list of temporary-allow rules.
146 self
.violations
= set()
148 def AddError(self
, dependee_status
):
149 for violation
in dependee_status
.violations
:
150 self
.violations
.add(violation
.include_path
)
152 def GetResults(self
):
153 return [' "!%s",' % path
for path
in sorted(self
.violations
)]
155 def PrintResults(self
):
156 for result
in self
.GetResults():
160 class CountViolationsFormatter(ResultsFormatter
):
161 """A results formatter that produces a number, the count of #include
162 statements that are in violation of the dependency rules.
164 Note that you normally want to instantiate DepsChecker with
165 ignore_temp_rules=True when you use this formatter.
171 def AddError(self
, dependee_status
):
172 self
.count
+= len(dependee_status
.violations
)
174 def GetResults(self
):
175 return '%d' % self
.count
177 def PrintResults(self
):