lizard 1.17.10__py2.py3-none-any.whl → 1.17.13__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lizard
3
- Version: 1.17.10
3
+ Version: 1.17.13
4
4
  Summary: A code analyzer without caring the C/C++ header files. It works with Java, C/C++, JavaScript, Python, Ruby, Swift, Objective C. Metrics includes cyclomatic complexity number etc.
5
5
  Home-page: http://www.lizard.ws
6
6
  Download-URL: https://pypi.python.org/lizard/
@@ -23,11 +23,12 @@ Classifier: Programming Language :: Java
23
23
  Classifier: Programming Language :: JavaScript
24
24
  Classifier: Programming Language :: Objective C
25
25
  Classifier: Programming Language :: Python
26
- Classifier: Programming Language :: Python :: 2.7
27
- Classifier: Programming Language :: Python :: 3.4
28
- Classifier: Programming Language :: Python :: 3.5
29
- Classifier: Programming Language :: Python :: 3.6
26
+ Classifier: Programming Language :: Python :: 3.8
27
+ Classifier: Programming Language :: Python :: 3.9
28
+ Classifier: Programming Language :: Python :: 3.10
29
+ Classifier: Programming Language :: Python :: 3.11
30
30
  License-File: LICENSE.txt
31
+ Requires-Dist: pygments
31
32
 
32
33
  |Web Site| Lizard
33
34
  =================
@@ -66,6 +67,8 @@ A list of supported languages:
66
67
  - Rust
67
68
  - Fortran
68
69
  - Kotlin
70
+ - Solidity
71
+ - Erlang
69
72
 
70
73
  By default lizard will search for any source code that it knows and mix
71
74
  all the results together. This might not be what you want. You can use
@@ -88,7 +91,7 @@ often very hard to get all the included folders and files right when
88
91
  they are complicated. But we don't really need that kind of accuracy for
89
92
  cyclomatic complexity.
90
93
 
91
- It requires python2.7 or above (early versions are not verified).
94
+ It requires python3.8 or above (early versions are not verified).
92
95
 
93
96
  Installation
94
97
  ------------
@@ -112,7 +115,7 @@ Or if you've got the source:
112
115
 
113
116
  ::
114
117
 
115
- [sudo] python setup.py install --install-dir=/path/to/installation/directory/
118
+ [sudo] python setup.py install --prefix=/path/to/installation/directory/
116
119
 
117
120
  Usage
118
121
  -----
@@ -1,4 +1,4 @@
1
- lizard.py,sha256=y8kU4WIi5E-S8N99lTcp_TbdXYqDngi0sjNwciv6GMs,38272
1
+ lizard.py,sha256=KR3F6F-5GzGQP0GLxjWmpRRUsLbfL-Lthtz3jWLlyPY,38576
2
2
  lizard_ext/__init__.py,sha256=Cz0pvH6QHyadK-rAeeEhQVsm0hW5M-fBQgV4FBaX9zk,500
3
3
  lizard_ext/auto_open.py,sha256=byD_RbeVhvSUhR2bJMRitvA3zcKEapFwv0-XaDJ6GFo,1096
4
4
  lizard_ext/csvoutput.py,sha256=IGTGICiK_IJcldRGDhd_jNDohxFWJEWYOVxkemaY20Q,3051
@@ -25,16 +25,17 @@ lizard_ext/lizardns.py,sha256=8pztUoRS_UWN24MawwxeHEJgYh49id5PWODUBb6O72U,4184
25
25
  lizard_ext/lizardoutside.py,sha256=FGm2tbBZ17-2OCgmQlD-vobUCfQKb0FAygf86eM3xuM,336
26
26
  lizard_ext/lizardstatementcount.py,sha256=xYk6ixSIItSE1BWQXzrWmduFgGhA3VR817SNKLffyVQ,1182
