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