lizard 1.17.9__py2.py3-none-any.whl → 1.17.12__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,12 +1,13 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lizard
3
- Version: 1.17.9
3
+ Version: 1.17.12
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
+ Download-URL: https://pypi.python.org/lizard/
6
7
  Author: Terry Yin
7
8
  Author-email: terry@odd-e.com
8
9
  License: MIT
9
- Download-URL: https://pypi.python.org/lizard/
10
+ Project-URL: Source, https://github.com/terryyin/lizard
10
11
  Platform: any
11
12
  Classifier: Development Status :: 5 - Production/Stable
12
13
  Classifier: Intended Audience :: Developers
@@ -22,10 +23,11 @@ Classifier: Programming Language :: Java
22
23
  Classifier: Programming Language :: JavaScript
23
24
  Classifier: Programming Language :: Objective C
24
25
  Classifier: Programming Language :: Python
25
- Classifier: Programming Language :: Python :: 2.7
26
- Classifier: Programming Language :: Python :: 3.4
27
- Classifier: Programming Language :: Python :: 3.5
28
- 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
+ License-File: LICENSE.txt
29
31
 
30
32
  |Web Site| Lizard
31
33
  =================
@@ -63,6 +65,9 @@ A list of supported languages:
63
65
  - Lua
64
66
  - Rust
65
67
  - Fortran
68
+ - Kotlin
69
+ - Solidity
70
+ - Erlang
66
71
 
67
72
  By default lizard will search for any source code that it knows and mix
68
73
  all the results together. This might not be what you want. You can use
@@ -85,7 +90,7 @@ often very hard to get all the included folders and files right when
85
90
  they are complicated. But we don't really need that kind of accuracy for
86
91
  cyclomatic complexity.
87
92
 
88
- It requires python2.7 or above (early versions are not verified).
93
+ It requires python3.8 or above (early versions are not verified).
89
94
 
90
95
  Installation
91
96
  ------------
@@ -109,7 +114,7 @@ Or if you've got the source:
109
114
 
110
115
  ::
111
116
 
112
- [sudo] python setup.py install --install-dir=/path/to/installation/directory/
117
+ [sudo] python setup.py install --prefix=/path/to/installation/directory/
113
118
 
114
119
  Usage
115
120
  -----
@@ -1,4 +1,4 @@
1
- lizard.py,sha256=B-IJWqsIEmR_dHugY_i85-MtAdLJCRPsRWjvkfjI1a0,38150
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,36 +25,39 @@ 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=w0u2NprX_SchtgIWwb7GvCCipCok28egUEqabe1Qdns,181
28
+ lizard_ext/version.py,sha256=vHwwcIFibVozQB9PB9t8W0GArqtRDBM3HzpcDelMWq8,182
29
29
  lizard_ext/xmloutput.py,sha256=-cbh0he4O_X-wX56gkv9AnSPNN0qvR7FACqlBeezUS4,5609
30
- lizard_languages/__init__.py,sha256=_FNuZ0xNP_XHjVHH49kKorr8c7Dz1OSvNTkClG_Y444,1101
31
- lizard_languages/clike.py,sha256=-VKcd8VLuc0d7RXzcI7TiIzpoDzl2eB_d8d1tOv5XZc,10635
32
- lizard_languages/code_reader.py,sha256=8O_lm1WHcbqwDcZth_Sj7ZcjXc5xqsvPd8Q2zJXFbc0,5416
30
+ lizard_languages/__init__.py,sha256=iIbCcjN1AzmVtqCB7caRcLWQ4CdQwyT0UAiRKCkVeL0,1273
31
+ lizard_languages/clike.py,sha256=YgB0dHYdQ5Ae1pN00zcstkuXl94n8Ugo-aTYUNmJr7o,10723
32
+ lizard_languages/code_reader.py,sha256=KTZ7v2MtaowH118yS2sd5GKgUW3hkLWUZ8YBiX3ZsL8,6180
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
41
42
  lizard_languages/js_style_regex_expression.py,sha256=1d4eK5RR0GBAFg2eDb2cKA_YHIYlxjhG7PXAuMOKnRA,743
