lizard 1.18.0__tar.gz → 1.20.0__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.18.0 → lizard-1.20.0}/PKG-INFO +30 -20
- {lizard-1.18.0 → lizard-1.20.0}/README.rst +28 -18
- {lizard-1.18.0 → lizard-1.20.0}/lizard.egg-info/PKG-INFO +30 -20
- {lizard-1.18.0 → lizard-1.20.0}/lizard.egg-info/SOURCES.txt +1 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard_ext/__init__.py +0 -1
- {lizard-1.18.0 → lizard-1.20.0}/lizard_ext/htmloutput.py +86 -17
- {lizard-1.18.0 → lizard-1.20.0}/lizard_ext/lizardcomplextags.py +6 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard_ext/lizardmccabe.py +6 -1
- {lizard-1.18.0 → lizard-1.20.0}/lizard_ext/lizardmodified.py +7 -2
- {lizard-1.18.0 → lizard-1.20.0}/lizard_ext/lizardnd.py +64 -1
- {lizard-1.18.0 → lizard-1.20.0}/lizard_ext/lizardnonstrict.py +2 -1
- {lizard-1.18.0 → lizard-1.20.0}/lizard_ext/lizardns.py +31 -8
- {lizard-1.18.0 → lizard-1.20.0}/lizard_ext/version.py +1 -1
- {lizard-1.18.0 → lizard-1.20.0}/lizard_languages/__init__.py +2 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard_languages/clike.py +6 -3
- {lizard-1.18.0 → lizard-1.20.0}/lizard_languages/code_reader.py +27 -3
- {lizard-1.18.0 → lizard-1.20.0}/lizard_languages/csharp.py +21 -2
- {lizard-1.18.0 → lizard-1.20.0}/lizard_languages/erlang.py +9 -1
- {lizard-1.18.0 → lizard-1.20.0}/lizard_languages/fortran.py +5 -6
- {lizard-1.18.0 → lizard-1.20.0}/lizard_languages/gdscript.py +6 -2
- {lizard-1.18.0 → lizard-1.20.0}/lizard_languages/kotlin.py +6 -3
- {lizard-1.18.0 → lizard-1.20.0}/lizard_languages/perl.py +8 -4
- {lizard-1.18.0 → lizard-1.20.0}/lizard_languages/php.py +6 -2
- lizard-1.20.0/lizard_languages/plsql.py +422 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard_languages/python.py +6 -4
- {lizard-1.18.0 → lizard-1.20.0}/lizard_languages/r.py +9 -6
- {lizard-1.18.0 → lizard-1.20.0}/lizard_languages/rubylike.py +6 -3
- {lizard-1.18.0 → lizard-1.20.0}/lizard_languages/rust.py +7 -2
- {lizard-1.18.0 → lizard-1.20.0}/lizard_languages/scala.py +6 -2
- {lizard-1.18.0 → lizard-1.20.0}/lizard_languages/solidity.py +6 -1
- {lizard-1.18.0 → lizard-1.20.0}/lizard_languages/st.py +9 -5
- {lizard-1.18.0 → lizard-1.20.0}/lizard_languages/swift.py +6 -2
- {lizard-1.18.0 → lizard-1.20.0}/lizard_languages/tnsdl.py +6 -1
- {lizard-1.18.0 → lizard-1.20.0}/lizard_languages/tsx.py +2 -2
- {lizard-1.18.0 → lizard-1.20.0}/lizard_languages/ttcn.py +5 -3
- {lizard-1.18.0 → lizard-1.20.0}/lizard_languages/typescript.py +58 -4
- {lizard-1.18.0 → lizard-1.20.0}/lizard_languages/zig.py +7 -1
- {lizard-1.18.0 → lizard-1.20.0}/test/testNestedStructures.py +55 -0
- {lizard-1.18.0 → lizard-1.20.0}/test/testNestingDepth.py +48 -0
- lizard-1.20.0/test/testOutputHTML.py +42 -0
- lizard-1.18.0/test/testOutputHTML.py +0 -21
- {lizard-1.18.0 → lizard-1.20.0}/LICENSE.txt +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard.egg-info/dependency_links.txt +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard.egg-info/entry_points.txt +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard.egg-info/requires.txt +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard.egg-info/top_level.txt +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard_ext/auto_open.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard_ext/checkstyleoutput.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard_ext/csvoutput.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard_ext/default_ordered_dict.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard_ext/extension_base.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard_ext/keywords.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard_ext/lizardboolcount.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard_ext/lizardcpre.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard_ext/lizarddependencycount.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard_ext/lizarddumpcomments.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard_ext/lizardduplicate.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard_ext/lizardduplicated_param_list.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard_ext/lizardexitcount.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard_ext/lizardgotocount.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard_ext/lizardignoreassert.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard_ext/lizardio.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard_ext/lizardoutside.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard_ext/lizardstatementcount.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard_ext/lizardwordcount.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard_ext/xmloutput.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard_languages/go.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard_languages/golike.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard_languages/java.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard_languages/javascript.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard_languages/js_style_regex_expression.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard_languages/lua.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard_languages/objc.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard_languages/ruby.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard_languages/script_language.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/lizard_languages/vue.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/setup.cfg +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/setup.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/test/testApplication.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/test/testAssertionExtension.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/test/testBasicFunctionInfo.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/test/testCOutsideComplexity.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/test/testCPreprocessorExtension.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/test/testCommentOptions.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/test/testCyclomaticComplexity.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/test/testExtension.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/test/testFilesFilter.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/test/testFunctionDependencyCount.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/test/testFunctionExitCount.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/test/testFunctionGotoCount.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/test/testFunctionStatementCount.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/test/testHelpers.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/test/testLanguages.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/test/testMcCabe.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/test/testOutput.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/test/testOutputCSV.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/test/testOutputFile.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/test/testTokenizer.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/test/test_analyzer.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/test/test_auto_open.py +0 -0
- {lizard-1.18.0 → lizard-1.20.0}/test/test_options.py +0 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: lizard
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.20.0
|
|
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/
|
|
7
6
|
Author: Terry Yin
|
|
8
7
|
Author-email: terry@odd-e.com
|
|
9
8
|
License: MIT
|
|
9
|
+
Download-URL: https://pypi.python.org/lizard/
|
|
10
10
|
Project-URL: Source, https://github.com/terryyin/lizard
|
|
11
11
|
Platform: any
|
|
12
12
|
Classifier: Development Status :: 5 - Production/Stable
|
|
@@ -48,31 +48,32 @@ code analysis.
|
|
|
48
48
|
|
|
49
49
|
A list of supported languages:
|
|
50
50
|
|
|
51
|
+
- C# (C Sharp)
|
|
51
52
|
- C/C++ (works with C++14)
|
|
53
|
+
- Erlang
|
|
54
|
+
- Fortran
|
|
55
|
+
- GDScript
|
|
56
|
+
- Golang
|
|
52
57
|
- Java
|
|
53
|
-
- C# (C Sharp)
|
|
54
58
|
- JavaScript (With ES6 and JSX)
|
|
55
|
-
-
|
|
56
|
-
-
|
|
59
|
+
- Kotlin
|
|
60
|
+
- Lua
|
|
57
61
|
- Objective-C
|
|
58
|
-
-
|
|
62
|
+
- Perl
|
|
63
|
+
- PHP
|
|
64
|
+
- PL/SQL
|
|
59
65
|
- Python
|
|
66
|
+
- R
|
|
60
67
|
- Ruby
|
|
61
|
-
- TTCN-3
|
|
62
|
-
- PHP
|
|
63
|
-
- Scala
|
|
64
|
-
- GDScript
|
|
65
|
-
- Golang
|
|
66
|
-
- Lua
|
|
67
68
|
- Rust
|
|
68
|
-
-
|
|
69
|
-
- Kotlin
|
|
69
|
+
- Scala
|
|
70
70
|
- Solidity
|
|
71
|
-
- Erlang
|
|
72
|
-
- Zig
|
|
73
|
-
- Perl
|
|
74
71
|
- Structured Text (St)
|
|
75
|
-
-
|
|
72
|
+
- Swift
|
|
73
|
+
- TTCN-3
|
|
74
|
+
- TypeScript (With TSX)
|
|
75
|
+
- VueJS
|
|
76
|
+
- Zig
|
|
76
77
|
|
|
77
78
|
By default lizard will search for any source code that it knows and mix
|
|
78
79
|
all the results together. This might not be what you want. You can use
|
|
@@ -160,7 +161,7 @@ Options
|
|
|
160
161
|
search for all languages it knows. `lizard -l cpp -l java`searches for
|
|
161
162
|
C++ and Java code. The available languages are: cpp, java, csharp,
|
|
162
163
|
javascript, python, objectivec, ttcn, ruby, php, swift, scala, GDScript,
|
|
163
|
-
go, lua, rust, typescript
|
|
164
|
+
go, lua, rust, typescript, plsql
|
|
164
165
|
-V, --verbose Output in verbose mode (long function name)
|
|
165
166
|
-C CCN, --CCN CCN Threshold for cyclomatic complexity number warning. The default value is
|
|
166
167
|
15. Functions with CCN bigger than it will generate warning
|
|
@@ -195,7 +196,7 @@ Options
|
|
|
195
196
|
-X, --xml Generate XML in cppncss style instead of the tabular output. Useful to
|
|
196
197
|
generate report in Jenkins server
|
|
197
198
|
--csv Generate CSV output as a transform of the default output
|
|
198
|
-
-H, --html Output HTML report
|
|
199
|
+
-H, --html Output HTML report with interactive DataTables (sortable, searchable, filterable)
|
|
199
200
|
--checkstyle Generate Checkstyle XML output for integration with Jenkins and other tools
|
|
200
201
|
-m, --modified Calculate modified cyclomatic complexity number , which count a
|
|
201
202
|
switch/case with multiple cases as one CCN.
|
|
@@ -413,5 +414,14 @@ Lizard is also used as a plugin for fastlane to help check code complexity and s
|
|
|
413
414
|
- `European research project FASTEN (Fine-grained Analysis of SofTware Ecosystems as Networks, <http://fasten-project.eu/)>`_
|
|
414
415
|
- `for a quality analyzer <https://github.com/fasten-project/quality-analyzer>`_
|
|
415
416
|
|
|
417
|
+
How To Contribute
|
|
418
|
+
-----------------
|
|
419
|
+
|
|
420
|
+
Contributions are welcome. Please refer to the rules and development workflow in:
|
|
421
|
+
|
|
422
|
+
- https://github.com/terryyin/lizard/tree/master/.cursor/rules
|
|
423
|
+
|
|
424
|
+
These guidelines are usable by both AI assistants and human contributors — what works for AI works for "I" as well — to keep changes cohesive, simple, and well-tested.
|
|
425
|
+
|
|
416
426
|
|
|
417
427
|
|
|
@@ -17,31 +17,32 @@ code analysis.
|
|
|
17
17
|
|
|
18
18
|
A list of supported languages:
|
|
19
19
|
|
|
20
|
+
- C# (C Sharp)
|
|
20
21
|
- C/C++ (works with C++14)
|
|
22
|
+
- Erlang
|
|
23
|
+
- Fortran
|
|
24
|
+
- GDScript
|
|
25
|
+
- Golang
|
|
21
26
|
- Java
|
|
22
|
-
- C# (C Sharp)
|
|
23
27
|
- JavaScript (With ES6 and JSX)
|
|
24
|
-
-
|
|
25
|
-
-
|
|
28
|
+
- Kotlin
|
|
29
|
+
- Lua
|
|
26
30
|
- Objective-C
|
|
27
|
-
-
|
|
31
|
+
- Perl
|
|
32
|
+
- PHP
|
|
33
|
+
- PL/SQL
|
|
28
34
|
- Python
|
|
35
|
+
- R
|
|
29
36
|
- Ruby
|
|
30
|
-
- TTCN-3
|
|
31
|
-
- PHP
|
|
32
|
-
- Scala
|
|
33
|
-
- GDScript
|
|
34
|
-
- Golang
|
|
35
|
-
- Lua
|
|
36
37
|
- Rust
|
|
37
|
-
-
|
|
38
|
-
- Kotlin
|
|
38
|
+
- Scala
|
|
39
39
|
- Solidity
|
|
40
|
-
- Erlang
|
|
41
|
-
- Zig
|
|
42
|
-
- Perl
|
|
43
40
|
- Structured Text (St)
|
|
44
|
-
-
|
|
41
|
+
- Swift
|
|
42
|
+
- TTCN-3
|
|
43
|
+
- TypeScript (With TSX)
|
|
44
|
+
- VueJS
|
|
45
|
+
- Zig
|
|
45
46
|
|
|
46
47
|
By default lizard will search for any source code that it knows and mix
|
|
47
48
|
all the results together. This might not be what you want. You can use
|
|
@@ -129,7 +130,7 @@ Options
|
|
|
129
130
|
search for all languages it knows. `lizard -l cpp -l java`searches for
|
|
130
131
|
C++ and Java code. The available languages are: cpp, java, csharp,
|
|
131
132
|
javascript, python, objectivec, ttcn, ruby, php, swift, scala, GDScript,
|
|
132
|
-
go, lua, rust, typescript
|
|
133
|
+
go, lua, rust, typescript, plsql
|
|
133
134
|
-V, --verbose Output in verbose mode (long function name)
|
|
134
135
|
-C CCN, --CCN CCN Threshold for cyclomatic complexity number warning. The default value is
|
|
135
136
|
15. Functions with CCN bigger than it will generate warning
|
|
@@ -164,7 +165,7 @@ Options
|
|
|
164
165
|
-X, --xml Generate XML in cppncss style instead of the tabular output. Useful to
|
|
165
166
|
generate report in Jenkins server
|
|
166
167
|
--csv Generate CSV output as a transform of the default output
|
|
167
|
-
-H, --html Output HTML report
|
|
168
|
+
-H, --html Output HTML report with interactive DataTables (sortable, searchable, filterable)
|
|
168
169
|
--checkstyle Generate Checkstyle XML output for integration with Jenkins and other tools
|
|
169
170
|
-m, --modified Calculate modified cyclomatic complexity number , which count a
|
|
170
171
|
switch/case with multiple cases as one CCN.
|
|
@@ -382,3 +383,12 @@ Lizard is also used as a plugin for fastlane to help check code complexity and s
|
|
|
382
383
|
- `European research project FASTEN (Fine-grained Analysis of SofTware Ecosystems as Networks, <http://fasten-project.eu/)>`_
|
|
383
384
|
- `for a quality analyzer <https://github.com/fasten-project/quality-analyzer>`_
|
|
384
385
|
|
|
386
|
+
How To Contribute
|
|
387
|
+
-----------------
|
|
388
|
+
|
|
389
|
+
Contributions are welcome. Please refer to the rules and development workflow in:
|
|
390
|
+
|
|
391
|
+
- https://github.com/terryyin/lizard/tree/master/.cursor/rules
|
|
392
|
+
|
|
393
|
+
These guidelines are usable by both AI assistants and human contributors — what works for AI works for "I" as well — to keep changes cohesive, simple, and well-tested.
|
|
394
|
+
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: lizard
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.20.0
|
|
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/
|
|
7
6
|
Author: Terry Yin
|
|
8
7
|
Author-email: terry@odd-e.com
|
|
9
8
|
License: MIT
|
|
9
|
+
Download-URL: https://pypi.python.org/lizard/
|
|
10
10
|
Project-URL: Source, https://github.com/terryyin/lizard
|
|
11
11
|
Platform: any
|
|
12
12
|
Classifier: Development Status :: 5 - Production/Stable
|
|
@@ -48,31 +48,32 @@ code analysis.
|
|
|
48
48
|
|
|
49
49
|
A list of supported languages:
|
|
50
50
|
|
|
51
|
+
- C# (C Sharp)
|
|
51
52
|
- C/C++ (works with C++14)
|
|
53
|
+
- Erlang
|
|
54
|
+
- Fortran
|
|
55
|
+
- GDScript
|
|
56
|
+
- Golang
|
|
52
57
|
- Java
|
|
53
|
-
- C# (C Sharp)
|
|
54
58
|
- JavaScript (With ES6 and JSX)
|
|
55
|
-
-
|
|
56
|
-
-
|
|
59
|
+
- Kotlin
|
|
60
|
+
- Lua
|
|
57
61
|
- Objective-C
|
|
58
|
-
-
|
|
62
|
+
- Perl
|
|
63
|
+
- PHP
|
|
64
|
+
- PL/SQL
|
|
59
65
|
- Python
|
|
66
|
+
- R
|
|
60
67
|
- Ruby
|
|
61
|
-
- TTCN-3
|
|
62
|
-
- PHP
|
|
63
|
-
- Scala
|
|
64
|
-
- GDScript
|
|
65
|
-
- Golang
|
|
66
|
-
- Lua
|
|
67
68
|
- Rust
|
|
68
|
-
-
|
|
69
|
-
- Kotlin
|
|
69
|
+
- Scala
|
|
70
70
|
- Solidity
|
|
71
|
-
- Erlang
|
|
72
|
-
- Zig
|
|
73
|
-
- Perl
|
|
74
71
|
- Structured Text (St)
|
|
75
|
-
-
|
|
72
|
+
- Swift
|
|
73
|
+
- TTCN-3
|
|
74
|
+
- TypeScript (With TSX)
|
|
75
|
+
- VueJS
|
|
76
|
+
- Zig
|
|
76
77
|
|
|
77
78
|
By default lizard will search for any source code that it knows and mix
|
|
78
79
|
all the results together. This might not be what you want. You can use
|
|
@@ -160,7 +161,7 @@ Options
|
|
|
160
161
|
search for all languages it knows. `lizard -l cpp -l java`searches for
|
|
161
162
|
C++ and Java code. The available languages are: cpp, java, csharp,
|
|
162
163
|
javascript, python, objectivec, ttcn, ruby, php, swift, scala, GDScript,
|
|
163
|
-
go, lua, rust, typescript
|
|
164
|
+
go, lua, rust, typescript, plsql
|
|
164
165
|
-V, --verbose Output in verbose mode (long function name)
|
|
165
166
|
-C CCN, --CCN CCN Threshold for cyclomatic complexity number warning. The default value is
|
|
166
167
|
15. Functions with CCN bigger than it will generate warning
|
|
@@ -195,7 +196,7 @@ Options
|
|
|
195
196
|
-X, --xml Generate XML in cppncss style instead of the tabular output. Useful to
|
|
196
197
|
generate report in Jenkins server
|
|
197
198
|
--csv Generate CSV output as a transform of the default output
|
|
198
|
-
-H, --html Output HTML report
|
|
199
|
+
-H, --html Output HTML report with interactive DataTables (sortable, searchable, filterable)
|
|
199
200
|
--checkstyle Generate Checkstyle XML output for integration with Jenkins and other tools
|
|
200
201
|
-m, --modified Calculate modified cyclomatic complexity number , which count a
|
|
201
202
|
switch/case with multiple cases as one CCN.
|
|
@@ -413,5 +414,14 @@ Lizard is also used as a plugin for fastlane to help check code complexity and s
|
|
|
413
414
|
- `European research project FASTEN (Fine-grained Analysis of SofTware Ecosystems as Networks, <http://fasten-project.eu/)>`_
|
|
414
415
|
- `for a quality analyzer <https://github.com/fasten-project/quality-analyzer>`_
|
|
415
416
|
|
|
417
|
+
How To Contribute
|
|
418
|
+
-----------------
|
|
419
|
+
|
|
420
|
+
Contributions are welcome. Please refer to the rules and development workflow in:
|
|
421
|
+
|
|
422
|
+
- https://github.com/terryyin/lizard/tree/master/.cursor/rules
|
|
423
|
+
|
|
424
|
+
These guidelines are usable by both AI assistants and human contributors — what works for AI works for "I" as well — to keep changes cohesive, simple, and well-tested.
|
|
425
|
+
|
|
416
426
|
|
|
417
427
|
|
|
@@ -21,7 +21,6 @@ def print_csv(results, options, _, total_factory):
|
|
|
21
21
|
|
|
22
22
|
def print_checkstyle(results, options, _, total_factory, file=None):
|
|
23
23
|
import sys
|
|
24
|
-
print("DEBUG: print_checkstyle called", file=sys.stderr)
|
|
25
24
|
output = checkstyle_output(total_factory(list(results)), options.verbose)
|
|
26
25
|
if file is None:
|
|
27
26
|
file = sys.stdout
|
|
@@ -48,6 +48,12 @@ TEMPLATE = '''<!DOCTYPE HTML PUBLIC
|
|
|
48
48
|
<head>
|
|
49
49
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|
50
50
|
<title>Code complexity report</title>
|
|
51
|
+
<!-- DataTables CSS -->
|
|
52
|
+
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.13.4/css/jquery.dataTables.min.css">
|
|
53
|
+
<!-- jQuery -->
|
|
54
|
+
<script src="https://code.jquery.com/jquery-3.7.0.min.js"></script>
|
|
55
|
+
<!-- DataTables JS -->
|
|
56
|
+
<script src="https://cdn.datatables.net/1.13.4/js/jquery.dataTables.min.js"></script>
|
|
51
57
|
<style>
|
|
52
58
|
h2
|
|
53
59
|
{
|
|
@@ -88,6 +94,42 @@ TEMPLATE = '''<!DOCTYPE HTML PUBLIC
|
|
|
88
94
|
font-family: sans-serif;
|
|
89
95
|
white-space: nowrap;
|
|
90
96
|
}
|
|
97
|
+
td.file-header
|
|
98
|
+
{
|
|
99
|
+
background-color: LightBlue;
|
|
100
|
+
font-weight: bold;
|
|
101
|
+
}
|
|
102
|
+
td.function-name
|
|
103
|
+
{
|
|
104
|
+
background-color: LightSteelBlue;
|
|
105
|
+
}
|
|
106
|
+
/* DataTables wrapper styling */
|
|
107
|
+
.dataTables_wrapper {
|
|
108
|
+
margin: 0 auto;
|
|
109
|
+
width: 95%;
|
|
110
|
+
}
|
|
111
|
+
/* Fallback styling if DataTables CSS doesn't load */
|
|
112
|
+
table#complexityTable {
|
|
113
|
+
border-collapse: collapse;
|
|
114
|
+
width: 95%;
|
|
115
|
+
margin: 0 auto;
|
|
116
|
+
}
|
|
117
|
+
table#complexityTable th {
|
|
118
|
+
background-color: #4CAF50;
|
|
119
|
+
color: white;
|
|
120
|
+
padding: 10px;
|
|
121
|
+
text-align: left;
|
|
122
|
+
border: 1px solid #ddd;
|
|
123
|
+
}
|
|
124
|
+
table#complexityTable td {
|
|
125
|
+
border: 1px solid #ddd;
|
|
126
|
+
}
|
|
127
|
+
table#complexityTable tr:nth-child(even) {
|
|
128
|
+
background-color: #f2f2f2;
|
|
129
|
+
}
|
|
130
|
+
table#complexityTable tr:hover {
|
|
131
|
+
background-color: #ddd;
|
|
132
|
+
}
|
|
91
133
|
</style>
|
|
92
134
|
</head>
|
|
93
135
|
<body>
|
|
@@ -95,26 +137,29 @@ TEMPLATE = '''<!DOCTYPE HTML PUBLIC
|
|
|
95
137
|
|
|
96
138
|
<center>
|
|
97
139
|
|
|
98
|
-
<table>
|
|
140
|
+
<table id="complexityTable" class="display" style="width:100%">
|
|
141
|
+
<thead>
|
|
142
|
+
<tr>
|
|
143
|
+
<th>File</th>
|
|
144
|
+
<th>Function name</th>
|
|
145
|
+
<th>Cyclomatic complexity ({{ thresholds["cyclomatic_complexity"] }})</th>
|
|
146
|
+
<th>LOC ({{ thresholds["nloc"] }})</th>
|
|
147
|
+
<th>
|
|
148
|
+
{% if thresholds["token_count"] %}
|
|
149
|
+
Token count ({{ thresholds["token_count"] }})
|
|
150
|
+
{% else %}
|
|
151
|
+
Token count
|
|
152
|
+
{% endif %}
|
|
153
|
+
</th>
|
|
154
|
+
<th>Parameter count ({{ thresholds["parameter_count"] }})</th>
|
|
155
|
+
</tr>
|
|
156
|
+
</thead>
|
|
157
|
+
<tbody>
|
|
99
158
|
{% for file in files %}
|
|
100
|
-
<tr><td colspan="7" style="background-color:LightBlue;">
|
|
101
|
-
Source file: <b>{{ file.filename }}</b></td></tr>
|
|
102
|
-
{% if file.functions|length > 0 %}
|
|
103
|
-
<tr><th>Function name</th><th></th><th>
|
|
104
|
-
Cyclomatic complexity
|
|
105
|
-
({{ thresholds["cyclomatic_complexity"] }})
|
|
106
|
-
</th><th>LOC ({{ thresholds["nloc"] }})</th><th>
|
|
107
|
-
{% if thresholds["token_count"] %}
|
|
108
|
-
Token count ({{ thresholds["token_count"] }})
|
|
109
|
-
{% else %}
|
|
110
|
-
Token count
|
|
111
|
-
{% endif %}
|
|
112
|
-
</th><th>Parameter count ({{ thresholds["parameter_count"] }})</th></tr>
|
|
113
|
-
{% endif %}
|
|
114
159
|
{% for func in file.functions %}
|
|
115
160
|
<tr>
|
|
116
|
-
<td
|
|
117
|
-
<td
|
|
161
|
+
<td>{{ file.filename }}</td>
|
|
162
|
+
<td class="function-name">{{ func.name }}</td>
|
|
118
163
|
{% if func.cyclomatic_complexity > thresholds["cyclomatic_complexity"] %}
|
|
119
164
|
<td class="greater-value">{{ func.cyclomatic_complexity }}</td>
|
|
120
165
|
{% else %}
|
|
@@ -145,6 +190,7 @@ Cyclomatic complexity
|
|
|
145
190
|
</tr>
|
|
146
191
|
{% endfor %}
|
|
147
192
|
{% endfor %}
|
|
193
|
+
</tbody>
|
|
148
194
|
</table>
|
|
149
195
|
<center>
|
|
150
196
|
|
|
@@ -154,6 +200,29 @@ Cyclomatic complexity
|
|
|
154
200
|
<a href="http://www.lizard.ws/">Lizard</a> on {{ date }}
|
|
155
201
|
</td></tr>
|
|
156
202
|
</table>
|
|
203
|
+
|
|
204
|
+
<script>
|
|
205
|
+
// Gracefully degrade if CDN is unavailable
|
|
206
|
+
if (typeof jQuery !== 'undefined' && typeof jQuery.fn.dataTable !== 'undefined') {
|
|
207
|
+
$(document).ready(function() {
|
|
208
|
+
try {
|
|
209
|
+
$('#complexityTable').DataTable({
|
|
210
|
+
"pageLength": 25,
|
|
211
|
+
"order": [[2, "desc"]], // Sort by cyclomatic complexity descending by default
|
|
212
|
+
"columnDefs": [
|
|
213
|
+
{ "type": "num", "targets": [2, 3, 4, 5] } // Ensure numeric sorting for metric columns
|
|
214
|
+
]
|
|
215
|
+
});
|
|
216
|
+
} catch (e) {
|
|
217
|
+
console.warn('DataTables initialization failed. Displaying static table.', e);
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
} else {
|
|
221
|
+
// Fallback: Table will display as static HTML
|
|
222
|
+
console.info('DataTables not available. Displaying static HTML table.');
|
|
223
|
+
}
|
|
224
|
+
</script>
|
|
225
|
+
|
|
157
226
|
</body>
|
|
158
227
|
</html>
|
|
159
228
|
|
|
@@ -5,10 +5,16 @@ that adding the complexity and the line numbers of the keywords appear.
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class LizardExtension(object): # pylint: disable=R0903
|
|
8
|
+
"""
|
|
9
|
+
Complex tags extension: records all complexity-adding keywords and their line numbers.
|
|
10
|
+
Uses reader.conditions (combined set of all condition types) to track all
|
|
11
|
+
complexity contributors: control flow, logical operators, case labels, and ternary.
|
|
12
|
+
"""
|
|
8
13
|
|
|
9
14
|
# pylint: disable=W0221
|
|
10
15
|
def __call__(self, tokens, reader):
|
|
11
16
|
context = reader.context
|
|
17
|
+
# Use combined conditions set - intentionally includes all types
|
|
12
18
|
conditions = reader.conditions
|
|
13
19
|
for token in tokens:
|
|
14
20
|
yield token
|
|
@@ -14,9 +14,14 @@ from .extension_base import ExtensionBase
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
class LizardExtension(ExtensionBase): # pylint: disable=R0903
|
|
17
|
+
"""
|
|
18
|
+
McCabe extension: only counts the first 'case' in a switch statement.
|
|
19
|
+
Consecutive cases without code between them don't add to complexity.
|
|
20
|
+
Works by detecting case tokens (conceptually from reader.case_keywords).
|
|
21
|
+
"""
|
|
17
22
|
|
|
18
23
|
def _state_global(self, token):
|
|
19
|
-
if token == "case":
|
|
24
|
+
if token == "case": # Detect case keywords
|
|
20
25
|
self._state = self._in_case
|
|
21
26
|
|
|
22
27
|
def _in_case(self, token):
|
|
@@ -6,14 +6,19 @@ where the whole switch/case will be counted as 1.
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class LizardExtension(object): # pylint: disable=R0903
|
|
9
|
+
"""
|
|
10
|
+
Modified CCN extension: counts entire switch/case as 1 complexity.
|
|
11
|
+
Adds +1 for 'switch', subtracts -1 for each 'case'.
|
|
12
|
+
Works with switch/case keywords (conceptually from reader.case_keywords).
|
|
13
|
+
"""
|
|
9
14
|
|
|
10
15
|
def __call__(self, tokens, reader):
|
|
11
16
|
for token in tokens:
|
|
12
|
-
if token == 'switch':
|
|
17
|
+
if token == 'switch': # Add complexity for switch statement
|
|
13
18
|
reader.context.add_condition()
|
|
14
19
|
if hasattr(reader.context, "add_nd_condition"):
|
|
15
20
|
reader.context.add_nd_condition()
|
|
16
|
-
elif token == 'case':
|
|
21
|
+
elif token == 'case': # Subtract complexity for each case
|
|
17
22
|
reader.context.add_condition(-1)
|
|
18
23
|
if hasattr(reader.context, "add_nd_condition"):
|
|
19
24
|
reader.context.add_nd_condition(-1)
|
|
@@ -45,11 +45,43 @@ class LizardExtension(object): # pylint: disable=R0903
|
|
|
45
45
|
else:
|
|
46
46
|
indent_indicator = ';'
|
|
47
47
|
for token in tokens:
|
|
48
|
-
|
|
48
|
+
# Handle opening parenthesis - start of condition
|
|
49
|
+
if token == '(':
|
|
50
|
+
reader.context.set_in_condition(True)
|
|
51
|
+
reader.context.increment_condition_depth()
|
|
52
|
+
reader.context.set_logical_operator_added(False) # Reset for new condition
|
|
53
|
+
# Handle closing parenthesis - end of condition
|
|
54
|
+
elif token == ')':
|
|
55
|
+
reader.context.decrement_condition_depth()
|
|
56
|
+
if reader.context.get_condition_depth() == 0:
|
|
57
|
+
reader.context.set_in_condition(False)
|
|
58
|
+
reader.context.set_logical_operator_added(False)
|
|
59
|
+
|
|
60
|
+
# Handle logical operators && and || within conditions
|
|
61
|
+
elif token in ('&&', '||'):
|
|
62
|
+
if reader.context.get_in_condition():
|
|
63
|
+
# Only add nesting depth for the first logical operator in a condition
|
|
64
|
+
# Subsequent && or || operators in the same condition don't add depth
|
|
65
|
+
if not reader.context.get_logical_operator_added():
|
|
66
|
+
l_depth = reader.context.add_nd_condition()
|
|
67
|
+
if not reader.context.get_loop_status():
|
|
68
|
+
reader.context.add_hidden_bracket_condition()
|
|
69
|
+
reader.context.loop_bracket_status()
|
|
70
|
+
reader.context.set_logical_operator_added(True)
|
|
71
|
+
else:
|
|
72
|
+
# Not in a condition, treat as regular nesting
|
|
73
|
+
l_depth = reader.context.add_nd_condition()
|
|
74
|
+
if not reader.context.get_loop_status():
|
|
75
|
+
reader.context.add_hidden_bracket_condition()
|
|
76
|
+
reader.context.loop_bracket_status()
|
|
77
|
+
|
|
78
|
+
# Handle other loop keywords (if, for, while, etc.)
|
|
79
|
+
elif token in loops and token not in ('&&', '||'):
|
|
49
80
|
l_depth = reader.context.add_nd_condition()
|
|
50
81
|
if not reader.context.get_loop_status():
|
|
51
82
|
reader.context.add_hidden_bracket_condition()
|
|
52
83
|
reader.context.loop_bracket_status()
|
|
84
|
+
|
|
53
85
|
if token == loop_indicator:
|
|
54
86
|
reader.context.loop_bracket_status()
|
|
55
87
|
if token == bracket:
|
|
@@ -82,6 +114,7 @@ class NDFileInfoAddition(FileInfoBuilder):
|
|
|
82
114
|
self.current_function.nesting_depth = 0
|
|
83
115
|
self.current_function.hidden_bracket = 0
|
|
84
116
|
self.current_function.bracket_loop = False
|
|
117
|
+
self.reset_condition_tracking()
|
|
85
118
|
|
|
86
119
|
def add_hidden_bracket_condition(self, inc=1):
|
|
87
120
|
self.current_function.hidden_bracket += inc
|
|
@@ -96,6 +129,33 @@ class NDFileInfoAddition(FileInfoBuilder):
|
|
|
96
129
|
def get_loop_status(self):
|
|
97
130
|
return self.current_function.bracket_loop
|
|
98
131
|
|
|
132
|
+
def set_in_condition(self, in_condition):
|
|
133
|
+
self.current_function.in_condition = in_condition
|
|
134
|
+
|
|
135
|
+
def get_in_condition(self):
|
|
136
|
+
return self.current_function.in_condition
|
|
137
|
+
|
|
138
|
+
def increment_condition_depth(self):
|
|
139
|
+
self.current_function.condition_depth += 1
|
|
140
|
+
|
|
141
|
+
def decrement_condition_depth(self):
|
|
142
|
+
if self.current_function.condition_depth > 0:
|
|
143
|
+
self.current_function.condition_depth -= 1
|
|
144
|
+
|
|
145
|
+
def get_condition_depth(self):
|
|
146
|
+
return self.current_function.condition_depth
|
|
147
|
+
|
|
148
|
+
def reset_condition_tracking(self):
|
|
149
|
+
self.current_function.in_condition = False
|
|
150
|
+
self.current_function.condition_depth = 0
|
|
151
|
+
self.current_function.logical_operator_added = False
|
|
152
|
+
|
|
153
|
+
def set_logical_operator_added(self, added):
|
|
154
|
+
self.current_function.logical_operator_added = added
|
|
155
|
+
|
|
156
|
+
def get_logical_operator_added(self):
|
|
157
|
+
return self.current_function.logical_operator_added
|
|
158
|
+
|
|
99
159
|
|
|
100
160
|
def get_method(cls, name):
|
|
101
161
|
""" python3 doesn't need the __func__ to get the func of the
|
|
@@ -127,6 +187,9 @@ def _init_nesting_depth_data(self, *_):
|
|
|
127
187
|
self.max_nesting_depth = 0
|
|
128
188
|
self.hidden_bracket = 0
|
|
129
189
|
self.bracket_loop = False
|
|
190
|
+
self.in_condition = False # Track if we're inside a condition
|
|
191
|
+
self.condition_depth = 0 # Track nesting depth within conditions
|
|
192
|
+
self.logical_operator_added = False # Track if we've added nesting for logical operators in current condition
|
|
130
193
|
|
|
131
194
|
|
|
132
195
|
patch(NDFileInfoAddition, FileInfoBuilder)
|
|
@@ -9,5 +9,6 @@ class LizardExtension(object): # pylint: disable=R0903
|
|
|
9
9
|
|
|
10
10
|
# pylint: disable=W0221
|
|
11
11
|
def __call__(self, tokens, reader):
|
|
12
|
-
|
|
12
|
+
# Remove logical operators from conditions (non-strict mode)
|
|
13
|
+
reader.conditions -= reader.logical_operators
|
|
13
14
|
return tokens
|
|
@@ -67,10 +67,35 @@ class LizardExtension(ExtensionBase): # pylint: disable=R0903
|
|
|
67
67
|
|
|
68
68
|
def __init__(self):
|
|
69
69
|
super(LizardExtension, self).__init__(None)
|
|
70
|
-
self.structure_piles = [0]
|
|
70
|
+
self.structure_piles = [0] # Invariant: must always have at least one element
|
|
71
71
|
|
|
72
|
-
def
|
|
72
|
+
def _push_scope(self):
|
|
73
|
+
"""Push a new scope level. Safe to call anytime."""
|
|
74
|
+
self.structure_piles.append(0)
|
|
75
|
+
|
|
76
|
+
def _pop_scope(self):
|
|
77
|
+
"""Pop a scope level. Maintains invariant of at least one element."""
|
|
78
|
+
if len(self.structure_piles) > 1:
|
|
79
|
+
self.structure_piles.pop()
|
|
80
|
+
|
|
81
|
+
def _increment_current_scope(self):
|
|
82
|
+
"""Increment structure count in current scope. Safe even if piles corrupted."""
|
|
83
|
+
if not self.structure_piles:
|
|
84
|
+
self.structure_piles = [0] # Restore invariant
|
|
73
85
|
self.structure_piles[-1] += 1
|
|
86
|
+
|
|
87
|
+
def _reset_or_decrement_current_scope(self, decrement=False):
|
|
88
|
+
"""Reset or decrement current scope counter. Safe even if piles corrupted."""
|
|
89
|
+
if not self.structure_piles:
|
|
90
|
+
self.structure_piles = [0] # Restore invariant
|
|
91
|
+
return
|
|
92
|
+
if decrement:
|
|
93
|
+
self.structure_piles[-1] -= 1
|
|
94
|
+
else:
|
|
95
|
+
self.structure_piles[-1] = 0
|
|
96
|
+
|
|
97
|
+
def pile_up_within_block(self):
|
|
98
|
+
self._increment_current_scope()
|
|
74
99
|
cur_level = sum(self.structure_piles)
|
|
75
100
|
# Is there a path around _state_global?
|
|
76
101
|
if not hasattr(self.context.current_function, "max_nested_structures"):
|
|
@@ -83,10 +108,10 @@ class LizardExtension(ExtensionBase): # pylint: disable=R0903
|
|
|
83
108
|
if not hasattr(self.context.current_function, "max_nested_structures"):
|
|
84
109
|
self.context.current_function.max_nested_structures = 0
|
|
85
110
|
if token == '{':
|
|
86
|
-
self.
|
|
111
|
+
self._push_scope()
|
|
87
112
|
elif token in ';}':
|
|
88
113
|
if token == '}':
|
|
89
|
-
self.
|
|
114
|
+
self._pop_scope()
|
|
90
115
|
self._state = self._block_ending
|
|
91
116
|
elif token in self.structures:
|
|
92
117
|
self._state = self._in_structure_head
|
|
@@ -98,10 +123,8 @@ class LizardExtension(ExtensionBase): # pylint: disable=R0903
|
|
|
98
123
|
self._state(token)
|
|
99
124
|
|
|
100
125
|
def _block_ending(self, token):
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
else:
|
|
104
|
-
self.structure_piles[-1] = 0
|
|
126
|
+
decrement = token in self.matching_structures
|
|
127
|
+
self._reset_or_decrement_current_scope(decrement=decrement)
|
|
105
128
|
self._state = self._state_global
|
|
106
129
|
self._state(token)
|
|
107
130
|
|
|
@@ -26,6 +26,7 @@ from .vue import VueReader
|
|
|
26
26
|
from .perl import PerlReader
|
|
27
27
|
from .st import StReader
|
|
28
28
|
from .r import RReader
|
|
29
|
+
from .plsql import PLSQLReader
|
|
29
30
|
|
|
30
31
|
|
|
31
32
|
def languages():
|
|
@@ -56,6 +57,7 @@ def languages():
|
|
|
56
57
|
PerlReader,
|
|
57
58
|
StReader,
|
|
58
59
|
RReader,
|
|
60
|
+
PLSQLReader,
|
|
59
61
|
]
|
|
60
62
|
|
|
61
63
|
|