rspec/ci/asciidoc_validation/validate_environment.py
Marco Borgeaud cd424756a0
Validate asciidoc ifdef/endif (#3311)
Fix kotlin:S6511
2023-10-18 09:43:40 +00:00

106 lines
3.1 KiB
Python

# Validate the asciidoc environment directives in the given file(s).
# Errors are printed to the standard output stream.
#
# "ifdef" commands has to start the line without any leading spaces,
# as per asciidoc format.
#
# Only one form is allowed:
# ifdef::env-github,rspecator-view[]
#
# The closing command is:
# endif::env-github,rspecator-view[]
#
# It must be in the same file.
# Only one such environment is allowed per file.
from pathlib import Path
import sys
VALID_IFDEF = "ifdef::env-github,rspecator-view[]"
VALID_ENDIF = "endif::env-github,rspecator-view[]"
class Checker:
def __init__(self, file: Path):
assert file.exists()
assert file.is_file()
self._file = file
self._is_env_open = False
self._has_env = False
self._is_valid = True
def process(self) -> bool:
content = self._file.read_text(encoding="utf-8")
lines = content.splitlines(keepends=False)
for line_index, line in enumerate(lines):
line_number = line_index + 1
if line.startswith("ifdef::"):
self._process_open(line_number, line)
if line.startswith("endif::"):
self._process_close(line_number, line)
if self._is_env_open:
self._on_error(len(lines), "The ifdef command is not closed.")
return self._is_valid
def _process_open(self, line_number: int, line: str):
if self._has_env:
self._on_error(line_number, "Only one ifdef command is allowed per file.")
if self._is_env_open:
self._on_error(line_number, "The previous ifdef command was not closed.")
self._has_env = True
self._is_env_open = True
# IDEs should be configured to properly display the description,
# not the other way around.
# "env-vscode" was used in the passed. Instead, user should be able to
# toggle the rspecator view based on their needs. Help these users migrate.
if "vscode" in line:
self._on_error(
line_number,
"Configure VS Code to display rspecator-view by setting the asciidoctor attribute.",
)
if line != VALID_IFDEF:
self._on_error(
line_number,
f'Incorrect asciidoc environment. "{VALID_IFDEF}" should be used instead.',
)
def _process_close(self, line_number: int, line: str):
if not self._is_env_open:
self._on_error(line_number, "Unexpected endif command.")
self._is_env_open = False
if line != VALID_ENDIF:
self._on_error(
line_number,
f'Incorrect endif command. "{VALID_ENDIF}" should be used instead.',
)
def _on_error(self, line_number: int, message: str):
print(f"{self._file}:{line_number} {message}")
self._is_valid = False
def main():
files = sys.argv[1:]
if not files:
sys.exit("Missing input files")
valid = True
for file in files:
if not Checker(Path(file)).process():
valid = False
if not valid:
sys.exit(1)
if __name__ == "__main__":
main()