43
+ lizard_languages/kotlin.py,sha256=v_o2orEzA5gB9vM_0h-E4QXjrc5Yum-0K6W6_laOThc,2844
42
44
  lizard_languages/lua.py,sha256=3nqBcunBzJrhv4Iqaf8xvbyqxZy3aSxJ-IiHimHFlac,1573
43
45
  lizard_languages/objc.py,sha256=2a1teLdaXZBtCeFiIZer1j_sVx9LZ1CbF2XfnqlvLmk,2319
44
46
  lizard_languages/php.py,sha256=8OufyR2TIWyf3bXuTmp37Vwf_tEPF4YV5M3i5_jnguA,1377
45
- lizard_languages/python.py,sha256=HljeW-gQqmWjmc8vB7Kt75RBHq3OfKj89bpZL3QmdEY,3252
47
+ lizard_languages/python.py,sha256=JDXqQ7SEnNSXlbK5sMyUKwCFBTEto20Wg8_ZkzYisSI,3721
46
48
  lizard_languages/ruby.py,sha256=gUrFsaS6ZJbjb9CixBHP9n0BxGOb8HsDEg7jJ2bz_80,2187
47
49
  lizard_languages/rubylike.py,sha256=dAGZ2wqW8nqaESMU8HkeR9gwQ-q9fmZqE6AANvVZD1Q,3426
48
50
  lizard_languages/rust.py,sha256=DG2RkR9JWwcD6gIw-BPzg-Yo_lxQtSvfgHioFWIQm9o,610
49
51
  lizard_languages/scala.py,sha256=6Jr_TG945VYqB3o5weD7jN7S4beHt4aVj3r-fmKeMAM,1316
50
52
  lizard_languages/script_language.py,sha256=FOzB9Rg5-XTnFDeeRRyIrp2rDomRDHhaPsxsxeCx9GU,539
51
- lizard_languages/swift.py,sha256=D0z87M2CoBhG83pN8M1RylZURD97qPBcVuQhx9IS3g4,2404
53
+ lizard_languages/solidity.py,sha256=Z0GD7U5bI5eUikdy7m_iKWeFD5yXRYq4r3zycscOhJQ,553
54
+ lizard_languages/swift.py,sha256=p8S2OAkQOx9YQ02yhoVXFkr7pMqUH1Nb3RVXPHRU_9M,2450
52
55
  lizard_languages/tnsdl.py,sha256=pGcalA_lHY362v2wwPS86seYBOOBBjvmU6vd4Yy3A9g,2803
53
56
  lizard_languages/ttcn.py,sha256=ygjw_raBmPF-4mgoM8m6CAdyEMpTI-n1kZJK1RL4Vxo,2131
54
57
  lizard_languages/typescript.py,sha256=yjUTVDkiONbg2v089pZC4wrCJSo1J5NVbQzbCfF4k6s,1547
55
- lizard-1.17.9.dist-info/LICENSE.txt,sha256=05ZjgQ8Cl1dD9p0BhW-Txzkc5rhCogGJVEuf1GT2Y_M,1303
56
- lizard-1.17.9.dist-info/METADATA,sha256=ZZZNi4vjB0Q9JKxuMtbUzPo_lxmFdRomQi8u_bGMgVs,15267
57
- lizard-1.17.9.dist-info/WHEEL,sha256=Z-nyYpwrcSqxfdux5Mbn_DQ525iP7J2DG3JgGvOYyTQ,110
58
- lizard-1.17.9.dist-info/entry_points.txt,sha256=pPMMwoHAltzGHqR2WeJQItLeeyR7pbX5R2S_POC-xoo,40
59
- lizard-1.17.9.dist-info/top_level.txt,sha256=5NTrTaOLhHuTzXaGcZPKfuaOgUv7WafNGe0Zl5aycpg,35
60
- lizard-1.17.9.dist-info/RECORD,,
58
+ lizard-1.17.12.dist-info/LICENSE.txt,sha256=05ZjgQ8Cl1dD9p0BhW-Txzkc5rhCogGJVEuf1GT2Y_M,1303
59
+ lizard-1.17.12.dist-info/METADATA,sha256=449xh2XT8PSdqHs1N-nAQVoyKRFp7bYdJGtUNVK5SMc,15379
60
+ lizard-1.17.12.dist-info/WHEEL,sha256=fS9sRbCBHs7VFcwJLnLXN1MZRR0_TVTxvXKzOnaSFs8,110
61
+ lizard-1.17.12.dist-info/entry_points.txt,sha256=pPMMwoHAltzGHqR2WeJQItLeeyR7pbX5R2S_POC-xoo,40
62
+ lizard-1.17.12.dist-info/top_level.txt,sha256=5NTrTaOLhHuTzXaGcZPKfuaOgUv7WafNGe0Zl5aycpg,35
63
+ lizard-1.17.12.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.36.2)
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
@@ -281,7 +281,6 @@ class FunctionInfo(Nesting): # pylint: disable=R0902
281
281
  self.full_parameters = []
