lizard 1.17.10__tar.gz → 1.17.13__tar.gz
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.10 → lizard-1.17.13}/PKG-INFO +9 -7
- {lizard-1.17.10 → lizard-1.17.13}/README.rst +4 -2
- {lizard-1.17.10 → lizard-1.17.13}/lizard.egg-info/PKG-INFO +9 -7
- {lizard-1.17.10 → lizard-1.17.13}/lizard.egg-info/SOURCES.txt +3 -0
- lizard-1.17.13/lizard.egg-info/requires.txt +1 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard.py +8 -3
- {lizard-1.17.10 → lizard-1.17.13}/lizard_ext/version.py +1 -1
- {lizard-1.17.10 → lizard-1.17.13}/lizard_languages/__init__.py +5 -1
- {lizard-1.17.10 → lizard-1.17.13}/lizard_languages/clike.py +2 -1
- {lizard-1.17.10 → lizard-1.17.13}/lizard_languages/code_reader.py +21 -3
- lizard-1.17.13/lizard_languages/erlang.py +112 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_languages/fortran.py +4 -3
- {lizard-1.17.10 → lizard-1.17.13}/lizard_languages/golike.py +28 -2
- {lizard-1.17.10 → lizard-1.17.13}/lizard_languages/python.py +7 -0
- lizard-1.17.13/lizard_languages/solidity.py +22 -0
- {lizard-1.17.10 → lizard-1.17.13}/setup.py +5 -4
- {lizard-1.17.10 → lizard-1.17.13}/test/testLanguages.py +8 -1
- {lizard-1.17.10 → lizard-1.17.13}/test/testOutputCSV.py +2 -2
- {lizard-1.17.10 → lizard-1.17.13}/test/testOutputHTML.py +1 -2
- {lizard-1.17.10 → lizard-1.17.13}/LICENSE.txt +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard.egg-info/dependency_links.txt +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard.egg-info/entry_points.txt +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard.egg-info/top_level.txt +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_ext/__init__.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_ext/auto_open.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_ext/csvoutput.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_ext/default_ordered_dict.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_ext/extension_base.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_ext/htmloutput.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_ext/keywords.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_ext/lizardboolcount.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_ext/lizardcomplextags.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_ext/lizardcpre.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_ext/lizarddependencycount.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_ext/lizarddumpcomments.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_ext/lizardduplicate.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_ext/lizardduplicated_param_list.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_ext/lizardexitcount.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_ext/lizardgotocount.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_ext/lizardignoreassert.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_ext/lizardio.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_ext/lizardmccabe.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_ext/lizardmodified.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_ext/lizardnd.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_ext/lizardnonstrict.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_ext/lizardns.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_ext/lizardoutside.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_ext/lizardstatementcount.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_ext/lizardwordcount.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_ext/xmloutput.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_languages/csharp.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_languages/gdscript.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_languages/go.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_languages/java.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_languages/javascript.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_languages/js_style_language_states.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_languages/js_style_regex_expression.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_languages/kotlin.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_languages/lua.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_languages/objc.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_languages/php.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_languages/ruby.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_languages/rubylike.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_languages/rust.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_languages/scala.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_languages/script_language.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_languages/swift.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_languages/tnsdl.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_languages/ttcn.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/lizard_languages/typescript.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/setup.cfg +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/test/testApplication.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/test/testAssertionExtension.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/test/testBasicFunctionInfo.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/test/testCOutsideComplexity.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/test/testCPreprocessorExtension.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/test/testCommentOptions.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/test/testCyclomaticComplexity.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/test/testExtension.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/test/testFilesFilter.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/test/testFunctionDependencyCount.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/test/testFunctionExitCount.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/test/testFunctionGotoCount.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/test/testFunctionStatementCount.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/test/testHelpers.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/test/testMcCabe.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/test/testNestedStructures.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/test/testNestingDepth.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/test/testOutput.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/test/testOutputFile.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/test/testTokenizer.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/test/test_analyzer.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/test/test_auto_open.py +0 -0
- {lizard-1.17.10 → lizard-1.17.13}/test/test_options.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: lizard
|
|
3
|
-
Version: 1.17.
|
|
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,10 +23,10 @@ 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 ::
|
|
27
|
-
Classifier: Programming Language :: Python :: 3.
|
|
28
|
-
Classifier: Programming Language :: Python :: 3.
|
|
29
|
-
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
30
|
License-File: LICENSE.txt
|
|
31
31
|
|
|
32
32
|
|Web Site| Lizard
|
|
@@ -66,6 +66,8 @@ A list of supported languages:
|
|
|
66
66
|
- Rust
|
|
67
67
|
- Fortran
|
|
68
68
|
- Kotlin
|
|
69
|
+
- Solidity
|
|
70
|
+
- Erlang
|
|
69
71
|
|
|
70
72
|
By default lizard will search for any source code that it knows and mix
|
|
71
73
|
all the results together. This might not be what you want. You can use
|
|
@@ -88,7 +90,7 @@ often very hard to get all the included folders and files right when
|
|
|
88
90
|
they are complicated. But we don't really need that kind of accuracy for
|
|
89
91
|
cyclomatic complexity.
|
|
90
92
|
|
|
91
|
-
It requires
|
|
93
|
+
It requires python3.8 or above (early versions are not verified).
|
|
92
94
|
|
|
93
95
|
Installation
|
|
94
96
|
------------
|
|
@@ -112,7 +114,7 @@ Or if you've got the source:
|
|
|
112
114
|
|
|
113
115
|
::
|
|
114
116
|
|
|
115
|
-
[sudo] python setup.py install --
|
|
117
|
+
[sudo] python setup.py install --prefix=/path/to/installation/directory/
|
|
116
118
|
|
|
117
119
|
Usage
|
|
118
120
|
-----
|
|
@@ -35,6 +35,8 @@ A list of supported languages:
|
|
|
35
35
|
- Rust
|
|
36
36
|
- Fortran
|
|
37
37
|
- Kotlin
|
|
38
|
+
- Solidity
|
|
39
|
+
- Erlang
|
|
38
40
|
|
|
39
41
|
By default lizard will search for any source code that it knows and mix
|
|
40
42
|
all the results together. This might not be what you want. You can use
|
|
@@ -57,7 +59,7 @@ often very hard to get all the included folders and files right when
|
|
|
57
59
|
they are complicated. But we don't really need that kind of accuracy for
|
|
58
60
|
cyclomatic complexity.
|
|
59
61
|
|
|
60
|
-
It requires
|
|
62
|
+
It requires python3.8 or above (early versions are not verified).
|
|
61
63
|
|
|
62
64
|
Installation
|
|
63
65
|
------------
|
|
@@ -81,7 +83,7 @@ Or if you've got the source:
|
|
|
81
83
|
|
|
82
84
|
::
|
|
83
85
|
|
|
84
|
-
[sudo] python setup.py install --
|
|
86
|
+
[sudo] python setup.py install --prefix=/path/to/installation/directory/
|
|
85
87
|
|
|
86
88
|
Usage
|
|
87
89
|
-----
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: lizard
|
|
3
|
-
Version: 1.17.
|
|
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,10 +23,10 @@ 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 ::
|
|
27
|
-
Classifier: Programming Language :: Python :: 3.
|
|
28
|
-
Classifier: Programming Language :: Python :: 3.
|
|
29
|
-
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
30
|
License-File: LICENSE.txt
|
|
31
31
|
|
|
32
32
|
|Web Site| Lizard
|
|
@@ -66,6 +66,8 @@ A list of supported languages:
|
|
|
66
66
|
- Rust
|
|
67
67
|
- Fortran
|
|
68
68
|
- Kotlin
|
|
69
|
+
- Solidity
|
|
70
|
+
- Erlang
|
|
69
71
|
|
|
70
72
|
By default lizard will search for any source code that it knows and mix
|
|
71
73
|
all the results together. This might not be what you want. You can use
|
|
@@ -88,7 +90,7 @@ often very hard to get all the included folders and files right when
|
|
|
88
90
|
they are complicated. But we don't really need that kind of accuracy for
|
|
89
91
|
cyclomatic complexity.
|
|
90
92
|
|
|
91
|
-
It requires
|
|
93
|
+
It requires python3.8 or above (early versions are not verified).
|
|
92
94
|
|
|
93
95
|
Installation
|
|
94
96
|
------------
|
|
@@ -112,7 +114,7 @@ Or if you've got the source:
|
|
|
112
114
|
|
|
113
115
|
::
|
|
114
116
|
|
|
115
|
-
[sudo] python setup.py install --
|
|
117
|
+
[sudo] python setup.py install --prefix=/path/to/installation/directory/
|
|
116
118
|
|
|
117
119
|
Usage
|
|
118
120
|
-----
|
|
@@ -7,6 +7,7 @@ lizard.egg-info/PKG-INFO
|
|
|
7
7
|
lizard.egg-info/SOURCES.txt
|
|
8
8
|
lizard.egg-info/dependency_links.txt
|
|
9
9
|
lizard.egg-info/entry_points.txt
|
|
10
|
+
lizard.egg-info/requires.txt
|
|
10
11
|
lizard.egg-info/top_level.txt
|
|
11
12
|
lizard_ext/__init__.py
|
|
12
13
|
lizard_ext/auto_open.py
|
|
@@ -40,6 +41,7 @@ lizard_languages/__init__.py
|
|
|
40
41
|
lizard_languages/clike.py
|
|
41
42
|
lizard_languages/code_reader.py
|
|
42
43
|
lizard_languages/csharp.py
|
|
44
|
+
lizard_languages/erlang.py
|
|
43
45
|
lizard_languages/fortran.py
|
|
44
46
|
lizard_languages/gdscript.py
|
|
45
47
|
lizard_languages/go.py
|
|
@@ -58,6 +60,7 @@ lizard_languages/rubylike.py
|
|
|
58
60
|
lizard_languages/rust.py
|
|
59
61
|
lizard_languages/scala.py
|
|
60
62
|
lizard_languages/script_language.py
|
|
63
|
+
lizard_languages/solidity.py
|
|
61
64
|
lizard_languages/swift.py
|
|
62
65
|
lizard_languages/tnsdl.py
|
|
63
66
|
lizard_languages/ttcn.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pygments
|
|
@@ -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.
|
|
304
|
+
parameter_count = property(lambda self: len(self.parameters))
|
|
305
305
|
|
|
306
306
|
@property
|
|
307
307
|
def parameters(self):
|
|
308
|
-
|
|
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])
|
|
@@ -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
|
|
|
@@ -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
|
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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():
|
|
@@ -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'
|
|
@@ -87,14 +87,15 @@ setup(
|
|
|
87
87
|
'Programming Language :: JavaScript',
|
|
88
88
|
'Programming Language :: Objective C',
|
|
89
89
|
'Programming Language :: Python',
|
|
90
|
-
'Programming Language :: Python ::
|
|
91
|
-
'Programming Language :: Python :: 3.
|
|
92
|
-
'Programming Language :: Python :: 3.
|
|
93
|
-
'Programming Language :: Python :: 3.
|
|
90
|
+
'Programming Language :: Python :: 3.8',
|
|
91
|
+
'Programming Language :: Python :: 3.9',
|
|
92
|
+
'Programming Language :: Python :: 3.10',
|
|
93
|
+
'Programming Language :: Python :: 3.11'],
|
|
94
94
|
cmdclass={'version': VersionCommand},
|
|
95
95
|
packages=['lizard_ext', 'lizard_languages'],
|
|
96
96
|
#data_files=[('lizard_ext', [])],
|
|
97
97
|
py_modules=['lizard'],
|
|
98
|
+
install_requires=['pygments'],
|
|
98
99
|
entry_points={'console_scripts': ['lizard = lizard:main']},
|
|
99
100
|
author='Terry Yin',
|
|
100
101
|
author_email='terry@odd-e.com',
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import unittest
|
|
2
|
-
from lizard_languages import get_reader_for, CLikeReader, JavaReader, ObjCReader, JavaScriptReader, ScalaReader
|
|
2
|
+
from lizard_languages import get_reader_for, CLikeReader, JavaReader, ObjCReader, JavaScriptReader, ScalaReader,\
|
|
3
|
+
GDScriptReader, SolidityReader, ErlangReader
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
class TestLanguageChooser(unittest.TestCase):
|
|
@@ -29,3 +30,9 @@ class TestLanguageChooser(unittest.TestCase):
|
|
|
29
30
|
|
|
30
31
|
def test_unknown_extension(self):
|
|
31
32
|
self.assertEqual(None, get_reader_for("a.unknown"))
|
|
33
|
+
|
|
34
|
+
def test_Solidity(self):
|
|
35
|
+
self.assertEqual(SolidityReader, get_reader_for("a.sol"))
|
|
36
|
+
|
|
37
|
+
def test_erlang(self):
|
|
38
|
+
self.assertEqual(ErlangReader, get_reader_for("a.erl"))
|
|
@@ -22,7 +22,7 @@ class TestCSVOutput(StreamStdoutTestCase):
|
|
|
22
22
|
options_mock.verbose = True
|
|
23
23
|
options_mock.extensions = []
|
|
24
24
|
csv_output(AllResult([self.fileSummary]), options_mock)
|
|
25
|
-
self.
|
|
25
|
+
self.assertRegex(sys.stdout.stream,
|
|
26
26
|
r"NLOC,CCN,token,PARAM,length,location,file,function,long_name,start,end")
|
|
27
27
|
|
|
28
28
|
def test_csv_header_with_extension(self):
|
|
@@ -35,7 +35,7 @@ class TestCSVOutput(StreamStdoutTestCase):
|
|
|
35
35
|
results = AllResult([self.fileSummary])
|
|
36
36
|
results.result[0].function_list[0].exit_count = 1
|
|
37
37
|
csv_output(results, options_mock)
|
|
38
|
-
self.
|
|
38
|
+
self.assertRegex(sys.stdout.stream,
|
|
39
39
|
r"NLOC,CCN,token,PARAM,length,location,file,function,long_name,start,end,exits")
|
|
40
40
|
|
|
41
41
|
def test_csv_no_header(self):
|
|
@@ -17,6 +17,5 @@ class TestHTMLOutput(StreamStdoutTestCase):
|
|
|
17
17
|
|
|
18
18
|
def test_should_have_html_body(self):
|
|
19
19
|
html_output([self.fileSummary], self.option, None, AllResult)
|
|
20
|
-
self.
|
|
21
|
-
r"\<html\>")
|
|
20
|
+
self.assertRegex(sys.stdout.stream, r"\<html\>")
|
|
22
21
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|