diff options
| author | Tobias Markmann <tm@ayena.de> | 2014-11-17 12:55:58 (GMT) | 
|---|---|---|
| committer | Swift Review <review@swift.im> | 2014-12-10 13:47:44 (GMT) | 
| commit | 08c90f11b20dc8413a3fb27a9334ff3f0466b116 (patch) | |
| tree | 7190765f29290fe8cf114bf5a692636f5c974bd2 | |
| parent | 59cf59db314becf523fea2b840d7a237c2f6f246 (diff) | |
| download | swift-08c90f11b20dc8413a3fb27a9334ff3f0466b116.zip swift-08c90f11b20dc8413a3fb27a9334ff3f0466b116.tar.bz2 | |
Add FixIncludes.py utility.
This tool reads in implementation or header files and groups and sorts include
statements at the top according to our guidelines.
It does not support files using #if statements in head of the file.
Change-Id: I34b02546ecaf1653372f6edd319126b2ebb22ab5
| -rw-r--r-- | BuildTools/FixIncludes.py | 134 | 
1 files changed, 134 insertions, 0 deletions
| diff --git a/BuildTools/FixIncludes.py b/BuildTools/FixIncludes.py new file mode 100644 index 0000000..def2dd5 --- /dev/null +++ b/BuildTools/FixIncludes.py @@ -0,0 +1,134 @@ +#!/usr/bin/env python + +import sys; +import os; +import re; +from sets import Set + +filename = sys.argv[1] + +filename_base = os.path.basename(filename) +(filename_name, filename_ext) = os.path.splitext(filename_base) + +c_stdlib_headers = Set(["assert.h",  "limits.h",  "signal.h",  "stdlib.h", "ctype.h", "locale.h",  "stdarg.h", "string.h", "errno.h", "math.h", "stddef.h", "time.h", "float.h",  "setjmp.h", "stdio.h", "iso646.h", "wchar.h", "wctype.h", "complex.h", "inttypes.h", "stdint.h", "tgmath.h", "fenv.h", "stdbool.h"]) + +cpp_stdlib_headers = Set(["algorithm", "fstream", "list", "regex", "typeindex", "array", "functional", "locale", "set", "typeinfo", "atomic", "future", "map", "sstream", "type_traits", "bitset", "initializer_list", "memory", "stack", "unordered_map", "chrono", "iomanip", "mutex", "stdexcept", "unordered_set", "codecvt", "ios", "new", "streambuf", "utility", "complex", "iosfwd", "numeric", "string", "valarray", "condition_variable", "iostream", "ostream", "strstream", "vector", "deque", "istream", "queue", "system_error", "exception", "iterator", "random", "thread", "forward_list", "limits", "ratio", "tuple", "cassert", "ciso646", "csetjmp", "cstdio", "ctime", "cctype", "climits", "csignal", "cstdlib", "cwchar", "cerrno", "clocale", "cstdarg", "cstring", "cwctype", "cfloat", "cmath", "cstddef"]) + +class HeaderType: +    PRAGMA_ONCE, CORRESPONDING_HEADER, C_STDLIB, CPP_STDLIB, BOOST, QT, OTHER, SWIFTEN, SWIFT_CONTROLLERS, SWIFTOOLS, SWIFT = range(11) + +def findHeaderBlock(lines): +  start = False +  end = False + +  for idx, line in enumerate(lines): +    if not start and line.startswith("#"): +      start = idx +    elif start and (not end) and (not line.startswith("#")) and line.strip(): +      end = idx-1 +      break +  return (start, end) + +def lineToFileName(line): +  match = re.match( r'#include "(.*)"', line) +  if match: +    return match.group(1) +  match = re.match( r'#include <(.*)>', line) +  if match: +    return match.group(1) +  return False + +def fileNameToHeaderType(name): +  if name.endswith(filename_name + ".h"): +    return HeaderType.CORRESPONDING_HEADER + +  if name in c_stdlib_headers: +    return HeaderType.C_STDLIB +   +  if name in cpp_stdlib_headers: +    return HeaderType.CPP_STDLIB + +  if name.startswith("boost"): +    return HeaderType.BOOST + +  if name.startswith("Q"): +    return HeaderType.QT + +  if name.startswith("Swiften"): +    return HeaderType.SWIFTEN + +  if name.startswith("Swift/Controllers"): +    return HeaderType.SWIFT_CONTROLLERS + +  if name.startswith("SwifTools"): +    return HeaderType.SWIFTOOLS + +  if name.startswith("Swift"): +    return HeaderType.SWIFT + +  return HeaderType.OTHER + +def serializeHeaderGroups(groups): +  headerList = [] +  for group in range(0, HeaderType.SWIFT + 1): +    if group in groups: +      headers = sorted(groups[group]) +      headerList.extend(headers) +      headerList.extend(["\n"]) +  headerList.pop() +  return headerList + +def cleanHeaderFile(content, headerStart, headerEnd, headerGroups): +  del content[headerStart:headerEnd] +  newHeaders = serializeHeaderGroups(headerGroups) +  content[headerStart:1] = newHeaders + +  for line in content: +    print line, + +def cleanImplementationFile(content, headerStart, headerEnd, headerGroups): +  del content[headerStart:headerEnd] +  newHeaders = serializeHeaderGroups(headerGroups) +  content[headerStart:1] = newHeaders + +  for line in content: +    print line, + + +containsIf = False + +with open(filename) as f: +  content = f.readlines() + +(headerStart, headerEnd) = findHeaderBlock(content) + +headerGroups = {} + +for line in content[headerStart:headerEnd]: +  if line.strip(): +    if line.strip().startswith("#if "): +      containsIf = True +      break + +    if line.strip().startswith("#pragma once"): +      headerType = HeaderType.PRAGMA_ONCE +    else: +      headerType = fileNameToHeaderType(lineToFileName(line)) +     +    filename = lineToFileName(line) +    if headerType in headerGroups: +      headerGroups[headerType].append(line) +    else: +      headerGroups[headerType] = [line] + +if containsIf: +  print "Cannot format headers containing preprocessor if statements" +  exit(1) + +if filename_base.endswith(".h"): +  if not HeaderType.PRAGMA_ONCE in headerGroups: +    print "Missing #pragma once!" +    exit(2) +  cleanHeaderFile(content, headerStart, headerEnd, headerGroups) +elif filename_base.endswith(".cpp"): +  cleanImplementationFile(content, headerStart, headerEnd, headerGroups) | 
 Swift
 Swift