282
282
  self.filename = filename
283
283
  self.top_nesting_level = -1
284
- self.length = 0
285
284
  self.fan_in = 0
286
285
  self.fan_out = 0
287
286
  self.general_fan_out = 0
@@ -302,14 +301,24 @@ class FunctionInfo(Nesting): # pylint: disable=R0902
302
301
  " %(name)s@%(start_line)s-%(end_line)s@%(filename)s"
303
302
  % self.__dict__)
304
303
 
305
- parameter_count = property(lambda self: len(self.full_parameters))
304
+ parameter_count = property(lambda self: len(self.parameters))
306
305
 
307
306
  @property
308
307
  def parameters(self):
309
- 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)
310
315
  for f in self.full_parameters]
311
316
  return [m.group(1) for m in matches if m]
312
317
 
318
+ @property
319
+ def length(self):
320
+ return self.end_line - self.start_line + 1
321
+
313
322
  def add_to_function_name(self, app):
314
323
  self.name += app
315
324
  self.long_name += app
@@ -361,7 +370,6 @@ class NestingStack(object):
361
370
  def __init__(self):
362
371
  self.nesting_stack = []
363
372
  self.pending_function = None
364
- self.function_stack = []
365
373
 
366
374
  def with_namespace(self, name):
367
375
  return ''.join([x.name_in_space for x in self.nesting_stack] + [name])
@@ -438,8 +446,6 @@ class FileInfoBuilder(object):
438
446
  self.fileinfo.nloc += count
439
447
  self.current_function.nloc += count
440
448
  self.current_function.end_line = self.current_line
441
- self.current_function.length = \
442
- self.current_line - self.current_function.start_line + 1
443
449
  self.newline = count > 0
444
450
 
445
451
  def try_new_function(self, name):
@@ -560,10 +566,13 @@ class FileAnalyzer(object): # pylint: disable=R0903
560
566
  context = FileInfoBuilder(filename)
561
567
  reader = (get_reader_for(filename) or CLikeReader)(context)
562
568
  tokens = reader.generate_tokens(code)
563
- for processor in self.processors:
564
- tokens = processor(tokens, reader)
565
- for _ in reader(tokens, reader):
566
- pass
569
+ try:
570
+ for processor in self.processors:
571
+ tokens = processor(tokens, reader)
572
+ for _ in reader(tokens, reader):
573
+ pass
574
+ except RecursionError as e:
575
+ sys.stderr.write("[skip] fail to process '%s' with RecursionError - %s\n" % (filename, e))
567
576
  return context.fileinfo
568
577
 
569
578
 
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.9"
6
+ version = "1.17.12"
@@ -1,8 +1,10 @@
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
7
+ from .kotlin import KotlinReader
6
8
  from .python import PythonReader
7
9
  from .objc import ObjCReader
8
10
  from .ttcn import TTCNReader
@@ -17,6 +19,7 @@ from .lua import LuaReader
17
19
  from .rust import RustReader
18
20
  from .typescript import TypeScriptReader
19
21
  from .fortran import FortranReader
22
+ from .solidity import SolidityReader
20
23
 
21
24
 
22
25
  def languages():
@@ -37,7 +40,10 @@ def languages():
37
40
  LuaReader,
38
41
  RustReader,
39
42
  TypeScriptReader,
40
- FortranReader
43
+ FortranReader,
44
+ KotlinReader,
45
+ SolidityReader,
46
+ ErlangReader,
41
47
  ]
