aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcoFalke <falke.marco@gmail.com>2018-08-13 07:07:23 -0400
committerMarcoFalke <falke.marco@gmail.com>2018-08-13 07:07:56 -0400
commitef86f2631e3ce5e1664e1913658fa6e807f35ff7 (patch)
tree1d86ce82e9dbc54c68d965e1d2e6dfdc5d2e86fd
parent2115cba9c60504ed1c0af8a56c5d90b5fd415497 (diff)
parent4441ad677a4cdc70ecac63e03edb4e236e36801e (diff)
Merge #13939: lint: Make format string linter understand basic template parameter syntax
4441ad677a Make format string linter understand basic template parameter syntax (practicalswift) Pull request description: Make format string linter understand basic template parameter syntax. Fixes issue described in https://github.com/bitcoin/bitcoin/pull/13705#issuecomment-412046126. Thanks to @ken2812221 for reporting! Tree-SHA512: 8fb995bc6b29d8b9926ef5969e02cf71c494e829434fcdeb4ed5fabad5ab96e86e5b8eea705e8a416927757b4fa4e58abc0fd4f483daa58c94e2c6fdcb8ee822
-rwxr-xr-xtest/lint/lint-format-strings.py38
1 files changed, 37 insertions, 1 deletions
diff --git a/test/lint/lint-format-strings.py b/test/lint/lint-format-strings.py
index c07dfe317b..60389176c9 100755
--- a/test/lint/lint-format-strings.py
+++ b/test/lint/lint-format-strings.py
@@ -123,6 +123,32 @@ def parse_function_call_and_arguments(function_name, function_call):
['foo(', '123', ')']
>>> parse_function_call_and_arguments("foo", 'foo("foo")')
['foo(', '"foo"', ')']
+ >>> parse_function_call_and_arguments("strprintf", 'strprintf("%s (%d)", std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,wchar_t>().to_bytes(buf), err);')
+ ['strprintf(', '"%s (%d)",', ' std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,wchar_t>().to_bytes(buf),', ' err', ')']
+ >>> parse_function_call_and_arguments("strprintf", 'strprintf("%s (%d)", foo<wchar_t>().to_bytes(buf), err);')
+ ['strprintf(', '"%s (%d)",', ' foo<wchar_t>().to_bytes(buf),', ' err', ')']
+ >>> parse_function_call_and_arguments("strprintf", 'strprintf("%s (%d)", foo().to_bytes(buf), err);')
+ ['strprintf(', '"%s (%d)",', ' foo().to_bytes(buf),', ' err', ')']
+ >>> parse_function_call_and_arguments("strprintf", 'strprintf("%s (%d)", foo << 1, err);')
+ ['strprintf(', '"%s (%d)",', ' foo << 1,', ' err', ')']
+ >>> parse_function_call_and_arguments("strprintf", 'strprintf("%s (%d)", foo<bar>() >> 1, err);')
+ ['strprintf(', '"%s (%d)",', ' foo<bar>() >> 1,', ' err', ')']
+ >>> parse_function_call_and_arguments("strprintf", 'strprintf("%s (%d)", foo < 1 ? bar : foobar, err);')
+ ['strprintf(', '"%s (%d)",', ' foo < 1 ? bar : foobar,', ' err', ')']
+ >>> parse_function_call_and_arguments("strprintf", 'strprintf("%s (%d)", foo < 1, err);')
+ ['strprintf(', '"%s (%d)",', ' foo < 1,', ' err', ')']
+ >>> parse_function_call_and_arguments("strprintf", 'strprintf("%s (%d)", foo > 1 ? bar : foobar, err);')
+ ['strprintf(', '"%s (%d)",', ' foo > 1 ? bar : foobar,', ' err', ')']
+ >>> parse_function_call_and_arguments("strprintf", 'strprintf("%s (%d)", foo > 1, err);')
+ ['strprintf(', '"%s (%d)",', ' foo > 1,', ' err', ')']
+ >>> parse_function_call_and_arguments("strprintf", 'strprintf("%s (%d)", foo <= 1, err);')
+ ['strprintf(', '"%s (%d)",', ' foo <= 1,', ' err', ')']
+ >>> parse_function_call_and_arguments("strprintf", 'strprintf("%s (%d)", foo <= bar<1, 2>(1, 2), err);')
+ ['strprintf(', '"%s (%d)",', ' foo <= bar<1, 2>(1, 2),', ' err', ')']
+ >>> parse_function_call_and_arguments("strprintf", 'strprintf("%s (%d)", foo>foo<1,2>(1,2)?bar:foobar,err)');
+ ['strprintf(', '"%s (%d)",', ' foo>foo<1,2>(1,2)?bar:foobar,', 'err', ')']
+ >>> parse_function_call_and_arguments("strprintf", 'strprintf("%s (%d)", foo>foo<1,2>(1,2),err)');
+ ['strprintf(', '"%s (%d)",', ' foo>foo<1,2>(1,2),', 'err', ')']
"""
assert(type(function_name) is str and type(function_call) is str and function_name)
remaining = normalize(escape(function_call))
@@ -131,9 +157,10 @@ def parse_function_call_and_arguments(function_name, function_call):
parts = [expected_function_call]
remaining = remaining[len(expected_function_call):]
open_parentheses = 1
+ open_template_arguments = 0
in_string = False
parts.append("")
- for char in remaining:
+ for i, char in enumerate(remaining):
parts.append(parts.pop() + char)
if char == "\"":
in_string = not in_string
@@ -151,6 +178,15 @@ def parse_function_call_and_arguments(function_name, function_call):
parts.append(parts.pop()[:-1])
parts.append(char)
break
+ prev_char = remaining[i - 1] if i - 1 >= 0 else None
+ next_char = remaining[i + 1] if i + 1 <= len(remaining) - 1 else None
+ if char == "<" and next_char not in [" ", "<", "="] and prev_char not in [" ", "<"]:
+ open_template_arguments += 1
+ continue
+ if char == ">" and next_char not in [" ", ">", "="] and prev_char not in [" ", ">"] and open_template_arguments > 0:
+ open_template_arguments -= 1
+ if open_template_arguments > 0:
+ continue
if char == ",":
parts.append("")
return parts