#!/usr/bin/python # Copyright (C) 2010 Google Inc. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # This script looks for unnecessary #includes in the given header file, # or in all header files that can be recursively found in the given directory. import os import re import sys headerFile = re.compile(r'\.h$') includeLine = re.compile(r'^#include ("|"]') smartPointerString = "(ListRefPtr|OwnArrayPtr|OwnPtr|PassOwnPtr|PassRefPtr|RefPtr)" allowedIncludes = set(["Forward", "PlatformString", "StringHash", "Threading"]) # Check if 'line' needs any class in 'unnecessaryIncludes' to be included in the header file. def checkLine(line, unnecessaryIncludes): unnecessaryIncludesCopy = unnecessaryIncludes.copy() for includedClass in unnecessaryIncludesCopy: if re.search(includedClass, line): if re.search(includedClass + "\*", line): continue smartPointerClassString = smartPointerString.replace("className", includedClass) if re.search(smartPointerClassString, line): continue unnecessaryIncludes.remove(includedClass) # Look for unnecessary includes in the given file def checkFile(fileName): if headerFile.search(fileName): f = open(fileName, "r") unnecessaryIncludes = set() for line in f: match = includeLine.match(line) if match: className = match.group(2) if className == "PlatformString": unnecessaryIncludes.add("String") elif className not in allowedIncludes: unnecessaryIncludes.add(className) else: checkLine(line, unnecessaryIncludes) if len(unnecessaryIncludes) > 0: print fileName for includedClass in unnecessaryIncludes: print includedClass print # If 'path' is a file, check if it has unnecessary includes. # If 'path' is a directory, traverse it recursively and look # for unnecessary includes in all header files. def checkPath(path): if os.path.isfile(path): checkFile(path) elif os.path.isdir(path): dirList = os.listdir(path) for dirName in dirList: checkPath(path + "/" + dirName) else: print path, "is not a file or directory." def main(): if len(sys.argv) <= 1: print "Usage:", sys.argv[0], "" return -1 checkPath(sys.argv[1]) if __name__ == "__main__": main()