Home | History | Annotate | Download | only in lint
      1 #!/usr/bin/python
      2 #
      3 # Checks C++ files to make sure they conform to LLVM standards, as specified in
      4 # http://llvm.org/docs/CodingStandards.html .
      5 #
      6 # TODO: add unittests for the verifier functions:
      7 # http://docs.python.org/library/unittest.html .
      8 
      9 import common_lint
     10 import re
     11 import sys
     12 
     13 def VerifyIncludes(filename, lines):
     14   """Makes sure the #includes are in proper order and no disallows files are
     15   #included.
     16 
     17   Args:
     18     filename: the file under consideration as string
     19     lines: contents of the file as string array
     20   """
     21   lint = []
     22 
     23   include_gtest_re = re.compile(r'^#include "gtest/(.*)"')
     24   include_llvm_re = re.compile(r'^#include "llvm/(.*)"')
     25   include_support_re = re.compile(r'^#include "(Support/.*)"')
     26   include_config_re = re.compile(r'^#include "(Config/.*)"')
     27   include_system_re = re.compile(r'^#include <(.*)>')
     28 
     29   DISALLOWED_SYSTEM_HEADERS = ['iostream']
     30 
     31   line_num = 1
     32   prev_config_header = None
     33   prev_system_header = None
     34   for line in lines:
     35     # TODO: implement private headers
     36     # TODO: implement gtest headers
     37     # TODO: implement top-level llvm/* headers
     38     # TODO: implement llvm/Support/* headers
     39 
     40     # Process Config/* headers
     41     config_header = include_config_re.match(line)
     42     if config_header:
     43       curr_config_header = config_header.group(1)
     44       if prev_config_header:
     45         if prev_config_header > curr_config_header:
     46           lint.append((filename, line_num,
     47                        'Config headers not in order: "%s" before "%s"' % (
     48                          prev_config_header, curr_config_header)))
     49 
     50     # Process system headers
     51     system_header = include_system_re.match(line)
     52     if system_header:
     53       curr_system_header = system_header.group(1)
     54 
     55       # Is it blacklisted?
     56       if curr_system_header in DISALLOWED_SYSTEM_HEADERS:
     57         lint.append((filename, line_num,
     58                      'Disallowed system header: <%s>' % curr_system_header))
     59       elif prev_system_header:
     60         # Make sure system headers are alphabetized amongst themselves
     61         if prev_system_header > curr_system_header:
     62           lint.append((filename, line_num,
     63                        'System headers not in order: <%s> before <%s>' % (
     64                          prev_system_header, curr_system_header)))
     65 
     66       prev_system_header = curr_system_header
     67 
     68     line_num += 1
     69 
     70   return lint
     71 
     72 
     73 class CppLint(common_lint.BaseLint):
     74   MAX_LINE_LENGTH = 80
     75 
     76   def RunOnFile(self, filename, lines):
     77     lint = []
     78     lint.extend(VerifyIncludes(filename, lines))
     79     lint.extend(common_lint.VerifyLineLength(filename, lines,
     80                                              CppLint.MAX_LINE_LENGTH))
     81     lint.extend(common_lint.VerifyTabs(filename, lines))
     82     lint.extend(common_lint.VerifyTrailingWhitespace(filename, lines))
     83     return lint
     84 
     85 
     86 def CppLintMain(filenames):
     87   all_lint = common_lint.RunLintOverAllFiles(CppLint(), filenames)
     88   for lint in all_lint:
     89     print '%s:%d:%s' % (lint[0], lint[1], lint[2])
     90   return 0
     91 
     92 
     93 if __name__ == '__main__':
     94   sys.exit(CppLintMain(sys.argv[1:]))
     95