27
27
  lizard_ext/lizardwordcount.py,sha256=2QYXD7-AtkkgAbi9VSidunMbSsGQ7MKYb6IT-bS-cok,7575
28
- lizard_ext/version.py,sha256=7IvYS3aXsjeGGL5lIzocgukLm0cYtzRbMhvOLb8hZL0,182
28
+ lizard_ext/version.py,sha256=cV8SELFV7_EfiIev7wFOD2wke6gb9on99S4p_3CSUAc,182
29
29
  lizard_ext/xmloutput.py,sha256=-cbh0he4O_X-wX56gkv9AnSPNN0qvR7FACqlBeezUS4,5609
30
- lizard_languages/__init__.py,sha256=OT7nxb-UdSB_J5xHat5vkQvEJxmMDSTdy5ZwjuHBj20,1156
31
- lizard_languages/clike.py,sha256=-VKcd8VLuc0d7RXzcI7TiIzpoDzl2eB_d8d1tOv5XZc,10635
32
- lizard_languages/code_reader.py,sha256=532zy1K5hBoFJR6KYsKhpkGCsBcqtMlvdE6KUd8JrPw,5452
30
+ lizard_languages/__init__.py,sha256=iIbCcjN1AzmVtqCB7caRcLWQ4CdQwyT0UAiRKCkVeL0,1273
31
+ lizard_languages/clike.py,sha256=YgB0dHYdQ5Ae1pN00zcstkuXl94n8Ugo-aTYUNmJr7o,10723
32
+ lizard_languages/code_reader.py,sha256=95_juW_8vcTShV_BoWNmBiz5CmCk59VxRi0QWF67Bsw,6164
33
33
  lizard_languages/csharp.py,sha256=lVi-g-0JjHagqDR5r-lRdi2BuCdtR5aer9CYY-Nzw44,478
34
- lizard_languages/fortran.py,sha256=5AUT3y2g7fiP59qcpU0iuSz-Q_iT9RtJpqB8ghViv4I,7279
34
+ lizard_languages/erlang.py,sha256=AaPfIGq_phVi2hRUVHNrrmXiQSdlEktbSVOvPxORWf8,3822
35
+ lizard_languages/fortran.py,sha256=iXxS44sNJ2_h-nvJC58Pz6AGDyVx2HdBEVF-EeYGn84,7327
35
36
  lizard_languages/gdscript.py,sha256=KwlGoODilQnFgXvODpq_XlA6fV3hGbN9fd7bsiEUn78,637
36
37
  lizard_languages/go.py,sha256=dSbWxtWve7KSRW5i9w4DxhODtJ72EcBNrgp-7Xhn0Sg,465
37
- lizard_languages/golike.py,sha256=FsoJbCBDOmBQodEgpxR_1-H3TjGXgniJHaIp-W_VphE,1883
38
+ lizard_languages/golike.py,sha256=vRIfjTVvc0VmJf27lTOLht55ZF1AQ9wn0Fvu-9WabWk,2858
38
39
  lizard_languages/java.py,sha256=mfXCRicmZFZFxPW7QuTOQtAKzOZD3d-uh4tiALcGdX4,1186
39
40
  lizard_languages/javascript.py,sha256=agcEwJbrY0tFt8rGWwsO2pH-MKXvKmt9BMlcKkUB9m4,4314
40
41
  lizard_languages/js_style_language_states.py,sha256=2_dgrXLe113xEdfATByioohGquW428pPo9gI3I1duS4,4257
@@ -43,19 +44,20 @@ lizard_languages/kotlin.py,sha256=v_o2orEzA5gB9vM_0h-E4QXjrc5Yum-0K6W6_laOThc,28
43
44
  lizard_languages/lua.py,sha256=3nqBcunBzJrhv4Iqaf8xvbyqxZy3aSxJ-IiHimHFlac,1573
44
45
  lizard_languages/objc.py,sha256=2a1teLdaXZBtCeFiIZer1j_sVx9LZ1CbF2XfnqlvLmk,2319
