import os import sys import argparse import colorama from isledecomp.dir import walk_source_dir, is_file_cpp from isledecomp.parser import DecompLinter colorama.init() def display_errors(alerts, filename): sorted_alerts = sorted(alerts, key=lambda a: a.line_number) for alert in sorted_alerts: error_type = ( f"{colorama.Fore.RED}error: " if alert.is_error() else f"{colorama.Fore.YELLOW}warning: " ) components = [ colorama.Fore.LIGHTWHITE_EX, filename, ":", str(alert.line_number), " : ", error_type, colorama.Fore.LIGHTWHITE_EX, alert.code.name.lower(), ] print("".join(components)) if alert.line is not None: print(f"{colorama.Fore.WHITE} {alert.line}") def parse_args() -> dict: p = argparse.ArgumentParser( description="Syntax checking and linting for decomp annotation markers." ) p.add_argument("target", help="The file or directory to check.") p.add_argument( "--enforce", action=argparse.BooleanOptionalAction, default=False, help="Fail if syntax errors are found.", ) p.add_argument( "--module", required=False, type=str, help="If present, run targeted checks for markers from the given module.", ) p.add_argument( "--warnfail", action=argparse.BooleanOptionalAction, default=False, help="Fail if syntax warnings are found and enforce is enabled.", ) args = p.parse_args() return vars(args) def process_files(files, module=None): warning_count = 0 error_count = 0 linter = DecompLinter() for filename in files: success = linter.check_file(filename, module) warnings = [a for a in linter.alerts if a.is_warning()] errors = [a for a in linter.alerts if a.is_error()] error_count += len(errors) warning_count += len(warnings) if not success: display_errors(linter.alerts, filename) print() return (warning_count, error_count) def main(): args = parse_args() if os.path.isdir(args["target"]): files_to_check = list(walk_source_dir(args["target"])) elif os.path.isfile(args["target"]) and is_file_cpp(args["target"]): files_to_check = [args["target"]] else: sys.exit("Invalid target") (warning_count, error_count) = process_files(files_to_check, module=args["module"]) print(colorama.Style.RESET_ALL, end="") would_fail = error_count > 0 or (warning_count > 0 and args["warnfail"]) if args["enforce"] and would_fail: sys.exit(1) if __name__ == "__main__": main()