lizard 1.17.27__tar.gz → 1.17.29__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.
Files changed (100) hide show
  1. {lizard-1.17.27 → lizard-1.17.29}/PKG-INFO +1 -1
  2. {lizard-1.17.27 → lizard-1.17.29}/lizard.egg-info/PKG-INFO +1 -1
  3. {lizard-1.17.27 → lizard-1.17.29}/lizard_ext/version.py +1 -1
  4. {lizard-1.17.27 → lizard-1.17.29}/lizard_languages/java.py +9 -0
  5. lizard-1.17.29/lizard_languages/php.py +257 -0
  6. lizard-1.17.27/lizard_languages/php.py +0 -39
  7. {lizard-1.17.27 → lizard-1.17.29}/LICENSE.txt +0 -0
  8. {lizard-1.17.27 → lizard-1.17.29}/README.rst +0 -0
  9. {lizard-1.17.27 → lizard-1.17.29}/lizard.egg-info/SOURCES.txt +0 -0
  10. {lizard-1.17.27 → lizard-1.17.29}/lizard.egg-info/dependency_links.txt +0 -0
  11. {lizard-1.17.27 → lizard-1.17.29}/lizard.egg-info/entry_points.txt +0 -0
  12. {lizard-1.17.27 → lizard-1.17.29}/lizard.egg-info/requires.txt +0 -0
  13. {lizard-1.17.27 → lizard-1.17.29}/lizard.egg-info/top_level.txt +0 -0
  14. {lizard-1.17.27 → lizard-1.17.29}/lizard.py +0 -0
  15. {lizard-1.17.27 → lizard-1.17.29}/lizard_ext/__init__.py +0 -0
  16. {lizard-1.17.27 → lizard-1.17.29}/lizard_ext/auto_open.py +0 -0
  17. {lizard-1.17.27 → lizard-1.17.29}/lizard_ext/csvoutput.py +0 -0
  18. {lizard-1.17.27 → lizard-1.17.29}/lizard_ext/default_ordered_dict.py +0 -0
  19. {lizard-1.17.27 → lizard-1.17.29}/lizard_ext/extension_base.py +0 -0
  20. {lizard-1.17.27 → lizard-1.17.29}/lizard_ext/htmloutput.py +0 -0
  21. {lizard-1.17.27 → lizard-1.17.29}/lizard_ext/keywords.py +0 -0
  22. {lizard-1.17.27 → lizard-1.17.29}/lizard_ext/lizardboolcount.py +0 -0
  23. {lizard-1.17.27 → lizard-1.17.29}/lizard_ext/lizardcomplextags.py +0 -0
  24. {lizard-1.17.27 → lizard-1.17.29}/lizard_ext/lizardcpre.py +0 -0
  25. {lizard-1.17.27 → lizard-1.17.29}/lizard_ext/lizarddependencycount.py +0 -0
  26. {lizard-1.17.27 → lizard-1.17.29}/lizard_ext/lizarddumpcomments.py +0 -0
  27. {lizard-1.17.27 → lizard-1.17.29}/lizard_ext/lizardduplicate.py +0 -0
  28. {lizard-1.17.27 → lizard-1.17.29}/lizard_ext/lizardduplicated_param_list.py +0 -0
  29. {lizard-1.17.27 → lizard-1.17.29}/lizard_ext/lizardexitcount.py +0 -0
  30. {lizard-1.17.27 → lizard-1.17.29}/lizard_ext/lizardgotocount.py +0 -0
  31. {lizard-1.17.27 → lizard-1.17.29}/lizard_ext/lizardignoreassert.py +0 -0
  32. {lizard-1.17.27 → lizard-1.17.29}/lizard_ext/lizardio.py +0 -0
  33. {lizard-1.17.27 → lizard-1.17.29}/lizard_ext/lizardmccabe.py +0 -0
  34. {lizard-1.17.27 → lizard-1.17.29}/lizard_ext/lizardmodified.py +0 -0
  35. {lizard-1.17.27 → lizard-1.17.29}/lizard_ext/lizardnd.py +0 -0
  36. {lizard-1.17.27 → lizard-1.17.29}/lizard_ext/lizardnonstrict.py +0 -0
  37. {lizard-1.17.27 → lizard-1.17.29}/lizard_ext/lizardns.py +0 -0
  38. {lizard-1.17.27 → lizard-1.17.29}/lizard_ext/lizardoutside.py +0 -0
  39. {lizard-1.17.27 → lizard-1.17.29}/lizard_ext/lizardstatementcount.py +0 -0
  40. {lizard-1.17.27 → lizard-1.17.29}/lizard_ext/lizardwordcount.py +0 -0
  41. {lizard-1.17.27 → lizard-1.17.29}/lizard_ext/xmloutput.py +0 -0
  42. {lizard-1.17.27 → lizard-1.17.29}/lizard_languages/__init__.py +0 -0
  43. {lizard-1.17.27 → lizard-1.17.29}/lizard_languages/clike.py +0 -0
  44. {lizard-1.17.27 → lizard-1.17.29}/lizard_languages/code_reader.py +0 -0
  45. {lizard-1.17.27 → lizard-1.17.29}/lizard_languages/csharp.py +0 -0
  46. {lizard-1.17.27 → lizard-1.17.29}/lizard_languages/erlang.py +0 -0
  47. {lizard-1.17.27 → lizard-1.17.29}/lizard_languages/fortran.py +0 -0
  48. {lizard-1.17.27 → lizard-1.17.29}/lizard_languages/gdscript.py +0 -0
  49. {lizard-1.17.27 → lizard-1.17.29}/lizard_languages/go.py +0 -0
  50. {lizard-1.17.27 → lizard-1.17.29}/lizard_languages/golike.py +0 -0
  51. {lizard-1.17.27 → lizard-1.17.29}/lizard_languages/javascript.py +0 -0
  52. {lizard-1.17.27 → lizard-1.17.29}/lizard_languages/js_style_language_states.py +0 -0
  53. {lizard-1.17.27 → lizard-1.17.29}/lizard_languages/js_style_regex_expression.py +0 -0
  54. {lizard-1.17.27 → lizard-1.17.29}/lizard_languages/jsx.py +0 -0
  55. {lizard-1.17.27 → lizard-1.17.29}/lizard_languages/kotlin.py +0 -0
  56. {lizard-1.17.27 → lizard-1.17.29}/lizard_languages/lua.py +0 -0
  57. {lizard-1.17.27 → lizard-1.17.29}/lizard_languages/objc.py +0 -0
  58. {lizard-1.17.27 → lizard-1.17.29}/lizard_languages/perl.py +0 -0
  59. {lizard-1.17.27 → lizard-1.17.29}/lizard_languages/python.py +0 -0
  60. {lizard-1.17.27 → lizard-1.17.29}/lizard_languages/ruby.py +0 -0
  61. {lizard-1.17.27 → lizard-1.17.29}/lizard_languages/rubylike.py +0 -0
  62. {lizard-1.17.27 → lizard-1.17.29}/lizard_languages/rust.py +0 -0
  63. {lizard-1.17.27 → lizard-1.17.29}/lizard_languages/scala.py +0 -0
  64. {lizard-1.17.27 → lizard-1.17.29}/lizard_languages/script_language.py +0 -0
  65. {lizard-1.17.27 → lizard-1.17.29}/lizard_languages/solidity.py +0 -0
  66. {lizard-1.17.27 → lizard-1.17.29}/lizard_languages/swift.py +0 -0
  67. {lizard-1.17.27 → lizard-1.17.29}/lizard_languages/tnsdl.py +0 -0
  68. {lizard-1.17.27 → lizard-1.17.29}/lizard_languages/tsx.py +0 -0
  69. {lizard-1.17.27 → lizard-1.17.29}/lizard_languages/ttcn.py +0 -0
  70. {lizard-1.17.27 → lizard-1.17.29}/lizard_languages/typescript.py +0 -0
  71. {lizard-1.17.27 → lizard-1.17.29}/lizard_languages/vue.py +0 -0
  72. {lizard-1.17.27 → lizard-1.17.29}/lizard_languages/zig.py +0 -0
  73. {lizard-1.17.27 → lizard-1.17.29}/setup.cfg +0 -0
  74. {lizard-1.17.27 → lizard-1.17.29}/setup.py +0 -0
  75. {lizard-1.17.27 → lizard-1.17.29}/test/testApplication.py +0 -0
  76. {lizard-1.17.27 → lizard-1.17.29}/test/testAssertionExtension.py +0 -0
  77. {lizard-1.17.27 → lizard-1.17.29}/test/testBasicFunctionInfo.py +0 -0
  78. {lizard-1.17.27 → lizard-1.17.29}/test/testCOutsideComplexity.py +0 -0
  79. {lizard-1.17.27 → lizard-1.17.29}/test/testCPreprocessorExtension.py +0 -0
  80. {lizard-1.17.27 → lizard-1.17.29}/test/testCommentOptions.py +0 -0
  81. {lizard-1.17.27 → lizard-1.17.29}/test/testCyclomaticComplexity.py +0 -0
  82. {lizard-1.17.27 → lizard-1.17.29}/test/testExtension.py +0 -0
  83. {lizard-1.17.27 → lizard-1.17.29}/test/testFilesFilter.py +0 -0
  84. {lizard-1.17.27 → lizard-1.17.29}/test/testFunctionDependencyCount.py +0 -0
  85. {lizard-1.17.27 → lizard-1.17.29}/test/testFunctionExitCount.py +0 -0
  86. {lizard-1.17.27 → lizard-1.17.29}/test/testFunctionGotoCount.py +0 -0
  87. {lizard-1.17.27 → lizard-1.17.29}/test/testFunctionStatementCount.py +0 -0
  88. {lizard-1.17.27 → lizard-1.17.29}/test/testHelpers.py +0 -0
  89. {lizard-1.17.27 → lizard-1.17.29}/test/testLanguages.py +0 -0
  90. {lizard-1.17.27 → lizard-1.17.29}/test/testMcCabe.py +0 -0
  91. {lizard-1.17.27 → lizard-1.17.29}/test/testNestedStructures.py +0 -0
  92. {lizard-1.17.27 → lizard-1.17.29}/test/testNestingDepth.py +0 -0
  93. {lizard-1.17.27 → lizard-1.17.29}/test/testOutput.py +0 -0
  94. {lizard-1.17.27 → lizard-1.17.29}/test/testOutputCSV.py +0 -0
  95. {lizard-1.17.27 → lizard-1.17.29}/test/testOutputFile.py +0 -0
  96. {lizard-1.17.27 → lizard-1.17.29}/test/testOutputHTML.py +0 -0
  97. {lizard-1.17.27 → lizard-1.17.29}/test/testTokenizer.py +0 -0
  98. {lizard-1.17.27 → lizard-1.17.29}/test/test_analyzer.py +0 -0
  99. {lizard-1.17.27 → lizard-1.17.29}/test/test_auto_open.py +0 -0
  100. {lizard-1.17.27 → lizard-1.17.29}/test/test_options.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lizard