45
46
  lizard_languages/php.py,sha256=8OufyR2TIWyf3bXuTmp37Vwf_tEPF4YV5M3i5_jnguA,1377
46
- lizard_languages/python.py,sha256=GQFA0pqrDqJPPcNYQu3E4wh2rmUwph1P8hvwqsxgSIc,3445
47
+ lizard_languages/python.py,sha256=JDXqQ7SEnNSXlbK5sMyUKwCFBTEto20Wg8_ZkzYisSI,3721
47
48
  lizard_languages/ruby.py,sha256=gUrFsaS6ZJbjb9CixBHP9n0BxGOb8HsDEg7jJ2bz_80,2187
48
49
  lizard_languages/rubylike.py,sha256=dAGZ2wqW8nqaESMU8HkeR9gwQ-q9fmZqE6AANvVZD1Q,3426
49
50
  lizard_languages/rust.py,sha256=DG2RkR9JWwcD6gIw-BPzg-Yo_lxQtSvfgHioFWIQm9o,610
50
51
  lizard_languages/scala.py,sha256=6Jr_TG945VYqB3o5weD7jN7S4beHt4aVj3r-fmKeMAM,1316
51
52
  lizard_languages/script_language.py,sha256=FOzB9Rg5-XTnFDeeRRyIrp2rDomRDHhaPsxsxeCx9GU,539
53
+ lizard_languages/solidity.py,sha256=Z0GD7U5bI5eUikdy7m_iKWeFD5yXRYq4r3zycscOhJQ,553
52
54
  lizard_languages/swift.py,sha256=p8S2OAkQOx9YQ02yhoVXFkr7pMqUH1Nb3RVXPHRU_9M,2450
53
55
  lizard_languages/tnsdl.py,sha256=pGcalA_lHY362v2wwPS86seYBOOBBjvmU6vd4Yy3A9g,2803
54
56
  lizard_languages/ttcn.py,sha256=ygjw_raBmPF-4mgoM8m6CAdyEMpTI-n1kZJK1RL4Vxo,2131
55
57
  lizard_languages/typescript.py,sha256=yjUTVDkiONbg2v089pZC4wrCJSo1J5NVbQzbCfF4k6s,1547
56
- lizard-1.17.10.dist-info/LICENSE.txt,sha256=05ZjgQ8Cl1dD9p0BhW-Txzkc5rhCogGJVEuf1GT2Y_M,1303
57
- lizard-1.17.10.dist-info/METADATA,sha256=8Sxwujdsg565s5lDDGCVRA_PRNKgrR-s2OQVb3Cfwwo,15360
58
- lizard-1.17.10.dist-info/WHEEL,sha256=z9j0xAa_JmUKMpmz72K0ZGALSM_n-wQVmGbleXx2VHg,110
59
- lizard-1.17.10.dist-info/entry_points.txt,sha256=pPMMwoHAltzGHqR2WeJQItLeeyR7pbX5R2S_POC-xoo,40
60
- lizard-1.17.10.dist-info/top_level.txt,sha256=5NTrTaOLhHuTzXaGcZPKfuaOgUv7WafNGe0Zl5aycpg,35
61
- lizard-1.17.10.dist-info/RECORD,,
58
+ lizard-1.17.13.dist-info/LICENSE.txt,sha256=05ZjgQ8Cl1dD9p0BhW-Txzkc5rhCogGJVEuf1GT2Y_M,1303
59
+ lizard-1.17.13.dist-info/METADATA,sha256=XwvrQB7WJSc664t-xQovyEcKuufzKizZCnyUPSTowq8,15403
60
+ lizard-1.17.13.dist-info/WHEEL,sha256=fS9sRbCBHs7VFcwJLnLXN1MZRR0_TVTxvXKzOnaSFs8,110
61
+ lizard-1.17.13.dist-info/entry_points.txt,sha256=pPMMwoHAltzGHqR2WeJQItLeeyR7pbX5R2S_POC-xoo,40
62
+ lizard-1.17.13.dist-info/top_level.txt,sha256=5NTrTaOLhHuTzXaGcZPKfuaOgUv7WafNGe0Zl5aycpg,35
63
+ lizard-1.17.13.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.37.1)
2
+ Generator: bdist_wheel (0.44.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py2-none-any
5
5
  Tag: py3-none-any
lizard.py CHANGED
@@ -301,11 +301,17 @@ class FunctionInfo(Nesting): # pylint: disable=R0902
301
301
  " %(name)s@%(start_line)s-%(end_line)s@%(filename)s"
302
302
  % self.__dict__)
