format_whitespace.py 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. import re
  2. import subprocess
  3. UPSTREAM = 'https://github.com/Grasscutters/Grasscutter.git'
  4. RATCHET = 'LintRatchet'
  5. RATCHET_FALLBACK = 'c517b8a2c95473811eb07e12e73c4a69e59fbbdc'
  6. re_leading_whitespace = re.compile(r'^[ \t]+', re.MULTILINE) # Replace with \1.replace('\t', ' ')
  7. re_trailing_whitespace = re.compile(r'[ \t]+$', re.MULTILINE) # Replace with ''
  8. # Replace 'for (foo){bar' with 'for (foo) {bar'
  9. re_bracket_space = re.compile(r'\) *\{(?!\})') # Replace with ') {'
  10. # Replace 'for(foo)' with 'foo (bar)'
  11. re_keyword_space = re.compile(r'(?<=\b)(if|for|while|switch|try|else|catch|finally|synchronized) *(?=[\(\{])') # Replace with '\1 '
  12. def get_changed_filelist():
  13. # subprocess.run(['git', 'fetch', UPSTREAM, f'{RATCHET}:{RATCHET}']) # Ensure LintRatchet ref is matched to upstream
  14. # result = subprocess.run(['git', 'diff', RATCHET, '--name-only'], capture_output=True, text=True)
  15. # if result.returncode != 0:
  16. # print(f'{RATCHET} not found, trying fallback {RATCHET_FALLBACK}')
  17. print(f'Attempting to diff against {RATCHET_FALLBACK}')
  18. result = subprocess.run(['git', 'diff', RATCHET_FALLBACK, '--name-only'], capture_output=True, text=True)
  19. if result.returncode != 0:
  20. # print('Fallback is also missing, aborting.')
  21. print(f'Could not find {RATCHET_FALLBACK}, aborting.')
  22. exit(1)
  23. return result.stdout.strip().split('\n')
  24. def format_string(data: str):
  25. data = re_leading_whitespace.sub(lambda m: m.group(0).replace('\t', ' '), data)
  26. data = re_trailing_whitespace.sub('', data)
  27. data = re_bracket_space.sub(') {', data)
  28. data = re_keyword_space.sub(r'\1 ', data)
  29. if not data.endswith('\n'): # Enforce trailing \n
  30. data = data + '\n'
  31. return data
  32. def format_file(filename: str) -> bool:
  33. try:
  34. with open(filename, 'r') as file:
  35. data = file.read()
  36. data = format_string(data)
  37. with open(filename, 'w') as file:
  38. file.write(data)
  39. return True
  40. except FileNotFoundError:
  41. print(f'File not found, probably deleted: {filename}')
  42. return False
  43. def main():
  44. filelist = [f for f in get_changed_filelist() if f.endswith('.java') and not f.startswith('src/generated')]
  45. replaced = 0
  46. not_found = 0
  47. if not filelist:
  48. print('No changed files due for formatting!')
  49. return
  50. print('Changed files due for formatting: ', filelist)
  51. for file in filelist:
  52. if format_file(file):
  53. replaced += 1
  54. else:
  55. not_found += 1
  56. print(f'Format complete! {replaced} formatted, {not_found} missing.')
  57. if __name__ == '__main__':
  58. main()