⛏️ index : haiku.git

#!/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 &lt; 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")