summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKlaus Aehlig <klaus.aehlig@huawei.com>2025-06-12 12:24:34 +0200
committerKlaus Aehlig <klaus.aehlig@huawei.com>2025-06-13 12:19:02 +0200
commit2e2a8362aaa25b70bd11fe14c3035227f41960dd (patch)
tree54bf7d9509e8e6ba21567796c4c93b67a1c7f4aa
parentd46051807e37bd1e28a4c6ecd60d3a9f92103cc7 (diff)
downloadjustbuild-2e2a8362aaa25b70bd11fe14c3035227f41960dd.tar.gz
Add lint target for clang-format
-rw-r--r--lint/TARGETS25
-rwxr-xr-xlint/create-diff.py30
-rwxr-xr-xlint/run_clang_format.py59
3 files changed, 113 insertions, 1 deletions
diff --git a/lint/TARGETS b/lint/TARGETS
index a5456c85..0a52a37d 100644
--- a/lint/TARGETS
+++ b/lint/TARGETS
@@ -1,7 +1,10 @@
{ "":
{ "type": "install"
, "tainted": ["lint", "test"]
- , "dirs": [["LINT: clang-tidy", "clang-tidy"]]
+ , "dirs":
+ [ ["LINT: clang-tidy", "clang-tidy"]
+ , ["LINT: clang-format", "clang-format"]
+ ]
}
, "clang toolchain":
{ "type": "configure"
@@ -40,4 +43,24 @@
, ["@", "tests", "", "ALL"]
]
}
+, "LINT: clang-format":
+ { "type": ["@", "rules", "lint", "targets"]
+ , "tainted": ["test"]
+ , "name": ["clang-format"]
+ , "linter": ["run_clang_format.py"]
+ , "summarizer": ["summary.py"]
+ , "config": [["@", "src", "", ".clang-format"], "clang"]
+ , "targets":
+ [ ["@", "src", "src/buildtool/main", "just"]
+ , ["@", "src", "src/other_tools/just_mr", "just-mr"]
+ , ["@", "tests", "", "ALL"]
+ ]
+ }
+, "format.diff":
+ { "type": "generic"
+ , "tainted": ["lint", "test"]
+ , "cmds": ["./create-diff.py"]
+ , "outs": ["format.diff"]
+ , "deps": ["LINT: clang-format", "create-diff.py"]
+ }
}
diff --git a/lint/create-diff.py b/lint/create-diff.py
new file mode 100755
index 00000000..753aed28
--- /dev/null
+++ b/lint/create-diff.py
@@ -0,0 +1,30 @@
+#!/usr/bin/env python3
+# Copyright 2025 Huawei Cloud Computing Technology Co., Ltd.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import json
+
+with open("out/failures.json") as f:
+ failures = json.load(f)
+
+with open("format.diff", "w") as f:
+ for k, v in failures.items():
+ src = v["config"]["src"]
+ if src.startswith("work/"):
+ src = src[len("work/"):]
+ diff = v["log"].splitlines()
+ f.write("--- a/%s\n" % (src, ))
+ f.write("+++ b/%s\n" % (src, ))
+ for l in diff[2:]:
+ f.write(l + "\n")
diff --git a/lint/run_clang_format.py b/lint/run_clang_format.py
new file mode 100755
index 00000000..b33f0c1f
--- /dev/null
+++ b/lint/run_clang_format.py
@@ -0,0 +1,59 @@
+#!/usr/bin/env python3
+# Copyright 2025 Huawei Cloud Computing Technology Co., Ltd.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import json
+import os
+import shutil
+import subprocess
+import sys
+
+
+def dump_meta(src, cmd):
+ 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):
+ dump_meta(src, cmd)
+ config = os.environ.get("CONFIG")
+ out = os.environ.get("OUT")
+ shutil.copyfile(os.path.join(config, ".clang-format"), ".clang-format")
+ extra = []
+ if src.endswith(".tpp"):
+ extra = ["-x", "c++"]
+ db = [{
+ "directory": os.getcwd(),
+ "arguments": cmd[:1] + extra + cmd[1:],
+ "file": src
+ }]
+ with open("compile_commands.json", "w") as f:
+ json.dump(db, f)
+ new_cmd = [
+ os.path.join(config, "toolchain", "bin", "clang-format"),
+ "-style=file",
+ src,
+ ]
+ formatted = os.path.join(out, "formatted")
+ with open(formatted, "w") as f:
+ res = subprocess.run(new_cmd, stdout=f).returncode
+ if res != 0:
+ return res
+ return subprocess.run(["diff", "-u", src, formatted]).returncode
+
+
+if __name__ == "__main__":
+ sys.exit(run_lint(sys.argv[1], sys.argv[2:]))