Skip to content

Commit

Permalink
scripts: ci: check_compliancy: Add zephyr-keep-sorted regex support
Browse files Browse the repository at this point in the history
To support checking for sorted blocks of multi-line text add
an optional regex pattern for the KeepSorted compliance check.

Signed-off-by: Pieter De Gendt <pieter.degendt@basalte.be>
  • Loading branch information
pdgendt authored and nashif committed Nov 16, 2024
1 parent 8e4dc4e commit 5d49d5c
Showing 1 changed file with 40 additions and 19 deletions.
59 changes: 40 additions & 19 deletions scripts/ci/check_compliance.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import argparse
import collections
from email.utils import parseaddr
from itertools import takewhile
import json
import logging
import os
Expand Down Expand Up @@ -1543,20 +1544,39 @@ class KeepSorted(ComplianceTest):

MARKER = "zephyr-keep-sorted"

def block_is_sorted(self, block_data):
lines = []
def block_check_sorted(self, block_data, regex):
def _test_indent(txt: str):
return txt.startswith((" ", "\t"))

for line in textwrap.dedent(block_data).splitlines():
if len(lines) > 0 and line.startswith((" ", "\t")):
# Fold back indented lines
lines[-1] += line.strip()
if regex is None:
block_data = textwrap.dedent(block_data)

lines = block_data.splitlines()
last = ''

for idx, line in enumerate(lines):
if not line.strip():
# Ignore blank lines
continue

if regex:
# check for regex
if not re.match(regex, line):
continue
else:
lines.append(line.strip())
if _test_indent(line):
continue

# Fold back indented lines after the current one
for cont in takewhile(_test_indent, lines[idx + 1:]):
line += cont.strip()

if line < last:
return idx

if lines != sorted(lines):
return False
last = line

return True
return -1

def check_file(self, file, fp):
mime_type = magic.from_file(file, mime=True)
Expand All @@ -1569,8 +1589,9 @@ def check_file(self, file, fp):

start_marker = f"{self.MARKER}-start"
stop_marker = f"{self.MARKER}-stop"
start_line = None
stop_line = None
regex_marker = r"re\((.+)\)"
start_line = 0
regex = None

for line_num, line in enumerate(fp.readlines(), start=1):
if start_marker in line:
Expand All @@ -1581,22 +1602,22 @@ def check_file(self, file, fp):
in_block = True
block_data = ""
start_line = line_num + 1

# Test for a regex block
match = re.search(regex_marker, line)
regex = match.group(1) if match else None
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
stop_line = line_num - 1

if not self.block_is_sorted(block_data):
desc = (f"sorted block is not sorted, sort by running: " +
f"\"ex -s -c '{start_line},{stop_line} sort i|x' {file}\"")
idx = self.block_check_sorted(block_data, regex)
if idx >= 0:
desc = f"sorted block has out-of-order line at {start_line + idx}"
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:
block_data += line

Expand Down

0 comments on commit 5d49d5c

Please sign in to comment.