apply_cpplint_header_guard.py 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. #!/usr/bin/env python3
  2. # Copyright 2021 The Chromium Authors. All rights reserved.
  3. # Use of this source code is governed by a BSD-style license that can be
  4. # found in the LICENSE file.
  5. """Applies cpplint build/header_guard recommendations.
  6. Reads cpplint build/header_guard recommendations from stdin and applies them.
  7. Run cpplint for a single header:
  8. cpplint.py --filter=-,+build/header_guard foo.h 2>&1 | grep build/header_guard
  9. Run cpplint for all headers in dir foo in parallel:
  10. find foo -name '*.h' | \
  11. xargs parallel cpplint.py --filter=-,+build/header_guard -- 2>&1 | \
  12. grep build/header_guard
  13. """
  14. import sys
  15. IFNDEF_MSG = ' #ifndef header guard has wrong style, please use'
  16. ENDIF_MSG_START = ' #endif line should be "'
  17. ENDIF_MSG_END = '" [build/header_guard] [5]'
  18. NO_GUARD_MSG = ' No #ifndef header guard found, suggested CPP variable is'
  19. def process_cpplint_recommendations(cpplint_data):
  20. root = sys.argv[1] if len(sys.argv) > 1 else ''
  21. root = "_".join(root.upper().strip(r'[/]+').split('/'))+"_"
  22. for entry in cpplint_data:
  23. entry = entry.split(':')
  24. header = entry[0]
  25. line = entry[1]
  26. index = int(line) - 1
  27. msg = entry[2].rstrip()
  28. if msg == IFNDEF_MSG:
  29. assert len(entry) == 4
  30. with open(header, 'rb') as f:
  31. content = f.readlines()
  32. if not content[index + 1].startswith(b'#define '):
  33. raise Exception('Missing #define: %s:%d' % (header, index + 2))
  34. guard = entry[3].split(' ')[1]
  35. guard = guard.replace(root, '') if len(root) > 1 else guard
  36. content[index] = ('#ifndef %s\n' % guard).encode('utf-8')
  37. # Since cpplint does not print messages for the #define line, just
  38. # blindly overwrite the #define that was here.
  39. content[index + 1] = ('#define %s\n' % guard).encode('utf-8')
  40. elif msg.startswith(ENDIF_MSG_START):
  41. assert len(entry) == 3
  42. assert msg.endswith(ENDIF_MSG_END)
  43. with open(header, 'rb') as f:
  44. content = f.readlines()
  45. endif = msg[len(ENDIF_MSG_START):-len(ENDIF_MSG_END)]
  46. endif = endif.replace(root, '') if len(root) > 1 else endif
  47. content[index] = ('%s\n' % endif).encode('utf-8')
  48. elif msg == NO_GUARD_MSG:
  49. assert index == -1
  50. continue
  51. else:
  52. raise Exception('Unknown cpplint message: %s for %s:%s' %
  53. (msg, header, line))
  54. with open(header, 'wb') as f:
  55. f.writelines(content)
  56. if __name__ == '__main__':
  57. process_cpplint_recommendations(sys.stdin)