2 from __future__
import print_function
7 from concurrent.futures
import ProcessPoolExecutor
9 from fnmatch
import fnmatch
14 return "{: >4d} ".format(line)
17 lines = code.split(
"\n")
20 lines = [
line_fmt(i+start) + l
for i, l
in enumerate(lines)]
22 nlup =
int(maxlines/2)
23 nllo = maxlines - nlup - 1
26 lines = lines[:nlup] + [
" "*5 +
"// ..."] + lines[-nllo:]
28 return "\n".join(lines)
34 match_local = list(re.finditer(
r"(#ifndef [A-Za-z0-9_]*\n#define [A-Za-z0-9_]*.*)\n((:?.|\n)+?)#endif", text))
35 match_global = re.search(
r"#ifndef (.*)\n#define \1.*\n[\s\S]+#endif[A-Za-z0-9\-_/* ]*$", text)
41 if match_global
is not None and len(match_local) <= 1:
44 errbuf +=
"This looks like a file-spanning include guard\n"
45 errbuf +=
"This is discouraged as per [ACTS-450]"
46 errbuf +=
"(https://its.cern.ch/jira/browse/ACTS-450)" +
"\n"*2
48 start = text[:match_global.start()].count(
"\n")+1
49 errbuf +=
code_print(match_global.group(0), start)
52 if valid_global
or len(match_local) > 1:
55 lineno = text[:m.start()].count(
"\n") + 1
58 errbuf +=
"This looks like a local #ifndef / include-guard\n"
59 errbuf +=
"This is discouraged as per [ACTS-450]"
60 errbuf +=
"(https://its.cern.ch/jira/browse/ACTS-450)" +
"\n"*2
67 return valid_local, valid_global, errbuf
70 p = argparse.ArgumentParser()
73 Input files: either file path, dir path (will glob for headers) or custom glob pattern
75 p.add_argument(
"input", help=input_help.strip())
76 p.add_argument(
"--fail-local",
"-l", action=
"store_true", help=
"Fail on local include guards")
77 p.add_argument(
"--fail-global",
"-g", action=
"store_true", help=
"Fail on global include guards")
78 p.add_argument(
"--quiet-local",
"-ql", action=
"store_true")
79 p.add_argument(
"--quiet-global",
"-qg", action=
"store_true")
80 p.add_argument(
"--exclude",
"-e", action=
"append", default=[])
86 if os.path.isfile(args.input):
87 headers = [args.input]
88 elif os.path.isdir(args.input):
89 patterns = [
"**/*.hpp",
"**/*.h"]
90 headers =
sum([glob(os.path.join(args.input, p), recursive=
True)
for p
in patterns], [])
92 headers = glob(args.input, recursive=
True)
99 if any([fnmatch(h, e)
for e
in args.exclude]):
112 if not valid_local
or not valid_global:
113 head =
"Issue(s) in file {}:\n".format(h)
121 print(
"Checked {} files".format(len(headers)))
122 print(
"Issues found in {} files".format(nlocal+nglobal))
123 print(
"{} files have local include guards".format(nlocal))
124 print(
"{} files have global include guards".format(nglobal))
132 if "__main__" == __name__: