From 98d9a7f86f5af8bebb98bda445ff3bbc3321c330 Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Mon, 22 May 2023 14:22:35 +0000 Subject: [PATCH] scripts: compliance: add a compliance check to keep blocks of code sorted This allows defining a list within two marker (zephyr-keep-sorted-start and zephyr-keep-sorted-stop), and have the CI validate that the block is kept sorted every time stuff gets added to it. This is mainly for Kconfig and CMake include lists so that there's no ambiguity on where to add new stuff. Signed-off-by: Fabio Baltieri --- .gitignore | 1 + scripts/ci/check_compliance.py | 53 ++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/.gitignore b/.gitignore index fae5aabbf30..13c99731c52 100644 --- a/.gitignore +++ b/.gitignore @@ -76,6 +76,7 @@ ImageSize.txt Kconfig.txt KconfigBasic.txt KconfigBasicNoModules.txt +KeepSorted.txt MaintainersFormat.txt ModulesMaintainers.txt Nits.txt diff --git a/scripts/ci/check_compliance.py b/scripts/ci/check_compliance.py index 779da01f2c5..cbbd0da9b66 100755 --- a/scripts/ci/check_compliance.py +++ b/scripts/ci/check_compliance.py @@ -1163,6 +1163,59 @@ class YAMLLint(ComplianceTest): p.line, col=p.column, desc=p.desc) +class KeepSorted(ComplianceTest): + """ + Check for blocks of code or config that should be kept sorted. + """ + name = "KeepSorted" + doc = "Check for blocks of code or config that should be kept sorted." + path_hint = "" + + MARKER = "zephyr-keep-sorted" + + def check_file(self, file, fp): + lines = [] + in_block = False + + start_marker = f"{self.MARKER}-start" + stop_marker = f"{self.MARKER}-stop" + + for line_num, line in enumerate(fp.readlines(), start=1): + if start_marker in line: + if in_block: + desc = f"nested {start_marker}" + self.fmtd_failure("error", "KeepSorted", file, line_num, + desc=desc) + in_block = True + lines = [] + elif stop_marker in line: + if not in_block: + desc = f"{stop_marker} without {start_marker}" + self.fmtd_failure("error", "KeepSorted", file, line_num, + desc=desc) + in_block = False + + if lines != sorted(lines): + desc = f"sorted block is not sorted" + self.fmtd_failure("error", "KeepSorted", file, line_num, + desc=desc) + elif not line.strip() or line.startswith("#"): + # Ignore comments and blank lines + continue + elif in_block: + if line.startswith((" ", "\t")): + lines[-1] += line + else: + lines.append(line) + + if in_block: + self.failure(f"unterminated {start_marker} in {file}") + + def run(self): + for file in get_files(filter="d"): + with open(file, "r") as fp: + self.check_file(file, fp) + def init_logs(cli_arg): # Initializes logging