Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 48 additions & 73 deletions cpplint.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -5914,7 +5914,26 @@ def ExpectingFunctionArgs(clean_lines, linenum):
('<utility>', ('forward', 'make_pair', 'move', 'swap')),
)

_RE_PATTERN_STRING = re.compile(r'\bstring\b')
# Non templated types or global objects
_HEADERS_TYPES_OR_OBJS = (
# String and others are special -- it is a non-templatized type in STL.
('<string>', ('string',)),
('<iostream>', ('cin', 'cout', 'cerr', 'clog', 'wcin', 'wcout',
'wcerr', 'wclog')),
('<cstdio>', ('FILE', 'fpos_t')))

# Non templated functions
_HEADERS_FUNCTIONS = (
('<cstdio>', ('fopen', 'freopen',
'fclose', 'fflush', 'setbuf', 'setvbuf', 'fread',
'fwrite', 'fgetc', 'getc', 'fgets', 'fputc', 'putc',
'fputs', 'getchar', 'gets', 'putchar', 'puts', 'ungetc',
'scanf', 'fscanf', 'sscanf', 'vscanf', 'vfscanf',
'vsscanf', 'printf', 'fprintf', 'sprintf', 'snprintf',
'vprintf', 'vfprintf', 'vsprintf', 'vsnprintf',
'ftell', 'fgetpos', 'fseek', 'fsetpos',
'clearerr', 'feof', 'ferror', 'perror',
'tmpfile', 'tmpnam'),),)

_re_pattern_headers_maybe_templates = []
for _header, _templates in _HEADERS_MAYBE_TEMPLATES:
Expand Down Expand Up @@ -5945,6 +5964,23 @@ def ExpectingFunctionArgs(clean_lines, linenum):
_template + '<>',
_header))

_re_pattern_types_or_objs = []
for _header, _types_or_objs in _HEADERS_TYPES_OR_OBJS:
for _type_or_obj in _types_or_objs:
_re_pattern_types_or_objs.append(
(re.compile(r'\b' + _type_or_obj + r'\b'),
_type_or_obj,
_header))

_re_pattern_functions = []
for _header, _functions in _HEADERS_FUNCTIONS:
for _function in _functions:
# Match printf(..., ...), but not foo->printf, foo.printf or
# 'type::printf()'.
_re_pattern_functions.append(
(re.compile(r'([^>.]|^)\b' + _function + r'\([^\)]'),
_function,
_header))

def FilesBelongToSameModule(filename_cc, filename_h):
"""Check if these two filenames belong to the same module.
Expand Down Expand Up @@ -6004,34 +6040,6 @@ def FilesBelongToSameModule(filename_cc, filename_h):
return files_belong_to_same_module, common_path


def UpdateIncludeState(filename, include_dict, io=codecs):
"""Fill up the include_dict with new includes found from the file.

Args:
filename: the name of the header to read.
include_dict: a dictionary in which the headers are inserted.
io: The io factory to use to read the file. Provided for testability.

Returns:
True if a header was successfully added. False otherwise.
"""
headerfile = None
try:
with io.open(filename, 'r', 'utf8', 'replace') as headerfile:
linenum = 0
for line in headerfile:
linenum += 1
clean_line = CleanseComments(line)
match = _RE_PATTERN_INCLUDE.search(clean_line)
if match:
include = match.group(2)
include_dict.setdefault(include, linenum)
return True
except IOError:
return False



def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error,
io=codecs):
"""Reports for missing stl includes.
Expand All @@ -6058,14 +6066,17 @@ def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error,
if not line or line[0] == '#':
continue

# String is special -- it is a non-templatized type in STL.
matched = _RE_PATTERN_STRING.search(line)
if matched:
# Don't warn about strings in non-STL namespaces:
# (We check only the first match per line; good enough.)
prefix = line[:matched.start()]
if prefix.endswith('std::') or not prefix.endswith('::'):
required['<string>'] = (linenum, 'string')
_re_patterns = []
_re_patterns.extend(_re_pattern_types_or_objs)
_re_patterns.extend(_re_pattern_functions)
for pattern, item, header in _re_patterns:
matched = pattern.search(line)
if matched:
# Don't warn about strings in non-STL namespaces:
# (We check only the first match per line; good enough.)
prefix = line[:matched.start()]
if prefix.endswith('std::') or not prefix.endswith('::'):
required[header] = (linenum, item)

