Deleted Added
sdiff udiff text old ( 10692:ab81a0feab55 ) new ( 11319:7ca84595249c )
full compact
1#! /usr/bin/env python
2# Copyright (c) 2014 ARM Limited
3# All rights reserved
4#
5# The license below extends only to copyright in the software and shall
6# not be construed as granting a license to any other intellectual
7# property including but not limited to intellectual property relating
8# to a hardware implementation of the functionality of the software
9# licensed hereunder. You may use the software subject to the license
10# terms below provided that you ensure that this notice is replicated
11# unmodified and in its entirety in all distributions of the software,
12# modified or unmodified, in source code or in binary form.
13#
14# Copyright (c) 2006 The Regents of The University of Michigan
15# Copyright (c) 2007,2011 The Hewlett-Packard Development Company
16# Copyright (c) 2016 Advanced Micro Devices, Inc.
17# All rights reserved.
18#
19# Redistribution and use in source and binary forms, with or without
20# modification, are permitted provided that the following conditions are
21# met: redistributions of source code must retain the above copyright
22# notice, this list of conditions and the following disclaimer;
23# redistributions in binary form must reproduce the above copyright
24# notice, this list of conditions and the following disclaimer in the

--- 10 unchanged lines hidden (view full) ---

35# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
36# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
40# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41#
42# Authors: Nathan Binkert
43# Steve Reinhardt
44
45import heapq
46import os
47import re
48import sys
49
50from os.path import dirname, join as joinpath
51from itertools import count

--- 7 unchanged lines hidden (view full) ---

59import sort_includes
60from file_types import lang_type
61
62all_regions = Regions(Region(neg_inf, pos_inf))
63
64tabsize = 8
65lead = re.compile(r'^([ \t]+)')
66trail = re.compile(r'([ \t]+)$')
67any_control = re.compile(r'\b(if|while|for)([ \t]*)\(')
68
69format_types = set(('C', 'C++'))
70
71
72def re_ignore(expr):
73 """Helper function to create regular expression ignore file
74 matcher functions"""
75

--- 73 unchanged lines hidden (view full) ---

149
150class StdioUI(UserInterface):
151 def do_prompt(self, prompt, results, default):
152 return raw_input(prompt) or default
153
154 def write(self, string):
155 sys.stdout.write(string)
156
157
158class Verifier(object):
159 """Base class for style verifier objects
160
161 Subclasses must define these class attributes:
162 languages = set of strings identifying applicable languages
163 test_name = long descriptive name of test, will be used in
164 messages such as "error in <foo>" or "invalid <foo>"
165 opt_name = short name used to generate command-line options to
166 control the test (--fix-<foo>, --ignore-<foo>, etc.)
167 """
168
169 def __init__(self, ui, repo, opts):
170 self.ui = ui
171 self.repo = repo
172 # opt_name must be defined as a class attribute of derived classes.
173 # Check test-specific opts first as these have precedence.
174 self.opt_fix = opts.get('fix_' + self.opt_name, False)
175 self.opt_ignore = opts.get('ignore_' + self.opt_name, False)
176 self.opt_skip = opts.get('skip_' + self.opt_name, False)
177 # If no test-specific opts were set, then set based on "-all" opts.
178 if not (self.opt_fix or self.opt_ignore or self.opt_skip):
179 self.opt_fix = opts.get('fix_all', False)
180 self.opt_ignore = opts.get('ignore_all', False)
181 self.opt_skip = opts.get('skip_all', False)
182
183 def __getattr__(self, attr):
184 if attr in ('prompt', 'write'):
185 return getattr(self.ui, attr)
186
187 if attr == 'wctx':
188 try:
189 wctx = repo.workingctx()

--- 24 unchanged lines hidden (view full) ---