42
48
 
43
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=re.NOFLAG):
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 = ["<<=", ">>=", "||", "&&", "===", "!==",
@@ -124,6 +126,9 @@ class CodeReader:
124
126
  r"(?:" +
125
127
  r"\/\*.*?\*\/" +
126
128
  add +
129
+ r"|(?:\d+\')+\d+" +
130
+ r"|0x(?:[0-9A-Fa-f]+\')+[0-9A-Fa-f]+" +
131
+ r"|0b(?:[01]+\')+[01]+" +
127
132
  r"|\w+" +
128
133
  r"|\"(?:\\.|[^\"\\])*\"" +
129
134
  r"|\'(?:\\.|[^\'\\])*?\'" +
@@ -135,7 +140,7 @@ class CodeReader:
135
140
  r"|\\\n" +
136
141
  r"|\n" +
137
142
  r"|[^\S\n]+" +
138
- r"|.)", re.M | re.S)
143
+ r"|.)", re.M | re.S | flags)
139
144
  macro = ""
140
145
  for match in token_pattern.finditer(source):
141
146
  token = token_class(match)
@@ -153,7 +158,21 @@ class CodeReader:
153
158
  if macro:
154
159
  yield macro
155
160
 
156
- 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), re.NOFLAG)
174
+
175
+ return _generate_tokens(source_code, pattern.sub('', addition), flags=flags)
157
176
 
158
177
  def __call__(self, tokens, reader):
159
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():
@@ -0,0 +1,92 @@
1
+ '''
2
+ Language parser for Apple Swift
3
+ '''
4
+
5
+ from .clike import CCppCommentsMixin
6
+ from .code_reader import CodeReader, CodeStateMachine
7
+ from .golike import GoLikeStates
8
+ from .swift import SwiftReplaceLabel
9
+
10
+
11
+ class KotlinReader(CodeReader, CCppCommentsMixin, SwiftReplaceLabel):
12
+ # pylint: disable=R0903
13
+
14
+ ext = ['kt', 'kts']
15
+ language_names = ['kotlin']
16
+ _conditions = {
17
+ 'if', 'for', 'while', 'catch', '&&', '||', '?:'
18
+ }
19
+
20
+ def __init__(self, context):
21
+ super(KotlinReader, self).__init__(context)
22
+ self.parallel_states = [KotlinStates(context)]
23
+
24
+ @staticmethod
25
+ def generate_tokens(source_code, addition='', token_class=None):
26
+ return CodeReader.generate_tokens(
27
+ source_code,
28
+ r"|`\w+`" +
29
+ r"|\w+\?" +
30
+ r"|\w+\!!" +
31
+ r"|\?\?" +
32
+ r"|\?:" +
33
+ addition
34
+ )
35
+
36
+
37
+ class KotlinStates(GoLikeStates): # pylint: disable=R0903
38
+
39
+ FUNC_KEYWORD = 'fun'
40
+
41
+ def __init__(self, context, in_when_cases=False):
42
+ super().__init__(context)
43
+ self._in_when_cases = in_when_cases
44
+
45
+ def _state_global(self, token):
46
+ if token in ('get', 'set'):
47
+ self.context.push_new_function(token)
48
+ self._state = self._expect_function_impl
49
+ elif token == '->':
50
+ if self._in_when_cases:
51
+ self.context.add_condition()
52
+ else:
53
+ self.context.push_new_function("(anonymous)")
54
+ self._state = super(KotlinStates, self)._expect_function_impl
55
+ elif token in ('val', 'var', ','):
56
+ self._state = self._expect_declaration_name
57
+ elif token == 'interface':
58
+ self._state = self._interface
59
+ elif token == 'when':
60
+ self._state = self._when_cases
61
+ else:
62
+ super(KotlinStates, self)._state_global(token)
63
+
64
+ def _expect_declaration_name(self, token):
65
+ self._state = self._state_global
66
+
67
+ def _expect_function_impl(self, token):
68
+ if token == '{' or token == '=':
69
+ self.next(self._function_impl, token)
70
+
71
+ @CodeStateMachine.read_inside_brackets_then("{}")
72
+ def _interface(self, end_token):
73
+ if end_token == "}":
74
+ self._state = self._state_global
75
+
76
+ def _function_name(self, token):
77
+ if token == "<":
78
+ self.next(self._template, token)
79
+ else:
80
+ return super(KotlinStates, self)._function_name(token)
81
+
82
+ @CodeStateMachine.read_inside_brackets_then("<>", "_function_name")
83
+ def _template(self, tokens):
84
+ pass
85
+
86
+ def _when_cases(self, token):
87
+ def callback():
88
+ self.context.add_condition(inc=-1)
89
+ self.next(self._state_global)
90
+ if token != '{':
91
+ return
92
+ self.sub_state(KotlinStates(self.context, in_when_cases=True), callback)
@@ -53,7 +53,9 @@ class PythonReader(CodeReader, ScriptLanguageMixIn):
53
53
  current_leading_spaces += count_spaces(token)
