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.
- {lizard-1.17.9.dist-info → lizard-1.17.12.dist-info}/METADATA +13 -8
- {lizard-1.17.9.dist-info → lizard-1.17.12.dist-info}/RECORD +18 -15
- {lizard-1.17.9.dist-info → lizard-1.17.12.dist-info}/WHEEL +1 -1
- lizard.py +19 -10
- lizard_ext/version.py +1 -1
- lizard_languages/__init__.py +7 -1
- lizard_languages/clike.py +2 -1
- lizard_languages/code_reader.py +22 -3
- lizard_languages/erlang.py +112 -0
- lizard_languages/fortran.py +4 -3
- lizard_languages/golike.py +28 -2
- lizard_languages/kotlin.py +92 -0
- lizard_languages/python.py +10 -1
- lizard_languages/solidity.py +22 -0
- lizard_languages/swift.py +18 -15
- {lizard-1.17.9.dist-info → lizard-1.17.12.dist-info}/LICENSE.txt +0 -0
- {lizard-1.17.9.dist-info → lizard-1.17.12.dist-info}/entry_points.txt +0 -0
- {lizard-1.17.9.dist-info → lizard-1.17.12.dist-info}/top_level.txt +0 -0
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: lizard
|
|
3
|
-
Version: 1.17.
|
|
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
|
-
|
|
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 ::
|
|
26
|
-
Classifier: Programming Language :: Python :: 3.
|
|
27
|
-
Classifier: Programming Language :: Python :: 3.
|
|
28
|
-
Classifier: Programming Language :: Python :: 3.
|
|
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
|
|
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 --
|
|
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=
|
|
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=
|
|
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=
|
|
31
|
-
lizard_languages/clike.py,sha256
|
|
32
|
-
lizard_languages/code_reader.py,sha256=
|
|
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/
|
|
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=
|
|
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=
|
|
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/
|
|
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.
|
|
56
|
-
lizard-1.17.
|
|
57
|
-
lizard-1.17.
|
|
58
|
-
lizard-1.17.
|
|
59
|
-
lizard-1.17.
|
|
60
|
-
lizard-1.17.
|
|
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,,
|
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.
|
|
304
|
+
parameter_count = property(lambda self: len(self.parameters))
|
|
306
305
|
|
|
307
306
|
@property
|
|
308
307
|
def parameters(self):
|
|
309
|
-
|
|
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
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
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
lizard_languages/__init__.py
CHANGED
|
@@ -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
|
-
|
|
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
|
|
lizard_languages/code_reader.py
CHANGED
|
@@ -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
|
-
|
|
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)
|
lizard_languages/fortran.py
CHANGED
|
@@ -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()
|
lizard_languages/golike.py
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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)
|
lizard_languages/python.py
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|