3
- Version: 1.17.27
3
+ Version: 1.17.29
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/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lizard
3
- Version: 1.17.27
3
+ Version: 1.17.29
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/
@@ -3,4 +3,4 @@
3
3
  #
4
4
  # pylint: disable=missing-docstring,invalid-name
5
5
 
6
- version = "1.17.27"
6
+ version = "1.17.29"
@@ -111,10 +111,19 @@ class JavaFunctionBodyStates(JavaStates):
111
111
  self.in_method_body = True
112
112
  self.ignore_tokens = False # Additional flag to ignore tokens that could confuse the parser
113
113
  self.handling_dot_class = False # Flag to handle .class token specifically
114
+ self.handling_method_ref = False # Flag to handle method references
114
115
 
115
116
  @CodeStateMachine.read_inside_brackets_then("{}", "_state_dummy")
116
117
  @CodeStateMachine.read_inside_brackets_then("()", "_state_dummy")
117
118
  def _state_global(self, token):
119
+ # Handle method references (::new, ::methodName)
120
+ if token == "::":
121
+ self.handling_method_ref = True
122
+ return
123
+ if self.handling_method_ref:
124
+ self.handling_method_ref = False
125
+ return
126
+
118
127
  # Special handling for .class token
119
128
  if token == "." and not self.handling_dot_class:
