Skip to content

Commit 5d2a134

Browse files
authored
Merge pull request #31 from jwnimmer-tri/c-style-80
cpplint: Enforce line_length on C-style comments
2 parents 47a6f40 + c532aed commit 5d2a134

File tree

2 files changed

+77
-14
lines changed

2 files changed

+77
-14
lines changed

cpplint/cpplint.py

Lines changed: 60 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1384,12 +1384,61 @@ def FindNextMultiLineCommentEnd(lines, lineix):
13841384
return len(lines)
13851385

13861386

1387-
def RemoveMultiLineCommentsFromRange(lines, begin, end):
1388-
"""Clears a range of lines for multi-line comments."""
1389-
# Having // dummy comments makes the lines non-empty, so we will not get
1390-
# unnecessary blank line warnings later in the code.
1387+
def ReplaceMultiLineCommentsInRange(filename, lines, begin, end, error):
1388+
"""Replaces multi-line C-style comments with line-by-line C++ comments.
1389+
This enables the existing line-by-line comment linting to take effect.
1390+
Retains empty lines, line length, and indentation to the extent practical.
1391+
"""
1392+
assert begin + 1 <= end - 1, "The range must be multi-line"
1393+
# Find the common whitespace prefix for all lines.
1394+
prefix, _ = lines[begin].split('/*', 2)
1395+
if len(prefix.strip()) > 0:
1396+
error(filename, i, 'readability/multiline_comment', 5,
1397+
'Multi-line comments should start on a dedicated line')
1398+
return
1399+
# Rewrite each line to C++ comment instead of C comment.
13911400
for i in range(begin, end):
1392-
lines[i] = '/**/'
1401+
line = lines[i]
1402+
# Handle the first line specially.
1403+
# Change "/* Foo" to "// Foo", "/** Bar" to "/// Bar".
1404+
if i == begin:
1405+
lines[i] = line.replace('*', '/')
1406+
continue
1407+
# Leave interior blank lines untouched.
1408+
if len(line) == 0:
1409+
continue
1410+
# Check for the common whitespace prefix.
1411+
if not line.startswith(prefix):
1412+
error(filename, i, 'readability/multiline_comment', 5,
1413+
'Inconsistent indentation on multi-line comment')
1414+
continue
1415+
suffix = line[len(prefix):]
1416+
# Handle the last line specially.
1417+
if i == (end - 1):
1418+
# Check that there is nothing after the comment close.
1419+
_, after = suffix.split('*/', 2)
1420+
if after:
1421+
error(filename, i, 'readability/multiline_comment', 5,
1422+
'There should not be anything after the */ that closes a '
1423+
'multi-line comment')
1424+
continue
1425+
# Change "Foo */" to "Foo ./" and then treat it like a middle line.
1426+
suffix = suffix.replace('*', '.')
1427+
# Add a leading '//' to non-initial lines.
1428+
if len(prefix) > 4:
1429+
# We can overwrite the prefix while retaining 2-space indent.
1430+
lines[i] = prefix[:-4] + '// ' + suffix
1431+
elif len(suffix) < 3:
1432+
# The line is trivially short. Not much we can do.
1433+
lines[i] = '/' * len(line)
1434+
else:
1435+
# Shorten the comment by deleting 3 letters in the middle. This
1436+
# preserves the end of line (for trailing whitespace complaints)
1437+
# and the start of line (for http URLs to still look like URLs).
1438+
mid = len(suffix) // 2
1439+
new_suffix = suffix[:mid-2] + suffix[mid+1:]
1440+
# Insert the comment marker and then the trimmed suffix.
1441+
lines[i] = prefix + '// ' + new_suffix
13931442

13941443

13951444
def RemoveMultiLineComments(filename, lines, error):
@@ -1404,7 +1453,8 @@ def RemoveMultiLineComments(filename, lines, error):
14041453
error(filename, lineix_begin + 1, 'readability/multiline_comment', 5,
14051454
'Could not find end of multi-line comment')
14061455
return
1407-
RemoveMultiLineCommentsFromRange(lines, lineix_begin, lineix_end + 1)
1456+
ReplaceMultiLineCommentsInRange(
1457+
filename, lines, lineix_begin, lineix_end + 1, error)
14081458
lineix = lineix_end + 1
14091459

14101460

@@ -4418,11 +4468,15 @@ def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
44184468
# URLs can be long too. It's possible to split these, but it makes them
44194469
# harder to cut&paste.
44204470
#
4471+
# Tables of data (1.0 | 2.0 | 3.0 | ...) are sometimes easier grok as long
4472+
# lines, so we pass any comment with at least two " | ".
4473+
#
44214474
# The "$Id:...$" comment may also get very long without it being the
44224475
# developers fault.
44234476
if (not line.startswith('#include') and not is_header_guard and
44244477
not Match(r'^\s*//.*http(s?)://\S*$', line) and
44254478
not Match(r'^\s*//\s*[^\s]*$', line) and
4479+
not Match(r'^\s*//(.* \| ){2,}', line) and
44264480
not Match(r'^// \$Id:.*#[0-9]+ \$$', line)):
44274481
line_width = GetLineWidth(line)
44284482
if line_width > _line_length:

cpplint/cpplint_unittest.py

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -361,10 +361,21 @@ def testFindNextMultiLineCommentEnd(self):
361361
lines = ['a', 'b', ' c */']
362362
self.assertEquals(2, cpplint.FindNextMultiLineCommentEnd(lines, 0))
363363

364-
def testRemoveMultiLineCommentsFromRange(self):
365-
lines = ['a', ' /* comment ', ' * still comment', ' comment */ ', 'b']
366-
cpplint.RemoveMultiLineCommentsFromRange(lines, 1, 4)
367-
self.assertEquals(['a', '/**/', '/**/', '/**/', 'b'], lines)
364+
def testReplaceMultiLineCommentsInRange(self):
365+
lines = [
366+
'a',
367+
' /* comment ',
368+
' * still comment',
369+
' comment */',
370+
'b']
371+
cpplint.ReplaceMultiLineCommentsInRange(None, lines, 1, 4, None)
372+
self.assertEquals([
373+
'a',
374+
' // comment ',
375+
' // * sticomment',
376+
' // comt ./',
377+
'b'],
378+
lines)
368379

369380
def testSpacesAtEndOfLine(self):
370381
self.TestLint(
@@ -513,9 +524,7 @@ def testErrorSuppression(self):
513524
'// NOLINT(build/header_guard)',
514525
'// NOLINT(build/pragma_once)',
515526
'int64 a = (uint64) 65;',
516-
'/* Prevent warnings about the modeline',
517-
modeline,
518-
'*/',
527+
'// ' + modeline,
519528
''],
520529
error_collector)
521530
self.assertEquals('', error_collector.Results())
@@ -1317,7 +1326,7 @@ def testMultiLineComments(self):
13171326
class Foo {
13181327
Foo(int f); // should cause a lint warning in code
13191328
}
1320-
*/ """,
1329+
*/""",
13211330
'')
13221331
self.TestMultiLineLint(
13231332
r"""/* int a = 0; multi-liner

0 commit comments

Comments
 (0)