303
303
 
304
- parameter_count = property(lambda self: len(self.full_parameters))
304
+ parameter_count = property(lambda self: len(self.parameters))
305
305
 
306
306
  @property
307
307
  def parameters(self):
308
- matches = [re.search(r'(\w+)(\s=.*)?$', f)
308
+ # Exclude empty tokens as parameters. These can occur in languages
309
+ # allowing a trailing comma on the last parameter in an function
310
+ # argument list.
311
+ # Regex matches the parameter name, then optionally:
312
+ # - a default value given after an '=' sign
313
+ # - a type annotation given after a ':'
314
+ matches = [re.search(r'(\w+)(\s=.*)?(\s:.*)?$', f)
309
315
  for f in self.full_parameters]
310
316
  return [m.group(1) for m in matches if m]
311
317
 
@@ -364,7 +370,6 @@ class NestingStack(object):
364
370
  def __init__(self):
365
371
  self.nesting_stack = []
366
372
  self.pending_function = None
367
- self.function_stack = []
368
373
 
369
374
  def with_namespace(self, name):
370
375
  return ''.join([x.name_in_space for x in self.nesting_stack] + [name])
lizard_ext/version.py CHANGED
@@ -3,4 +3,4 @@
3
3
  #
4
4
  # pylint: disable=missing-docstring,invalid-name
5
5
 
6
- version = "1.17.10"
6
+ version = "1.17.13"
@@ -1,6 +1,7 @@
1
1
  ''' programming languages of lizard '''
2
2
 
3
3
  from .clike import CLikeReader
4
+ from .erlang import ErlangReader
4
5
  from .java import JavaReader
5
6
  from .javascript import JavaScriptReader
6
7
  from .kotlin import KotlinReader
@@ -18,6 +19,7 @@ from .lua import LuaReader
18
19
  from .rust import RustReader
19
20
  from .typescript import TypeScriptReader
20
21
  from .fortran import FortranReader
22
+ from .solidity import SolidityReader
21
23
 
22
24
 
23
25
  def languages():
@@ -39,7 +41,9 @@ def languages():
39
41
  RustReader,
40
42
  TypeScriptReader,
41
43
  FortranReader,
42
- KotlinReader
44
+ KotlinReader,
45
+ SolidityReader,
46
+ ErlangReader,
43
47
  ]
44
48
 
45
49
 
lizard_languages/clike.py CHANGED
@@ -196,7 +196,8 @@ class CLikeStates(CodeStateMachine):
196
196
  else:
197
197
  self.next(self._state_global)
198
198
  elif len(self.bracket_stack) == 1:
199
- self.context.parameter(token)
199
+ if token != 'void': # void is a reserved keyword, meaning no parameters
200
+ self.context.parameter(token)
200
201
  return
201
202
  self.context.add_to_long_function_name(token)
202
203
 
@@ -4,6 +4,8 @@ Base class for all language parsers
4
4
 
5
5
  import re
6
6
  from copy import copy
7
+ from functools import reduce
8
+ from operator import or_
7
9
 
8
10
 
9
11
  class CodeStateMachine(object):
@@ -112,7 +114,7 @@ class CodeReader:
112
114
  if not token_class:
