Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1623)

Unified Diff: third_party/WebKit/Tools/Scripts/webkitpy/style/checkers/cpp.py

Issue 2800883004: Port cpplint's C++11 raw string support to blink's cpp style checker. (Closed)
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | third_party/WebKit/Tools/Scripts/webkitpy/style/checkers/cpp_unittest.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/WebKit/Tools/Scripts/webkitpy/style/checkers/cpp.py
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/style/checkers/cpp.py b/third_party/WebKit/Tools/Scripts/webkitpy/style/checkers/cpp.py
index c7a179f7c1adec8b7e1e33e79d87fbbe9664d714..0872b56b1b83e24c821420b391678d59bcbd1799 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/style/checkers/cpp.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/style/checkers/cpp.py
@@ -689,6 +689,80 @@ def is_cpp_string(line):
return ((line.count('"') - line.count(r'\"') - line.count("'\"'")) & 1) == 1
+def cleanse_raw_strings(raw_lines):
+ """Removes C++11 raw strings from lines.
+
+ Before:
+ static const char kData[] = R"(
+ multi-line string
+ )";
+
+ After:
+ static const char kData[] = ""
+ (replaced by blank line)
+ "";
+
+ Args:
+ raw_lines: list of raw lines.
+
+ Returns:
+ list of lines with C++11 raw strings replaced by empty strings.
+ """
+
+ delimiter = None
+ lines_without_raw_strings = []
+ for line in raw_lines:
+ if delimiter:
+ # Inside a raw string, look for the end
+ end = line.find(delimiter)
+ if end >= 0:
+ # Found the end of the string, match leading space for this
+ # line and resume copying the original lines, and also insert
+ # a "" on the last line.
+ leading_space = match(r'^(\s*)\S', line)
+ line = leading_space.group(1) + '""' + line[end + len(delimiter):]
+ delimiter = None
+ else:
+ # Haven't found the end yet, append a blank line.
+ line = '""'
+
+ # Look for beginning of a raw string, and replace them with
+ # empty strings. This is done in a loop to handle multiple raw
+ # strings on the same line.
+ while delimiter is None:
+ # Look for beginning of a raw string.
+ # See 2.14.15 [lex.string] for syntax.
+ #
+ # Once we have matched a raw string, we check the prefix of the
+ # line to make sure that the line is not part of a single line
+ # comment. It's done this way because we remove raw strings
+ # before removing comments as opposed to removing comments
+ # before removing raw strings. This is because there are some
+ # cpplint checks that requires the comments to be preserved, but
+ # we don't want to check comments that are inside raw strings.
+ matched = match(r'^(.*?)\b(?:R|u8R|uR|UR|LR)"([^\s\\()]*)\((.*)$', line)
+ if matched and not match(r'^([^\'"]|\'(\\.|[^\'])*\'|"(\\.|[^"])*")*//', matched.group(1)):
+ delimiter = ')' + matched.group(2) + '"'
+
+ end = matched.group(3).find(delimiter)
+ if end >= 0:
+ # Raw string ended on same line
+ line = (matched.group(1) + '""' +
+ matched.group(3)[end + len(delimiter):])
+ delimiter = None
+ else:
+ # Start of a multi-line raw string
+ line = matched.group(1) + '""'
+ else:
+ break
+
+ lines_without_raw_strings.append(line)
+
+ # TODO(unknown): if delimiter is not None here, we might want to
+ # emit a warning for unterminated string.
+ return lines_without_raw_strings
+
+
def find_next_multi_line_comment_start(lines, line_index):
"""Find the beginning marker for a multiline comment."""
while line_index < len(lines):
@@ -750,12 +824,14 @@ def cleanse_comments(line):
class CleansedLines(object):
- """Holds 3 copies of all lines with different preprocessing applied to them.
-
- 1) elided member contains lines without strings and comments,
- 2) lines member contains lines without comments, and
- 3) raw member contains all the lines without processing.
- All these three members are of <type 'list'>, and of the same length.
+ """Holds 4 copies of all lines with different preprocessing applied to them.
+
+ 1) elided member contains lines without strings and comments.
+ 2) lines member contains lines without comments.
+ 3) raw_lines member contains all the lines without processing.
+ 4) lines_without_raw_strings member is same as raw_lines, but with C++11 raw
+ strings removed.
+ All these members are of <type 'list'>, and of the same length.
"""
def __init__(self, lines):
@@ -763,9 +839,10 @@ class CleansedLines(object):
self.lines = []
self.raw_lines = lines
self._num_lines = len(lines)
- for line_number in range(len(lines)):
- self.lines.append(cleanse_comments(lines[line_number]))
- elided = self.collapse_strings(lines[line_number])
+ self.lines_without_raw_strings = cleanse_raw_strings(lines)
+ for line_number in range(len(self.lines_without_raw_strings)):
+ self.lines.append(cleanse_comments(self.lines_without_raw_strings[line_number]))
+ elided = self.collapse_strings(self.lines_without_raw_strings[line_number])
self.elided.append(cleanse_comments(elided))
def num_lines(self):
@@ -916,7 +993,7 @@ def get_header_guard_cpp_variable(filename):
return standard_name
-def check_for_header_guard(filename, lines, error):
+def check_for_header_guard(filename, clean_lines, error):
"""Checks that the file contains a header guard.
Logs an error if no #ifndef header guard is present. For other
@@ -927,6 +1004,7 @@ def check_for_header_guard(filename, lines, error):
lines: An array of strings, each representing a line of the file.
error: The function to call with any errors found.
"""
+ raw_lines = clean_lines.lines_without_raw_strings
legacy_cpp_var = get_legacy_header_guard_cpp_variable(filename)
cpp_var = get_header_guard_cpp_variable(filename)
@@ -934,7 +1012,7 @@ def check_for_header_guard(filename, lines, error):
ifndef = None
ifndef_line_number = 0
define = None
- for line_number, line in enumerate(lines):
+ for line_number, line in enumerate(raw_lines):
line_split = line.split()
if len(line_split) >= 2:
# find the first occurrence of #ifndef and #define, save arg
@@ -1704,7 +1782,11 @@ def check_spacing(file_extension, clean_lines, line_number, error):
error: The function to call with any errors found.
"""
- line = clean_lines.elided[line_number] # get rid of comments and strings
+ # Don't use "elided" lines here, otherwise we can't check commented lines.
+ # Don't want to use "raw" either, because we don't want to check inside C++11
+ # raw strings,
+ raw = clean_lines.lines_without_raw_strings
+ line = raw[line_number]
# You shouldn't have a space before a semicolon at the end of the line.
# There's a special case for "for" since the style guide allows space before
@@ -2351,7 +2433,10 @@ def check_style(clean_lines, line_number, file_extension, class_state, file_stat
error: The function to call with any errors found.
"""
- raw_lines = clean_lines.raw_lines
+ # Don't use "elided" lines here, otherwise we can't check commented lines.
+ # Don't want to use "raw" either, because we don't want to check inside C++11
+ # raw strings,
+ raw_lines = clean_lines.lines_without_raw_strings
line = raw_lines[line_number]
# Some more style checks
@@ -3278,12 +3363,12 @@ def _process_lines(filename, file_extension, lines, error, min_confidence):
class_state = _ClassState()
check_for_copyright(lines, error)
+ remove_multi_line_comments(lines, error)
+ clean_lines = CleansedLines(lines)
if file_extension == 'h':
- check_for_header_guard(filename, lines, error)
+ check_for_header_guard(filename, clean_lines, error)
- remove_multi_line_comments(lines, error)
- clean_lines = CleansedLines(lines)
file_state = _FileState(clean_lines, file_extension)
enum_state = _EnumState()
for line in xrange(clean_lines.num_lines()):
« no previous file with comments | « no previous file | third_party/WebKit/Tools/Scripts/webkitpy/style/checkers/cpp_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698