80 for dirpath, dirnames, filenames
in os.walk(SRC):
81 dirnames[:] = [d
for d
in dirnames
if d
not in (
"external",
"build")]
83 if fn.endswith((
".h",
".hpp",
".c",
".cc",
".cpp")):
84 full = os.path.join(dirpath, fn)
85 yield os.path.relpath(full, REPO), full
89 show_all =
"--all" in sys.argv
90 as_json =
"--json" in sys.argv
93 forwards = collections.defaultdict(list)
97 lines = open(full, errors=
"ignore").read().split(
"\n")
100 is_header = rel.endswith((
".h",
".hpp"))
101 for n, line
in enumerate(lines, 1):
104 forwards[m.group(1)].append((rel, n))
106 for pat
in (DEF_CLOSE, DEF_OPEN):
111 definitions.setdefault(d.group(1), rel)
114 for name, places
in forwards.items():
115 home = definitions.get(name)
119 if home_layer
is None:
121 for rel, line
in places:
123 if here
is None or rel == home:
125 upward = home_layer > here
126 if upward
or show_all:
137 "forward_declared_in": f
"{rel}:{line}",
138 "declaring_layer": here,
140 "defining_layer": home_layer,
142 "prototypes_using_it": uses,
146 print(json.dumps(findings, indent=2))
149 up = [f
for f
in findings
if f[
"upward"]]
150 with_api = [f
for f
in up
if f[
"prototypes_using_it"] > 0]
151 passthrough = [f
for f
in up
if f[
"prototypes_using_it"] == 0]
153 print(f
"{len(up)} forward declaration(s) reaching a higher layer "
154 f
"({len(with_api)} with prototypes over the type, {len(passthrough)} bare)\n")
156 print(
"--- reaching UP and used in prototypes: an API that may be in the wrong place ---")
157 for f
in sorted(with_api, key=
lambda x: (-x[
"defining_layer"] + x[
"declaring_layer"],
158 x[
"forward_declared_in"])):
159 print(f
" {f['type']} (layer {f['declaring_layer']} -> {f['defining_layer']}, "
160 f
"{f['prototypes_using_it']} prototype(s))")
161 print(f
" declared {f['forward_declared_in']}")
162 print(f
" defined {f['defined_in']}")
164 print(f
"\n--- reaching UP, bare (opaque handles; usually fine) : {len(passthrough)} ---")
165 by_pair = collections.Counter(
166 (f[
"forward_declared_in"].split(
":")[0], f[
"defined_in"])
for f
in passthrough)
167 for (h, d), n
in by_pair.most_common(20):
168 print(f
" {n:3d} {h} -> {d}")