| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # | 2 # |
| 3 # Copyright (c) 2013 The Chromium Authors. All rights reserved. | 3 # Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
| 6 | 6 |
| 7 """Add all generated lint_result.xml files to suppressions.xml""" | 7 """Add all generated lint_result.xml files to suppressions.xml""" |
| 8 | 8 |
| 9 # pylint: disable=no-member | 9 # pylint: disable=no-member |
| 10 | 10 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 ' globally if it is not applicable to the project.\n' | 36 ' globally if it is not applicable to the project.\n' |
| 37 '- You can also automatically add issues found so for in the\n' | 37 '- You can also automatically add issues found so for in the\n' |
| 38 ' build process by running:\n\n' | 38 ' build process by running:\n\n' |
| 39 ' ' + os.path.relpath(_THIS_FILE, host_paths.DIR_SOURCE_ROOT) + '\n\n' | 39 ' ' + os.path.relpath(_THIS_FILE, host_paths.DIR_SOURCE_ROOT) + '\n\n' |
| 40 ' which will generate this file (Comments are not preserved).\n' | 40 ' which will generate this file (Comments are not preserved).\n' |
| 41 ' Note: PRODUCT_DIR will be substituted at run-time with actual\n' | 41 ' Note: PRODUCT_DIR will be substituted at run-time with actual\n' |
| 42 ' directory path (e.g. out/Debug)\n' | 42 ' directory path (e.g. out/Debug)\n' |
| 43 ) | 43 ) |
| 44 | 44 |
| 45 | 45 |
| 46 _Issue = collections.namedtuple('Issue', ['severity', 'paths']) | 46 _Issue = collections.namedtuple('Issue', ['severity', 'paths', 'regexps']) |
| 47 | 47 |
| 48 | 48 |
| 49 def _ParseConfigFile(config_path): | 49 def _ParseConfigFile(config_path): |
| 50 print 'Parsing %s' % config_path | 50 print 'Parsing %s' % config_path |
| 51 issues_dict = {} | 51 issues_dict = {} |
| 52 dom = minidom.parse(config_path) | 52 dom = minidom.parse(config_path) |
| 53 for issue in dom.getElementsByTagName('issue'): | 53 for issue in dom.getElementsByTagName('issue'): |
| 54 issue_id = issue.attributes['id'].value | 54 issue_id = issue.attributes['id'].value |
| 55 severity = issue.getAttribute('severity') | 55 severity = issue.getAttribute('severity') |
| 56 paths = set( | 56 |
| 57 [p.attributes['path'].value for p in | 57 path_elements = ( |
| 58 issue.getElementsByTagName('ignore')]) | 58 p.attributes.get('path') |
| 59 issues_dict[issue_id] = _Issue(severity, paths) | 59 for p in issue.getElementsByTagName('ignore')) |
| 60 paths = set(p.value for p in path_elements if p) |
| 61 |
| 62 regexp_elements = ( |
| 63 p.attributes.get('regexp') |
| 64 for p in issue.getElementsByTagName('ignore')) |
| 65 regexps = set(r.value for r in regexp_elements if r) |
| 66 |
| 67 issues_dict[issue_id] = _Issue(severity, paths, regexps) |
| 60 return issues_dict | 68 return issues_dict |
| 61 | 69 |
| 62 | 70 |
| 63 def _ParseAndMergeResultFile(result_path, issues_dict): | 71 def _ParseAndMergeResultFile(result_path, issues_dict): |
| 64 print 'Parsing and merging %s' % result_path | 72 print 'Parsing and merging %s' % result_path |
| 65 dom = minidom.parse(result_path) | 73 dom = minidom.parse(result_path) |
| 66 for issue in dom.getElementsByTagName('issue'): | 74 for issue in dom.getElementsByTagName('issue'): |
| 67 issue_id = issue.attributes['id'].value | 75 issue_id = issue.attributes['id'].value |
| 68 severity = issue.attributes['severity'].value | 76 severity = issue.attributes['severity'].value |
| 69 path = issue.getElementsByTagName('location')[0].attributes['file'].value | 77 path = issue.getElementsByTagName('location')[0].attributes['file'].value |
| 70 if issue_id not in issues_dict: | 78 if issue_id not in issues_dict: |
| 71 issues_dict[issue_id] = _Issue(severity, set()) | 79 issues_dict[issue_id] = _Issue(severity, set(), set()) |
| 72 issues_dict[issue_id].paths.add(path) | 80 issues_dict[issue_id].paths.add(path) |
| 73 | 81 |
| 74 | 82 |
| 75 def _WriteConfigFile(config_path, issues_dict): | 83 def _WriteConfigFile(config_path, issues_dict): |
| 76 new_dom = minidom.getDOMImplementation().createDocument(None, 'lint', None) | 84 new_dom = minidom.getDOMImplementation().createDocument(None, 'lint', None) |
| 77 top_element = new_dom.documentElement | 85 top_element = new_dom.documentElement |
| 78 top_element.appendChild(new_dom.createComment(_DOC)) | 86 top_element.appendChild(new_dom.createComment(_DOC)) |
| 79 for issue_id in sorted(issues_dict.keys()): | 87 for issue_id, issue in sorted(issues_dict.iteritems(), key=lambda i: i[0]): |
| 80 severity = issues_dict[issue_id].severity | 88 issue_element = new_dom.createElement('issue') |
| 81 paths = issues_dict[issue_id].paths | 89 issue_element.attributes['id'] = issue_id |
| 82 issue = new_dom.createElement('issue') | 90 if issue.severity: |
| 83 issue.attributes['id'] = issue_id | 91 issue_element.attributes['severity'] = issue.severity |
| 84 if severity: | 92 if issue.severity == 'ignore': |
| 85 issue.attributes['severity'] = severity | |
| 86 if severity == 'ignore': | |
| 87 print 'Warning: [%s] is suppressed globally.' % issue_id | 93 print 'Warning: [%s] is suppressed globally.' % issue_id |
| 88 else: | 94 else: |
| 89 for path in sorted(paths): | 95 for path in sorted(issue.paths): |
| 90 ignore = new_dom.createElement('ignore') | 96 ignore_element = new_dom.createElement('ignore') |
| 91 ignore.attributes['path'] = path | 97 ignore_element.attributes['path'] = path |
| 92 issue.appendChild(ignore) | 98 issue_element.appendChild(ignore_element) |
| 93 top_element.appendChild(issue) | 99 for regexp in sorted(issue.regexps): |
| 100 ignore_element = new_dom.createElement('ignore') |
| 101 ignore_element.attributes['regexp'] = regexp |
| 102 issue_element.appendChild(ignore_element) |
| 103 top_element.appendChild(issue_element) |
| 94 | 104 |
| 95 with open(config_path, 'w') as f: | 105 with open(config_path, 'w') as f: |
| 96 f.write(new_dom.toprettyxml(indent=' ', encoding='utf-8')) | 106 f.write(new_dom.toprettyxml(indent=' ', encoding='utf-8')) |
| 97 print 'Updated %s' % config_path | 107 print 'Updated %s' % config_path |
| 98 | 108 |
| 99 | 109 |
| 100 def _Suppress(config_path, result_path): | 110 def _Suppress(config_path, result_path): |
| 101 issues_dict = _ParseConfigFile(config_path) | 111 issues_dict = _ParseConfigFile(config_path) |
| 102 _ParseAndMergeResultFile(result_path, issues_dict) | 112 _ParseAndMergeResultFile(result_path, issues_dict) |
| 103 _WriteConfigFile(config_path, issues_dict) | 113 _WriteConfigFile(config_path, issues_dict) |
| 104 | 114 |
| 105 | 115 |
| 106 def main(): | 116 def main(): |
| 107 parser = optparse.OptionParser(usage='%prog RESULT-FILE') | 117 parser = optparse.OptionParser(usage='%prog RESULT-FILE') |
| 108 _, args = parser.parse_args() | 118 _, args = parser.parse_args() |
| 109 | 119 |
| 110 if len(args) != 1 or not os.path.exists(args[0]): | 120 if len(args) != 1 or not os.path.exists(args[0]): |
| 111 parser.error('Must provide RESULT-FILE') | 121 parser.error('Must provide RESULT-FILE') |
| 112 | 122 |
| 113 _Suppress(_CONFIG_PATH, args[0]) | 123 _Suppress(_CONFIG_PATH, args[0]) |
| 114 | 124 |
| 115 | 125 |
| 116 if __name__ == '__main__': | 126 if __name__ == '__main__': |
| 117 main() | 127 main() |
| OLD | NEW |