Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:10:43

0001 #!/usr/bin/env python3
0002 import argparse
0003 import os
0004 from glob import glob
0005 import re
0006 from fnmatch import fnmatch
0007 import sys
0008 
0009 
0010 def line_fmt(line):
0011     return "{: >4d} ".format(line)
0012 
0013 
0014 def code_print(code, start, maxlines=15):
0015     lines = code.split("\n")
0016     nlines = len(lines)
0017 
0018     lines = [line_fmt(i + start) + l for i, l in enumerate(lines)]
0019 
0020     nlup = int(maxlines / 2)
0021     nllo = maxlines - nlup - 1
0022 
0023     if nlines > maxlines:
0024         lines = lines[:nlup] + [" " * 5 + "// ..."] + lines[-nllo:]
0025 
0026     return "\n".join(lines)
0027 
0028 
0029 def check_include_guards(file):
0030     with open(file) as f:
0031         text = f.read()
0032 
0033     match_local = list(
0034         re.finditer(
0035             r"(#ifndef [A-Za-z0-9_]*\n#define [A-Za-z0-9_]*.*)\n((:?.|\n)+?)#endif",
0036             text,
0037         )
0038     )
0039     match_global = re.search(
0040         r"#ifndef (.*)\n#define \1.*\n[\s\S]+#endif[A-Za-z0-9\-_/* ]*$", text
0041     )
0042 
0043     valid_global = True
0044     valid_local = True
0045     errbuf = ""
0046 
0047     if match_global is not None and len(match_local) <= 1:
0048         valid_global = False
0049 
0050         errbuf += "This looks like a file-spanning include guard\n"
0051         errbuf += "This is discouraged as per [ACTS-450]"
0052         errbuf += "(https://its.cern.ch/jira/browse/ACTS-450)" + "\n" * 2
0053 
0054         start = text[: match_global.start()].count("\n") + 1
0055         errbuf += code_print(match_global.group(0), start)
0056         errbuf += "\n" * 2
0057 
0058     if valid_global or len(match_local) > 1:
0059         for m in match_local:
0060             lineno = text[: m.start()].count("\n") + 1
0061 
0062             valid_local = False
0063             errbuf += "This looks like a local #ifndef / include-guard\n"
0064             errbuf += "This is discouraged as per [ACTS-450]"
0065             errbuf += "(https://its.cern.ch/jira/browse/ACTS-450)" + "\n" * 2
0066             errbuf += code_print(m.group(0), lineno)
0067             errbuf += "\n" * 2
0068 
0069     return valid_local, valid_global, errbuf
0070 
0071 
0072 def main():
0073     p = argparse.ArgumentParser()
0074 
0075     input_help = """
0076 Input files: either file path, dir path (will glob for headers) or custom glob pattern
0077     """
0078     p.add_argument("input", nargs="+", help=input_help.strip())
0079     p.add_argument(
0080         "--fail-local", "-l", action="store_true", help="Fail on local include guards"
0081     )
0082     p.add_argument(
0083         "--fail-global", "-g", action="store_true", help="Fail on global include guards"
0084     )
0085     p.add_argument("--quiet-local", "-ql", action="store_true")
0086     p.add_argument("--quiet-global", "-qg", action="store_true")
0087     p.add_argument("--exclude", "-e", action="append", default=[])
0088 
0089     args = p.parse_args()
0090 
0091     headers = []
0092 
0093     if len(args.input) == 1:
0094         if os.path.isdir(args.input[0]):
0095             patterns = ["**/*.hpp", "**/*.h"]
0096             headers = sum(
0097                 [
0098                     glob(os.path.join(args.input[0], p), recursive=True)
0099                     for p in patterns
0100                 ],
0101                 [],
0102             )
0103         else:
0104             headers = glob(args.input[0], recursive=True)
0105     elif all([os.path.isfile(i) for i in args.input]):
0106         headers = args.input
0107 
0108     valid = True
0109     nlocal = 0
0110     nglobal = 0
0111 
0112     for h in headers:
0113         if any([fnmatch(h, e) for e in args.exclude]):
0114             continue
0115         valid_local, valid_global, errbuf = check_include_guards(h)
0116 
0117         if not valid_local:
0118             nlocal += 1
0119             if args.fail_local:
0120                 valid = False
0121         if not valid_global:
0122             nglobal += 1
0123             if args.fail_global:
0124                 valid = False
0125 
0126         if not valid_local or not valid_global:
0127             head = "Issue(s) in file {}:\n".format(h)
0128             print("-" * len(head))
0129             print(head)
0130             print(errbuf)
0131             print("\n")
0132 
0133     print("=" * 40)
0134     print("Checked {} files".format(len(headers)))
0135     print("Issues found in {} files".format(nlocal + nglobal))
0136     print("{} files have local include guards".format(nlocal))
0137     print("{} files have global include guards".format(nglobal))
0138 
0139     if valid:
0140         sys.exit(0)
0141     else:
0142         sys.exit(1)
0143 
0144 
0145 if "__main__" == __name__:
0146     main()