Changeset View
Changeset View
Standalone View
Standalone View
test/lint/lint-format-strings.py
Show First 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | def parse_function_calls(function_name, source_code): | ||||
True | True | ||||
>>> parse_function_calls("foo", "foo(1);bar(1);foo(2);bar(2);")[1].startswith("foo(2);") | >>> parse_function_calls("foo", "foo(1);bar(1);foo(2);bar(2);")[1].startswith("foo(2);") | ||||
True | True | ||||
>>> len(parse_function_calls("foo", "foo();bar();// foo();bar();")) | >>> len(parse_function_calls("foo", "foo();bar();// foo();bar();")) | ||||
1 | 1 | ||||
>>> len(parse_function_calls("foo", "#define FOO foo();")) | >>> len(parse_function_calls("foo", "#define FOO foo();")) | ||||
0 | 0 | ||||
""" | """ | ||||
assert type(function_name) is str and type( | assert isinstance(function_name, str) and isinstance( | ||||
source_code) is str and function_name | source_code, str) and function_name | ||||
lines = [re.sub("// .*", " ", line).strip() | lines = [re.sub("// .*", " ", line).strip() | ||||
for line in source_code.split("\n") | for line in source_code.split("\n") | ||||
if not line.strip().startswith("#")] | if not line.strip().startswith("#")] | ||||
return re.findall(r"[^a-zA-Z_](?=({}\(.*).*)".format(function_name), " " + " ".join(lines)) | return re.findall(r"[^a-zA-Z_](?=({}\(.*).*)".format(function_name), " " + " ".join(lines)) | ||||
def normalize(s): | def normalize(s): | ||||
"""Return a normalized version of string s with newlines, tabs and C style comments ("/* ... */") | """Return a normalized version of string s with newlines, tabs and C style comments ("/* ... */") | ||||
replaced with spaces. Multiple spaces are replaced with a single space. | replaced with spaces. Multiple spaces are replaced with a single space. | ||||
>>> normalize(" /* nothing */ foo\tfoo /* bar */ foo ") | >>> normalize(" /* nothing */ foo\tfoo /* bar */ foo ") | ||||
'foo foo foo' | 'foo foo foo' | ||||
""" | """ | ||||
assert type(s) is str | assert isinstance(s, str) | ||||
s = s.replace("\n", " ") | s = s.replace("\n", " ") | ||||
s = s.replace("\t", " ") | s = s.replace("\t", " ") | ||||
s = re.sub(r"/\*.*?\*/", " ", s) | s = re.sub(r"/\*.*?\*/", " ", s) | ||||
s = re.sub(" {2,}", " ", s) | s = re.sub(" {2,}", " ", s) | ||||
return s.strip() | return s.strip() | ||||
ESCAPE_MAP = { | ESCAPE_MAP = { | ||||
r"\n": "[escaped-newline]", | r"\n": "[escaped-newline]", | ||||
r"\t": "[escaped-tab]", | r"\t": "[escaped-tab]", | ||||
r'\"': "[escaped-quote]", | r'\"': "[escaped-quote]", | ||||
} | } | ||||
def escape(s): | def escape(s): | ||||
"""Return the escaped version of string s with "\\\"", "\\n" and "\\t" escaped as | """Return the escaped version of string s with "\\\"", "\\n" and "\\t" escaped as | ||||
"[escaped-backslash]", "[escaped-newline]" and "[escaped-tab]". | "[escaped-backslash]", "[escaped-newline]" and "[escaped-tab]". | ||||
>>> unescape(escape("foo")) == "foo" | >>> unescape(escape("foo")) == "foo" | ||||
True | True | ||||
>>> escape(r'foo \\t foo \\n foo \\\\ foo \\ foo \\"bar\\"') | >>> escape(r'foo \\t foo \\n foo \\\\ foo \\ foo \\"bar\\"') | ||||
'foo [escaped-tab] foo [escaped-newline] foo \\\\\\\\ foo \\\\ foo [escaped-quote]bar[escaped-quote]' | 'foo [escaped-tab] foo [escaped-newline] foo \\\\\\\\ foo \\\\ foo [escaped-quote]bar[escaped-quote]' | ||||
""" | """ | ||||
assert type(s) is str | assert isinstance(s, str) | ||||
for raw_value, escaped_value in ESCAPE_MAP.items(): | for raw_value, escaped_value in ESCAPE_MAP.items(): | ||||
s = s.replace(raw_value, escaped_value) | s = s.replace(raw_value, escaped_value) | ||||
return s | return s | ||||
def unescape(s): | def unescape(s): | ||||
"""Return the unescaped version of escaped string s. | """Return the unescaped version of escaped string s. | ||||
Reverses the replacements made in function escape(s). | Reverses the replacements made in function escape(s). | ||||
>>> unescape(escape("bar")) | >>> unescape(escape("bar")) | ||||
'bar' | 'bar' | ||||
>>> unescape("foo [escaped-tab] foo [escaped-newline] foo \\\\\\\\ foo \\\\ foo [escaped-quote]bar[escaped-quote]") | >>> unescape("foo [escaped-tab] foo [escaped-newline] foo \\\\\\\\ foo \\\\ foo [escaped-quote]bar[escaped-quote]") | ||||
'foo \\\\t foo \\\\n foo \\\\\\\\ foo \\\\ foo \\\\"bar\\\\"' | 'foo \\\\t foo \\\\n foo \\\\\\\\ foo \\\\ foo \\\\"bar\\\\"' | ||||
""" | """ | ||||
assert type(s) is str | assert isinstance(s, str) | ||||
for raw_value, escaped_value in ESCAPE_MAP.items(): | for raw_value, escaped_value in ESCAPE_MAP.items(): | ||||
s = s.replace(escaped_value, raw_value) | s = s.replace(escaped_value, raw_value) | ||||
return s | return s | ||||
def parse_function_call_and_arguments(function_name, function_call): | def parse_function_call_and_arguments(function_name, function_call): | ||||
"""Split string function_call into an array of strings consisting of: | """Split string function_call into an array of strings consisting of: | ||||
* the string function_call followed by "(" | * the string function_call followed by "(" | ||||
Show All 16 Lines | def parse_function_call_and_arguments(function_name, function_call): | ||||
['foo(', 'bar(foobar(barfoo("foo"))),', ' foobar', ')'] | ['foo(', 'bar(foobar(barfoo("foo"))),', ' foobar', ')'] | ||||
>>> parse_function_call_and_arguments("foo", "foo()") | >>> parse_function_call_and_arguments("foo", "foo()") | ||||
['foo(', '', ')'] | ['foo(', '', ')'] | ||||
>>> parse_function_call_and_arguments("foo", "foo(123)") | >>> parse_function_call_and_arguments("foo", "foo(123)") | ||||
['foo(', '123', ')'] | ['foo(', '123', ')'] | ||||
>>> parse_function_call_and_arguments("foo", 'foo("foo")') | >>> parse_function_call_and_arguments("foo", 'foo("foo")') | ||||
['foo(', '"foo"', ')'] | ['foo(', '"foo"', ')'] | ||||
""" | """ | ||||
assert type(function_name) is str and type( | assert isinstance(function_name, str) and isinstance( | ||||
function_call) is str and function_name | function_call, str) and function_name | ||||
remaining = normalize(escape(function_call)) | remaining = normalize(escape(function_call)) | ||||
expected_function_call = "{}(".format(function_name) | expected_function_call = "{}(".format(function_name) | ||||
assert remaining.startswith(expected_function_call) | assert remaining.startswith(expected_function_call) | ||||
parts = [expected_function_call] | parts = [expected_function_call] | ||||
remaining = remaining[len(expected_function_call):] | remaining = remaining[len(expected_function_call):] | ||||
open_parentheses = 1 | open_parentheses = 1 | ||||
in_string = False | in_string = False | ||||
parts.append("") | parts.append("") | ||||
Show All 35 Lines | def parse_string_content(argument): | ||||
'foo bar' | 'foo bar' | ||||
>>> parse_string_content('""') | >>> parse_string_content('""') | ||||
'' | '' | ||||
>>> parse_string_content('') | >>> parse_string_content('') | ||||
'' | '' | ||||
>>> parse_string_content('1 2 3') | >>> parse_string_content('1 2 3') | ||||
'' | '' | ||||
""" | """ | ||||
assert type(argument) is str | assert isinstance(argument, str) | ||||
string_content = "" | string_content = "" | ||||
in_string = False | in_string = False | ||||
for char in normalize(escape(argument)): | for char in normalize(escape(argument)): | ||||
if char == "\"": | if char == "\"": | ||||
in_string = not in_string | in_string = not in_string | ||||
elif in_string: | elif in_string: | ||||
string_content += char | string_content += char | ||||
return string_content | return string_content | ||||
Show All 10 Lines | def count_format_specifiers(format_string): | ||||
2 | 2 | ||||
>>> count_format_specifiers("foo %d bar %i foo %% foo") | >>> count_format_specifiers("foo %d bar %i foo %% foo") | ||||
2 | 2 | ||||
>>> count_format_specifiers("foo %d bar %i foo %% foo %d foo") | >>> count_format_specifiers("foo %d bar %i foo %% foo %d foo") | ||||
3 | 3 | ||||
>>> count_format_specifiers("foo %d bar %i foo %% foo %*d foo") | >>> count_format_specifiers("foo %d bar %i foo %% foo %*d foo") | ||||
4 | 4 | ||||
""" | """ | ||||
assert type(format_string) is str | assert isinstance(format_string, str) | ||||
n = 0 | n = 0 | ||||
in_specifier = False | in_specifier = False | ||||
for i, char in enumerate(format_string): | for i, char in enumerate(format_string): | ||||
if format_string[i - 1:i + 1] == "%%" or format_string[i:i + 2] == "%%": | if format_string[i - 1:i + 1] == "%%" or format_string[i:i + 2] == "%%": | ||||
pass | pass | ||||
elif char == "%": | elif char == "%": | ||||
in_specifier = True | in_specifier = True | ||||
n += 1 | n += 1 | ||||
▲ Show 20 Lines • Show All 55 Lines • Show Last 20 Lines |