Home | History | Annotate | Download | only in checkdeps
      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.
      4 
      5 
      6 """Results object and results formatters for checkdeps tool."""
      7 
      8 
      9 class DependencyViolation(object):
     10   """A single dependency violation."""
     11 
     12   def __init__(self, include_path, violated_rule, rules):
     13     # The include or import path that is in violation of a rule.
     14     self.include_path = include_path
     15 
     16     # The violated rule.
     17     self.violated_rule = violated_rule
     18 
     19     # The set of rules containing self.violated_rule.
     20     self.rules = rules
     21 
     22 
     23 class DependeeStatus(object):
     24   """Results object for a dependee file."""
     25 
     26   def __init__(self, dependee_path):
     27     # Path of the file whose nonconforming dependencies are listed in
     28     # self.violations.
     29     self.dependee_path = dependee_path
     30 
     31     # List of DependencyViolation objects that apply to the dependee
     32     # file.  May be empty.
     33     self.violations = []
     34 
     35   def AddViolation(self, violation):
     36     """Adds a violation."""
     37     self.violations.append(violation)
     38 
     39   def HasViolations(self):
     40     """Returns True if this dependee is violating one or more rules."""
     41     return not not self.violations
     42 
     43 
     44 class ResultsFormatter(object):
     45   """Base class for results formatters."""
     46 
     47   def AddError(self, dependee_status):
     48     """Add a formatted result to |self.results| for |dependee_status|,
     49     which is guaranteed to return True for
     50     |dependee_status.HasViolations|.
     51     """
     52     raise NotImplementedError()
     53 
     54   def GetResults(self):
     55     """Returns the results.  May be overridden e.g. to process the
     56     results that have been accumulated.
     57     """
     58     raise NotImplementedError()
     59 
     60   def PrintResults(self):
     61     """Prints the results to stdout."""
     62     raise NotImplementedError()
     63 
     64 
     65 class NormalResultsFormatter(ResultsFormatter):
     66   """A results formatting object that produces the classical,
     67   detailed, human-readable output of the checkdeps tool.
     68   """
     69 
     70   def __init__(self, verbose):
     71     self.results = []
     72     self.verbose = verbose
     73 
     74   def AddError(self, dependee_status):
     75     lines = []
     76     lines.append('\nERROR in %s' % dependee_status.dependee_path)
     77     for violation in dependee_status.violations:
     78       lines.append(self.FormatViolation(violation, self.verbose))
     79     self.results.append('\n'.join(lines))
     80 
     81   @staticmethod
     82   def FormatViolation(violation, verbose=False):
     83     lines = []
     84     if verbose:
     85       lines.append('  For %s' % violation.rules)
     86     lines.append(
     87         '  Illegal include: "%s"\n    Because of %s' %
     88         (violation.include_path, str(violation.violated_rule)))
     89     return '\n'.join(lines)
     90 
     91   def GetResults(self):
     92     return self.results
     93 
     94   def PrintResults(self):
     95     for result in self.results:
     96       print result
     97     if self.results:
     98       print '\nFAILED\n'
     99 
    100 
    101 class TemporaryRulesFormatter(ResultsFormatter):
    102   """A results formatter that produces a single line per nonconforming
    103   include. The combined output is suitable for directly pasting into a
    104   DEPS file as a list of temporary-allow rules.
    105   """
    106 
    107   def __init__(self):
    108     self.violations = set()
    109 
    110   def AddError(self, dependee_status):
    111     for violation in dependee_status.violations:
    112       self.violations.add(violation.include_path)
    113 
    114   def GetResults(self):
    115     return ['  "!%s",' % path for path in sorted(self.violations)]
    116 
    117   def PrintResults(self):
    118     for result in self.GetResults():
    119       print result
    120 
    121 
    122 class CountViolationsFormatter(ResultsFormatter):
    123   """A results formatter that produces a number, the count of #include
    124   statements that are in violation of the dependency rules.
    125 
    126   Note that you normally want to instantiate DepsChecker with
    127   ignore_temp_rules=True when you use this formatter.
    128   """
    129 
    130   def __init__(self):
    131     self.count = 0
    132 
    133   def AddError(self, dependee_status):
    134     self.count += len(dependee_status.violations)
    135 
    136   def GetResults(self):
    137     return '%d' % self.count
    138 
    139   def PrintResults(self):
    140     print self.count
    141