54
54
  else:
55
55
  if not token.startswith('#'):
56
- indents.set_nesting(current_leading_spaces, token)
56
+ current_function = self.context.current_function
57
+ if current_function.name == '*global*' or current_function.long_name.endswith(')'):
58
+ indents.set_nesting(current_leading_spaces, token)
57
59
  reading_leading_space = False
58
60
  else:
59
61
  reading_leading_space = True
@@ -82,6 +84,8 @@ class PythonStates(CodeStateMachine): # pylint: disable=R0903
82
84
  def _dec(self, token):
83
85
  if token == ')':
84
86
  self._state = self._state_colon
87
+ elif token == '[':
88
+ self._state = self._state_parameterized_type_annotation
85
89
  else:
86
90
  self.context.parameter(token)
87
91
  return
@@ -98,3 +102,8 @@ class PythonStates(CodeStateMachine): # pylint: disable=R0903
98
102
  if token.startswith('"""') or token.startswith("'''"):
99
103
  self.context.add_nloc(-token.count('\n') - 1)
100
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'
lizard_languages/swift.py CHANGED
@@ -7,7 +7,24 @@ from .clike import CCppCommentsMixin
7
7
  from .golike import GoLikeStates
8
8
 
9
9
 
10
- class SwiftReader(CodeReader, CCppCommentsMixin):
10
+ class SwiftReplaceLabel:
11
+ def preprocess(self, tokens):
12
+ tokens = list(t for t in tokens if not t.isspace() or t == '\n')
13
+
14
+ def replace_label(tokens, target, replace):
15
+ for i in range(0, len(tokens) - len(target)):
16
+ if tokens[i:i + len(target)] == target:
17
+ for j, repl in enumerate(replace):
18
+ tokens[i + j] = repl
19
+ return tokens
20
+
21
+ for k in (k for k in self.conditions if k.isalpha()):
22
+ tokens = replace_label(tokens, ["(", k, ":"], ["(", "_" + k, ":"])
23
+ tokens = replace_label(tokens, [",", k, ":"], [",", "_" + k, ":"])
24
+ return tokens
25
+
26
+
27
+ class SwiftReader(CodeReader, CCppCommentsMixin, SwiftReplaceLabel):
11
28
  # pylint: disable=R0903
12
29
 
13
30
  FUNC_KEYWORD = 'def'
@@ -30,20 +47,6 @@ class SwiftReader(CodeReader, CCppCommentsMixin):
30
47
  r"|\?\?" +
31
48
  addition)
32
49
 
33
- def preprocess(self, tokens):
34
- tokens = list(t for t in tokens if not t.isspace() or t == '\n')
35
-
36
- def replace_label(tokens, target, replace):
37
- for i in range(0, len(tokens) - len(target)):
38
- if tokens[i:i + len(target)] == target:
39
- for j, repl in enumerate(replace):
40
- tokens[i + j] = repl
41
- return tokens
42
- for k in (k for k in self.conditions if k.isalpha()):
43
- tokens = replace_label(tokens, ["(", k, ":"], ["(", "_" + k, ":"])
44
- tokens = replace_label(tokens, [",", k, ":"], [",", "_" + k, ":"])
45
- return tokens
46
-
47
50
 
48
51
  class SwiftStates(GoLikeStates): # pylint: disable=R0903
49
52
  def _state_global(self, token):