| Index: tools/checkdeps/results.py
|
| diff --git a/tools/checkdeps/results.py b/tools/checkdeps/results.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..b52880ccca3259408aa699ee8a05292105779bae
|
| --- /dev/null
|
| +++ b/tools/checkdeps/results.py
|
| @@ -0,0 +1,178 @@
|
| +# Copyright (c) 2012 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.
|
| +
|
| +
|
| +"""Results object and results formatters for checkdeps tool."""
|
| +
|
| +
|
| +import json
|
| +
|
| +
|
| +class DependencyViolation(object):
|
| + """A single dependency violation."""
|
| +
|
| + def __init__(self, include_path, violated_rule, rules):
|
| + # The include or import path that is in violation of a rule.
|
| + self.include_path = include_path
|
| +
|
| + # The violated rule.
|
| + self.violated_rule = violated_rule
|
| +
|
| + # The set of rules containing self.violated_rule.
|
| + self.rules = rules
|
| +
|
| +
|
| +class DependeeStatus(object):
|
| + """Results object for a dependee file."""
|
| +
|
| + def __init__(self, dependee_path):
|
| + # Path of the file whose nonconforming dependencies are listed in
|
| + # self.violations.
|
| + self.dependee_path = dependee_path
|
| +
|
| + # List of DependencyViolation objects that apply to the dependee
|
| + # file. May be empty.
|
| + self.violations = []
|
| +
|
| + def AddViolation(self, violation):
|
| + """Adds a violation."""
|
| + self.violations.append(violation)
|
| +
|
| + def HasViolations(self):
|
| + """Returns True if this dependee is violating one or more rules."""
|
| + return not not self.violations
|
| +
|
| +
|
| +class ResultsFormatter(object):
|
| + """Base class for results formatters."""
|
| +
|
| + def AddError(self, dependee_status):
|
| + """Add a formatted result to |self.results| for |dependee_status|,
|
| + which is guaranteed to return True for
|
| + |dependee_status.HasViolations|.
|
| + """
|
| + raise NotImplementedError()
|
| +
|
| + def GetResults(self):
|
| + """Returns the results. May be overridden e.g. to process the
|
| + results that have been accumulated.
|
| + """
|
| + raise NotImplementedError()
|
| +
|
| + def PrintResults(self):
|
| + """Prints the results to stdout."""
|
| + raise NotImplementedError()
|
| +
|
| +
|
| +class NormalResultsFormatter(ResultsFormatter):
|
| + """A results formatting object that produces the classical,
|
| + detailed, human-readable output of the checkdeps tool.
|
| + """
|
| +
|
| + def __init__(self, verbose):
|
| + self.results = []
|
| + self.verbose = verbose
|
| +
|
| + def AddError(self, dependee_status):
|
| + lines = []
|
| + lines.append('\nERROR in %s' % dependee_status.dependee_path)
|
| + for violation in dependee_status.violations:
|
| + lines.append(self.FormatViolation(violation, self.verbose))
|
| + self.results.append('\n'.join(lines))
|
| +
|
| + @staticmethod
|
| + def FormatViolation(violation, verbose=False):
|
| + lines = []
|
| + if verbose:
|
| + lines.append(' For %s' % violation.rules)
|
| + lines.append(
|
| + ' Illegal include: "%s"\n Because of %s' %
|
| + (violation.include_path, str(violation.violated_rule)))
|
| + return '\n'.join(lines)
|
| +
|
| + def GetResults(self):
|
| + return self.results
|
| +
|
| + def PrintResults(self):
|
| + for result in self.results:
|
| + print result
|
| + if self.results:
|
| + print '\nFAILED\n'
|
| +
|
| +
|
| +class JSONResultsFormatter(ResultsFormatter):
|
| + """A results formatter that outputs results to a file as JSON."""
|
| +
|
| + def __init__(self, output_path, wrapped_formatter=None):
|
| + self.output_path = output_path
|
| + self.wrapped_formatter = wrapped_formatter
|
| +
|
| + self.results = []
|
| +
|
| + def AddError(self, dependee_status):
|
| + self.results.append({
|
| + 'dependee_path': dependee_status.dependee_path,
|
| + 'violations': [{
|
| + 'include_path': violation.include_path,
|
| + 'violated_rule': violation.violated_rule.AsDependencyTuple(),
|
| + } for violation in dependee_status.violations]
|
| + })
|
| +
|
| + if self.wrapped_formatter:
|
| + self.wrapped_formatter.AddError(dependee_status)
|
| +
|
| + def GetResults(self):
|
| + with open(self.output_path, 'w') as f:
|
| + f.write(json.dumps(self.results))
|
| +
|
| + return self.results
|
| +
|
| + def PrintResults(self):
|
| + if self.wrapped_formatter:
|
| + self.wrapped_formatter.PrintResults()
|
| + return
|
| +
|
| + print self.results
|
| +
|
| +
|
| +class TemporaryRulesFormatter(ResultsFormatter):
|
| + """A results formatter that produces a single line per nonconforming
|
| + include. The combined output is suitable for directly pasting into a
|
| + DEPS file as a list of temporary-allow rules.
|
| + """
|
| +
|
| + def __init__(self):
|
| + self.violations = set()
|
| +
|
| + def AddError(self, dependee_status):
|
| + for violation in dependee_status.violations:
|
| + self.violations.add(violation.include_path)
|
| +
|
| + def GetResults(self):
|
| + return [' "!%s",' % path for path in sorted(self.violations)]
|
| +
|
| + def PrintResults(self):
|
| + for result in self.GetResults():
|
| + print result
|
| +
|
| +
|
| +class CountViolationsFormatter(ResultsFormatter):
|
| + """A results formatter that produces a number, the count of #include
|
| + statements that are in violation of the dependency rules.
|
| +
|
| + Note that you normally want to instantiate DepsChecker with
|
| + ignore_temp_rules=True when you use this formatter.
|
| + """
|
| +
|
| + def __init__(self):
|
| + self.count = 0
|
| +
|
| + def AddError(self, dependee_status):
|
| + self.count += len(dependee_status.violations)
|
| +
|
| + def GetResults(self):
|
| + return '%d' % self.count
|
| +
|
| + def PrintResults(self):
|
| + print self.count
|
|
|