113
115
  token_class = create_token
114
116
 
115
- def _generate_tokens(source, add):
117
+ def _generate_tokens(source, add, flags=0):
116
118
  # DO NOT put any sub groups in the regex. Good for performance
117
119
  _until_end = r"(?:\\\n|[^\n])*"
118
120
  combined_symbols = ["<<=", ">>=", "||", "&&", "===", "!==",
@@ -125,6 +127,8 @@ class CodeReader:
125
127
  r"\/\*.*?\*\/" +
126
128
  add +
127
129
  r"|(?:\d+\')+\d+" +
130
+ r"|0x(?:[0-9A-Fa-f]+\')+[0-9A-Fa-f]+" +
131
+ r"|0b(?:[01]+\')+[01]+" +
128
132
  r"|\w+" +
129
133
  r"|\"(?:\\.|[^\"\\])*\"" +
130
134
  r"|\'(?:\\.|[^\'\\])*?\'" +
@@ -136,7 +140,7 @@ class CodeReader:
136
140
  r"|\\\n" +
137
141
  r"|\n" +
138
142
  r"|[^\S\n]+" +
139
- r"|.)", re.M | re.S)
143
+ r"|.)", re.M | re.S | flags)
140
144
  macro = ""
141
145
  for match in token_pattern.finditer(source):
142
146
  token = token_class(match)
@@ -154,7 +158,21 @@ class CodeReader:
154
158
  if macro:
155
159
  yield macro
156
160
 
157
- return _generate_tokens(source_code, addition)
161
+ flag_dict = {
162
+ 'a': re.A, # ASCII-only matching
163
+ 'i': re.I, # Ignore case
164
+ 'L': re.L, # Locale dependent
165
+ 'm': re.M, # Multi-line
166
+ 's': re.S, # Dot matches all
167
+ 'u': re.U, # Unicode matching
168
+ 'x': re.X # Verbose
169
+ }
170
+
171
+ pattern = re.compile(r'\(\?[aiLmsux]+\)')
172
+ re_flags = ''.join(opt[2:-1] for opt in pattern.findall(addition))
173
+ flags = reduce(or_, (flag_dict[flag] for flag in re_flags), 0)
174
+
175
+ return _generate_tokens(source_code, pattern.sub('', addition), flags=flags)
158
176
 
159
177
  def __call__(self, tokens, reader):
160
178
  self.context = reader.context
