diff options
author | Paul Cristian Sarbu <paul.cristian.sarbu@huawei.com> | 2025-06-16 15:13:22 +0200 |
---|---|---|
committer | Paul Cristian Sarbu <paul.cristian.sarbu@huawei.com> | 2025-06-17 13:51:48 +0200 |
commit | 1fa9984b7f65638515c0be743abe15bb0b8170e8 (patch) | |
tree | de548e2622c4c4fb3759e6aa1c0290cf38210f1b | |
parent | 9b8989da51d55ac3b4664ffcfd07abbb305ee8a9 (diff) | |
download | justbuild-1fa9984b7f65638515c0be743abe15bb0b8170e8.tar.gz |
lint scripts: Add typing and basic documentation
-rwxr-xr-x | lint/run_clang_format.py | 30 | ||||
-rwxr-xr-x | lint/run_clang_tidy.py | 37 | ||||
-rwxr-xr-x | lint/run_iwyu.py | 35 | ||||
-rwxr-xr-x | lint/run_strict_deps.py | 32 | ||||
-rwxr-xr-x | lint/summary.py | 11 |
5 files changed, 97 insertions, 48 deletions
diff --git a/lint/run_clang_format.py b/lint/run_clang_format.py index b33f0c1f..7bb20ba5 100755 --- a/lint/run_clang_format.py +++ b/lint/run_clang_format.py @@ -19,19 +19,28 @@ import shutil import subprocess import sys +from typing import List -def dump_meta(src, cmd): + +def dump_meta(src: str, cmd: List[str]) -> None: + """Dump linter action metadata for further analysis.""" OUT = os.environ.get("OUT") if OUT: with open(os.path.join(OUT, "config.json"), "w") as f: json.dump({"src": src, "cmd": cmd}, f) -def run_lint(src, cmd): +def run_lint(src: str, cmd: List[str]) -> int: + """Run the lint command for the specified source file.""" dump_meta(src, cmd) - config = os.environ.get("CONFIG") - out = os.environ.get("OUT") - shutil.copyfile(os.path.join(config, ".clang-format"), ".clang-format") + + CONFIG = os.environ.get("CONFIG") + if CONFIG is None: + print("Failed to get CONFIG", file=sys.stderr) + return 1 + + shutil.copyfile(os.path.join(CONFIG, ".clang-format"), ".clang-format") + extra = [] if src.endswith(".tpp"): extra = ["-x", "c++"] @@ -42,13 +51,20 @@ def run_lint(src, cmd): }] with open("compile_commands.json", "w") as f: json.dump(db, f) + new_cmd = [ - os.path.join(config, "toolchain", "bin", "clang-format"), + os.path.join(CONFIG, "toolchain", "bin", "clang-format"), "-style=file", src, ] - formatted = os.path.join(out, "formatted") + + OUT = os.environ.get("OUT") + if OUT is None: + print("Failed to get OUT", file=sys.stderr) + sys.exit(1) + formatted = os.path.join(OUT, "formatted") with open(formatted, "w") as f: + print("Running cmd %r with db %r" % (new_cmd, db), file=sys.stderr) res = subprocess.run(new_cmd, stdout=f).returncode if res != 0: return res diff --git a/lint/run_clang_tidy.py b/lint/run_clang_tidy.py index 7f48e007..b8df6fef 100755 --- a/lint/run_clang_tidy.py +++ b/lint/run_clang_tidy.py @@ -19,39 +19,47 @@ import shutil import subprocess import sys +from typing import List + CXX_LIB_VERSION = "13.3.0" -def dump_meta(src, cmd): + +def dump_meta(src: str, cmd: List[str]) -> None: + """Dump linter action metadata for further analysis.""" OUT = os.environ.get("OUT") - if OUT: + if OUT is not None: with open(os.path.join(OUT, "config.json"), "w") as f: json.dump({"src": src, "cmd": cmd}, f) -def run_lint(src, cmd): +def run_lint(src: str, cmd: List[str]) -> int: + """Run the lint command for the specified source file.""" dump_meta(src, cmd) - config = os.environ.get("CONFIG") - shutil.copyfile(os.path.join(config, ".clang-tidy"), ".clang-tidy") - extra = [ "-Wno-unused-command-line-argument"] + CONFIG = os.environ.get("CONFIG") + if CONFIG is None: + print("Failed to get CONFIG", file=sys.stderr) + return 1 + shutil.copyfile(os.path.join(CONFIG, ".clang-tidy"), ".clang-tidy") + + extra = ["-Wno-unused-command-line-argument"] # add include paths from the bundled toolchain - baseincludepath = os.path.join( - config, "toolchain", "include", "c++", CXX_LIB_VERSION - ) + baseincludepath = os.path.join(CONFIG, "toolchain", "include", "c++", + CXX_LIB_VERSION) # We're using the native toolchain, so arch-specific headers are # only available for one arch. Hence we can try all supported candidates # and add the ones found for arch in ["x86_64", "arm"]: - idir = os.path.join(baseincludepath, - "%s-pc-linux-gnu" % (arch,)) + idir = os.path.join(baseincludepath, "%s-pc-linux-gnu" % (arch, )) if os.path.exists(idir): extra += ["-isystem", idir] extra += [ - "-isystem", baseincludepath, + "-isystem", + baseincludepath, ] - if src.endswith(".tpp"): extra += ["-x", "c++"] + db = [{ "directory": os.getcwd(), "arguments": cmd[:1] + extra + cmd[1:], @@ -59,8 +67,9 @@ def run_lint(src, cmd): }] with open("compile_commands.json", "w") as f: json.dump(db, f) + new_cmd = [ - os.path.join(config, "toolchain", "bin", "clang-tidy"), + os.path.join(CONFIG, "toolchain", "bin", "clang-tidy"), src, ] print("Running cmd %r with db %r" % (new_cmd, db), file=sys.stderr) diff --git a/lint/run_iwyu.py b/lint/run_iwyu.py index f4be3604..ef8413b5 100755 --- a/lint/run_iwyu.py +++ b/lint/run_iwyu.py @@ -19,19 +19,29 @@ import shutil import subprocess import sys +from typing import List + CXX_LIB_VERSION = "13.3.0" -def dump_meta(src, cmd): + +def dump_meta(src: str, cmd: List[str]) -> None: + """Dump linter action metadata for further analysis.""" OUT = os.environ.get("OUT") if OUT: with open(os.path.join(OUT, "config.json"), "w") as f: json.dump({"src": src, "cmd": cmd}, f) -def run_lint(src, cmd): +def run_lint(src: str, cmd: List[str]) -> int: + """Run the lint command for the specified source file.""" dump_meta(src, cmd) - config = os.environ.get("CONFIG") - shutil.copyfile(os.path.join(config, "iwyu-mapping"), "iwyu-mapping.imp") + + CONFIG = os.environ.get("CONFIG") + if CONFIG is None: + print("Failed to get CONFIG", file=sys.stderr) + return 1 + + shutil.copyfile(os.path.join(CONFIG, "iwyu-mapping"), "iwyu-mapping.imp") # Currently, .tpp files cannot be processed to produce meaningful suggestions # Their corresponding .hpp files are analyzed separately, so just skip @@ -67,7 +77,7 @@ def run_lint(src, cmd): os.path.realpath(fake_stem) + ".o" ] + cmd[e_index + 2:] - iwyu_flags = [ + iwyu_flags: List[str] = [ "--cxx17ns", # suggest the more concise syntax introduced in C++17 "--no_fwd_decls", # do not use forward declarations "--no_default_mappings", # do not add iwyu's default mappings @@ -77,25 +87,24 @@ def run_lint(src, cmd): "--max_line_length=1000" # don't limit explanation messages ] - iwyu_options = [] + iwyu_options: List[str] = [] for option in iwyu_flags: iwyu_options.append("-Xiwyu") iwyu_options.append(option) # add include paths from the bundled toolchain - baseincludepath = os.path.join( - config, "toolchain", "include", "c++", CXX_LIB_VERSION - ) + baseincludepath = os.path.join(CONFIG, "toolchain", "include", "c++", + CXX_LIB_VERSION) # We're using the native toolchain, so arch-specific headers are # only available for one arch. Hence we can try all supported candidates # and add the ones found for arch in ["x86_64", "arm"]: - idir = os.path.join(baseincludepath, - "%s-pc-linux-gnu" % (arch,)) + idir = os.path.join(baseincludepath, "%s-pc-linux-gnu" % (arch, )) if os.path.exists(idir): iwyu_options += ["-isystem", idir] iwyu_options += [ - "-isystem", baseincludepath, + "-isystem", + baseincludepath, ] iwyu_options.extend(cmd[1:]) @@ -105,7 +114,7 @@ def run_lint(src, cmd): # So we "ask" IWYU here to include all non-system dependencies with quotes iwyu_options = ["-I" if x == "-isystem" else x for x in iwyu_options] - new_cmd = [os.path.join(config, "toolchain", "bin", "include-what-you-use")] + new_cmd = [os.path.join(CONFIG, "toolchain", "bin", "include-what-you-use")] new_cmd.extend(iwyu_options) new_cmd.append(src) diff --git a/lint/run_strict_deps.py b/lint/run_strict_deps.py index c963f3cd..7f2ddcf4 100755 --- a/lint/run_strict_deps.py +++ b/lint/run_strict_deps.py @@ -16,25 +16,33 @@ import json import os -import json -import os import sys +from typing import List -def dump_meta(src, cmd): + +def dump_meta(src: str, cmd: List[str]) -> None: + """Dump linter action metadata for further analysis.""" OUT = os.environ.get("OUT") if OUT: with open(os.path.join(OUT, "config.json"), "w") as f: json.dump({"src": src, "cmd": cmd}, f) -def run_lint(src, cmd): +def run_lint(src: str, cmd: List[str]) -> int: + """Run the lint command for the specified source file.""" dump_meta(src, cmd) - with open(os.environ.get("META")) as f: + META = os.environ.get("META") + if META is None: + print("Failed to get META", file=sys.stderr) + return 1 + + direct: List[str] = [] + with open(META) as f: direct = json.load(f)["direct deps artifact names"] - include_dirs = [] + include_dirs: List[str] = [] for i in range(len(cmd)): if cmd[i] in ["-I", "-isystem"]: include_dirs += [cmd[i + 1]] @@ -42,16 +50,16 @@ def run_lint(src, cmd): with open(src) as f: lines = f.read().splitlines() - failed = False + failed: bool = False - def include_covered(include_path): + def include_covered(include_path: str) -> bool: for d in direct: rel_path = os.path.relpath(include_path, d) if not rel_path.startswith('../'): return True return False - def handle_resolved_include(i, to_include, resolved): + def handle_resolved_include(i: int, resolved: str) -> None: nonlocal failed if not include_covered(resolved): failed = True @@ -60,11 +68,11 @@ def run_lint(src, cmd): " ---> including %r which is only provided by an indirect dependency" % (resolved, )) - def handle_include(i, to_include): + def handle_include(i: int, to_include: str) -> None: for d in include_dirs: candidate = os.path.join(d, to_include) if os.path.exists(candidate): - handle_resolved_include(i, to_include, candidate) + handle_resolved_include(i, candidate) for i in range(len(lines)): to_include = None @@ -72,7 +80,7 @@ def run_lint(src, cmd): to_include = lines[i].split('"')[1] if lines[i].startswith('#include <'): to_include = lines[i].split('<', 1)[1].split('>')[0] - if to_include: + if to_include: # if non-empty string handle_include(i, to_include) return 1 if failed else 0 diff --git a/lint/summary.py b/lint/summary.py index ca7445db..49126c61 100755 --- a/lint/summary.py +++ b/lint/summary.py @@ -17,7 +17,9 @@ import json import os import sys -FAILED = {} +from typing import Any, Dict + +FAILED: Dict[str, Any] = {} for lint in sorted(os.listdir()): if os.path.isdir(lint): @@ -34,7 +36,12 @@ for lint in sorted(os.listdir()): record["log"] = log FAILED[lint] = record -with open(os.path.join(os.environ.get("OUT"), "failures.json"), "w") as f: +OUT = os.environ.get("OUT") +if OUT is None: + print("Failed to get OUT") + sys.exit(1) + +with open(os.path.join(OUT, "failures.json"), "w") as f: json.dump(FAILED, f) failures = list(FAILED.keys()) |