181 args = [a
for a
in sys.argv[1:]
if not a.startswith(
"--")]
185 as_json =
"--json" in sys.argv
187 if "--only" in sys.argv:
188 only = sys.argv[sys.argv.index(
"--only") + 1]
190 header = os.path.join(SRC, rel)
191 if not os.path.isfile(header):
192 sys.exit(f
"error: no such header: {header}")
199 supplier.setdefault(sym, os.path.relpath(dep, SRC))
201 basename = os.path.basename(rel)
204 include_re = re.compile(
205 r'^\s*#\s*include\s+["<](?:.*/)?' + re.escape(basename) +
r'[">]', re.M)
209 if os.path.samefile(path, header):
212 if not include_re.search(raw):
215 words = set(re.findall(
r"\b[A-Za-z_]\w*\b", body))
222 for line
in include_re.sub(
" ", raw).split(
"\n"):
223 m = INCLUDE.match(line)
226 target =
resolve(m.group(1), os.path.dirname(path))
230 already = {os.path.relpath(h, SRC)
for h
in already}
232 used_own = sorted(own & words)
233 used_via = collections.defaultdict(list)
234 for sym
in words & supplier.keys():
235 if supplier[sym]
in already:
237 used_via[supplier[sym]].append(sym)
239 kind =
"own" if used_own
else (
"via" if used_via
else "unused")
241 "file": os.path.relpath(path, REPO),
243 "own_symbols": used_own,
244 "via": {k: sorted(v)
for k, v
in sorted(used_via.items())},
248 rows = [r
for r
in rows
if r[
"kind"] == only]
251 print(json.dumps(rows, indent=2))
254 counts = collections.Counter(r[
"kind"]
for r
in rows)
255 print(f
"{len(rows)} file(s) include {rel}: "
256 f
"{counts['own']} use its own symbols, {counts['via']} only pull others through it, "
257 f
"{counts['unused']} use nothing\n")
262 demand = collections.Counter()
264 demand.update(r[
"own_symbols"])
265 print(f
"--- own symbols in demand ({len(demand)} of {len(own)} declared) ---")
266 for sym, n
in demand.most_common():
267 print(f
" {n:4d} {sym}")
268 unwanted = sorted(own - set(demand))
269 print(f
"\n--- declared but used by no includer ({len(unwanted)}) ---")
270 print(
" " +
", ".join(unwanted)
if unwanted
else " (none)")
272 print(f
"\n--- files that only pull other headers through it ({counts['via']}) ---")
273 for r
in sorted(rows, key=
lambda x: x[
"file"]):
274 if r[
"kind"] !=
"via":
276 print(f
" {r['file']}")
277 for hdr, syms
in r[
"via"].
items():
278 print(f
" {hdr}: {', '.join(syms[:6])}"
279 + (
" ..." if len(syms) > 6
else ""))
281 print(f
"\n--- files using nothing from it ({counts['unused']}) ---")
282 for r
in sorted(rows, key=
lambda x: x[
"file"]):
283 if r[
"kind"] ==
"unused":
284 print(f
" {r['file']}")