@@ -0,0 +1,112 @@
1
+ """
2
+ Language parser for erlang
3
+ """
4
+
5
+ import re
6
+ from lizard_languages.code_reader import CodeReader, CodeStateMachine
7
+ import pygments.token as py_token
8
+ from pygments import lex, lexers
9
+
10
+
11
+ class ErlangReader(CodeReader):
12
+ # pylint: disable=R0903
13
+
14
+ ext = ['erl', 'hrl', 'es', 'escript']
15
+ language_names = ['erlang']
16
+ _conditions = {'and', 'case', 'catch', 'if', 'not', 'or', '?', 'when'}
17
+
18
+ def __init__(self, context):
19
+ super(ErlangReader, self).__init__(context)
20
+ self.parallel_states = [ErlangStates(context)]
21
+
22
+ @staticmethod
23
+ def get_comment_from_token(token):
24
+ if token.startswith("%%"):
25
+ return token[2:]
26
+
27
+ @staticmethod
28
+ def generate_tokens(source_code, addition='', token_class=None):
29
+ return map(lambda x: x[1], filter(lambda x: x[0] != py_token.Whitespace,
30
+ lex(source_code, lexer=lexers.get_lexer_by_name('erlang'))))
31
+
32
+
33
+ class ErlangStates(CodeStateMachine):
34
+ # pylint: disable=R0903
35
+
36
+ func_name_pattern = re.compile("[a-zA-Z]+[a-zA-Z0-9_]*")
37
+
38
+ def __init__(self, context):
39
+ super(ErlangStates, self).__init__(context)
40
+ self.punctuated = False
41
+
42
+ def _state_global(self, token):
43
+ if token == '-':
44
+ self.punctuated = True
45
+ elif self.func_name_pattern.match(token) and not self.punctuated:
46
+ self.context.push_new_function(token)
47
+ self._state = self._state_after_name
48
+ elif token == 'end':
49
+ self._state = self._state_nested_end
50
+ elif token == '.' or token == ';':
51
+ self.statemachine_return()
52
+ else:
53
+ self.punctuated = False
54
+
55
+ def _state_after_name(self, token):
56
+ if token == '(':
57
+ self._state = self._state_start_of_params
58
+ self.context.add_to_long_function_name(token)
59
+ self.lbr = 1
60
+ self.rbr = 0
61
+ else:
62
+ self.func_match_failed(token)
63
+
64
+ def _state_start_of_params(self, token):
65
+ if token == ')':
66
+ self.rbr += 1
67
+ if self.lbr == self.rbr:
68
+ self._state = self._state_end_of_params
69
+ self.context.add_to_long_function_name(" " + token)
70
+ self.punctuated = False
71
+ return
72
+ if token == '(':
73
+ self.lbr += 1
74
+ self.context.parameter(token)
75
+
76
+ def _state_end_of_params(self, token):
77
+ if token == '-':
78
+ self.punctuated = True
79
+ elif token == '>' and self.punctuated:
80
+ if len(self.context.stacked_functions) <= 1 or \
81
+ self.context.current_function.name == 'fun':
82
+ self.next(self._state_func_first_line, token)
83
+ else:
84
+ self.func_match_failed(token)
85
+
86
+ def _state_func_first_line(self, _):
87
+ def callback():
88
+ self._state = self._state_global
89
+ self.context.end_of_function()
90
+
91
+ self.sub_state(self.statemachine_clone(), callback)
92
+ self.punctuated = False
93
+
94
+ def _state_nested_end(self, token):
95
+ if token == '.' or token == ',':
96
+ if len(self.context.stacked_functions) > 1 \
97
+ and self.context.stacked_functions[-1].name == 'fun':
98
+ self.statemachine_return()
99
+ return
100
+
101
+ self._state = self._state_global
102
+
103
+ def func_match_failed(self, token):
104
+ self.punctuated = False
105
+ self._state = self._state_global
106
+ curr_cyc_comp = self.context.current_function.cyclomatic_complexity - 1
107
+ if self.context.stacked_functions:
108
+ self.context.current_function = self.context.stacked_functions.pop()
109
+ else:
110
+ self.context.current_function = self.context.global_pseudo_function
111
+ self.context.add_condition(curr_cyc_comp)
112
+ self.next(self._state_global, token)
@@ -35,11 +35,10 @@ class FortranReader(CodeReader, FortranCommentsMixin):
35
35
  _until_end = r'(?:\\\n|[^\n])*'
