26 prefix =
'GRPC_' if not fpath.startswith(
'include/')
else ''
27 return prefix +
'_'.join(
28 fpath.replace(
'++',
'XX').replace(
'.',
'_').upper().
split(
'/')[1:])
32 with open(fpath,
'r')
as f:
37 with open(fpath,
'w')
as f:
44 self.
ifndef_re = re.compile(
r'#ifndef ([A-Z][A-Z_1-9]*)')
45 self.
define_re = re.compile(
r'#define ([A-Z][A-Z_1-9]*)')
47 r'#endif /\* (?: *\\\n *)?([A-Z][A-Z_1-9]*) (?:\\\n *)?\*/$')
48 self.
endif_re = re.compile(
r'#endif // ([A-Z][A-Z_1-9]*)')
50 r'^((//.*?$|/\*.*?\*/|[ \r\n\t])*)(([ \r\n\t]|#include .*)*)(#ifndef [^\n]*\n#define [^\n]*\n)',
51 re.DOTALL | re.MULTILINE)
55 return 'include' in fpath
and not (
'grpc++' in fpath
or 'grpcpp'
56 in fpath
or 'event_engine' in fpath)
58 def fail(self, fpath, regexp, fcontents, match_txt, correct, fix):
61 invalid_guards_msg_template = (
62 '{0}: Missing preprocessor guards (RE {1}). '
63 'Please wrap your code around the following guards:\n'
68 '...\n') + (
'#endif /* {2} */'
69 if c_core_header
else '#endif // {2}')
72 (invalid_guards_msg_template.format(fpath, regexp.pattern,
76 print(((
'{}: Wrong preprocessor guards (RE {}):'
77 '\n\tFound {}, expected {}').
format(fpath, regexp.pattern,
80 print((
'Fixing {}...\n'.
format(fpath)))
81 fixed_fcontents = re.sub(match_txt, correct, fcontents)
84 return fixed_fcontents
93 fcontents =
load(fpath)
97 print((
'something drastically wrong with: %s' % fpath))
99 if match.lastindex
is None:
101 self.
fail(fpath, match.re, match.string,
'',
'',
False)
105 running_guard = match.group(1)
106 if not running_guard.endswith(
'_H'):
107 fcontents = self.
fail(fpath, match.re, match.string, match.group(1),
110 save(fpath, fcontents)
113 if running_guard != valid_guard:
114 fcontents = self.
fail(fpath, match.re, match.string, match.group(1),
117 save(fpath, fcontents)
121 if match.lastindex
is None:
123 self.
fail(fpath, match.re, match.string,
'',
'',
False)
127 if match.group(1) != running_guard:
128 fcontents = self.
fail(fpath, match.re, match.string, match.group(1),
131 save(fpath, fcontents)
134 flines = fcontents.rstrip().splitlines()
136 if not match
and not c_core_header:
141 if flines[-1] ==
'#endif':
144 (
' /* {} */\n'.
format(valid_guard)
145 if c_core_header
else ' // {}\n'.
format(valid_guard)))
147 fcontents =
'\n'.join(flines)
148 save(fpath, fcontents)
154 flines[-1],
'',
'',
False)
155 elif match.group(1) != running_guard:
158 match.group(1), valid_guard, fix)
160 save(fpath, fcontents)
164 bad_includes = match.group(3)
167 "includes after initial comments but before include guards in",
170 fcontents = fcontents[:match.start(3)] + match.group(
171 5) + match.group(3) + fcontents[match.end(5):]
172 save(fpath, fcontents)
178 ROOT = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]),
'../..'))
182 argp = argparse.ArgumentParser(description=
'include guard checker')
183 argp.add_argument(
'-f',
'--fix', default=
False, action=
'store_true')
184 argp.add_argument(
'--precommit', default=
False, action=
'store_true')
185 args = argp.parse_args()
187 grep_filter =
r"grep -E '^(include|src/core)/.*\.h$'"
189 git_command =
'git diff --name-only HEAD'
191 git_command =
'git ls-tree -r --name-only -r HEAD'
193 FILE_LIST_COMMAND =
' | '.join((git_command, grep_filter))
199 filename_list = subprocess.check_output(FILE_LIST_COMMAND,
200 shell=
True).
decode().splitlines()
202 filename_list = (f
for f
in filename_list
if os.path.isfile(f))
203 except subprocess.CalledProcessError:
208 for filename
in filename_list:
210 if (filename.endswith(
'.upb.h')
or filename.endswith(
'.upb.c')
or
211 filename.endswith(
'.upbdefs.h')
or filename.endswith(
'.upbdefs.c')):
213 ok = ok
and validator.check(filename, args.fix)
215 sys.exit(0
if ok
else 1)