Skip to content

Commit efff450

Browse files
authored
Prepare to become ProhibitUnusedVariable to default-enabled (#275)
* Upgrade Vital.vim * Refactor scope_plugin internal * Add a test for #274 * Visit into NodeType.CURLYNAMEEXPR * NodeType.CURLYNAME should be classified as dynamic * Refactor IdentifierClassifier internal * Rename the fixture for #274 to prepare for a test for * Analyze NodeType.CALL for `call` or `function` when the first arg is NodeType.STRING * fixup! Add a test for #274 * Refactor scope_plugin internal * Fix false positives that is referenced at #274 comments * Support ignored patterns for ProhibitUnusedVariable * Fix a typo * "..." should be not reported by ProhibitUnusedVariable * Initial implementation for line config comments * Add a test for README * Better debugging * fixup! Initial implementation for line config comments * fixup! Add a test for README * Fix order of plugins * Keep disabled * Update README.rst * Fix tests * Change line config comment to next line config comment * `traverse()` can visit into NodeType.LAMBDA * fixup! Initial implementation for line config comments * Fix bug that caused by unexpected side-sffect of * Add `source_name` to config_dict to debugging * Fix a bug that occurred when a next line is skipped * Tweak debugging output * Fix a bug that is caused by unexpected side-effects from multiple linting * Support lambda * Allow func arg names that have a same name as builtins * Fix tests * Fix a test * Care Python 2
1 parent 4a73405 commit efff450

File tree

71 files changed

+2749
-1409
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+2749
-1409
lines changed

README.rst

+9-3
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,16 @@ You can enable/disable linting policies by a comment as following:
143143
let &cpo = s:save_cpo
144144
unlet s:save_cpo
145145
146-
This syntax is: ``" vint: [+-]<PolicyName> [+-]<PolicyName> ...``.
146+
And you can use line config comments. It can enable/disable linting policies in only one line by the postfix comment:
147147

148-
You can see all policy names on `Vint linting policy
149-
summary <https://github.com/Kuniwak/vint/wiki/Vint-linting-policy-summary>`__.
148+
.. code:: vim
149+
150+
" vint: next-line -ProhibitUnusedVariable
151+
let s:foobar = 'x'
152+
echo s:{'foo' . 'bar'}
153+
154+
This syntax is: `" vint: [next-line] [+-]<PolicyName> [+-]<PolicyName> ...`.
155+
You can see all policy names on `Vint linting policy summary <https://github.com/Kuniwak/vint/wiki/Vint-linting-policy-summary>`__.
150156

151157
Code health
152158
-----------

dev_tool/show_scope.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,16 @@ def prettify_node_type(node):
2828
enable_neovim = namespace['enable_neovim']
2929

3030
scope_plugin = ScopePlugin()
31-
parser = Parser(plugins={'scope': scope_plugin}, enable_neovim=enable_neovim)
31+
parser = Parser(plugins=[scope_plugin], enable_neovim=enable_neovim)
3232

3333
for filepath in filepaths:
3434
ast = parser.parse_file(filepath)
3535
traverse(ast, on_enter=prettify_node_type)
3636

37-
print("////////// AST //////////\n")
38-
pprint(ast)
37+
print("////////// SCOPE TREE //////////\n")
38+
pprint(scope_plugin._ref_tester._scope_linker.scope_tree)
3939
print("\n\n")
4040

41-
print("////////// SCOPE TREE //////////\n")
42-
pprint(scope_plugin._ref_tester._scope_tree)
41+
print("////////// LINK REGISTRY //////////\n")
42+
pprint(scope_plugin._ref_tester._scope_linker.link_registry._vars_to_declarative_ids_map)
43+
pprint(scope_plugin._ref_tester._scope_linker.link_registry._ids_to_scopes_map)

test/asserting/policy.py

+19-54
Original file line numberDiff line numberDiff line change
@@ -2,66 +2,35 @@
22
from pathlib import Path
33
from pprint import pprint
44
from vint.compat.itertools import zip_longest
5+
from vint.linting.policy_set import PolicySet
56
from vint.linting.linter import Linter
6-
from vint.linting.config.config_default_source import ConfigDefaultSource
7+
from vint.linting.level import Level
78

89

910
class PolicyAssertion(unittest.TestCase):
10-
class StubPolicySet(object):
11-
def __init__(self, *policies):
12-
self._policies = policies
13-
14-
15-
def get_enabled_policies(self):
16-
return self._policies
17-
18-
19-
def update_by_config(self, policy_enabling_map):
20-
pass
21-
22-
23-
class StubConfigContainer(object):
24-
def __init__(self, policy_names_to_enable):
25-
26-
default_config_dict = ConfigDefaultSource(None).get_config_dict()
27-
policy_options = default_config_dict.get('policies', {})
28-
29-
for policy, options in policy_options.items():
30-
options['enabled'] = False
31-
32-
for policy in policy_names_to_enable:
33-
options = policy_options.setdefault(policy, {})
34-
options['enabled'] = True
35-
36-
self._config_dict = {
37-
'policies': policy_options,
38-
}
39-
40-
41-
def append_config_source(self, config_source):
42-
# Ignore a comment config source
43-
pass
44-
45-
46-
def get_config_dict(self):
47-
return self._config_dict
48-
49-
5011
def assertFoundNoViolations(self, path, Policy, policy_options=None):
5112
self.assertFoundViolationsEqual(path, Policy, [], policy_options)
5213

5314

5415
def assertFoundViolationsEqual(self, path, Policy, expected_violations, policy_options=None):
55-
policy_to_test = Policy()
5616
policy_name = Policy.__name__
57-
58-
policy_set = PolicyAssertion.StubPolicySet(policy_to_test)
59-
config = PolicyAssertion.StubConfigContainer(policy_name)
17+
policy_set = PolicySet([Policy])
18+
19+
config_dict = {
20+
'cmdargs': {
21+
'severity': Level.STYLE_PROBLEM,
22+
},
23+
'policies': {
24+
policy_name: {
25+
'enabled': True,
26+
}
27+
},
28+
}
6029

6130
if policy_options is not None:
62-
config.get_config_dict()['policies'][policy_name].update(policy_options)
31+
config_dict['policies'][policy_name] = policy_options
6332

64-
linter = Linter(policy_set, config.get_config_dict())
33+
linter = Linter(policy_set, config_dict)
6534
violations = linter.lint_file(path)
6635

6736
pprint(violations)
@@ -74,13 +43,9 @@ def assertFoundViolationsEqual(self, path, Policy, expected_violations, policy_o
7443
def assertViolation(self, actual_violation, expected_violation):
7544
self.assertIsNot(actual_violation, None)
7645
self.assertIsNot(expected_violation, None)
77-
78-
pprint(actual_violation)
79-
80-
assert actual_violation['name'] == expected_violation['name']
81-
assert actual_violation['position'] == expected_violation['position']
82-
assert actual_violation['level'] == expected_violation['level']
83-
46+
self.assertEqual(actual_violation['name'], expected_violation['name'])
47+
self.assertEqual(actual_violation['position'], expected_violation['position'])
48+
self.assertEqual(actual_violation['level'], expected_violation['level'])
8449
self.assertIsInstance(actual_violation['description'], str)
8550

8651

Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
call call('s:Foo', [])
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
let s:{x} = ""
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
function! s:foo(x) abort
2+
let x = 'x'
3+
let y = l:{x}
4+
endfunction
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
call function('s:Foo')
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
call map([], { i, ... -> y })

test/fixture/cli/vital.vim

Submodule vital.vim updated 48 files
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
echo 'report me because I have no line config comments'
2+
3+
" vint: next-line -ProhibitStringPolicy
4+
call map([], '"do not report me"')
5+
6+
echo 'report me because I have no line config comments, but the previous line have it'
7+
8+
" vint: next-line -ProhibitStringPolicy
9+
call map(
10+
\ [],
11+
\ '"report me because I have no line config comments, but the parent node have it"'
12+
\)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
let s:x = 'report me because I have no line config comments'
2+
3+
" vint: next-line -ProhibitStringPolicy
4+
let s:x = 'do not report me because I have a line config comment'
5+
6+
let s:x = 'report me because I have no line config comments, but the previous line have it'

test/fixture/policy/prohibit_implicit_scope_builtin_variable_valid.vim

+7-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ call b:BufferLocalFunc()
4545
call w:WindowLocalFunc()
4646
call t:TabLocalFunc()
4747

48-
function! g:FuncContext(param)
48+
function! FuncContext(param)
4949
echo a:0
5050
echo a:000
5151
echo a:param
@@ -68,3 +68,9 @@ echo b:
6868
echo w:
6969
echo t:
7070
echo v:
71+
72+
73+
" Allow function parameter that have same name as builtins
74+
function! FuncContext(count)
75+
echo a:count
76+
endfunction
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
" Prohibit implicit scope variables
2-
let explicit_global_var = 101
2+
let implicit_global_var = 101
33

44
redir => output
55
redir END
66

7-
" Prohibit implicit builtin variables
8-
let count = 110
9-
107
function! ImplicitGlobalFunc(param)
118
" Make it easy to fix missing a:
129
echo param
@@ -15,3 +12,5 @@ endfunction
1512
" Implicit global variable 'i'
1613
for i in [1, 2, 3]
1714
endfor
15+
16+
call { -> implicit_global_var_in_lambda }()

test/fixture/policy/prohibit_implicit_scope_variable_valid.vim

+3
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,6 @@ call ImplicitGlobalFunc()
6969
function! autoload#ImplicitGlobalAutoloadFunc()
7070
endfunction
7171
call autoload#ImplicitGlobalAutoloadFunc()
72+
73+
" Lambda arguments can not have any scope prefix
74+
call { i, ... -> i }(0)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
let s:unused = 'report me'
2+
let s:unused_but_ignored = 'not report me'
3+
let s:used = 'not report me'
4+
let s:used_but_ignored = 'not report me'
5+
echo s:used_but_ignored
6+
echo s:used

test/fixture/policy/prohibit_unused_variable_invalid.vim

+2
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,5 @@ function! g:FuncContext(param_var, param_func)
1111
let l:explicit_func_local_var = 106
1212
let implicit_func_local_var = 107
1313
endfunction
14+
15+
call { i -> 0 }()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
function! s:foo() abort
2+
let x = 'x'
3+
let y = l:{x}
4+
echo y
5+
endfunction
6+
7+
call call('s:foo', [])
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
" vint: next-line -ProhibitUnusedVariable
2+
let s:foobar = 'x'
3+
echo s:{'foo' . 'bar'}

test/fixture/policy/prohibit_unused_variable_valid.vim

+5-3
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ function! s:ScriptLocalFunc()
1717
endfunction
1818
call s:ScriptLocalFunc()
1919

20-
redir => l:redit_variable
20+
redir => l:redir_variable
2121
redir END
22-
echo l:redit_variable
22+
echo l:redir_variable
2323

2424
function! g:FuncContext(param_var, param_func, param_member)
2525
" Parameter should be used
@@ -38,4 +38,6 @@ function! g:FuncContext(param_var, param_func, param_member)
3838
endfunction
3939

4040
" redir variable should be used
41-
redir => l:redit_variable
41+
redir => l:redir_variable
42+
43+
call { i, ... -> i }(0)

test/integration/vint/linting/policy/test_prohibit_implicit_scope_variable.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ def test_get_violation_if_found_when_file_is_invalid(self):
3030
expected_violations = [
3131
self.create_violation(2, 5),
3232
self.create_violation(4, 10),
33-
self.create_violation(8, 5),
34-
self.create_violation(12, 10),
35-
self.create_violation(16, 5),
33+
self.create_violation(9, 10),
34+
self.create_violation(13, 5),
35+
self.create_violation(16, 11),
3636
]
3737

3838
self.assertFoundViolationsEqual(PATH_INVALID_VIM_SCRIPT,
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,69 @@
11
import unittest
2+
import enum
23
from test.asserting.policy import PolicyAssertion, get_fixture_path
3-
44
from vint.linting.level import Level
55
from vint.linting.policy.prohibit_unused_variable import ProhibitUnusedVariable
66

7-
PATH_VALID_VIM_SCRIPT = get_fixture_path('prohibit_unused_variable_valid.vim')
8-
PATH_INVALID_VIM_SCRIPT = get_fixture_path('prohibit_unused_variable_invalid.vim')
7+
class Fixtures(enum.Enum):
8+
VALID_VIM_SCRIPT = get_fixture_path('prohibit_unused_variable_valid.vim')
9+
INVALID_VIM_SCRIPT = get_fixture_path('prohibit_unused_variable_invalid.vim')
10+
ISSUE_274 = get_fixture_path('prohibit_unused_variable_issue_274.vim')
11+
IGNORED_PATTERNS = get_fixture_path('prohibit_unused_variable_ignored_patterns.vim')
12+
README = get_fixture_path('prohibit_unused_variable_readme.vim')
913

1014

1115
class TestProhibitUnusedVariable(PolicyAssertion, unittest.TestCase):
1216
def test_get_violation_if_found_when_file_is_valid(self):
13-
self.assertFoundNoViolations(PATH_VALID_VIM_SCRIPT,
17+
self.assertFoundNoViolations(Fixtures.VALID_VIM_SCRIPT.value,
1418
ProhibitUnusedVariable)
1519

1620

17-
def create_violation(self, line, column):
21+
def create_violation(self, line, column, path):
1822
return {
1923
'name': 'ProhibitUnusedVariable',
2024
'level': Level.WARNING,
2125
'position': {
2226
'line': line,
2327
'column': column,
24-
'path': PATH_INVALID_VIM_SCRIPT
28+
'path': path
2529
}
2630
}
2731

2832

2933
def test_get_violation_if_found_when_file_is_invalid(self):
3034
expected_violations = [
31-
self.create_violation(2, 5),
32-
self.create_violation(4, 11),
33-
self.create_violation(7, 25),
34-
self.create_violation(7, 36),
35-
self.create_violation(11, 9),
36-
self.create_violation(12, 9),
35+
self.create_violation(2, 5, Fixtures.INVALID_VIM_SCRIPT.value),
36+
self.create_violation(4, 11, Fixtures.INVALID_VIM_SCRIPT.value),
37+
self.create_violation(7, 25, Fixtures.INVALID_VIM_SCRIPT.value),
38+
self.create_violation(7, 36, Fixtures.INVALID_VIM_SCRIPT.value),
39+
self.create_violation(11, 9, Fixtures.INVALID_VIM_SCRIPT.value),
40+
self.create_violation(12, 9, Fixtures.INVALID_VIM_SCRIPT.value),
41+
self.create_violation(15, 8, Fixtures.INVALID_VIM_SCRIPT.value),
3742
]
3843

39-
self.assertFoundViolationsEqual(PATH_INVALID_VIM_SCRIPT,
44+
self.assertFoundViolationsEqual(Fixtures.INVALID_VIM_SCRIPT.value,
4045
ProhibitUnusedVariable,
4146
expected_violations)
4247

48+
def test_issue_274(self):
49+
self.assertFoundNoViolations(Fixtures.ISSUE_274.value, ProhibitUnusedVariable)
50+
51+
52+
def test_ignored_patterns(self):
53+
expected_violations = [
54+
self.create_violation(1, 5, Fixtures.IGNORED_PATTERNS.value),
55+
]
56+
57+
self.assertFoundViolationsEqual(Fixtures.IGNORED_PATTERNS.value,
58+
ProhibitUnusedVariable,
59+
expected_violations,
60+
policy_options={'ignored_patterns': ['_ignored$']})
61+
62+
63+
def test_readme(self):
64+
self.assertFoundNoViolations(Fixtures.README.value,
65+
ProhibitUnusedVariable)
66+
67+
4368
if __name__ == '__main__':
4469
unittest.main()

0 commit comments

Comments
 (0)