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.
12 from pylib import cmd_helper
13 from pylib import constants
16 def _PrintMessage(warnings, title, action, known_bugs_file):
20 print '%s warnings.' % title
21 print '%s %s' % (action, known_bugs_file)
23 for warning in warnings:
29 def _StripLineNumbers(current_warnings):
30 re_line = r':\[line.*?\]$'
31 return [re.sub(re_line, '', x) for x in current_warnings]
34 def _DiffKnownWarnings(current_warnings_set, known_bugs_file):
35 with open(known_bugs_file, 'r') as known_bugs:
36 known_bugs_set = set(known_bugs.read().splitlines())
38 new_warnings = current_warnings_set - known_bugs_set
39 _PrintMessage(sorted(new_warnings), 'New', 'Please fix, or perhaps add to',
42 obsolete_warnings = known_bugs_set - current_warnings_set
43 _PrintMessage(sorted(obsolete_warnings), 'Obsolete', 'Please remove from',
46 count = len(new_warnings) + len(obsolete_warnings)
48 print '*** %d FindBugs warning%s! ***' % (count, 's' * (count > 1))
50 print '*** %d: new ***' % len(new_warnings)
51 if len(obsolete_warnings):
52 print '*** %d: obsolete ***' % len(obsolete_warnings)
54 print 'Alternatively, rebaseline with --rebaseline command option'
57 print 'No new FindBugs warnings.'
62 def _Rebaseline(current_warnings_set, known_bugs_file):
63 with file(known_bugs_file, 'w') as known_bugs:
64 for warning in sorted(current_warnings_set):
65 print >> known_bugs, warning
69 def _GetChromeClasses(release_version):
73 path = os.path.join(constants.DIR_SOURCE_ROOT, 'out', version)
74 cmd = 'find %s -name "*.class"' % path
75 out = cmd_helper.GetCmdOutput(shlex.split(cmd))
77 print 'No classes found in %s' % path
81 def _Run(exclude, known_bugs, classes_to_analyze, auxiliary_classes,
82 rebaseline, release_version, findbug_args):
86 exclude: the exclude xml file, refer to FindBugs's -exclude command option.
87 known_bugs: the text file of known bugs. The bugs in it will not be
89 classes_to_analyze: the list of classes need to analyze, refer to FindBug's
90 -onlyAnalyze command line option.
91 auxiliary_classes: the classes help to analyze, refer to FindBug's
92 -auxclasspath command line option.
93 rebaseline: True if the known_bugs file needs rebaseline.
94 release_version: True if the release version needs check, otherwise check
96 findbug_args: addtional command line options needs pass to Findbugs.
99 chrome_src = constants.DIR_SOURCE_ROOT
100 sdk_root = constants.ANDROID_SDK_ROOT
101 sdk_version = constants.ANDROID_SDK_VERSION
104 system_classes.append(os.path.join(sdk_root, 'platforms',
105 'android-%s' % sdk_version, 'android.jar'))
106 if auxiliary_classes:
107 for classes in auxiliary_classes:
108 system_classes.append(os.path.abspath(classes))
110 findbugs_javacmd = 'java'
111 findbugs_home = os.path.join(chrome_src, 'third_party', 'findbugs')
112 findbugs_jar = os.path.join(findbugs_home, 'lib', 'findbugs.jar')
113 findbugs_pathsep = ':'
114 findbugs_maxheap = '768'
116 cmd = '%s ' % findbugs_javacmd
117 cmd = '%s -classpath %s%s' % (cmd, findbugs_jar, findbugs_pathsep)
118 cmd = '%s -Xmx%sm ' % (cmd, findbugs_maxheap)
119 cmd = '%s -Dfindbugs.home="%s" ' % (cmd, findbugs_home)
120 cmd = '%s -jar %s ' % (cmd, findbugs_jar)
122 cmd = '%s -textui -sortByClass ' % cmd
123 cmd = '%s -pluginList %s' % (cmd, os.path.join(chrome_src, 'tools', 'android',
124 'findbugs_plugin', 'lib',
125 'chromiumPlugin.jar'))
126 if len(system_classes):
127 cmd = '%s -auxclasspath %s ' % (cmd, ':'.join(system_classes))
129 if classes_to_analyze:
130 cmd = '%s -onlyAnalyze %s ' % (cmd, classes_to_analyze)
133 cmd = '%s -exclude %s ' % (cmd, os.path.abspath(exclude))
136 cmd = '%s %s ' % (cmd, findbug_args)
138 chrome_classes = _GetChromeClasses(release_version)
139 if not chrome_classes:
141 cmd = '%s %s ' % (cmd, chrome_classes)
143 proc = subprocess.Popen(shlex.split(cmd),
144 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
145 out, _err = proc.communicate()
146 current_warnings_set = set(_StripLineNumbers(filter(None, out.splitlines())))
149 return _Rebaseline(current_warnings_set, known_bugs)
151 return _DiffKnownWarnings(current_warnings_set, known_bugs)
155 known_bugs_file = None
158 exclude_file = options.exclude
159 elif options.base_dir:
160 exclude_file = os.path.join(options.base_dir, 'findbugs_exclude.xml')
162 if options.known_bugs:
163 known_bugs_file = options.known_bugs
164 elif options.base_dir:
165 known_bugs_file = os.path.join(options.base_dir, 'findbugs_known_bugs.txt')
168 if options.auxclasspath:
169 auxclasspath = options.auxclasspath.split(':')
170 return _Run(exclude_file, known_bugs_file, options.only_analyze, auxclasspath,
171 options.rebaseline, options.release_build, options.findbug_args)
174 def GetCommonParser():
175 parser = optparse.OptionParser()
176 parser.add_option('-r',
180 help='Rebaseline known findbugs issues.')
182 parser.add_option('-a',
187 help='Set aux classpath for analysis.')
189 parser.add_option('-o',
194 help='Only analyze the given classes and packages.')
196 parser.add_option('-e',
201 help='Exclude bugs matching given filter.')
203 parser.add_option('-k',
208 help='Not report the bugs in the given file.')
210 parser.add_option('-l',
213 dest='release_build',
214 help='Analyze release build instead of debug.')
216 parser.add_option('-f',
221 help='Additional findbug arguments.')
223 parser.add_option('-b',
228 help='Base directory for configuration file.')
234 parser = GetCommonParser()
235 options, _ = parser.parse_args()
240 if __name__ == '__main__':