15a16
> # Copyright (c) 2016 Advanced Micro Devices, Inc.
41a43
> # Steve Reinhardt
65,66c67
< any_control = re.compile(r'\b(if|while|for)[ \t]*[(]')
< good_control = re.compile(r'\b(if|while|for) [(]')
---
> any_control = re.compile(r'\b(if|while|for)([ \t]*)\(')
155a157
>
157c159,169
< def __init__(self, ui, repo):
---
> """Base class for style verifier objects
>
> Subclasses must define these class attributes:
> languages = set of strings identifying applicable languages
> test_name = long descriptive name of test, will be used in
> messages such as "error in <foo>" or "invalid <foo>"
> opt_name = short name used to generate command-line options to
> control the test (--fix-<foo>, --ignore-<foo>, etc.)
> """
>
> def __init__(self, ui, repo, opts):
159a172,181
> # opt_name must be defined as a class attribute of derived classes.
> # Check test-specific opts first as these have precedence.
> self.opt_fix = opts.get('fix_' + self.opt_name, False)
> self.opt_ignore = opts.get('ignore_' + self.opt_name, False)
> self.opt_skip = opts.get('skip_' + self.opt_name, False)
> # If no test-specific opts were set, then set based on "-all" opts.
> if not (self.opt_fix or self.opt_ignore or self.opt_skip):
> self.opt_fix = opts.get('fix_all', False)
> self.opt_ignore = opts.get('ignore_all', False)
> self.opt_skip = opts.get('skip_all', False)
199a222,232
> """Check specified regions of file 'filename'.
>
> Line-by-line checks can simply provide a check_line() method
> that returns True if the line is OK and False if it has an
> error. Verifiers that need a multi-line view (like
> SortedIncludes) must override this entire function.
>
> Returns a count of errors (0 if none), though actual non-zero
> count value is not currently used anywhere.
> """
>
208c241
< (self.test_name, filename, num + 1))
---
> (self.test_name, filename, num + 1))
210c243
< self.write(">>%s<<\n" % line[-1])
---
> self.write(">>%s<<\n" % line[:-1])
214a248,254
> """Fix specified regions of file 'filename'.
>
> Line-by-line fixes can simply provide a fix_line() method that
> returns the fixed line. Verifiers that need a multi-line view
> (like SortedIncludes) must override this entire function.
> """
>
229,230c269,281
< def apply(self, filename, prompt, regions=all_regions):
< if not self.skip(filename):
---
>
> def apply(self, filename, regions=all_regions):
> """Possibly apply to specified regions of file 'filename'.
>
> Verifier is skipped if --skip-<test> option was provided or if
> file is not of an applicable type. Otherwise file is checked
> and error messages printed. Errors are fixed or ignored if
> the corresponding --fix-<test> or --ignore-<test> options were
> provided. If neither, the user is prompted for an action.
>
> Returns True to abort, False otherwise.
> """
> if not (self.opt_skip or self.skip(filename)):
232,234c283,293
< if errors:
< if prompt(filename, self.fix, regions):
< return True
---
> if errors and not self.opt_ignore:
> if self.opt_fix:
> self.fix(filename, regions)
> else:
> result = self.ui.prompt("(a)bort, (i)gnore, or (f)ix?",
> 'aif', 'a')
> if result == 'f':
> self.fix(filename, regions)
> elif result == 'a':
> return True # abort
>
238a298,304
> """Check whitespace.
>
> Specifically:
> - No tabs used for indent
> - No trailing whitespace
> """
>
240a307,308
> opt_name = 'white'
>
267a336,352
>
> class ControlSpace(Verifier):
> """Check for exactly one space after if/while/for"""
>
> languages = set(('C', 'C++'))
> test_name = 'spacing after if/while/for'
> opt_name = 'control'
>
> def check_line(self, line):
> match = any_control.search(line)
> return not (match and match.group(2) != " ")
>
> def fix_line(self, line):
> new_line = any_control.sub(r'\1 (', line)
> return new_line
>
>
268a354,355
> """Check for proper sorting of include statements"""
>
269a357,359
> test_name = 'include file order'
> opt_name = 'include'
>
316a407,413
> # list of all verifier classes
> all_verifiers = [
> Whitespace,
> ControlSpace,
> SortedIncludes
> ]
>
414c511
< if match and not good_control.search(line):
---
> if match and match.group(2) != " ":
467,474d563
< """
< opt_fix_all = opts.get('fix_all', False)
< if not opt_fix_all:
< opt_fix_white = opts.get('fix_white', False)
< opt_fix_include = opts.get('fix_include', False)
< else:
< opt_fix_white = True
< opt_fix_include = True
476c565,566
< ui = MercurialUI(hgui, verbose=hgui.verbose)
---
> The --fix-<check>, --ignore-<check>, and --skip-<check> options
> can be used to control individual style checks:
478,483c568,569
< def prompt(name, func, regions=all_regions):
< result = ui.prompt("(a)bort, (i)gnore, or (f)ix?", 'aif', 'a')
< if result == 'a':
< return True
< elif result == 'f':
< func(name, regions)
---
> --fix-<check> will perform the check and automatically attempt to
> fix sny style error (printing a warning if unsuccessful)
485c571,572
< return False
---
> --ignore-<check> will perform the check but ignore any errors
> found (other than printing a message for each)
487,489c574
< def no_prompt(name, func, regions=all_regions):
< func(name, regions)
< return False
---
> --skip-<check> will skip performing the check entirely
491,492c576,577
< prompt_white = prompt if not opt_fix_white else no_prompt
< prompt_include = prompt if not opt_fix_include else no_prompt
---
> If none of these options are given, all checks will be performed
> and the user will be prompted on how to handle each error.
494,498c579,584
< whitespace = Whitespace(ui, repo)
< sorted_includes = SortedIncludes(ui, repo)
< for fname, mod_regions in _modified_regions(repo, pats, **opts):
< if whitespace.apply(fname, prompt_white, mod_regions):
< return True
---
> --fix-all, --ignore-all, and --skip-all are equivalent to specifying
> --fix-<check>, --ignore-<check>, or --skip-<check> for all checks,
> respectively. However, option settings for specific checks take
> precedence. Thus --skip-all --fix-white can be used to skip every
> check other than whitespace errors, which will be checked and
> automatically fixed.
500,501c586,588
< if sorted_includes.apply(fname, prompt_include, mod_regions):
< return True
---
> The -v/--verbose flag will display the offending line(s) as well
> as their location.
> """
502a590,599
> ui = MercurialUI(hgui, verbose=hgui.verbose)
>
> # instantiate varifier objects
> verifiers = [v(ui, repo, opts) for v in all_verifiers]
>
> for fname, mod_regions in _modified_regions(repo, pats, **opts):
> for verifier in verifiers:
> if verifier.apply(fname, mod_regions):
> return True
>
538a636,637
> # This function provides a hook that is called before transaction
> # commit and on qrefresh
572a672,684
>
> fix_opts = [('f', 'fix-all', False, _("fix all style errors"))] + \
> [('', 'fix-' + v.opt_name, False,
> _('fix errors in ' + v.test_name)) for v in all_verifiers]
> ignore_opts = [('', 'ignore-all', False, _("ignore all style errors"))] + \
> [('', 'ignore-' + v.opt_name, False,
> _('ignore errors in ' + v.test_name)) for v in all_verifiers]
> skip_opts = [('', 'skip-all', False, _("skip all style error checks"))] + \
> [('', 'skip-' + v.opt_name, False,
> _('skip checking for ' + v.test_name)) for v in all_verifiers]
> all_opts = fix_opts + ignore_opts + skip_opts
>
>
575,579c687
< do_check_style, [
< ('f', 'fix-all', False, _("automatically fix style issues")),
< ('', 'fix-white', False, _("automatically fix white space issues")),
< ('', 'fix-include', False, _("automatically fix include ordering")),
< ] + _common_region_options + commands.walkopts,
---
> do_check_style, all_opts + _common_region_options + commands.walkopts,