95 """symbol -> [header relpaths], best candidate first."""
96 index = collections.defaultdict(list)
97 for dirpath, dirnames, filenames
in os.walk(SRC):
98 dirnames[:] = [d
for d
in dirnames
if d
not in (
"external",
"build")]
100 if not fn.endswith((
".h",
".hpp"))
or fn.endswith(
".cmake.h"):
102 full = os.path.join(dirpath, fn)
103 rel = os.path.relpath(full, SRC)
105 with open(full, errors=
"ignore")
as fh:
109 text = COMMENT_LINE.sub(
" ", COMMENT_BLOCK.sub(
" ", text))
110 for line
in text.split(
"\n"):
114 index[m.group(1)].append(rel)
115 m = ENUM_MEMBER.match(line)
117 index[m.group(1)].append(rel)
118 for sym, headers
in index.items():
121 seen = sorted(set(headers), key=
lambda h: (
layer_of(h), h.count(os.sep), len(h)))
174 dry =
"--dry-run" in sys.argv
175 log = sys.stdin.read()
177 wanted = collections.defaultdict(set)
178 for line
in log.split(
"\n"):
179 line = line.replace(REPO +
"/",
"")
181 m = pat.match(line.strip())
183 wanted[m.group(
"file")].add(m.group(
"sym"))
187 print(
"no missing symbols found in the log")
191 unresolved = collections.Counter()
192 for path, syms
in sorted(wanted.items()):
193 if not os.path.exists(path):
195 self_header = os.path.splitext(path)[0] +
".h"
197 for sym
in sorted(syms):
202 cands = index.get(sym)
207 pick = next((c
for c
in cands
208 if os.path.normpath(os.path.join(SRC, c)) != os.path.normpath(self_header)),
212 headers = sorted(set(headers))
216 print(f
"{path}: + {', '.join(headers)}")
220 print(f
"{path}: + {', '.join(added)}")
223 print(
"\nunresolved symbols (no header declares them):", file=sys.stderr)
224 for sym, n
in unresolved.most_common(20):
225 print(f
" {n:3d} {sym}", file=sys.stderr)