for pattern, template, header in _re_pattern_headers_maybe_templates:
if pattern.search(line):
Expand All @@ -6084,46 +6095,10 @@ def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error,
if prefix.endswith('std::') or not prefix.endswith('::'):
required[header] = (linenum, template)

# The policy is that if you #include something in foo.h you don't need to
# include it again in foo.cc. Here, we will look at possible includes.
# Let's flatten the include_state include_list and copy it into a dictionary.
include_dict = dict([item for sublist in include_state.include_list
for item in sublist])

# Did we find the header for this file (if any) and successfully load it?
header_found = False

# Use the absolute path so that matching works properly.
abs_filename = FileInfo(filename).FullName()

# For Emacs's flymake.
# If cpplint is invoked from Emacs's flymake, a temporary file is generated
# by flymake and that file name might end with '_flymake.cc'. In that case,
# restore original file name here so that the corresponding header file can be
# found.
# e.g. If the file name is 'foo_flymake.cc', we should search for 'foo.h'
# instead of 'foo_flymake.h'
abs_filename = re.sub(r'_flymake\.cc$', '.cc', abs_filename)

# include_dict is modified during iteration, so we iterate over a copy of
# the keys.
header_keys = list(include_dict.keys())
for header in header_keys:
(same_module, common_path) = FilesBelongToSameModule(abs_filename, header)
fullpath = common_path + header
if same_module and UpdateIncludeState(fullpath, include_dict, io):
header_found = True

# If we can't find the header file for a .cc, assume it's because we don't
# know where to look. In that case we'll give up as we're not sure they
# didn't include it in the .h file.
# TODO(unknown): Do a better job of finding .h files so we are confident that
# not having the .h file means there isn't one.
if not header_found:
for extension in GetNonHeaderExtensions():
if filename.endswith('.' + extension):
return

