1cb93a386Sopenharmony_ci# Copyright (c) 2012 The Chromium Authors. All rights reserved. 2cb93a386Sopenharmony_ci# Use of this source code is governed by a BSD-style license that can be 3cb93a386Sopenharmony_ci# found in the LICENSE file. 4cb93a386Sopenharmony_ci 5cb93a386Sopenharmony_ci"""Results object and results formatters for checkdeps tool.""" 6cb93a386Sopenharmony_ci 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci 9cb93a386Sopenharmony_ciimport json 10cb93a386Sopenharmony_ci 11cb93a386Sopenharmony_ci 12cb93a386Sopenharmony_ciclass DependencyViolation(object): 13cb93a386Sopenharmony_ci """A single dependency violation.""" 14cb93a386Sopenharmony_ci 15cb93a386Sopenharmony_ci def __init__(self, include_path, violated_rule, rules): 16cb93a386Sopenharmony_ci # The include or import path that is in violation of a rule. 17cb93a386Sopenharmony_ci self.include_path = include_path 18cb93a386Sopenharmony_ci 19cb93a386Sopenharmony_ci # The violated rule. 20cb93a386Sopenharmony_ci self.violated_rule = violated_rule 21cb93a386Sopenharmony_ci 22cb93a386Sopenharmony_ci # The set of rules containing self.violated_rule. 23cb93a386Sopenharmony_ci self.rules = rules 24cb93a386Sopenharmony_ci 25cb93a386Sopenharmony_ci 26cb93a386Sopenharmony_ciclass DependeeStatus(object): 27cb93a386Sopenharmony_ci """Results object for a dependee file.""" 28cb93a386Sopenharmony_ci 29cb93a386Sopenharmony_ci def __init__(self, dependee_path): 30cb93a386Sopenharmony_ci # Path of the file whose nonconforming dependencies are listed in 31cb93a386Sopenharmony_ci # self.violations. 32cb93a386Sopenharmony_ci self.dependee_path = dependee_path 33cb93a386Sopenharmony_ci 34cb93a386Sopenharmony_ci # List of DependencyViolation objects that apply to the dependee 35cb93a386Sopenharmony_ci # file. May be empty. 36cb93a386Sopenharmony_ci self.violations = [] 37cb93a386Sopenharmony_ci 38cb93a386Sopenharmony_ci def AddViolation(self, violation): 39cb93a386Sopenharmony_ci """Adds a violation.""" 40cb93a386Sopenharmony_ci self.violations.append(violation) 41cb93a386Sopenharmony_ci 42cb93a386Sopenharmony_ci def HasViolations(self): 43cb93a386Sopenharmony_ci """Returns True if this dependee is violating one or more rules.""" 44cb93a386Sopenharmony_ci return not not self.violations 45cb93a386Sopenharmony_ci 46cb93a386Sopenharmony_ci 47cb93a386Sopenharmony_ciclass ResultsFormatter(object): 48cb93a386Sopenharmony_ci """Base class for results formatters.""" 49cb93a386Sopenharmony_ci 50cb93a386Sopenharmony_ci def AddError(self, dependee_status): 51cb93a386Sopenharmony_ci """Add a formatted result to |self.results| for |dependee_status|, 52cb93a386Sopenharmony_ci which is guaranteed to return True for 53cb93a386Sopenharmony_ci |dependee_status.HasViolations|. 54cb93a386Sopenharmony_ci """ 55cb93a386Sopenharmony_ci raise NotImplementedError() 56cb93a386Sopenharmony_ci 57cb93a386Sopenharmony_ci def GetResults(self): 58cb93a386Sopenharmony_ci """Returns the results. May be overridden e.g. to process the 59cb93a386Sopenharmony_ci results that have been accumulated. 60cb93a386Sopenharmony_ci """ 61cb93a386Sopenharmony_ci raise NotImplementedError() 62cb93a386Sopenharmony_ci 63cb93a386Sopenharmony_ci def PrintResults(self): 64cb93a386Sopenharmony_ci """Prints the results to stdout.""" 65cb93a386Sopenharmony_ci raise NotImplementedError() 66cb93a386Sopenharmony_ci 67cb93a386Sopenharmony_ci 68cb93a386Sopenharmony_ciclass NormalResultsFormatter(ResultsFormatter): 69cb93a386Sopenharmony_ci """A results formatting object that produces the classical, 70cb93a386Sopenharmony_ci detailed, human-readable output of the checkdeps tool. 71cb93a386Sopenharmony_ci """ 72cb93a386Sopenharmony_ci 73cb93a386Sopenharmony_ci def __init__(self, verbose): 74cb93a386Sopenharmony_ci self.results = [] 75cb93a386Sopenharmony_ci self.verbose = verbose 76cb93a386Sopenharmony_ci 77cb93a386Sopenharmony_ci def AddError(self, dependee_status): 78cb93a386Sopenharmony_ci lines = [] 79cb93a386Sopenharmony_ci lines.append('\nERROR in %s' % dependee_status.dependee_path) 80cb93a386Sopenharmony_ci for violation in dependee_status.violations: 81cb93a386Sopenharmony_ci lines.append(self.FormatViolation(violation, self.verbose)) 82cb93a386Sopenharmony_ci self.results.append('\n'.join(lines)) 83cb93a386Sopenharmony_ci 84cb93a386Sopenharmony_ci @staticmethod 85cb93a386Sopenharmony_ci def FormatViolation(violation, verbose=False): 86cb93a386Sopenharmony_ci lines = [] 87cb93a386Sopenharmony_ci if verbose: 88cb93a386Sopenharmony_ci lines.append(' For %s' % violation.rules) 89cb93a386Sopenharmony_ci lines.append( 90cb93a386Sopenharmony_ci ' Illegal include: "%s"\n Because of %s' % 91cb93a386Sopenharmony_ci (violation.include_path, str(violation.violated_rule))) 92cb93a386Sopenharmony_ci return '\n'.join(lines) 93cb93a386Sopenharmony_ci 94cb93a386Sopenharmony_ci def GetResults(self): 95cb93a386Sopenharmony_ci return self.results 96cb93a386Sopenharmony_ci 97cb93a386Sopenharmony_ci def PrintResults(self): 98cb93a386Sopenharmony_ci for result in self.results: 99cb93a386Sopenharmony_ci print(result) 100cb93a386Sopenharmony_ci if self.results: 101cb93a386Sopenharmony_ci print('\nFAILED\n') 102cb93a386Sopenharmony_ci 103cb93a386Sopenharmony_ci 104cb93a386Sopenharmony_ciclass JSONResultsFormatter(ResultsFormatter): 105cb93a386Sopenharmony_ci """A results formatter that outputs results to a file as JSON.""" 106cb93a386Sopenharmony_ci 107cb93a386Sopenharmony_ci def __init__(self, output_path, wrapped_formatter=None): 108cb93a386Sopenharmony_ci self.output_path = output_path 109cb93a386Sopenharmony_ci self.wrapped_formatter = wrapped_formatter 110cb93a386Sopenharmony_ci 111cb93a386Sopenharmony_ci self.results = [] 112cb93a386Sopenharmony_ci 113cb93a386Sopenharmony_ci def AddError(self, dependee_status): 114cb93a386Sopenharmony_ci self.results.append({ 115cb93a386Sopenharmony_ci 'dependee_path': dependee_status.dependee_path, 116cb93a386Sopenharmony_ci 'violations': [{ 117cb93a386Sopenharmony_ci 'include_path': violation.include_path, 118cb93a386Sopenharmony_ci 'violated_rule': violation.violated_rule.AsDependencyTuple(), 119cb93a386Sopenharmony_ci } for violation in dependee_status.violations] 120cb93a386Sopenharmony_ci }) 121cb93a386Sopenharmony_ci 122cb93a386Sopenharmony_ci if self.wrapped_formatter: 123cb93a386Sopenharmony_ci self.wrapped_formatter.AddError(dependee_status) 124cb93a386Sopenharmony_ci 125cb93a386Sopenharmony_ci def GetResults(self): 126cb93a386Sopenharmony_ci with open(self.output_path, 'w') as f: 127cb93a386Sopenharmony_ci f.write(json.dumps(self.results)) 128cb93a386Sopenharmony_ci 129cb93a386Sopenharmony_ci return self.results 130cb93a386Sopenharmony_ci 131cb93a386Sopenharmony_ci def PrintResults(self): 132cb93a386Sopenharmony_ci if self.wrapped_formatter: 133cb93a386Sopenharmony_ci self.wrapped_formatter.PrintResults() 134cb93a386Sopenharmony_ci return 135cb93a386Sopenharmony_ci 136cb93a386Sopenharmony_ci print(self.results) 137cb93a386Sopenharmony_ci 138cb93a386Sopenharmony_ci 139cb93a386Sopenharmony_ciclass TemporaryRulesFormatter(ResultsFormatter): 140cb93a386Sopenharmony_ci """A results formatter that produces a single line per nonconforming 141cb93a386Sopenharmony_ci include. The combined output is suitable for directly pasting into a 142cb93a386Sopenharmony_ci DEPS file as a list of temporary-allow rules. 143cb93a386Sopenharmony_ci """ 144cb93a386Sopenharmony_ci 145cb93a386Sopenharmony_ci def __init__(self): 146cb93a386Sopenharmony_ci self.violations = set() 147cb93a386Sopenharmony_ci 148cb93a386Sopenharmony_ci def AddError(self, dependee_status): 149cb93a386Sopenharmony_ci for violation in dependee_status.violations: 150cb93a386Sopenharmony_ci self.violations.add(violation.include_path) 151cb93a386Sopenharmony_ci 152cb93a386Sopenharmony_ci def GetResults(self): 153cb93a386Sopenharmony_ci return [' "!%s",' % path for path in sorted(self.violations)] 154cb93a386Sopenharmony_ci 155cb93a386Sopenharmony_ci def PrintResults(self): 156cb93a386Sopenharmony_ci for result in self.GetResults(): 157cb93a386Sopenharmony_ci print(result) 158cb93a386Sopenharmony_ci 159cb93a386Sopenharmony_ci 160cb93a386Sopenharmony_ciclass CountViolationsFormatter(ResultsFormatter): 161cb93a386Sopenharmony_ci """A results formatter that produces a number, the count of #include 162cb93a386Sopenharmony_ci statements that are in violation of the dependency rules. 163cb93a386Sopenharmony_ci 164cb93a386Sopenharmony_ci Note that you normally want to instantiate DepsChecker with 165cb93a386Sopenharmony_ci ignore_temp_rules=True when you use this formatter. 166cb93a386Sopenharmony_ci """ 167cb93a386Sopenharmony_ci 168cb93a386Sopenharmony_ci def __init__(self): 169cb93a386Sopenharmony_ci self.count = 0 170cb93a386Sopenharmony_ci 171cb93a386Sopenharmony_ci def AddError(self, dependee_status): 172cb93a386Sopenharmony_ci self.count += len(dependee_status.violations) 173cb93a386Sopenharmony_ci 174cb93a386Sopenharmony_ci def GetResults(self): 175cb93a386Sopenharmony_ci return '%d' % self.count 176cb93a386Sopenharmony_ci 177cb93a386Sopenharmony_ci def PrintResults(self): 178cb93a386Sopenharmony_ci print(self.count) 179