120
129
  self.handling_dot_class = True
@@ -0,0 +1,257 @@
1
+ '''
2
+ Language parser for PHP
3
+ '''
4
+
5
+ import re
6
+ from .code_reader import CodeReader, CodeStateMachine
7
+ from .clike import CCppCommentsMixin
8
+
9
+
10
+ class PHPLanguageStates(CodeStateMachine):
11
+ """
12
+ PHP-specific state machine that properly handles modern PHP syntax
13
+ including classes, visibility modifiers and return types.
14
+ """
15
+
16
+ def __init__(self, context):
17
+ super(PHPLanguageStates, self).__init__(context)
18
+ self.function_name = ''
19
+ self.class_name = None
20
+ self.trait_name = None
21
+ self.in_class = False
22
+ self.in_trait = False
23
+ self.bracket_level = 0
24
+ self.brace_level = 0
25
+ self.started_function = False
26
+ self.last_token = ''
27
+ self.last_tokens = ''
28
+ self.is_function_declaration = False
29
+ self.assignments = []
30
+ self.in_match = False
31
+ self.match_case_count = 0
32
+
33
+ def _state_global(self, token):
34
+ if token == 'class':
35
+ self._state = self._class_declaration
36
+ elif token == 'trait':
37
+ self._state = self._trait_declaration
38
+ elif token == 'function':
39
+ self.is_function_declaration = True
40
+ self._state = self._function_name
41
+ elif token == 'fn':
42
+ # Skip arrow functions (PHP 7.4+), don't treat them as full functions
43
+ pass
44
+ elif token == 'match':
45
+ self.in_match = True
46
+ self.match_case_count = 0
47
+ self.next(self._match_expression)
48
+ elif token in ('if', 'switch', 'for', 'foreach', 'while', 'catch'):
49
+ self.next(self._condition_expected)
50
+ elif token in ('public', 'private', 'protected', 'static'):
51
+ # Skip visibility modifiers
52
+ pass
53
+ elif token == '=>' and self.in_match:
54
+ # Count each case in a match expression
55
+ self.match_case_count += 1
56
+ elif token == '}' and self.in_match:
57
+ # End of match expression
58
+ self.in_match = False
59
+ # Add the match cases to complexity (subtract 1 because the 'match' keyword is already counted)
60
+ if self.match_case_count > 0:
61
+ for _ in range(self.match_case_count - 1):
62
+ self.context.add_condition()
63
+ self.match_case_count = 0
64
+ elif token == '=':
65
+ # Handle function assignment
66
+ self.function_name = self.last_tokens.strip()
67
+ self.assignments.append(self.function_name)
68
+ elif token == '{':
69
+ self.brace_level += 1
70
+ elif token == '}':
71
+ self.brace_level -= 1
72
+ if self.brace_level == 0:
73
+ if self.in_class:
74
+ self.in_class = False
75
+ self.class_name = None
76
+ if self.in_trait:
77
+ self.in_trait = False
78
+ self.trait_name = None
79
+
80
+ # Update tokens
81
+ self.last_token = token
82
+ if token not in [' ', '\t', '\n']:
83
+ if token not in ['=', ';', '{', '}', '(', ')', ',']:
84
+ self.last_tokens = token
85
+ elif token == '=' and self.last_tokens:
86
+ # Keep the last tokens for assignment
87
+ pass
88
+ else:
89
+ self.last_tokens = ''
90
+
91
+ def _trait_declaration(self, token):
92
+ if token and not token.isspace() and token not in ['{', '(']:
93
+ self.trait_name = token
94
+ self.in_trait = True
95
+ self._state = self._state_global
96
+ elif token == '{':
97
+ self.brace_level += 1
98
+ self._state = self._state_global
99
+
100
+ def _class_declaration(self, token):
101
+ if token and not token.isspace() and token not in ['{', '(', 'extends', 'implements']:
102
+ self.class_name = token
103
+ self.in_class = True
104
+ self._state = self._state_global
105
+ elif token == '{':
106
+ self.brace_level += 1
107
+ self._state = self._state_global
108
+
109
+ def _function_name(self, token):
110
+ if token and not token.isspace() and token != '(':
111
+ method_name = token
112
+ if self.in_class and self.class_name:
113
+ # In class, use ClassName::methodName format
114
+ long_name = f"{self.class_name}::{method_name}"
115
+ short_name = method_name # Store original name for compatibility with old tests
116
+ elif self.in_trait and self.trait_name:
117
+ # In trait, use TraitName::methodName format
118
+ long_name = f"{self.trait_name}::{method_name}"
119
+ short_name = method_name
120
+ else:
121
+ long_name = method_name
122
+ short_name = method_name
123
+ self.function_name = long_name
124
+ self._state = self._function_args
125
+ # Store original name for backward compatibility
126
+ self.short_function_name = short_name
127
+ elif token == '(':
128
+ # Anonymous function
129
+ if self.in_class:
130
+ self.function_name = f"{self.class_name}::(anonymous)"
131
+ elif self.in_trait:
132
+ self.function_name = f"{self.trait_name}::(anonymous)"
133
+ else:
134
+ if self.assignments and self.assignments[-1]:
135
+ self.function_name = self.assignments[-1]
136
+ self.assignments.pop()
137
+ else:
138
+ self.function_name = "(anonymous)"
139
+ self.bracket_level = 1
140
+ self._state = self._function_args_continue
141
+ self.context.push_new_function(self.function_name)
142
+ self.started_function = True
143
+
144
+ def _function_args(self, token):
145
+ if token == '(':
146
+ self.bracket_level = 1
147
+ # Compatibility handling for old tests
148
+ if self.in_class and self.class_name and not self.is_function_declaration:
149
+ self.context.push_new_function(self.short_function_name)
150
+ else:
151
+ self.context.push_new_function(self.function_name)
152
+ self.started_function = True
153
+ self._state = self._function_args_continue
154
+
155
+ def _function_args_continue(self, token):
156
+ if token == '(':
157
+ self.bracket_level += 1
158
+ elif token == ')':
159
+ self.bracket_level -= 1
160
+ if self.bracket_level == 0:
161
+ self._state = self._function_return_type_or_body
162
+ elif token.startswith('$'):
163
+ # Found a parameter (PHP parameters start with $)
164
+ if self.started_function:
165
+ # Make sure we count each parameter uniquely
166
+ self.context.add_to_long_function_name(" " + token)
167
+ self.context.parameter(token)
168
+
169
+ def _function_return_type_or_body(self, token):
170
+ if token == ':':
171
+ # Skip return type declaration
172
+ self._state = self._function_body_or_return_type
173
+ elif token == '{':
174
+ # Function body starts
175
+ self.brace_level += 1
176
+ self._state = self._function_body
177
+ elif token == ';':
178
+ # Handle forward declarations in interface
179
+ if self.started_function:
180
+ self.context.end_of_function()
181
+ self.started_function = False
182
+ self._state = self._state_global
183
+
184
+ def _function_body_or_return_type(self, token):
185
+ if token == '{':
186
+ # Found the function body opening after return type
187
+ self.brace_level += 1
188
+ self._state = self._function_body
189
+
190
+ def _function_body(self, token):
191
+ if token == '{':
192
+ self.brace_level += 1
193
+ elif token == '}':
194
+ self.brace_level -= 1
195
+ if self.brace_level == self.in_class: # Using in_class as boolean (0/1)
196
+ # End of function
197
+ if self.started_function:
198
+ self.context.end_of_function()
199
+ self.started_function = False
200
+ self._state = self._state_global
201
+
202
+ def _condition_expected(self, token):
203
+ if token == '(':
204
+ self.bracket_level = 1
205
+ self._state = self._condition_continue
206
+
207
+ def _condition_continue(self, token):
208
+ if token == '(':
209
+ self.bracket_level += 1
210
+ elif token == ')':
211
+ self.bracket_level -= 1
212
+ if self.bracket_level == 0:
213
+ self._state = self._state_global
214
+
215
+ def _match_expression(self, token):
216
+ if token == '(':
217
+ self.bracket_level = 1
218
+ self._state = self._match_expression_continue
219
+
220
+ def _match_expression_continue(self, token):
221
+ if token == '(':
222
+ self.bracket_level += 1
223
+ elif token == ')':
224
+ self.bracket_level -= 1
225
+ if self.bracket_level == 0:
226
+ self._state = self._state_global
227
+
228
+
229
+ class PHPReader(CodeReader, CCppCommentsMixin):
230
+ # pylint: disable=R0903
231
+
232
+ ext = ['php']
233
+ language_names = ['php']
234
+ _conditions = set(['if', 'elseif', 'for', 'foreach', 'while', '&&', '||', '?',
235
+ 'catch', 'case', 'match'])
236
+
237
+ @staticmethod
238
+ def generate_tokens(source_code, addition='', token_class=None):
239
+ addition += r"|(?:\$\w+)"
240
+ addition += r"|(?:\<{3}(?P<quote>\w+).*?(?P=quote))"
241
+ current_pos = 0
242
+ code_block_pattern = re.compile(
243
+ r"\<\?(?:php)?(.*?)(?:(\?\>)|\Z)",
244
+ re.M | re.S)
245
+ for match in code_block_pattern.finditer(source_code):
246
+ if source_code[current_pos:match.start()]:
247
+ yield '"' + source_code[current_pos:match.start()] + '"'
248
+ for token in CodeReader.generate_tokens(
249
+ match.group(1), addition, token_class):
250
+ yield token
251
+ current_pos = match.end()
252
+ if source_code[current_pos:]:
253
+ yield '"' + source_code[current_pos:] + '"'
254
+
255
+ def __init__(self, context):
256
+ super(PHPReader, self).__init__(context)
257
+ self.parallel_states = [PHPLanguageStates(context)]
@@ -1,39 +0,0 @@
1
- '''
2
- Language parser for JavaScript
3
- '''
4
-
5
- import re
6
- from .code_reader import CodeReader
7
- from .clike import CCppCommentsMixin
8
- from .js_style_language_states import JavaScriptStyleLanguageStates
9
-
10
-
11
- class PHPReader(CodeReader, CCppCommentsMixin):
12
- # pylint: disable=R0903
13
-
14
- ext = ['php']
15
- language_names = ['php']
16
- _conditions = set(['if', 'elseif', 'for', 'while', '&&', '||', '?',
17
- 'catch', 'case'])
18
-
19
- @staticmethod
20
- def generate_tokens(source_code, addition='', token_class=None):
21
- addition += r"|(?:\$\w+)"
22
- addition += r"|(?:\<{3}(?P<quote>\w+).*?(?P=quote))"
23
- current_pos = 0
24
- code_block_pattern = re.compile(
25
- r"\<\?(?:php)?(.*?)(?:(\?\>)|\Z)",
26
- re.M | re.S)
27
- for match in code_block_pattern.finditer(source_code):
28
- if source_code[current_pos:match.start()]:
29
- yield '"' + source_code[current_pos:match.start()] + '"'
30
- for token in CodeReader.generate_tokens(
31
- match.group(1), addition, token_class):
32
- yield token
33
- current_pos = match.end()
34
- if source_code[current_pos:]:
35
- yield '"' + source_code[current_pos:] + '"'
36
-
37
- def __init__(self, context):
38
- super(PHPReader, self).__init__(context)
39
- self.parallel_states = [JavaScriptStyleLanguageStates(context)]
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