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
5 # found in the LICENSE file.
7 """Add all generated lint_result.xml files to suppressions.xml"""
9 # pylint: disable=no-member
16 from xml
.dom
import minidom
18 _BUILD_ANDROID_DIR
= os
.path
.join(os
.path
.dirname(__file__
), '..')
19 sys
.path
.append(_BUILD_ANDROID_DIR
)
21 from pylib
import constants
24 _THIS_FILE
= os
.path
.abspath(__file__
)
25 _CONFIG_PATH
= os
.path
.join(os
.path
.dirname(_THIS_FILE
), 'suppressions.xml')
27 '\nSTOP! It looks like you want to suppress some lint errors:\n'
28 '- Have you tried identifing the offending patch?\n'
29 ' Ask the author for a fix and/or revert the patch.\n'
30 '- It is preferred to add suppressions in the code instead of\n'
31 ' sweeping it under the rug here. See:\n\n'
32 ' http://developer.android.com/tools/debugging/improving-w-lint.html\n'
35 '- You can edit this file manually to suppress an issue\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'
38 ' build process by running:\n\n'
39 ' ' + os
.path
.relpath(_THIS_FILE
, constants
.DIR_SOURCE_ROOT
) + '\n\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'
42 ' directory path (e.g. out/Debug)\n'
46 _Issue
= collections
.namedtuple('Issue', ['severity', 'paths'])
49 def _ParseConfigFile(config_path
):
50 print 'Parsing %s' % config_path
52 dom
= minidom
.parse(config_path
)
53 for issue
in dom
.getElementsByTagName('issue'):
54 issue_id
= issue
.attributes
['id'].value
55 severity
= issue
.getAttribute('severity')
57 [p
.attributes
['path'].value
for p
in
58 issue
.getElementsByTagName('ignore')])
59 issues_dict
[issue_id
] = _Issue(severity
, paths
)
63 def _ParseAndMergeResultFile(result_path
, issues_dict
):
64 print 'Parsing and merging %s' % result_path
65 dom
= minidom
.parse(result_path
)
66 for issue
in dom
.getElementsByTagName('issue'):
67 issue_id
= issue
.attributes
['id'].value
68 severity
= issue
.attributes
['severity'].value
69 path
= issue
.getElementsByTagName('location')[0].attributes
['file'].value
70 if issue_id
not in issues_dict
:
71 issues_dict
[issue_id
] = _Issue(severity
, set())
72 issues_dict
[issue_id
].paths
.add(path
)
75 def _WriteConfigFile(config_path
, issues_dict
):
76 new_dom
= minidom
.getDOMImplementation().createDocument(None, 'lint', None)
77 top_element
= new_dom
.documentElement
78 top_element
.appendChild(new_dom
.createComment(_DOC
))
79 for issue_id
in sorted(issues_dict
.keys()):
80 severity
= issues_dict
[issue_id
].severity
81 paths
= issues_dict
[issue_id
].paths
82 issue
= new_dom
.createElement('issue')
83 issue
.attributes
['id'] = issue_id
85 issue
.attributes
['severity'] = severity
86 if severity
== 'ignore':
87 print 'Warning: [%s] is suppressed globally.' % issue_id
89 for path
in sorted(paths
):
90 ignore
= new_dom
.createElement('ignore')
91 ignore
.attributes
['path'] = path
92 issue
.appendChild(ignore
)
93 top_element
.appendChild(issue
)
95 with
open(config_path
, 'w') as f
:
96 f
.write(new_dom
.toprettyxml(indent
=' ', encoding
='utf-8'))
97 print 'Updated %s' % config_path
100 def _Suppress(config_path
, result_path
):
101 issues_dict
= _ParseConfigFile(config_path
)
102 _ParseAndMergeResultFile(result_path
, issues_dict
)
103 _WriteConfigFile(config_path
, issues_dict
)
107 parser
= optparse
.OptionParser(usage
='%prog RESULT-FILE')
108 _
, args
= parser
.parse_args()
110 if len(args
) != 1 or not os
.path
.exists(args
[0]):
111 parser
.error('Must provide RESULT-FILE')
113 _Suppress(_CONFIG_PATH
, args
[0])
116 if __name__
== '__main__':