[gjs/iwyu: 30/34] build: Postprocess IWYU output
- From: Philip Chimento <pchimento src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs/iwyu: 30/34] build: Postprocess IWYU output
- Date: Thu, 21 May 2020 05:45:38 +0000 (UTC)
commit c5f24a7cf4a2f2d23d519d2651aa68488f6899e1
Author: Philip Chimento <philip chimento gmail com>
Date: Fri May 15 23:26:39 2020 -0700
build: Postprocess IWYU output
When running IWYU, the output is really hard to read. Ideally we want
only a diff of which lines to add or remove for each file, and no output
for a file that needs no changes.
Also take this opportunity to implement the "fwd-decls" header
js/TypeDecls.h in the postprocessor so that we don't get requests to
forward-declare JSContext everywhere; and make the postprocessor
suppress false positives.
tools/process_iwyu.py | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++
tools/run_iwyu.sh | 17 +++---
2 files changed, 154 insertions(+), 8 deletions(-)
---
diff --git a/tools/process_iwyu.py b/tools/process_iwyu.py
new file mode 100755
index 00000000..f91778a2
--- /dev/null
+++ b/tools/process_iwyu.py
@@ -0,0 +1,145 @@
+# coding: utf8
+
+# IWYU is missing the feature to designate a certain header as a "forward-decls
+# header". In the case of SpiderMonkey, there are certain commonly used forward
+# declarations that are all gathered in js/TypeDecls.h.
+# We postprocess the IWYU output to fix this, and also fix the output format
+# which is quite verbose, making it tedious to scroll through for 60 files.
+
+import re
+import sys
+
+
+class Colors:
+ NORMAL = '\33[0m'
+ RED = '\33[31m'
+ GREEN = '\33[32m'
+
+
+ADD, REMOVE, FULL = range(3)
+state = None
+file = None
+add = {}
+remove = {}
+all_includes = {}
+
+# When encountering one of these lines, move to a different state
+MATCHERS = {
+ r'\.\./(.*) should add these lines:': ADD,
+ r'\.\./(.*) should remove these lines:': REMOVE,
+ r'The full include-list for \.\./(.*):': FULL,
+ r'\(\.\./(.*) has correct #includes/fwd-decls\)': None
+}
+
+FWD_HEADER = '#include <js/TypeDecls.h>'
+FWD_DECLS_IN_HEADER = (
+ 'class JSAtom;',
+ 'struct JSContext;',
+ 'class JSFunction;',
+ 'class JSObject;',
+ 'struct JSRuntime;',
+ 'class JSScript;',
+ 'class JSString;',
+ 'class JSTracer;',
+ 'struct JSFreeOp;',
+ 'namespace js { class TempAllocPolicy; }'
+ 'namespace JS { struct PropertyKey; }',
+ 'namespace JS { class Symbol; }',
+ 'namespace JS { class BigInt; }',
+ 'namespace JS { union Value; }',
+ 'namespace JS { class Compartment; }',
+ 'namespace JS { class Realm; }',
+ 'namespace JS { struct Runtime; }',
+ 'namespace JS { class Zone; }',
+)
+add_fwd_header = False
+
+FALSE_POSITIVES = (
+ # The bodies of these structs already come before their usage,
+ # we don't need to have forward declarations of them as well
+ ('gjs/atoms.h', 'class GjsAtoms;', ''),
+ ('gjs/atoms.h', 'struct GjsSymbolAtom;', ''),
+
+ # IWYU weird false positive when using std::vector::emplace_back() or
+ # std::vector::push_back()
+ ('gi/private.cpp', '#include <algorithm>', 'for max'),
+ ('gjs/importer.cpp', '#include <algorithm>', 'for max'),
+ ('modules/cairo-context.cpp', '#include <algorithm>', 'for max'),
+)
+
+
+def output():
+ global file, state, add_fwd_header
+
+ if add_fwd_header:
+ if FWD_HEADER not in all_includes:
+ if FWD_HEADER in remove:
+ remove.pop(FWD_HEADER, None)
+ else:
+ add[FWD_HEADER] = ''
+
+ if add or remove:
+ print(f'\n== {file} ==')
+ for line, why in add.items():
+ if why:
+ why = ' // ' + why
+ print(f'{Colors.GREEN}+{line}{Colors.NORMAL}{why}')
+ for line, why in remove.items():
+ if why:
+ why = ' // ' + why
+ print(f'{Colors.RED}-{line}{Colors.NORMAL}{why}')
+
+ state = None
+ file = None
+ add.clear()
+ remove.clear()
+ all_includes.clear()
+ add_fwd_header = False
+
+
+for line in sys.stdin:
+ line = line.strip()
+ if not line:
+ continue
+
+ # filter out errors having to do with compiler arguments unknown to IWYU
+ if line.startswith('error:'):
+ continue
+
+ if line == '---':
+ output()
+ continue
+
+ state_changed = False
+ file_changed = False
+ for matcher, newstate in MATCHERS.items():
+ match = re.match(matcher, line)
+ if match:
+ state = newstate
+ if match.group(1) != file:
+ if file is not None:
+ file_changed = True
+ file = match.group(1)
+ state_changed = True
+ break
+ if file_changed:
+ output()
+ continue
+ if state_changed:
+ continue
+
+ line, _, why = line.partition(' // ')
+ line = line.strip()
+ if state == ADD:
+ if line in FWD_DECLS_IN_HEADER:
+ add_fwd_header = True
+ continue
+ if (file, line, why) in FALSE_POSITIVES:
+ continue
+ add[line] = why
+ elif state == REMOVE:
+ if line.startswith('- '):
+ line = line[2:]
+ remove[line] = why
+ elif state == FULL:
+ all_includes[line] = why
diff --git a/tools/run_iwyu.sh b/tools/run_iwyu.sh
index 57b7bc5e..ff3b9996 100755
--- a/tools/run_iwyu.sh
+++ b/tools/run_iwyu.sh
@@ -8,6 +8,7 @@ ninja
IWYU="iwyu_tool -p ."
PRIVATE_MAPPING="-Xiwyu --mapping_file=$SRCDIR/tools/gjs-private-iwyu.imp -Xiwyu --keep=config.h"
PUBLIC_MAPPING="-Xiwyu --mapping_file=$SRCDIR/tools/gjs-public-iwyu.imp"
+POSTPROCESS="python3 $SRCDIR/tools/process_iwyu.py"
for FILE in $SRCDIR/gi/*.cpp $SRCDIR/gjs/atoms.cpp $SRCDIR/gjs/byteArray.cpp \
$SRCDIR/gjs/coverage.cpp $SRCDIR/gjs/debugger.cpp \
@@ -19,24 +20,24 @@ for FILE in $SRCDIR/gi/*.cpp $SRCDIR/gjs/atoms.cpp $SRCDIR/gjs/byteArray.cpp \
$SRCDIR/modules/system.cpp $SRCDIR/test/*.cpp $SRCDIR/util/*.cpp \
$SRCDIR/libgjs-private/*.c
do
- $IWYU $FILE -- $PRIVATE_MAPPING
+ $IWYU $FILE -- $PRIVATE_MAPPING | $POSTPROCESS
done
$IWYU $SRCDIR/gjs/context.cpp -- $PRIVATE_MAPPING \
- -Xiwyu --check_also=$SRCDIR/gjs/context-private.h
+ -Xiwyu --check_also=$SRCDIR/gjs/context-private.h | $POSTPROCESS
$IWYU $SRCDIR/gjs/jsapi-dynamic-class.cpp -- $PRIVATE_MAPPING \
- -Xiwyu --check_also=$SRCDIR/gjs/jsapi-class.h
+ -Xiwyu --check_also=$SRCDIR/gjs/jsapi-class.h | $POSTPROCESS
$IWYU $SRCDIR/gjs/jsapi-util.cpp -- $PRIVATE_MAPPING \
-Xiwyu --check_also=$SRCDIR/gjs/jsapi-util-args.h \
- -Xiwyu --check_also=$SRCDIR/gjs/jsapi-util-root.h
+ -Xiwyu --check_also=$SRCDIR/gjs/jsapi-util-root.h | $POSTPROCESS
$IWYU $SRCDIR/gjs/mem.cpp -- $PRIVATE_MAPPING \
- -Xiwyu --check_also=$SRCDIR/gjs/mem-private.h
+ -Xiwyu --check_also=$SRCDIR/gjs/mem-private.h | $POSTPROCESS
$IWYU $SRCDIR/gjs/profiler.cpp -- $PRIVATE_MAPPING \
- -Xiwyu --check_also=$SRCDIR/gjs/profiler-private.h
+ -Xiwyu --check_also=$SRCDIR/gjs/profiler-private.h | $POSTPROCESS
$IWYU $SRCDIR/modules/cairo.cpp -- $PRIVATE_MAPPING \
-Xiwyu --check_also=$SRCDIR/modules/cairo-module.h \
- -Xiwyu --check_also=$SRCDIR/modules/cairo-private.h
+ -Xiwyu --check_also=$SRCDIR/modules/cairo-private.h | $POSTPROCESS
for FILE in $SRCDIR/gjs/console.cpp $SRCDIR/installed-tests/minijasmine.cpp
do
- $IWYU $FILE -- $PUBLIC_MAPPING
+ $IWYU $FILE -- $PUBLIC_MAPPING | $POSTPROCESS
done
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]