Skip to content

Commit fba96ac

Browse files
authored
Fix a bug caused by less args for map function (#257)
* Reproduce #256 * Fix crash caused by invalid map functions that have less arguments * Add ProhibitInvalidMapCall * Remove debug code
1 parent 476a6b3 commit fba96ac

File tree

7 files changed

+79
-3
lines changed

7 files changed

+79
-3
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
call string(map(foo), 'v:val')
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
call string(map([]), 'v:val')
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
call string(map([], 'v:val'))
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import unittest
2+
from test.asserting.policy import PolicyAssertion, get_fixture_path
3+
4+
from vint.linting.level import Level
5+
from vint.linting.policy.prohibit_invalid_map_call import ProhibitInvalidMapCall
6+
7+
PATH_VALID_VIM_SCRIPT = get_fixture_path('prohibit_invalid_map_call_valid.vim')
8+
PATH_INVALID_VIM_SCRIPT = get_fixture_path('prohibit_invalid_map_call_invalid.vim')
9+
10+
11+
class TestProhibitInvalidMapCall(PolicyAssertion, unittest.TestCase):
12+
def test_get_violation_if_found_with_valid(self):
13+
self.assertFoundNoViolations(PATH_VALID_VIM_SCRIPT, ProhibitInvalidMapCall)
14+
15+
16+
def test_get_violation_if_found_with_invalid(self):
17+
expected_violations = [
18+
{
19+
'name': 'ProhibitInvalidMapCall',
20+
'level': Level.ERROR,
21+
'position': {
22+
'line': 1,
23+
'column': 16,
24+
'path': PATH_INVALID_VIM_SCRIPT
25+
}
26+
}
27+
]
28+
self.assertFoundViolationsEqual(PATH_INVALID_VIM_SCRIPT,
29+
ProhibitInvalidMapCall,
30+
expected_violations)

test/unit/vint/ast/plugin/scope_plugin/test_map_and_filter_parser.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616

1717

1818
class Fixtures(enum.Enum):
19-
MAP_AND_FILTER_VARIABLE = Path(FIXTURE_BASE_PATH,
20-
'fixture_to_scope_plugin_map_and_filter.vim')
19+
MAP_AND_FILTER_VARIABLE = Path(FIXTURE_BASE_PATH, 'fixture_to_scope_plugin_map_and_filter.vim')
20+
ISSUE_256 = Path(FIXTURE_BASE_PATH, 'fixture_to_scope_plugin_issue_256.vim')
2121

2222

2323
class TestMapAndFilterParser(unittest.TestCase):
@@ -66,6 +66,13 @@ def enter_handler(node):
6666
self.assertTrue(all(is_map_and_filter_content_visited.values()))
6767

6868

69+
def test_issue_256(self):
70+
ast = self.create_ast(Fixtures.ISSUE_256)
71+
parser = MapAndFilterParser()
72+
got_ast = parser.process(ast)
73+
74+
self.assertIsNotNone(got_ast)
75+
6976

7077
if __name__ == '__main__':
7178
unittest.main()

vint/ast/plugin/scope_plugin/map_and_filter_parser.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,13 @@ def enter_handler(node):
3030
if not is_map_or_function_call:
3131
return
3232

33-
string_expr_node = node['rlist'][1]
33+
args = node['rlist']
34+
35+
# Prevent crash. See https://github.com/Kuniwak/vint/issues/256.
36+
if len(args) < 2:
37+
return
38+
39+
string_expr_node = args[1]
3440

3541
# We can analyze only STRING nodes by static analyzing.
3642
if NodeType(string_expr_node['type']) is not NodeType.STRING:
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
from vint.ast.node_type import NodeType
2+
from vint.linting.level import Level
3+
from vint.linting.policy.abstract_policy import AbstractPolicy
4+
from vint.linting.policy_registry import register_policy
5+
6+
7+
@register_policy
8+
class ProhibitInvalidMapCall(AbstractPolicy):
9+
def __init__(self):
10+
super(ProhibitInvalidMapCall, self).__init__()
11+
self.description = 'Number of arguments for map() must be 2 (if not, it will throw E118 or E119)'
12+
self.reference = ':help map()'
13+
self.level = Level.ERROR
14+
15+
16+
def listen_node_types(self):
17+
return [NodeType.CALL]
18+
19+
20+
def is_valid(self, node, lint_context):
21+
left_node = node['left']
22+
23+
if NodeType(left_node['type']) != NodeType.IDENTIFIER:
24+
return True
25+
26+
if left_node['value'] != 'map':
27+
return True
28+
29+
args = node['rlist']
30+
return len(args) == 2

0 commit comments

Comments
 (0)