# All the lines have been processed, report the errors found.
for required_header_unstripped in sorted(required, key=required.__getitem__):
template = required[required_header_unstripped][1]
Expand Down
63 changes: 14 additions & 49 deletions cpplint_unittest.py
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,7 @@ def testErrorSuppression(self):
error_collector = ErrorCollector(self.assertTrue)
cpplint.ProcessFileData('test.cc', 'cc',
['// Copyright 2014 Your Company.',
'#include <iostream>',
'for (int i = 0; i != 100; ++i) {',
' std::cout << i << std::endl;',
'}; // NOLINT',
Expand Down Expand Up @@ -932,13 +933,11 @@ def testTypedefForPointerToFunction(self):

def testIncludeWhatYouUseNoImplementationFiles(self):
code = 'std::vector<int> foo;'
for extension in ['h', 'hpp', 'hxx', 'h++', 'cuh']:
self.assertEqual('Add #include <vector> for vector<>'
for extension in ['h', 'hpp', 'hxx', 'h++', 'cuh',
'c', 'cc', 'cpp', 'cxx', 'c++', 'cu']:
self.assertEquals('Add #include <vector> for vector<>'
' [build/include_what_you_use] [4]',
self.PerformIncludeWhatYouUse(code, 'foo.' + extension))
for extension in ['c', 'cc', 'cpp', 'cxx', 'c++', 'cu']:
self.assertEqual('',
self.PerformIncludeWhatYouUse(code, 'foo.' + extension))

def testIncludeWhatYouUse(self):
self.TestIncludeWhatYouUse(
Expand Down Expand Up @@ -1025,6 +1024,12 @@ def testIncludeWhatYouUse(self):
bool foobar = min<int>(0,1);
""",
'Add #include <algorithm> for min [build/include_what_you_use] [4]')
self.TestIncludeWhatYouUse(
'cout << "hello world" << endl;',
'Add #include <iostream> for cout [build/include_what_you_use] [4]')
self.TestIncludeWhatYouUse(
'printf("hello world");',
'Add #include <cstdio> for printf [build/include_what_you_use] [4]')
self.TestIncludeWhatYouUse(
'void a(const string &foobar);',
'Add #include <string> for string [build/include_what_you_use] [4]')
Expand Down Expand Up @@ -1152,50 +1157,6 @@ def testIncludeWhatYouUse(self):
""",
'')

# Test the UpdateIncludeState code path.
mock_header_contents = ['#include "blah/foo.h"', '#include "blah/bar.h"']
message = self.PerformIncludeWhatYouUse(
'#include "blah/a.h"',
filename='blah/a.cc',
io=MockIo(mock_header_contents))
self.assertEqual(message, '')

mock_header_contents = ['#include <set>']
message = self.PerformIncludeWhatYouUse(
"""#include "blah/a.h"
std::set<int> foo;""",
filename='blah/a.cc',
io=MockIo(mock_header_contents))
self.assertEqual(message, '')

# Make sure we can find the correct header file if the cc file seems to be
# a temporary file generated by Emacs's flymake.
mock_header_contents = ['']
message = self.PerformIncludeWhatYouUse(
"""#include "blah/a.h"
std::set<int> foo;""",
filename='blah/a_flymake.cc',
io=MockIo(mock_header_contents))
self.assertEqual(message, 'Add #include <set> for set<> '
'[build/include_what_you_use] [4]')

# If there's just a cc and the header can't be found then it's ok.
message = self.PerformIncludeWhatYouUse(
"""#include "blah/a.h"
std::set<int> foo;""",
filename='blah/a.cc')
self.assertEqual(message, '')

# Make sure we find the headers with relative paths.
mock_header_contents = ['']
message = self.PerformIncludeWhatYouUse(
"""#include "%s/a.h"
std::set<int> foo;""" % os.path.basename(os.getcwd()),
filename='a.cc',
io=MockIo(mock_header_contents))
self.assertEqual(message, 'Add #include <set> for set<> '
'[build/include_what_you_use] [4]')

def testFilesBelongToSameModule(self):
f = cpplint.FilesBelongToSameModule
self.assertEqual((True, ''), f('a.cc', 'a.h'))
Expand Down Expand Up @@ -2452,6 +2413,8 @@ def testNonConstReference(self):
cpplint.ProcessFileData(
'foo.cc', 'cc',
['// Copyright 2014 Your Company. All Rights Reserved.',
'#include <string>',
'#include <utility>',
'void swap(int &x,',
' int &y) {',
'}',
Expand Down Expand Up @@ -3084,6 +3047,7 @@ def testStaticOrGlobalSTLStrings(self):
error_collector = ErrorCollector(self.assertTrue)
cpplint.ProcessFileData('foo.cc', 'cc',
['// Copyright 2014 Your Company.',
'#include <string>',
'string Class',
'::MemberFunction1();',
'string Class::',
Expand Down Expand Up @@ -5025,6 +4989,7 @@ def testBuildPrintfFormat(self):
cpplint.ProcessFileData(
'foo.cc', 'cc',
['// Copyright 2014 Your Company.',
'#include <cstdio>',
r'printf("\\%%%d", value);',
r'printf(R"(\[)");',
r'printf(R"(\[%s)", R"(\])");',
Expand Down
10 changes: 9 additions & 1 deletion samples/chromium-sample/simple.def
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,26 @@ Done processing src/chrome_content_renderer_client.cc
Done processing src/chrome_content_renderer_client.h
Done processing src/io_thread.cc
Done processing src/io_thread.h
Total errors found: 13
Total errors found: 21

src/chrome_content_renderer_client.cc:113: Include the directory when naming header files [build/include_subdir] [4]
src/chrome_content_renderer_client.cc:1156: Use int16/int64/etc, rather than the C type long [runtime/int] [4]
src/chrome_content_renderer_client.cc:1161: Use int16/int64/etc, rather than the C type long [runtime/int] [4]
src/chrome_content_renderer_client.cc:1203: Add #include <set> for set<> [build/include_what_you_use] [4]
src/chrome_content_renderer_client.cc:1245: Add #include <vector> for vector<> [build/include_what_you_use] [4]
src/chrome_content_renderer_client.cc:1359: Add #include <map> for map<> [build/include_what_you_use] [4]
src/chrome_content_renderer_client.cc:1366: Add #include <string> for string [build/include_what_you_use] [4]
src/chrome_content_renderer_client.cc:5: samples/chromium-sample/src/chrome_content_renderer_client.cc should include its header file samples/chromium-sample/src/chrome_content_renderer_client.h [build/include] [5]
src/chrome_content_renderer_client.h:5: #ifndef header guard has wrong style, please use: SAMPLES_CHROMIUM_SAMPLE_SRC_CHROME_CONTENT_RENDERER_CLIENT_H_ [build/header_guard] [5]
src/chrome_content_renderer_client.h:225: #endif line should be "#endif // SAMPLES_CHROMIUM_SAMPLE_SRC_CHROME_CONTENT_RENDERER_CLIENT_H_" [build/header_guard] [5]
src/chrome_content_renderer_client.h:115: Use int16/int64/etc, rather than the C type long [runtime/int] [4]
src/chrome_content_renderer_client.h:117: Use int16/int64/etc, rather than the C type long [runtime/int] [4]
src/io_thread.cc:1148: Closing ) should be moved to the previous line [whitespace/parens] [2]
src/io_thread.cc:1547: Missing space around colon in range-based for loop [whitespace/forcolon] [2]
src/io_thread.cc:651: Add #include <map> for map<> [build/include_what_you_use] [4]
src/io_thread.cc:1546: Add #include <unordered_set> for unordered_set<> [build/include_what_you_use] [4]
src/io_thread.cc:1609: Add #include <string> for string [build/include_what_you_use] [4]
src/io_thread.cc:1731: Add #include <memory> for unique_ptr<> [build/include_what_you_use] [4]
src/io_thread.cc:5: samples/chromium-sample/src/io_thread.cc should include its header file samples/chromium-sample/src/io_thread.h [build/include] [5]
src/io_thread.h:5: #ifndef header guard has wrong style, please use: SAMPLES_CHROMIUM_SAMPLE_SRC_IO_THREAD_H_ [build/header_guard] [5]
src/io_thread.h:565: #endif line should be "#endif // SAMPLES_CHROMIUM_SAMPLE_SRC_IO_THREAD_H_" [build/header_guard] [5]
Expand Down
6 changes: 5 additions & 1 deletion samples/codelite-sample/simple.def
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ src/*
4
Done processing src/pptable.cpp
Done processing src/pptable.h
Total errors found: 681
Total errors found: 685

src/pptable.cpp:0: No copyright message found. You should have a line: "Copyright [year] <Copyright Owner>" [legal/copyright] [5]
src/pptable.cpp:1: Include the directory when naming header files [build/include_subdir] [4]
Expand Down Expand Up @@ -605,6 +605,10 @@ src/pptable.cpp:660: Tab found; better to use spaces [whitespace/tab] [1]
src/pptable.cpp:661: Tab found; better to use spaces [whitespace/tab] [1]
src/pptable.cpp:662: Tab found; better to use spaces [whitespace/tab] [1]
src/pptable.cpp:663: Tab found; better to use spaces [whitespace/tab] [1]
src/pptable.cpp:526: Add #include <map> for map<> [build/include_what_you_use] [4]
src/pptable.cpp:592: Add #include <vector> for vector<> [build/include_what_you_use] [4]
src/pptable.cpp:602: Add #include <cstdio> for sprintf [build/include_what_you_use] [4]
src/pptable.cpp:648: Add #include <string> for string [build/include_what_you_use] [4]
src/pptable.h:0: No copyright message found. You should have a line: "Copyright [year] <Copyright Owner>" [legal/copyright] [5]
src/pptable.h:1: #ifndef header guard has wrong style, please use: SAMPLES_CODELITE_SAMPLE_SRC_PPTABLE_H_ [build/header_guard] [5]
src/pptable.h:131: #endif line should be "#endif // SAMPLES_CODELITE_SAMPLE_SRC_PPTABLE_H_" [build/header_guard] [5]
Expand Down
5 changes: 4 additions & 1 deletion samples/protobuf-sample/simple.def
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ src/*
Done processing src/descriptor.pb.cc
Done processing src/descriptor.pb.h
Done processing src/descriptor_unittest.cc
Total errors found: 2643
Total errors found: 2646

src/descriptor.pb.cc:0: No copyright message found. You should have a line: "Copyright [year] <Copyright Owner>" [legal/copyright] [5]
src/descriptor.pb.cc:9: Found C system header after C++ system header. Should be: descriptor.pb.h, c system, c++ system, other. [build/include_order] [4]
Expand Down Expand Up @@ -1626,6 +1626,8 @@ src/descriptor.pb.cc:15142: Lines should be <= 80 characters long [whitespace/
src/descriptor.pb.cc:15146: Lines should be <= 80 characters long [whitespace/line_length] [2]
src/descriptor.pb.cc:15150: Lines should be <= 80 characters long [whitespace/line_length] [2]
src/descriptor.pb.cc:15155: Lines should be <= 80 characters long [whitespace/line_length] [2]
src/descriptor.pb.cc:14981: Add #include <utility> for swap [build/include_what_you_use] [4]
src/descriptor.pb.cc:15069: Add #include <string> for string [build/include_what_you_use] [4]
src/descriptor.pb.cc:5: samples/protobuf-sample/src/descriptor.pb.cc should include its header file samples/protobuf-sample/src/descriptor.pb.h [build/include] [5]
src/descriptor.pb.h:0: No copyright message found. You should have a line: "Copyright [year] <Copyright Owner>" [legal/copyright] [5]
src/descriptor.pb.h:4: #ifndef header guard has wrong style, please use: SAMPLES_PROTOBUF_SAMPLE_SRC_DESCRIPTOR_PB_H_ [build/header_guard] [5]
Expand Down Expand Up @@ -2649,4 +2651,5 @@ src/descriptor_unittest.cc:5125: Closing ) should be moved to the previous line
src/descriptor_unittest.cc:5929: Single-parameter constructors should be marked explicit. [runtime/explicit] [5]
src/descriptor_unittest.cc:5968: Single-parameter constructors should be marked explicit. [runtime/explicit] [5]
src/descriptor_unittest.cc:6486: Redundant blank line at the end of a code block should be deleted. [whitespace/blank_line] [3]
src/descriptor_unittest.cc:6437: Add #include <string> for string [build/include_what_you_use] [4]

7 changes: 6 additions & 1 deletion samples/silly-sample/includeorder_cfirst.def
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
1
3
Done processing src/sillycode.cpp
Total errors found: 106
Total errors found: 111

src/sillycode.cpp:0: No copyright message found. You should have a line: "Copyright [year] <Copyright Owner>" [legal/copyright] [5]
src/sillycode.cpp:8: public: should be indented +1 space inside class Date [whitespace/indent] [3]
Expand Down Expand Up @@ -110,4 +110,9 @@ src/sillycode.cpp:257: Tab found; better to use spaces [whitespace/tab] [1]
src/sillycode.cpp:257: At least two spaces is best between code and comments [whitespace/comments] [2]
src/sillycode.cpp:260: Empty loop bodies should use {} or continue [whitespace/empty_loop_body] [5]
src/sillycode.cpp:260: At least two spaces is best between code and comments [whitespace/comments] [2]
src/sillycode.cpp:126: Add #include <utility> for swap [build/include_what_you_use] [4]
src/sillycode.cpp:168: Add #include <memory> for unique_ptr<> [build/include_what_you_use] [4]
src/sillycode.cpp:224: Add #include <limits> for numeric_limits<> [build/include_what_you_use] [4]
src/sillycode.cpp:237: Add #include <string> for string [build/include_what_you_use] [4]
src/sillycode.cpp:244: Add #include <iostream> for cout [build/include_what_you_use] [4]

5 changes: 5 additions & 0 deletions samples/silly-sample/sed.def
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,9 @@ sed -i '208s/\([^ ]\){/\1 {/' src/sillycode.cpp # Missing space before { [white
# src/sillycode.cpp:257: "At least two spaces is best between code and comments" [whitespace/comments] [2]
# src/sillycode.cpp:260: "Empty loop bodies should use {} or continue" [whitespace/empty_loop_body] [5]
# src/sillycode.cpp:260: "At least two spaces is best between code and comments" [whitespace/comments] [2]
# src/sillycode.cpp:126: "Add #include <utility> for swap" [build/include_what_you_use] [4]
# src/sillycode.cpp:168: "Add #include <memory> for unique_ptr<>" [build/include_what_you_use] [4]
# src/sillycode.cpp:224: "Add #include <limits> for numeric_limits<>" [build/include_what_you_use] [4]
# src/sillycode.cpp:237: "Add #include <string> for string" [build/include_what_you_use] [4]
# src/sillycode.cpp:244: "Add #include <iostream> for cout" [build/include_what_you_use] [4]

Loading