#!/usr/bin/env python # # Copyright 2009, Alexandre Deckner, alex@zappotek.com # Distributed under the terms of the MIT License. # import re, sys, os from utils import * def processMatches(matches, name, text, highlights): for match in matches: printMatch(name, match, text) highlights.append((match.start(), match.end(), name)) def run(fileSet, rules, outputFileName): openHtml(fileSet, outputFileName) for fileName in fileSet: print("\nChecking " + fileName + ":") file = open(fileName, 'r') text = file.read() highlights = [] for name, regexp in rules.items(): processMatches(regexp.finditer(text), name, text, highlights) highlights.sort() highlights = checkHighlights(highlights) file.close() renderHtml(text, highlights, fileName, outputFileName) closeHtml(outputFileName) def findCppFiles(dir): extensions = [".cpp", ".h"] vcsCacheDirectory = [".bzr", ".git", ".hg", ".svn"] results = [] for root, dirs, files in os.walk(dir): if os.path.split(root)[1] in vcsCacheDirectory: print(root + " cache directory has been ignored") continue for file in files: path = os.path.join(root, file) if os.path.splitext(file)[1] in extensions: print("adding", path) results.append(path) return results cppRules = {} cppRules["Line over 100 char"] = re.compile('[^\n]{101,}') cppRules["Spaces instead of tabs"] = re.compile(' ') cppRules["Missing space after control statement"] \ = re.compile('(for|if|while|switch)\(') cppRules["Missing space at comment start"] = re.compile('//\w') cppRules["Missing space after operator"] \ = re.compile('\w(==|[,=>/+\-*;\|])\w') cppRules["Operator at line end"] = re.compile('([*=/+\-\|\&\?]|\&&|\|\|)(?=\n)') cppRules["Missing space"] = re.compile('\){') cppRules["Mixed tabs/spaces"] = re.compile('( \t]|\t )+') cppRules["Malformed else"] = re.compile('}[ \t]*\n[ \t]*else') cppRules["Lines between functions > 2"] \ = re.compile('(?<=\n})([ \t]*\n){3,}(?=\n)') cppRules["Lines between functions < 2"] \ = re.compile('(?<=\n})([ \t]*\n){0,2}(?=.)') cppRules["Windows Line Ending"] = re.compile('\r') cppRules["Bad pointer/reference style"] \ = re.compile('(?<=\w) [*&](?=(\w|[,\)]))') # TODO: ignore some rules in comments #cppRules["-Comment 1"] = re.compile('[^/]/\*(.|[\r\n])*?\*/') #cppRules["-Comment 2"] = re.compile('(//)[^\n]*') if len(sys.argv) >= 2 and sys.argv[1] != "--help": files = [] for arg in sys.argv[1:]: if os.path.isfile(arg): files.append(arg) else: files.extend(findCppFiles(arg)) run(files, cppRules, "styleviolations.html") else: print("Usage: python checkstyle.py file.cpp [file2.cpp] [directory]\n") print("Checks c++ source files against the Haiku Coding Guidelines.") print("Outputs an html report in the styleviolations.html file.\n")