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() -> argparse.Namespace: 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( "--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.", ) (args, _) = p.parse_known_args() return 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 would_fail: sys.exit(1) if __name__ == "__main__": main()