36
36
  return CodeReader.generate_tokens(
37
37
  source_code,
38
- r'(?i)' +
39
- r'|\/\/' +
38
+ r'(?i)'
39
+ r'\/\/' +
40
40
  r'|\#' + _until_end +
41
41
  r'|\!' + _until_end +
42
- r'|^C' + _until_end +
43
42
  r'|^\*' + _until_end +
44
43
  r'|\.OR\.' +
45
44
  r'|\.AND\.' +
@@ -124,6 +123,8 @@ class FortranStates(CodeStateMachine):
124
123
  self.context.add_bare_nesting()
125
124
  elif token_upper.replace(' ', '') == 'ELSEIF':
126
125
  self.context.pop_nesting()
126
+ if token_upper == 'ELSEIF':
127
+ self.context.add_condition()
127
128
  self._state = self._if
128
129
  elif token_upper == 'END' or self._ends.match(token):
129
130
  self.context.pop_nesting()
@@ -13,15 +13,40 @@ class GoLikeStates(CodeStateMachine): # pylint: disable=R0903
13
13
  if token == self.FUNC_KEYWORD:
14
14
  self._state = self._function_name
15
15
  self.context.push_new_function('')
16
+ elif token == 'type':
17
+ self._state = self._type_definition
16
18
  elif token in '{':
17
19
  self.sub_state(self.statemachine_clone())
18
20
  elif token in '}':
19
21
  self.statemachine_return()
20
22
 
23
+ def _type_definition(self, token):
24
+ self._state = self._after_type_name
25
+
26
+ def _after_type_name(self, token):
27
+ if token == 'struct':
28
+ self._state = self._struct_definition
29
+ elif token == 'interface':
30
+ self._state = self._interface_definition
31
+ else:
32
+ self._state = self._state_global
33
+
34
+ @CodeStateMachine.read_inside_brackets_then("{}", "_state_global")
35
+ def _struct_definition(self, tokens):
36
+ pass
37
+
38
+ @CodeStateMachine.read_inside_brackets_then("{}", "_state_global")
39
+ def _interface_definition(self, tokens):
40
+ pass
41
+
21
42
  def _function_name(self, token):
22
43
  if token != '`':
23
44
  if token == '(':
24
- return self.next(self._member_function, token)
45
+ if len(self.context.stacked_functions) > 0\
46
+ and self.context.stacked_functions[-1].name != '*global*':
47
+ return self.next(self._function_dec, token)
48
+ else:
49
+ return self.next(self._member_function, token)
25
50
  if token == '{':
26
51
  return self.next(self._expect_function_impl, token)
27
52
  self.context.add_to_function_name(token)
@@ -49,7 +74,8 @@ class GoLikeStates(CodeStateMachine): # pylint: disable=R0903
49
74
  self.context.parameter(token)
50
75
 
51
76
  def _expect_function_impl(self, token):
52
- self.next_if(self._function_impl, token, '{')
77
+ if token == '{' and self.last_token != 'interface':
78
+ self.next(self._function_impl, token)
53
79
 
54
80
  def _function_impl(self, _):
55
81
  def callback():
@@ -84,6 +84,8 @@ class PythonStates(CodeStateMachine): # pylint: disable=R0903
84
84
  def _dec(self, token):
85
85
  if token == ')':
86
86
  self._state = self._state_colon
87
+ elif token == '[':
88
+ self._state = self._state_parameterized_type_annotation
87
89
  else:
88
90
  self.context.parameter(token)
89
91
  return
@@ -100,3 +102,8 @@ class PythonStates(CodeStateMachine): # pylint: disable=R0903
100
102
  if token.startswith('"""') or token.startswith("'''"):
101
103
  self.context.add_nloc(-token.count('\n') - 1)
102
104
  self._state_global(token)
105
+
106
+ def _state_parameterized_type_annotation(self, token):
107
+ self.context.add_to_long_function_name(" " + token)
108
+ if token == ']':
109
+ self._state = self._dec
@@ -0,0 +1,22 @@
1
+ '''
2
+ Language parser for Solidity
3
+ '''
4
+
5
+ from .clike import CCppCommentsMixin
6
+ from .code_reader import CodeReader
7
+ from .golike import GoLikeStates
8
+
9
+
10
+ class SolidityReader(CodeReader, CCppCommentsMixin):
11
+
12
+ ext = ['sol']
13
+ language_names = ['solidity']
14
+ _conditions = set(['if', 'for', 'while', '&&', '||', '?'])
15
+
16
+ def __init__(self, context):
17
+ super(SolidityReader, self).__init__(context)
18
+ self.parallel_states = [SolidityStates(context)]
19
+
20
+
21
+ class SolidityStates(GoLikeStates): # pylint: disable=R0903
22
+ FUNC_KEYWORD = 'function'