cpplint_wrapper.py
Go to the documentation of this file.
1 # Software License Agreement (BSD License)
2 #
3 # copyright (c) 2014-2015 roslint contributors
4 # all rights reserved
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 #
10 # * Redistributions of source code must retain the above copyright
11 # notice, this list of conditions and the following disclaimer.
12 # * Redistributions in binary form must reproduce the above
13 # copyright notice, this list of conditions and the following
14 # disclaimer in the documentation and/or other materials provided
15 # with the distribution.
16 # * Neither the name of Willow Garage, Inc. nor the names of its
17 # contributors may be used to endorse or promote products derived
18 # from this software without specific prior written permission.
19 #
20 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 # POSSIBILITY OF SUCH DAMAGE.
32 
33 from . import cpplint
34 from .cpplint import Match, IsBlankLine, main
35 from functools import partial
36 
37 import os.path
38 import re
39 import sys
40 
41 # Line length as per the ROS C++ Style Guide
42 cpplint._line_length = 120
43 
44 
45 def patch(original_module):
46  """ Decorator to easily allow wrapping/overriding of the Check* functions in cpplint. Should
47  decorate a function which matches the signature of the function it replaces expect with
48  the addition of a fn parameter, which is a pass-through of the replaced function, in case
49  the replacement would like call through to the original functionality. """
50  def wrap(override_fn):
51  original_fn = getattr(original_module, override_fn.__name__)
52  setattr(original_module, override_fn.__name__, partial(override_fn, original_fn))
53 
54  # Don't actually modify the function being decorated.
55  return override_fn
56  return wrap
57 
58 
59 def makeErrorFn(original_fn, suppress_categories, suppress_message_matches):
60  """ Create a return a wrapped version of the error-report function which suppresses specific
61  error categories. """
62  def newError(filename, linenum, category, confidence, message):
63  if category in suppress_categories:
64  return
65  if True in [bool(Match(r, message)) for r in suppress_message_matches]:
66  return
67  original_fn(filename, linenum, category, confidence, message)
68  return newError
69 
70 
71 @patch(cpplint)
72 def GetHeaderGuardCPPVariable(fn, filename):
73  """ Replacement for the function which determines the header guard variable, to pick one which
74  matches ROS C++ Style. """
75  var_parts = list()
76  head = filename
77  while head:
78  head, tail = os.path.split(head)
79  var_parts.insert(0, tail)
80  if head.endswith('include') or os.path.exists(os.path.join(head, "package.xml")) or tail == "":
81  break
82  return re.sub(r'[-./\s]', '_', "_".join(var_parts)).upper()
83 
84 
85 @patch(cpplint)
86 def CheckBraces(fn, filename, clean_lines, linenum, error):
87  """ Complete replacement for cpplint.CheckBraces, since the brace rules for ROS C++ Style
88  are completely different from the Google style guide ones. """
89  line = clean_lines.elided[linenum]
90  if Match(r'^(.*){(.*)}.*$', line):
91  # Special case when both braces are on the same line together, as is the
92  # case for one-line getters and setters, for example, or rows of a multi-
93  # dimenstional array initializer.
94  pass
95  else:
96  # Line does not contain both an opening and closing brace.
97  m = Match(r'^(.*){(.*)$', line)
98  if m and not (IsBlankLine(m.group(1))):
99  # Line contains a starting brace and is not empty, uh oh.
100  if "=" in line and Match(r'\)( *){$', line):
101  # Opening brace is permissable in case of an initializer.
102  pass
103  else:
104  error(filename, linenum, 'whitespace/braces', 4,
105  'when starting a new scope, { should be on a line by itself')
106  m = Match(r'^(.*)}(.*)$', line)
107  if m and (not IsBlankLine(m.group(1)) or not IsBlankLine(m.group(2))):
108  if m.group(2) != ";":
109  error(filename, linenum, 'whitespace/braces', 4,
110  '} should be on a line by itself')
111  pass
112 
113 
114 @patch(cpplint)
115 def CheckIncludeLine(fn, filename, clean_lines, linenum, include_state, error):
116  """ Run the function to get include state, but suppress all the errors, since
117  ROS C++ Style is silent on include order, and contains no prohibition on use of streams. """
118  fn(filename, clean_lines, linenum, include_state,
119  makeErrorFn(error, ['build/include_order', 'build/include_alpha', 'readability/streams'], []))
120 
121 
122 @patch(cpplint)
123 def CheckSpacing(fn, filename, clean_lines, linenum, nesting_state, error):
124  """ Do most of the original Spacing checks, but suppress the ones related to braces, since
125  the ROS C++ Style rules are different. """
126  fn(filename, clean_lines, linenum, nesting_state,
127  makeErrorFn(error, ['readability/braces', 'whitespace/braces'], []))
128 
129 
130 @patch(cpplint)
131 def ProcessLine(fn, filename, file_extension, clean_lines, line,
132  include_state, function_state, nesting_state, error,
133  extra_check_functions=[]):
134  """ Squelch the error about access control indents. """
135  fn(filename, file_extension, clean_lines, line,
136  include_state, function_state, nesting_state,
137  makeErrorFn(error, [], [r'(.*)should be indented \+1 space inside(.*)']),
138  extra_check_functions=[])
139 
140 
141 @patch(cpplint)
142 def CheckEmptyBlockBody(fn, filename, clean_lines, linenum, error):
143  """ Look for empty loop/conditional body with only a single semicolon,
144  but allow ros-style do while loops. """
145  from roslint.cpplint import CloseExpression
146 
147  # Search for loop keywords at the beginning of the line. Because only
148  # whitespaces are allowed before the keywords, this will also ignore most
149  # do-while-loops, since those lines should start with closing brace.
150  #
151  # We also check "if" blocks here, since an empty conditional block
152  # is likely an error.
153  line = clean_lines.elided[linenum]
154  matched = Match(r'\s*(for|while|if)\s*\(', line)
155  if matched:
156  # Find the end of the conditional expression
157  (end_line, end_linenum, end_pos) = CloseExpression(
158  clean_lines, linenum, line.find('('))
159 
160  # Output warning if what follows the condition expression is a
161  # semicolon. No warning for all other cases, including
162  # whitespace or newline, since we have a separate check for
163  # semicolons preceded by whitespace.
164  if end_pos >= 0 and Match(r';', end_line[end_pos:]):
165  if matched.group(1) == 'if':
166  error(filename, end_linenum,
167  'whitespace/empty_conditional_body', 5,
168  'Empty conditional bodies should use {}')
169  elif matched.group(1) == 'while' and linenum != 0 \
170  and "}" in clean_lines.elided[linenum-1]:
171  # Don't report an error for ros style do-whiles. Works
172  # by checking for a closing brace on the previous
173  # line, since that means it's probably a do-while
174  # loop.
175  return
176  else:
177  error(filename, end_linenum, 'whitespace/empty_loop_body', 5,
178  'Empty loop bodies should use {} or continue')
179 
180 
181 if __name__ == '__main__':
182  sys.argv.insert(1, "--filter=-runtime/references")
183  main()
roslint.cpplint_wrapper.CheckSpacing
def CheckSpacing(fn, filename, clean_lines, linenum, nesting_state, error)
Definition: cpplint_wrapper.py:123
roslint.cpplint_wrapper.GetHeaderGuardCPPVariable
def GetHeaderGuardCPPVariable(fn, filename)
Definition: cpplint_wrapper.py:72
roslint.cpplint_wrapper.CheckEmptyBlockBody
def CheckEmptyBlockBody(fn, filename, clean_lines, linenum, error)
Definition: cpplint_wrapper.py:142
roslint.cpplint.CloseExpression
def CloseExpression(clean_lines, linenum, pos)
Definition: cpplint.py:1600
roslint.cpplint
Definition: cpplint.py:1
roslint.cpplint_wrapper.patch
def patch(original_module)
Definition: cpplint_wrapper.py:45
roslint.cpplint_wrapper.ProcessLine
def ProcessLine(fn, filename, file_extension, clean_lines, line, include_state, function_state, nesting_state, error, extra_check_functions=[])
Definition: cpplint_wrapper.py:131
roslint.cpplint_wrapper.CheckBraces
def CheckBraces(fn, filename, clean_lines, linenum, error)
Definition: cpplint_wrapper.py:86
roslint.cpplint.IsBlankLine
def IsBlankLine(line)
Definition: cpplint.py:3020
roslint.cpplint_wrapper.CheckIncludeLine
def CheckIncludeLine(fn, filename, clean_lines, linenum, include_state, error)
Definition: cpplint_wrapper.py:115
roslint.cpplint.main
def main()
Definition: cpplint.py:6226
roslint.cpplint.Match
def Match(pattern, s)
Definition: cpplint.py:660
roslint.cpplint_wrapper.makeErrorFn
def makeErrorFn(original_fn, suppress_categories, suppress_message_matches)
Definition: cpplint_wrapper.py:59


roslint
Author(s): Mike Purvis, Jack O'Quin
autogenerated on Tue Mar 7 2023 03:27:03