diff options
author | Gil <mcg@google.com> | 2018-04-09 11:54:39 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-04-09 11:54:39 -0700 |
commit | 0a6618705389543191a8c44278d4c6791c84602a (patch) | |
tree | 4f195f31da90b29ffa5219e016b2cfd9ad0a7ccf /scripts/cpplint.py | |
parent | 2f2bb7f4c717bb95df69735e93ae84de8b8feaad (diff) |
Add lint checking for Objective-C++ sources (#1048)
* lint.sh now lints Objective-C++ too
* cpplint checks system-style includes that should be user-style
This prevents it from recognizing project sources as if they were C
system headers and then complaining that they're in the wrong place.
* cpplint checks #imports and #includes
* cpplint checks that C++ system headers aren't #imported
* cpplint checks for C system headers that could be C++ system headers
* cpplint checks that Objective-C sources include their headers
Diffstat (limited to 'scripts/cpplint.py')
-rw-r--r-- | scripts/cpplint.py | 38 |
1 files changed, 36 insertions, 2 deletions
diff --git a/scripts/cpplint.py b/scripts/cpplint.py index d1c80b3..f09695c 100644 --- a/scripts/cpplint.py +++ b/scripts/cpplint.py @@ -428,6 +428,11 @@ _CPP_HEADERS = frozenset([ 'cwctype', ]) +_C_SYSTEM_DIRECTORIES = frozenset([ + 'libkern', + 'sys', +]) + # Type names _TYPES = re.compile( r'^(?:' @@ -685,7 +690,7 @@ def Search(pattern, s): def _IsSourceExtension(s): """File extension (excluding dot) matches a source file extension.""" - return s in ('c', 'cc', 'cpp', 'cxx') + return s in ('c', 'cc', 'cpp', 'cxx', 'm', 'mm') class _IncludeState(object): @@ -4411,7 +4416,7 @@ def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state, CheckSectionSpacing(filename, clean_lines, classinfo, linenum, error) -_RE_PATTERN_INCLUDE = re.compile(r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$') +_RE_PATTERN_INCLUDE = re.compile(r'^\s*#\s*(?:include|import)\s*([<"])([^>"]*)[>"].*$') # Matches the first component of a filename delimited by -s and _s. That is: # _RE_FIRST_COMPONENT.match('foo').group(0) == 'foo' # _RE_FIRST_COMPONENT.match('foo.cc').group(0) == 'foo' @@ -4444,6 +4449,11 @@ def _DropCommonSuffixes(filename): if (filename.endswith(suffix) and len(filename) > len(suffix) and filename[-len(suffix) - 1] in ('-', '_')): return filename[:-len(suffix) - 1] + + for suffix in ['Tests.h', 'Test.m', 'Test.mm', 'Tests.m', 'Tests.mm']: + if (filename.endswith(suffix) and len(filename) > len(suffix)): + return filename[:-len(suffix)] + return os.path.splitext(filename)[0] @@ -4524,6 +4534,30 @@ def CheckIncludeLine(filename, clean_lines, linenum, include_state, error): fileinfo = FileInfo(filename) line = clean_lines.lines[linenum] + # system-style includes should not be used for project includes + match = Match(r'#include\s*<(([^/>]+)/[^>]+)', line) + if match: + if match.group(2) not in _C_SYSTEM_DIRECTORIES: + error(filename, linenum, 'build/include', 4, + '<%s> should be #include "%s" or #import <%s>' % + (match.group(1), match.group(1), match.group(1))) + + # C++ system files should not be #imported + match = Match(r'#import\s*<([^/>.]+)>', line) + if match: + error(filename, linenum, 'build/include', 4, + 'C++ header <%s> was #imported. Should be #include <%s>' % + (match.group(1), match.group(1))) + + # Prefer C++ wrappers for C headers + match = Match(r'#include\s*<(([^>]+).h)>', line) + if match: + wrapper = 'c' + match.group(2) + if wrapper in _CPP_HEADERS: + error(filename, linenum, 'build/include', 4, + 'Prefer C++ header <%s> for C system header %s' % + (wrapper, match.group(1))) + # "include" should use the new style "foo/bar.h" instead of just "bar.h" # Only do this check if the included header follows google naming # conventions. If not, assume that it's a 3rd party API that |