214 # the gem5 directory, it will be checked as a file, so symlink can be
215 # skipped. If the location is a file outside gem5, we don't want to
216 # check it anyway.
217 if os.path.islink(filename):
218 return True
219 return lang_type(filename) not in self.languages
220
221 def check(self, filename, regions=all_regions):
222 """Check specified regions of file 'filename'.
223
224 Line-by-line checks can simply provide a check_line() method
225 that returns True if the line is OK and False if it has an
226 error. Verifiers that need a multi-line view (like
227 SortedIncludes) must override this entire function.
228
229 Returns a count of errors (0 if none), though actual non-zero
230 count value is not currently used anywhere.
231 """
232
233 f = self.open(filename, 'r')
234
235 errors = 0
236 for num,line in enumerate(f):
237 if num not in regions:
238 continue
239 if not self.check_line(line):
240 self.write("invalid %s in %s:%d\n" % \
241 (self.test_name, filename, num + 1))
242 if self.ui.verbose:
243 self.write(">>%s<<\n" % line[:-1])
244 errors += 1
245 return errors
246
247 def fix(self, filename, regions=all_regions):
248 """Fix specified regions of file 'filename'.
249
250 Line-by-line fixes can simply provide a fix_line() method that
251 returns the fixed line. Verifiers that need a multi-line view
252 (like SortedIncludes) must override this entire function.
253 """
254
255 f = self.open(filename, 'r+')
256
257 lines = list(f)
258
259 f.seek(0)
260 f.truncate()
261
262 for i,line in enumerate(lines):
263 if i in regions:
264 line = self.fix_line(line)
265
266 f.write(line)
267 f.close()
268
269
270 def apply(self, filename, regions=all_regions):
271 """Possibly apply to specified regions of file 'filename'.
272
273 Verifier is skipped if --skip-<test> option was provided or if
274 file is not of an applicable type. Otherwise file is checked
275 and error messages printed. Errors are fixed or ignored if
276 the corresponding --fix-<test> or --ignore-<test> options were
277 provided. If neither, the user is prompted for an action.
278
279 Returns True to abort, False otherwise.
280 """
281 if not (self.opt_skip or self.skip(filename)):
282 errors = self.check(filename, regions)
283 if errors and not self.opt_ignore:
284 if self.opt_fix:
285 self.fix(filename, regions)
286 else:
287 result = self.ui.prompt("(a)bort, (i)gnore, or (f)ix?",
288 'aif', 'a')
289 if result == 'f':
290 self.fix(filename, regions)
291 elif result == 'a':
292 return True # abort
293
294 return False
295
296
297class Whitespace(Verifier):
298 """Check whitespace.
299
300 Specifically:
301 - No tabs used for indent
302 - No trailing whitespace
303 """
304
305 languages = set(('C', 'C++', 'swig', 'python', 'asm', 'isa', 'scons'))
306 test_name = 'whitespace'
307 opt_name = 'white'
308
309 def check_line(self, line):
310 match = lead.search(line)
311 if match and match.group(1).find('\t') != -1:
312 return False
313
314 match = trail.search(line)
315 if match:
316 return False

--- 11 unchanged lines hidden (view full) ---

328 else:
329 newline += line[i:]
330 break
331
332 line = newline
333
334 return line.rstrip() + '\n'
335
336
337class ControlSpace(Verifier):
338 """Check for exactly one space after if/while/for"""
339
340 languages = set(('C', 'C++'))
341 test_name = 'spacing after if/while/for'
342 opt_name = 'control'
343
344 def check_line(self, line):
345 match = any_control.search(line)
346 return not (match and match.group(2) != " ")
347
348 def fix_line(self, line):
349 new_line = any_control.sub(r'\1 (', line)
350 return new_line
351
352
353class SortedIncludes(Verifier):
354 """Check for proper sorting of include statements"""
355
356 languages = sort_includes.default_languages
357 test_name = 'include file order'
358 opt_name = 'include'
359
360 def __init__(self, *args, **kwargs):
361 super(SortedIncludes, self).__init__(*args, **kwargs)
362 self.sort_includes = sort_includes.SortIncludes()
363
364 def check(self, filename, regions=all_regions):
365 f = self.open(filename, 'r')
366
367 lines = [ l.rstrip('\n') for l in f.xreadlines() ]

--- 31 unchanged lines hidden (view full) ---

399 f.seek(0)
400 f.truncate()
401
402 for i,line in enumerate(sort_lines):
403 f.write(line)
404 f.write('\n')
405 f.close()
406
407# list of all verifier classes
408all_verifiers = [
409 Whitespace,
410 ControlSpace,
411 SortedIncludes
412]
413
414def linelen(line):
415 tabs = line.count('\t')
416 if not tabs:
417 return len(line)
418
419 count = 0
420 for c in line:
421 if c == '\t':

--- 81 unchanged lines hidden (view full) ---

503 stats.trailwhite +=1
504 if verbose > 1:
505 msg(i, line, 'trailing whitespace')
506 bad()
507
508 # for c++, exactly one space betwen if/while/for and (
509 if lang == 'C++':
510 match = any_control.search(line)
511 if match and match.group(2) != " ":
512 stats.badcontrol += 1
513 if verbose > 1:
514 msg(i, line, 'improper spacing after %s' % match.group(1))
515 bad()
516
517
518def _modified_regions(repo, patterns, **kwargs):
519 opt_all = kwargs.get('all', False)

--- 36 unchanged lines hidden (view full) ---

556 coding style violations. A list of files can be specified to limit
557 the checker to a subset of the repository. The style rules are
558 normally applied on a diff of the repository state (i.e., added
559 files are checked in their entirety while only modifications of
560 modified files are checked).
561
562 The --all option can be specified to include clean files and check
563 modified files in their entirety.
564
565 The --fix-<check>, --ignore-<check>, and --skip-<check> options
566 can be used to control individual style checks:
567
568 --fix-<check> will perform the check and automatically attempt to
569 fix sny style error (printing a warning if unsuccessful)
570
571 --ignore-<check> will perform the check but ignore any errors
572 found (other than printing a message for each)
573
574 --skip-<check> will skip performing the check entirely
575
576 If none of these options are given, all checks will be performed
577 and the user will be prompted on how to handle each error.
578
579 --fix-all, --ignore-all, and --skip-all are equivalent to specifying
580 --fix-<check>, --ignore-<check>, or --skip-<check> for all checks,
581 respectively. However, option settings for specific checks take
582 precedence. Thus --skip-all --fix-white can be used to skip every
583 check other than whitespace errors, which will be checked and
584 automatically fixed.
585
586 The -v/--verbose flag will display the offending line(s) as well
587 as their location.
588 """
589
590 ui = MercurialUI(hgui, verbose=hgui.verbose)
591
592 # instantiate varifier objects
593 verifiers = [v(ui, repo, opts) for v in all_verifiers]
594
595 for fname, mod_regions in _modified_regions(repo, pats, **opts):
596 for verifier in verifiers:
597 if verifier.apply(fname, mod_regions):
598 return True
599
600 return False
601
602def do_check_format(hgui, repo, *pats, **opts):
603 """check files for gem5 code formatting violations
604
605 Without an argument, checks all modified and added files for gem5
606 code formatting violations. A list of files can be specified to
607 limit the checker to a subset of the repository. The style rules

--- 20 unchanged lines hidden (view full) ---

628
629 return False
630
631def check_hook(hooktype):
632 if hooktype not in ('pretxncommit', 'pre-qrefresh'):
633 raise AttributeError, \
634 "This hook is not meant for %s" % hooktype
635
636# This function provides a hook that is called before transaction
637# commit and on qrefresh
638def check_style(ui, repo, hooktype, **kwargs):
639 check_hook(hooktype)
640 args = {}
641
642 try:
643 return do_check_style(ui, repo, **args)
644 except Exception, e:
645 import traceback

--- 18 unchanged lines hidden (view full) ---

664 return arg
665
666_common_region_options = [
667 ('a', 'all', False,
668 _("include clean files and unmodified parts of modified files")),
669 ('', 'no-ignore', False, _("ignore the style ignore list")),
670 ]
671
672
673fix_opts = [('f', 'fix-all', False, _("fix all style errors"))] + \
674 [('', 'fix-' + v.opt_name, False,
675 _('fix errors in ' + v.test_name)) for v in all_verifiers]
676ignore_opts = [('', 'ignore-all', False, _("ignore all style errors"))] + \
677 [('', 'ignore-' + v.opt_name, False,
678 _('ignore errors in ' + v.test_name)) for v in all_verifiers]
679skip_opts = [('', 'skip-all', False, _("skip all style error checks"))] + \
680 [('', 'skip-' + v.opt_name, False,
681 _('skip checking for ' + v.test_name)) for v in all_verifiers]
682all_opts = fix_opts + ignore_opts + skip_opts
683
684
685cmdtable = {
686 '^m5style' : (
687 do_check_style, all_opts + _common_region_options + commands.walkopts,
688 _('hg m5style [-a] [FILE]...')),
689 '^m5format' :
690 ( do_check_format, [
691 ] + _common_region_options + commands.walkopts,
692 _('hg m5format [FILE]...')),
693}
694
695if __name__ == '__main__':

--- 53 unchanged lines hidden ---