lizard 1.19.0__py2.py3-none-any.whl → 1.21.0__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lizard
3
- Version: 1.19.0
3
+ Version: 1.21.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
6
  Download-URL: https://pypi.python.org/lizard/
@@ -351,6 +351,15 @@ behavior of lizard. There are two types of forgiveness comments:
351
351
  ...
352
352
  }
353
353
 
354
+ Selective forgiveness: Use "#lizard forgives(metric1, metric2)" to forgive only specific metrics (e.g. length, cyclomatic_complexity, parameter_count, nloc, token_count).
355
+
356
+ ::
357
+
358
+ int foo() {
359
+ // #lizard forgives(length) // Forgive only length violations
360
+ ...
361
+ }
362
+
354
363
  2. Global code forgiveness: Put "#lizard forgive global" before global code to suppress warnings for all code outside of functions.
355
364
 
356
365
  ::
@@ -0,0 +1,70 @@
1
+ lizard.py,sha256=L5CBQ47VYvqzUwqrQD5LfzfcwCB5qBuUx4J59-zKOUU,42076
2
+ lizard_ext/__init__.py,sha256=UQ2oZ4ej1CCekgiY2Qj8sGx8HheoYyxjcOxvrwF70kc,871
3
+ lizard_ext/auto_open.py,sha256=byD_RbeVhvSUhR2bJMRitvA3zcKEapFwv0-XaDJ6GFo,1096
4
+ lizard_ext/checkstyleoutput.py,sha256=UzDHg837ErEZepXkR8I8YCoz2r1lkmzGctMA7dpyB-M,1245
5
+ lizard_ext/csvoutput.py,sha256=43fhmo8kB85qcdujCwySGNuTC4FkKUPLqIApPeljPnA,2663
6
+ lizard_ext/default_ordered_dict.py,sha256=YbVz6nPlQ6DjWc_EOFBz6AJN2XLo9dpnUdeyejQvUDE,831
7
+ lizard_ext/extension_base.py,sha256=rnjUL2mqSGToUVYydju7fa8ZwynLPY8S1F17gIJP55I,346
8
+ lizard_ext/htmloutput.py,sha256=G7MdLD7AwuR0LLCAkEpyHx4N_ssCcFQdXd7Xg5jZWX0,6537
9
+ lizard_ext/keywords.py,sha256=VxsxoATtKV-8egMKd7I8sd2qbZMtEFEpsszk__6rmjQ,893
10
+ lizard_ext/lizardboolcount.py,sha256=abmMA9X3VFRO5mziicUxWKmHldHNC0jBEe7NKAKA5fs,1062
11
+ lizard_ext/lizardcomplextags.py,sha256=z4Jsz8HNxbZXhDRuUeVnNfgt5Zv4FYEW2kRPO4G3F3E,1027
12
+ lizard_ext/lizardcpre.py,sha256=bVrMXffGUZlydv_zwIVtp-Ij9XyXMFEcap2R4DmLXPU,1277
13
+ lizard_ext/lizarddependencycount.py,sha256=6Nt2z69cyG8P3pceTUCTU6yh4h73lezL2awRFh7K77Y,2423
14
+ lizard_ext/lizarddumpcomments.py,sha256=-c46U3CP_beDfBuB9QhObpiB6wK7xq1u9jeRjgAyU90,683
15
+ lizard_ext/lizardduplicate.py,sha256=tlU-UTB_d_qjekiO4MSaXPBT1FSX8uTaOcfeXnjBzU8,9762
16
+ lizard_ext/lizardduplicated_param_list.py,sha256=_ApeSbjA-NU_rmICsivyfGEEg0-O94wWgWpeeE8F3Zc,1811
17
+ lizard_ext/lizardexitcount.py,sha256=ziAVFi5RgjxJOwAQy6LzdZZflkvvxTiXOIp0FAL0wKQ,692
18
+ lizard_ext/lizardgotocount.py,sha256=w2GWWwqVh4j7Fum41Wvg172b70JvtCm5BCzZUmmTlcM,514
19
+ lizard_ext/lizardignoreassert.py,sha256=sqLwcnJQ06SYqIk901ib4NQ8ECwjIe_qL4T6z1wLXAk,644
20
+ lizard_ext/lizardio.py,sha256=xQN-AgLGLKJarJkgfaqX_TKyupbb7GTcwPxrL2B1J1w,3357
21
+ lizard_ext/lizardmccabe.py,sha256=nLwfYjnAWn1DSoDc-k3iPvltiSX_YmAEdAfM3rOdLSQ,1538
22
+ lizard_ext/lizardmodified.py,sha256=51EY-HM840k_-jFiJugp_fOPBKvovX2Wu0s4ghLM3us,1002
23
+ lizard_ext/lizardnd.py,sha256=h4MaSsFAY5rK8kOSr61LkWntwJWV1KnhaEOWZgp3-c0,7496
24
+ lizard_ext/lizardnonstrict.py,sha256=DWdE2kTn39Gf8UkaRwIO9ogWTDuqA4lXNlQIBT3uLRM,457
25
+ lizard_ext/lizardns.py,sha256=3PYJrXZeFjzFnbotINZBm-MHeS8MQxVNtkQJd_S5fYA,5161
26
+ lizard_ext/lizardoutside.py,sha256=FGm2tbBZ17-2OCgmQlD-vobUCfQKb0FAygf86eM3xuM,336
27
+ lizard_ext/lizardstatementcount.py,sha256=xYk6ixSIItSE1BWQXzrWmduFgGhA3VR817SNKLffyVQ,1182
28
+ lizard_ext/lizardwordcount.py,sha256=2QYXD7-AtkkgAbi9VSidunMbSsGQ7MKYb6IT-bS-cok,7575
29
+ lizard_ext/version.py,sha256=sIUtJyuNVeq7CiJtEKzI_OdOiYNcDqIVBKdYY_OOYRg,181
30
+ lizard_ext/xmloutput.py,sha256=-cbh0he4O_X-wX56gkv9AnSPNN0qvR7FACqlBeezUS4,5609
31
+ lizard_languages/__init__.py,sha256=DniggHM3SOFlwkP8Tm4csEcisbf7_i1EvfoAkG9Atg0,1611
32
+ lizard_languages/clike.py,sha256=BMtIrqPuxmRur-KB7LG6imJtUvnOH2-7p4XFeIFLjME,14892
33
+ lizard_languages/code_reader.py,sha256=I2Kc9F0o4RNX4UUsasUMUieX34u4eOaS73ePhQLC9jg,7844
34
+ lizard_languages/csharp.py,sha256=UDuiG20Ydbb4KMD_mgb82shD37URq3ZvqNLpI77VBPE,3015
35
+ lizard_languages/erlang.py,sha256=tbVPDqi90jV2X1-luDYS32H1zK_2KHwssbJ-tCCOvzg,4249
36
+ lizard_languages/fortran.py,sha256=vwKz1VdwyUtWoECURXuR6e8E2kTR71HtpdbOsmDoyDw,8993
37
+ lizard_languages/gdscript.py,sha256=3mHeCarDq_ilDK_OZ2LOvwfWJqLTzK2lquprLDUnX08,737
38
+ lizard_languages/go.py,sha256=sntz0jOEuj4klPipoTFd16UDK1fAUQfwK7YX_cLMZAc,1346
39
+ lizard_languages/golike.py,sha256=vRIfjTVvc0VmJf27lTOLht55ZF1AQ9wn0Fvu-9WabWk,2858
40
+ lizard_languages/java.py,sha256=8t8G6TR-1qxLHGu3m_T5Kuny49WvMfwCQe1eYnvwZmk,6610
41
+ lizard_languages/javascript.py,sha256=vniCNMW-ea9Jpv6c8qCcjLVDYjT8VztjXigp5XRWt0E,317
42
+ lizard_languages/js_style_regex_expression.py,sha256=Xgyogch4xElYtCG4EnBKvalHTl3tjRPcIIcIQRRd61I,1970
43
+ lizard_languages/kotlin.py,sha256=1ao-VOHUrrSluxgGjMcMPIDt_-dqVfT1JOz15PJLJH8,3024
44
+ lizard_languages/lua.py,sha256=3nqBcunBzJrhv4Iqaf8xvbyqxZy3aSxJ-IiHimHFlac,1573
45
+ lizard_languages/objc.py,sha256=2a1teLdaXZBtCeFiIZer1j_sVx9LZ1CbF2XfnqlvLmk,2319
46
+ lizard_languages/perl.py,sha256=lxxdC0KJsr3tmNLMATO7vx3O7yWGgICxHxVTfmu7db8,12111
47
+ lizard_languages/php.py,sha256=ebHkNyKDOPLyzey5eDhKuu1AMsmGflxqGGmx1ZrlrGA,10542
48
+ lizard_languages/plsql.py,sha256=Wtny6-YW4Jc6G4EhCgoSuw8D86x6JVREprzaUEyKffw,17261
49
+ lizard_languages/python.py,sha256=-sI7ZzJ1erdmqo1MnCcg5cqn1krUhCHlR_phlhnmd_M,5978
50
+ lizard_languages/r.py,sha256=NHNPDGnWXcl8hMi1VL8OM6nw8F9pP6xZX7EgUIocOec,12930
51
+ lizard_languages/ruby.py,sha256=HL1ZckeuUUJU3QSVAOPsG_Zsl0C6X2PX5_VaWqclzkM,2277
52
+ lizard_languages/rubylike.py,sha256=vnfY2lSeIYEgfjJWrfNL6fg1ISHGiwo32H7bf7Stwos,3604
53
+ lizard_languages/rust.py,sha256=7ioyo-kpy5zSQ6Fwua6GcYopkLUdfyExg6kLP0Br3p0,1027
54
+ lizard_languages/scala.py,sha256=onEuS8IsT7aCB-HV0arVDjmgpezXWndk1RCOgoySUes,1436
55
+ lizard_languages/script_language.py,sha256=SKe45AbO6Z-axbN8KW_g7jf9g7YTXZ6dWzJj4ubDsM8,1172
56
+ lizard_languages/solidity.py,sha256=eg7HQ7cuV1d0Awwj4lTySu9f63F1vrK8czsPt_W5Kqw,680
57
+ lizard_languages/st.py,sha256=QiiGNYE8CzmfmZAF_wLQKovXk1Fyqa8QFGTXM1meNNk,4385
58
+ lizard_languages/swift.py,sha256=JcHmBV-p916K2o2XrTKf98U6Bt9-jAEOS9JqA1W5tkA,2570
59
+ lizard_languages/tnsdl.py,sha256=y2dcZI_PmriNd7UTP1Db9QEpWBzKeoH8odRzkiN-P1k,3009
60
+ lizard_languages/tsx.py,sha256=fY9qzPcSvhHSs-62ZFh0mMGyKVaSCEfsYZxBS_uHzww,17161
61
+ lizard_languages/ttcn.py,sha256=tSkPmtifsuUI5aUKBG-uHvwcmZTWcbtMWoUMF3Cw4cI,2199
62
+ lizard_languages/typescript.py,sha256=SOef4ja2GE-Idt9fSF7d0gZTW6bwCNl8K2IT67nIMyA,14805
63
+ lizard_languages/vue.py,sha256=KXUBUo2R1zNF8Pffrz_KsQEN44m5XFRMoGXylxKUeT0,1038
64
+ lizard_languages/zig.py,sha256=RiDZyjnCn97jqFmcl5EQl7pbuH0G1oI2Qo72EXvdtDU,813
65
+ lizard-1.21.0.dist-info/LICENSE.txt,sha256=05ZjgQ8Cl1dD9p0BhW-Txzkc5rhCogGJVEuf1GT2Y_M,1303
66
+ lizard-1.21.0.dist-info/METADATA,sha256=jLq4TDqRDAQd2RimhMDLBNUlv7ULP0vJ6pqybAtClPg,16978
67
+ lizard-1.21.0.dist-info/WHEEL,sha256=Kh9pAotZVRFj97E15yTA4iADqXdQfIVTHcNaZTjxeGM,110
68
+ lizard-1.21.0.dist-info/entry_points.txt,sha256=pPMMwoHAltzGHqR2WeJQItLeeyR7pbX5R2S_POC-xoo,40
69
+ lizard-1.21.0.dist-info/top_level.txt,sha256=5NTrTaOLhHuTzXaGcZPKfuaOgUv7WafNGe0Zl5aycpg,35
70
+ lizard-1.21.0.dist-info/RECORD,,
lizard.py CHANGED
@@ -291,6 +291,7 @@ class FunctionInfo(Nesting): # pylint: disable=R0902
291
291
  self.fan_out = 0
292
292
  self.general_fan_out = 0
293
293
  self.max_nesting_depth = 0 # Initialize max_nesting_depth to 0
294
+ self.forgiven_metrics = set()
294
295
 
295
296
  @property
296
297
  def name_in_space(self):
@@ -509,9 +510,15 @@ def comment_counter(tokens, reader):
509
510
  if comment is not None:
510
511
  for _ in comment.splitlines()[1:]:
511
512
  yield '\n'
512
- if comment.strip().startswith("#lizard forgive global"):
513
+ stripped = comment.strip()
514
+ if stripped.startswith("#lizard forgive global"):
513
515
  reader.context.forgive_global = True
514
- elif comment.strip().startswith("#lizard forgive"):
516
+ elif stripped.startswith("#lizard forgives("):
517
+ match = re.search(r'#lizard forgives?\(([^)]*)\)', stripped)
518
+ if match:
519
+ metrics = {m.strip() for m in match.group(1).split(',') if m.strip()}
520
+ reader.context.current_function.forgiven_metrics.update(metrics)
521
+ elif stripped.startswith("#lizard forgive"):
515
522
  reader.context.forgive = True
516
523
  if "GENERATED CODE" in comment:
517
524
  return
@@ -597,9 +604,16 @@ def warning_filter(option, module_infos):
597
604
  for file_info in module_infos:
598
605
  if file_info:
599
606
  for fun in file_info.function_list:
600
- if any(getattr(fun, attr) > limit for attr, limit in
601
- option.thresholds.items()):
602
- yield fun
607
+ violated_metrics = [
608
+ attr for attr, limit in option.thresholds.items()
609
+ if getattr(fun, attr) > limit
610
+ ]
611
+ if not violated_metrics:
612
+ continue
613
+ forgiven = getattr(fun, 'forgiven_metrics', set())
614
+ if all(metric in forgiven for metric in violated_metrics):
615
+ continue
616
+ yield fun
603
617
 
604
618
 
605
619
  def whitelist_filter(warnings, script=None, whitelist=None):
@@ -1109,7 +1123,8 @@ def main(argv=None):
1109
1123
  sys.stdout = original_stdout
1110
1124
  output_file.close()
1111
1125
  if 0 <= options.number < warning_count:
1112
- sys.exit(1)
1126
+ return 1
1127
+ return 0
1113
1128
 
1114
1129
 
1115
1130
  def print_extension_results(extensions):
@@ -1119,4 +1134,4 @@ def print_extension_results(extensions):
1119
1134
 
1120
1135
 
1121
1136
  if __name__ == "__main__":
1122
- main()
1137
+ sys.exit(main())
lizard_ext/__init__.py CHANGED
@@ -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
@@ -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)
@@ -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
- reader.conditions -= set(['&&', '||', 'and', 'or'])
12
+ # Remove logical operators from conditions (non-strict mode)
13
+ reader.conditions -= reader.logical_operators
13
14
  return tokens
lizard_ext/lizardns.py CHANGED
@@ -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 pile_up_within_block(self):
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.structure_piles.append(0)
111
+ self._push_scope()
87
112
  elif token in ';}':
88
113
  if token == '}':
89
- self.structure_piles.pop()
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
- if token in self.matching_structures:
102
- self.structure_piles[-1] -= 1
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
 
lizard_ext/version.py CHANGED
@@ -3,4 +3,4 @@
3
3
  #
4
4
  # pylint: disable=missing-docstring,invalid-name
5
5
 
6
- version = "1.19.0"
6
+ version = "1.21.0"
lizard_languages/clike.py CHANGED
@@ -32,8 +32,11 @@ class CLikeReader(CodeReader, CCppCommentsMixin):
32
32
 
33
33
  @staticmethod
34
34
  def generate_tokens(source_code, addition='', token_class=None):
35
- # Add pattern for floating point literals to the token generation
36
- addition = r"|(?:\d*\.\d+(?:[eE][-+]?\d+)?)" + \
35
+ # Add pattern for C++ raw string literals R"delimiter(content)delimiter"
36
+ # The delimiter can be empty or up to 16 chars (excluding parentheses, backslash, whitespace)
37
+ # Using a simplified pattern that handles most cases
38
+ addition = r"|R\"[^(\\]*\((?:[^)]|\)[^\"])*\)[^(\\]*\"" + \
39
+ r"|(?:\d*\.\d+(?:[eE][-+]?\d+)?)" + \
37
40
  r"|(?:\d+\.(?:\d+)?(?:[eE][-+]?\d+)?)" + \
38
41
  addition
39
42
  return CodeReader.generate_tokens(source_code, addition, token_class)
@@ -319,53 +322,77 @@ class CLikeStates(CodeStateMachine):
319
322
  def _state_lambda_check(self, token):
320
323
  """Check if this is a lambda expression or a function attribute."""
321
324
  if token == ']':
322
- # This is a lambda expression [](params) or [capture](params)
323
- # Skip the lambda and continue parsing normally
325
+ # This is an empty capture list [](params)
324
326
  self._state = self._state_lambda_params
325
327
  elif token == '[':
326
328
  # This is a function attribute [[attribute]]
327
329
  self._state = self._state_attribute
328
330
  else:
329
331
  # This is a lambda with capture list [capture](params)
330
- # Skip until we find the closing bracket
331
332
  self._state = self._state_lambda_capture
332
333
 
333
334
  def _state_lambda_params(self, token):
334
335
  """Handle lambda parameters and body."""
335
336
  if token == '(':
336
- # Start of parameter list, skip until closing parenthesis
337
+ # Start of parameter list
338
+ self.bracket_stack.append('(')
337
339
  self._state = self._state_lambda_param_list
338
340
  else:
339
- # No parameters, check for body
341
+ # No parameters, check for body or go back to global
340
342
  self._state = self._state_lambda_body
343
+ self._state(token)
341
344
 
342
345
  def _state_lambda_param_list(self, token):
343
- """Handle lambda parameter list."""
344
- if token == ')':
345
- # End of parameter list, check for body
346
- self._state = self._state_lambda_body
347
- # Otherwise, continue in parameter list
346
+ """Handle lambda parameter list with proper bracket tracking."""
347
+ if token == '(':
348
+ self.bracket_stack.append('(')
349
+ elif token == ')':
350
+ if self.bracket_stack and self.bracket_stack[-1] == '(':
351
+ self.bracket_stack.pop()
352
+ if not self.bracket_stack:
353
+ # End of parameter list, check for body
354
+ self._state = self._state_lambda_body
355
+ elif token in ('<', '['):
356
+ self.bracket_stack.append(token)
357
+ elif token == '>' and self.bracket_stack and self.bracket_stack[-1] == '<':
358
+ self.bracket_stack.pop()
359
+ elif token == ']' and self.bracket_stack and self.bracket_stack[-1] == '[':
360
+ self.bracket_stack.pop()
348
361
 
349
362
  def _state_lambda_body(self, token):
350
- """Handle lambda body."""
363
+ """Handle lambda body and qualifiers."""
351
364
  if token == '{':
352
- # Start of lambda body, skip until closing brace
365
+ # Start of lambda body
366
+ self.bracket_stack.append('{')
353
367
  self._state = self._state_lambda_body_skip
354
- elif token == ';':
355
- # Lambda without body, just a semicolon
368
+ elif token in ('mutable', 'noexcept', 'constexpr', 'consteval'):
369
+ # Lambda qualifiers, stay in this state
370
+ pass
371
+ elif token == '->':
372
+ # Trailing return type, stay in this state until we find '{'
373
+ pass
374
+ elif token in (';', ',', ')'):
375
+ # Lambda declaration ended, return to global
356
376
  self._state = self._state_global
357
- # Otherwise, continue
377
+ self._state(token)
378
+ else:
379
+ # Other tokens (type names, etc.) - stay in state
380
+ pass
358
381
 
359
382
  def _state_lambda_body_skip(self, token):
360
- """Skip lambda body until closing brace."""
361
- if token == '}':
362
- # End of lambda body, continue parsing normally
363
- self._state = self._state_global
364
- # Otherwise, continue skipping
383
+ """Skip lambda body with proper brace tracking."""
384
+ if token == '{':
385
+ self.bracket_stack.append('{')
386
+ elif token == '}':
387
+ if self.bracket_stack and self.bracket_stack[-1] == '{':
388
+ self.bracket_stack.pop()
389
+ if not self.bracket_stack:
390
+ # End of lambda body
391
+ self._state = self._state_global
365
392
 
366
393
  def _state_lambda_capture(self, token):
367
394
  """Handle lambda capture list."""
368
395
  if token == ']':
369
- # End of capture list, continue parsing normally
370
- self._state = self._state_global
396
+ # End of capture list, now expect parameters
397
+ self._state = self._state_lambda_params
371
398
  # Otherwise, continue in capture list
@@ -94,12 +94,36 @@ class CodeReader:
94
94
  ext = []
95
95
  languages = None
96
96
  extra_subclasses = set()
97
- _conditions = {'if', 'for', 'while', '&&', '||', '?', 'catch', 'case'}
97
+
98
+ # Condition categories - separate types that contribute to cyclomatic complexity
99
+ _control_flow_keywords = {'if', 'for', 'while', 'catch'}
100
+ _logical_operators = {'&&', '||'}
101
+ _case_keywords = {'case'}
102
+ _ternary_operators = {'?'}
103
+
104
+ @classmethod
105
+ def _build_conditions(cls):
106
+ """Build combined conditions set from separated categories.
107
+
108
+ Returns combined set of all condition types for CCN calculation.
109
+ """
110
+ return (cls._control_flow_keywords |
111
+ cls._logical_operators |
112
+ cls._case_keywords |
113
+ cls._ternary_operators)
98
114
 
99
115
  def __init__(self, context):
100
116
  self.parallel_states = []
101
117
  self.context = context
102
- self.conditions = copy(self._conditions)
118
+
119
+ # Build combined conditions set from separated categories
120
+ self.conditions = copy(self.__class__._build_conditions())
121
+
122
+ # Expose individual categories for extensions
123
+ self.control_flow_keywords = copy(self.__class__._control_flow_keywords)
124
+ self.logical_operators = copy(self.__class__._logical_operators)
125
+ self.case_keywords = copy(self.__class__._case_keywords)
126
+ self.ternary_operators = copy(self.__class__._ternary_operators)
103
127
 
104
128
  @classmethod
105
129
  def match_filename(cls, filename):
@@ -11,8 +11,11 @@ class CSharpReader(CLikeReader):
11
11
  ext = ['cs']
12
12
  language_names = ['csharp']
13
13
 
14
- _conditions = set(['if', 'for', 'while', '&&', '||', '?', 'catch',
15
- 'case', '??'])
14
+ # Separated condition categories
15
+ _control_flow_keywords = {'if', 'for', 'while', 'catch'}
16
+ _logical_operators = {'&&', '||'}
17
+ _case_keywords = {'case'}
18
+ _ternary_operators = {'?', '??'} # C# has both ?: and ?? (null-coalescing)
16
19
 
17
20
  def __init__(self, context):
18
21
  super(CSharpReader, self).__init__(context)
@@ -39,6 +42,22 @@ class CSharpStates(CLikeStates):
39
42
  if self.class_name and self.context.current_function:
40
43
  self.context.current_function.name = f"{self.class_name}::{name}"
41
44
 
45
+ def _state_dec_to_imp(self, token):
46
+ """Override to handle C# expression-bodied members (=>)"""
47
+ if token == '=>':
48
+ # Expression-bodied member: confirm function and enter expression body
49
+ self.context.confirm_new_function()
50
+ self._state = self._state_expression_body
51
+ else:
52
+ super(CSharpStates, self)._state_dec_to_imp(token)
53
+
54
+ def _state_expression_body(self, token):
55
+ """Read the expression body until semicolon, processing tokens for complexity"""
56
+ if token == ';':
57
+ # End of expression-bodied method, finalize function and return to global state
58
+ self.context.end_of_function()
59
+ self._state = self._state_global
60
+
42
61
  def _state_global(self, token):
43
62
  if token in ("class", "struct", "record"):
44
63
  self.class_name = None
@@ -13,7 +13,15 @@ class ErlangReader(CodeReader):
13
13
 
14
14
  ext = ['erl', 'hrl', 'es', 'escript']
15
15
  language_names = ['erlang']
16
- _conditions = {'and', 'case', 'catch', 'if', 'not', 'or', '?', 'when'}
16
+
17
+ # Separated condition categories
18
+ _control_flow_keywords = {'if', 'catch', 'when'} # when is used in guards
19
+ _logical_operators = {'and', 'or', 'not'}
20
+ _case_keywords = {'case'}
21
+ # Note: '?' in Erlang is a macro expansion operator (e.g., ?MODULE, ?EMPTY_NODE)
22
+ # Unlike C-style ternary, it's for compile-time macro substitution
23
+ # Included in ternary_operators because macro usage adds to code complexity
24
+ _ternary_operators = {'?'}
17
25
 
18
26
  def __init__(self, context):
19
27
  super(ErlangReader, self).__init__(context)
@@ -19,12 +19,11 @@ class FortranReader(CodeReader, FortranCommentsMixin):
19
19
  ext = ['f70', 'f90', 'f95', 'f03', 'f08', 'f', 'for', 'ftn', 'fpp']
20
20
  language_names = ['fortran']
21
21
 
22
- # Conditions need to have all the cases because the matching is case-insensitive
23
- # and is not done here.
24
- _conditions = {
25
- 'IF', 'DO', '.AND.', '.OR.', 'CASE',
26
- 'if', 'do', '.and.', '.or.', 'case'
27
- }
22
+ # Separated condition categories (case-insensitive language)
23
+ _control_flow_keywords = {'IF', 'DO', 'if', 'do'}
24
+ _logical_operators = {'.AND.', '.OR.', '.and.', '.or.'}
25
+ _case_keywords = {'CASE', 'case'}
26
+ _ternary_operators = set()
28
27
  _blocks = [
29
28
  'PROGRAM', 'MODULE', 'SUBMODULE', 'SUBROUTINE', 'FUNCTION', 'TYPE',
30
29
  'INTERFACE', 'BLOCK', 'IF', 'DO', 'FORALL', 'WHERE', 'SELECT', 'ASSOCIATE'
@@ -9,8 +9,12 @@ class GDScriptReader(PythonReader):
9
9
 
10
10
  ext = ['gd']
11
11
  language_names = ['GDScript']
12
- _conditions = set(['if', 'else', 'for', 'while', '&&', '||', '?', 'catch',
13
- 'case', 'do'])
12
+
13
+ # Separated condition categories
14
+ _control_flow_keywords = {'if', 'elif', 'for', 'while', 'catch', 'do'}
15
+ _logical_operators = {'&&', '||'}
16
+ _case_keywords = {'case'}
17
+ _ternary_operators = {'?'}
14
18
 
15
19
  def __init__(self, context):
16
20
  super(GDScriptReader, self).__init__(context)
lizard_languages/java.py CHANGED
@@ -54,11 +54,15 @@ class JavaStates(CLikeStates): # pylint: disable=R0903
54
54
 
55
55
  def _try_start_a_class(self, token):
56
56
  if token in ("class", "record", "enum"):
57
+ # "record" inside method bodies is a variable name, not a keyword
58
+ if token == "record" and self.in_method_body:
59
+ return False
57
60
  self.class_name = None
58
61
  self.is_record = token == "record"
59
62
  self.in_record_constructor = False
60
63
  self._state = self._state_class_declaration
61
64
  return True
65
+ return False
62
66
 
63
67
  def _state_global(self, token):
64
68
  if token == '@':
@@ -13,9 +13,12 @@ class KotlinReader(CodeReader, CCppCommentsMixin, SwiftReplaceLabel):
13
13
 
14
14
  ext = ['kt', 'kts']
15
15
  language_names = ['kotlin']
16
- _conditions = {
17
- 'if', 'for', 'while', 'catch', '&&', '||', '?:'
18
- }
16
+
17
+ # Separated condition categories
18
+ _control_flow_keywords = {'if', 'for', 'while', 'catch'}
19
+ _logical_operators = {'&&', '||'}
20
+ _case_keywords = set() # Kotlin uses 'when' expressions, not case
21
+ _ternary_operators = {'?:'} # Elvis operator
19
22
 
20
23
  def __init__(self, context):
21
24
  super(KotlinReader, self).__init__(context)
lizard_languages/perl.py CHANGED
@@ -19,8 +19,13 @@ class PerlReader(CodeReader, ScriptLanguageMixIn):
19
19
 
20
20
  ext = ['pl', 'pm']
21
21
  language_names = ['perl']
22
- _conditions = set(['if', 'elsif', 'unless', 'while', 'until', 'for', 'foreach',
23
- '&&', '||', '?', ':', 'when', 'given', 'default', 'do'])
22
+
23
+ # Separated condition categories
24
+ _control_flow_keywords = {'if', 'elsif', 'unless', 'while', 'until', 'for',
25
+ 'foreach', 'when', 'given', 'default', 'do'}
26
+ _logical_operators = {'&&', '||'} # Perl also has 'and', 'or' with different precedence
27
+ _case_keywords = set()
28
+ _ternary_operators = {'?', ':'} # Both parts of ternary operator
24
29
 
25
30
  def __init__(self, context):
26
31
  super(PerlReader, self).__init__(context)
@@ -65,8 +70,7 @@ class PerlReader(CodeReader, ScriptLanguageMixIn):
65
70
 
66
71
 
67
72
  class PerlStates(CodeStateMachine):
68
- _conditions = set(['if', 'elsif', 'unless', 'while', 'until', 'for', 'foreach',
69
- '&&', '||', '?', ':', 'when', 'given', 'default', 'do'])
73
+ # Note: _conditions removed - now inherited from PerlReader
70
74
 
71
75
  def __init__(self, context):
72
76
  super(PerlStates, self).__init__(context)
lizard_languages/php.py CHANGED
@@ -31,11 +31,15 @@ class PHPLanguageStates(CodeStateMachine):
31
31
  self.match_case_count = 0
32
32
 
33
33
  def _state_global(self, token):
34
- if token == 'class':
34
+ if token == 'use':
35
+ # Enter use statement state
36
+ self._state = self._state_use
37
+ elif token == 'class':
35
38
  self._state = self._class_declaration
36
39
  elif token == 'trait':
37
40
  self._state = self._trait_declaration
38
41
  elif token == 'function':
42
+ # Treat 'function' as function declaration
39
43
  self.is_function_declaration = True
40
44
  self._state = self._function_name
41
45
  elif token == 'fn':
@@ -88,6 +92,13 @@ class PHPLanguageStates(CodeStateMachine):
88
92
  else:
89
93
  self.last_tokens = ''
90
94
 
95
+ def _state_use(self, token):
96
+ """Handle use statements (use function, use const, etc.)"""
97
+ if token == ';':
98
+ # End of use statement, return to global state
99
+ self._state = self._state_global
100
+ # Ignore all other tokens in use statements
101
+
91
102
  def _trait_declaration(self, token):
92
103
  if token and not token.isspace() and token not in ['{', '(']:
93
104
  self.trait_name = token
@@ -231,8 +242,12 @@ class PHPReader(CodeReader, CCppCommentsMixin):
231
242
 
232
243
  ext = ['php']
233
244
  language_names = ['php']
234
- _conditions = set(['if', 'elseif', 'for', 'foreach', 'while', '&&', '||', '?',
235
- 'catch', 'case', 'match'])
245
+
246
+ # Separated condition categories
247
+ _control_flow_keywords = {'if', 'elseif', 'for', 'foreach', 'while', 'catch', 'match'}
248
+ _logical_operators = {'&&', '||'} # PHP also has 'and', 'or' with different precedence
249
+ _case_keywords = {'case'}
250
+ _ternary_operators = {'?'}
236
251
 
237
252
  @staticmethod
238
253
  def generate_tokens(source_code, addition='', token_class=None):
lizard_languages/plsql.py CHANGED
@@ -45,11 +45,14 @@ class PLSQLReader(CodeReader, CCppCommentsMixin):
45
45
  ext = ["sql", "pks", "pkb", "pls", "plb", "pck"]
46
46
  language_names = ["plsql", "pl/sql"]
47
47
 
48
- # PL/SQL conditions for cyclomatic complexity
48
+ # Separated condition categories
49
49
  # Note: 'loop' is NOT in this set because LOOP has special handling:
50
50
  # - standalone LOOP adds +1
51
51
  # - LOOP after WHILE/FOR should not add (it's part of the compound statement)
52
- _conditions = {"if", "elsif", "when", "while", "for", "and", "or"}
52
+ _control_flow_keywords = {"if", "elsif", "when", "while", "for"}
53
+ _logical_operators = {"and", "or"}
54
+ _case_keywords = set() # PL/SQL uses 'when' in case expressions
55
+ _ternary_operators = set()
53
56
 
54
57
  def __init__(self, context):
55
58
  super(PLSQLReader, self).__init__(context)
@@ -29,10 +29,12 @@ class PythonReader(CodeReader, ScriptLanguageMixIn):
29
29
 
30
30
  ext = ['py']
31
31
  language_names = ['python']
32
- _conditions = set([
33
- 'if', 'for', 'while', 'and', 'or',
34
- 'elif', 'except', 'finally'
35
- ])
32
+
33
+ # Separated condition categories
34
+ _control_flow_keywords = {'if', 'elif', 'for', 'while', 'except', 'finally'}
35
+ _logical_operators = {'and', 'or'}
36
+ _case_keywords = set() # Python uses if/elif, not case
37
+ _ternary_operators = set() # Python uses 'x if c else y' syntax, not ?
36
38
 
37
39
  def __init__(self, context):
38
40
  super(PythonReader, self).__init__(context)
lizard_languages/r.py CHANGED
@@ -12,12 +12,15 @@ class RReader(CodeReader, ScriptLanguageMixIn):
12
12
  ext = ['r', 'R']
13
13
  language_names = ['r', 'R']
14
14
 
15
- # R-specific conditions that increase cyclomatic complexity
16
- _conditions = {
17
- 'if', 'else if', 'for', 'while', 'repeat', 'switch',
18
- '&&', '||', '&', '|', 'ifelse',
19
- 'tryCatch', 'try'
20
- }
15
+ # Separated condition categories
16
+ _control_flow_keywords = {'if', 'else if', 'for', 'while', 'repeat', 'switch',
17
+ 'tryCatch', 'try', 'ifelse'} # ifelse is a vectorized control function
18
+ # R has both short-circuit (&&, ||) and element-wise (&, |) operators
19
+ # Both types count toward CCN as they represent conditional logic (vectorized or not)
20
+ # Users can use -Enonstrict to exclude logical operators if desired
21
+ _logical_operators = {'&&', '||', '&', '|'}
22
+ _case_keywords = set()
23
+ _ternary_operators = set()
21
24
 
22
25
  def __init__(self, context):
23
26
  super(RReader, self).__init__(context)
@@ -97,9 +97,12 @@ class RubylikeStateMachine(CodeStateMachine):
97
97
  class RubylikeReader(CodeReader, ScriptLanguageMixIn):
98
98
  # pylint: disable=R0903
99
99
 
100
- _conditions = set(['if', 'until', 'for', 'while', 'and', 'or',
101
- 'elsif', 'elseif', 'rescue',
102
- 'ensure', 'when', '||', '&&', '?'])
100
+ # Separated condition categories
101
+ _control_flow_keywords = {'if', 'elsif', 'elseif', 'until', 'for', 'while',
102
+ 'rescue', 'ensure', 'when'}
103
+ _logical_operators = {'and', 'or', '||', '&&'} # Both word and symbol forms
104
+ _case_keywords = set() # Ruby uses 'when' for case expressions
105
+ _ternary_operators = {'?'}
103
106
 
104
107
  def __init__(self, context):
105
108
  super(RubylikeReader, self).__init__(context)
lizard_languages/rust.py CHANGED
@@ -12,8 +12,13 @@ class RustReader(CodeReader, CCppCommentsMixin):
12
12
 
13
13
  ext = ['rs']
14
14
  language_names = ['rust']
15
- _conditions = set(['if', 'for', 'while', '&&', '||', '?', 'catch',
16
- 'case', 'match', 'where'])
15
+
16
+ # Separated condition categories
17
+ _control_flow_keywords = {'if', 'for', 'while', 'catch', 'match', 'where'}
18
+ _logical_operators = {'&&', '||'}
19
+ _case_keywords = set() # Rust uses match arms, not case keyword
20
+ # Note: '?' in Rust is the error propagation operator, not ternary
21
+ _ternary_operators = {'?'}
17
22
 
18
23
  def __init__(self, context):
19
24
  super().__init__(context)
lizard_languages/scala.py CHANGED
@@ -12,8 +12,12 @@ class ScalaReader(CodeReader, CCppCommentsMixin):
12
12
 
13
13
  ext = ['scala']
14
14
  language_names = ['scala']
15
- _conditions = set(['if', 'for', 'while', '&&', '||', '?', 'catch',
16
- 'case', 'do'])
15
+
16
+ # Separated condition categories
17
+ _control_flow_keywords = {'if', 'for', 'while', 'catch', 'do'}
18
+ _logical_operators = {'&&', '||'}
19
+ _case_keywords = {'case'} # Pattern matching
20
+ _ternary_operators = {'?'}
17
21
 
18
22
  def __init__(self, context):
19
23
  super(ScalaReader, self).__init__(context)
@@ -11,7 +11,12 @@ class SolidityReader(CodeReader, CCppCommentsMixin):
11
11
 
12
12
  ext = ['sol']
13
13
  language_names = ['solidity']
14
- _conditions = set(['if', 'for', 'while', '&&', '||', '?'])
14
+
15
+ # Separated condition categories
16
+ _control_flow_keywords = {'if', 'for', 'while'}
17
+ _logical_operators = {'&&', '||'}
18
+ _case_keywords = set()
19
+ _ternary_operators = {'?'}
15
20
 
16
21
  def __init__(self, context):
17
22
  super(SolidityReader, self).__init__(context)
lizard_languages/st.py CHANGED
@@ -22,11 +22,15 @@ class StReader(CodeReader, StCommentsMixin):
22
22
  language_names = ['st']
23
23
  macro_pattern = re.compile(r"#\s*(\w+)\s*(.*)", re.M | re.S)
24
24
 
25
- # track block starters
26
- _conditions = set([
27
- 'if', 'elsif', 'case', 'for', 'while', 'repeat',
28
- 'IF', 'ELSIF', 'CASE', 'FOR', 'WHILE', 'REPEAT'
29
- ])
25
+ # Separated condition categories (case-insensitive language)
26
+ _control_flow_keywords = {
27
+ 'if', 'elsif', 'for', 'while', 'repeat',
28
+ 'IF', 'ELSIF', 'FOR', 'WHILE', 'REPEAT'
29
+ }
30
+ # ST is case-insensitive, so include both lowercase and uppercase forms
31
+ _logical_operators = {'and', 'or', 'AND', 'OR'}
32
+ _case_keywords = {'case', 'CASE'}
33
+ _ternary_operators = set()
30
34
 
31
35
  _functions = set([
32
36
  'FUNCTION_BLOCK', 'FUNCTION', 'ACTION'
lizard_languages/swift.py CHANGED
@@ -30,8 +30,12 @@ class SwiftReader(CodeReader, CCppCommentsMixin, SwiftReplaceLabel):
30
30
  FUNC_KEYWORD = 'def'
31
31
  ext = ['swift']
32
32
  language_names = ['swift']
33
- _conditions = set(['if', 'for', 'while', '&&', '||', '?', 'catch',
34
- 'case', 'guard'])
33
+
34
+ # Separated condition categories
35
+ _control_flow_keywords = {'if', 'for', 'while', 'catch', 'guard'}
36
+ _logical_operators = {'&&', '||'}
37
+ _case_keywords = {'case'} # Pattern matching
38
+ _ternary_operators = {'?'}
35
39
 
36
40
  def __init__(self, context):
37
41
  super(SwiftReader, self).__init__(context)
lizard_languages/tnsdl.py CHANGED
@@ -84,7 +84,12 @@ class SDLReader(CodeReader, CCppCommentsMixin):
84
84
  if condition:
85
85
  return self.context.CONDITION()
86
86
 
87
- _conditions = set(['WHILE', 'AND', 'OR', '#if'])
87
+ # Separated condition categories
88
+ _control_flow_keywords = {'WHILE', '#if'}
89
+ _logical_operators = {'AND', 'OR'}
90
+ _case_keywords = set()
91
+ _ternary_operators = set()
92
+ # Note: No need to define _conditions - base class builds it automatically
88
93
 
89
94
  def _is_condition(self, token, last_token):
90
95
  if token == ':' and last_token == ')':
lizard_languages/tsx.py CHANGED
@@ -48,8 +48,8 @@ class JSXTypeScriptStates(CodeStateMachine):
48
48
  self.started_function = None
49
49
  self.pending_function_name = ''
50
50
  self._ts_declare = False
51
- self._conditions = set(['if', 'elseif', 'for', 'while', '&&', '||', '?',
52
- 'catch', 'case'])
51
+ # Note: Condition categories come from TypeScriptReader class level,
52
+ # no need to define instance-level duplicates
53
53
  self.inside_function = inside_function # Track if we're already inside a function
54
54
 
55
55
  def statemachine_before_return(self):
lizard_languages/ttcn.py CHANGED
@@ -10,9 +10,11 @@ class TTCNReader(CLikeReader): # pylint: disable=R0903
10
10
  ext = ['ttcn', 'ttcnpp']
11
11
  language_names = ['ttcn', 'ttcn3']
12
12
 
13
- _conditions = set(['if', 'else', 'for', 'while',
14
- 'altstep', 'case', 'goto', 'alt',
15
- 'interleave', 'and', 'or', 'xor'])
13
+ # Separated condition categories
14
+ _control_flow_keywords = {'if', 'for', 'while', 'altstep', 'alt', 'interleave', 'goto'}
15
+ _logical_operators = {'and', 'or', 'xor'}
16
+ _case_keywords = {'case'}
17
+ _ternary_operators = set()
16
18
 
17
19
  def __init__(self, context):
18
20
  super(TTCNReader, self).__init__(context)
@@ -51,8 +51,12 @@ class TypeScriptReader(CodeReader, CCppCommentsMixin):
51
51
 
52
52
  ext = ['ts']
53
53
  language_names = ['typescript', 'ts']
54
- _conditions = set(['if', 'elseif', 'for', 'while', '&&', '||', '?',
55
- 'catch', 'case'])
54
+
55
+ # Separated condition categories
56
+ _control_flow_keywords = {'if', 'elseif', 'for', 'while', 'catch'}
57
+ _logical_operators = {'&&', '||'}
58
+ _case_keywords = {'case'}
59
+ _ternary_operators = {'?'}
56
60
 
57
61
  def __init__(self, context):
58
62
  super().__init__(context)
lizard_languages/zig.py CHANGED
@@ -12,7 +12,13 @@ from .golike import GoLikeStates
12
12
  class ZigReader(CodeReader, CCppCommentsMixin):
13
13
  ext = ["zig"]
14
14
  language_names = ["zig"]
15
- _conditions = {"if", "for", "while", "and", "or", "orelse", "try", "catch", "=>"}
15
+
16
+ # Separated condition categories
17
+ _control_flow_keywords = {"if", "for", "while", "try", "catch"}
18
+ _logical_operators = {"and", "or", "orelse"} # orelse is Zig's null coalescing
19
+ _case_keywords = set()
20
+ # Note: '=>' is for error union and switch cases in Zig
21
+ _ternary_operators = {"=>"}
16
22
 
17
23
  def __init__(self, context):
18
24
  super().__init__(context)
@@ -1,70 +0,0 @@
1
- lizard.py,sha256=B0g5lEp5me31bQpjfMKVayF0iUfH0PalVecOKeUX3-A,41365
2
- lizard_ext/__init__.py,sha256=AkZYVqCgd7XX1hMwLMyh_ABm9geIHmobEch-thYXZz8,932
3
- lizard_ext/auto_open.py,sha256=byD_RbeVhvSUhR2bJMRitvA3zcKEapFwv0-XaDJ6GFo,1096
4
- lizard_ext/checkstyleoutput.py,sha256=UzDHg837ErEZepXkR8I8YCoz2r1lkmzGctMA7dpyB-M,1245
5
- lizard_ext/csvoutput.py,sha256=43fhmo8kB85qcdujCwySGNuTC4FkKUPLqIApPeljPnA,2663
6
- lizard_ext/default_ordered_dict.py,sha256=YbVz6nPlQ6DjWc_EOFBz6AJN2XLo9dpnUdeyejQvUDE,831
7
- lizard_ext/extension_base.py,sha256=rnjUL2mqSGToUVYydju7fa8ZwynLPY8S1F17gIJP55I,346
8
- lizard_ext/htmloutput.py,sha256=G7MdLD7AwuR0LLCAkEpyHx4N_ssCcFQdXd7Xg5jZWX0,6537
9
- lizard_ext/keywords.py,sha256=VxsxoATtKV-8egMKd7I8sd2qbZMtEFEpsszk__6rmjQ,893
10
- lizard_ext/lizardboolcount.py,sha256=abmMA9X3VFRO5mziicUxWKmHldHNC0jBEe7NKAKA5fs,1062
11
- lizard_ext/lizardcomplextags.py,sha256=flrwYg24P5DoDsBO3gdcK9SxkugX_brhfjuu8zgPnOc,681
12
- lizard_ext/lizardcpre.py,sha256=bVrMXffGUZlydv_zwIVtp-Ij9XyXMFEcap2R4DmLXPU,1277
13
- lizard_ext/lizarddependencycount.py,sha256=6Nt2z69cyG8P3pceTUCTU6yh4h73lezL2awRFh7K77Y,2423
14
- lizard_ext/lizarddumpcomments.py,sha256=-c46U3CP_beDfBuB9QhObpiB6wK7xq1u9jeRjgAyU90,683
15
- lizard_ext/lizardduplicate.py,sha256=tlU-UTB_d_qjekiO4MSaXPBT1FSX8uTaOcfeXnjBzU8,9762
16
- lizard_ext/lizardduplicated_param_list.py,sha256=_ApeSbjA-NU_rmICsivyfGEEg0-O94wWgWpeeE8F3Zc,1811
17
- lizard_ext/lizardexitcount.py,sha256=ziAVFi5RgjxJOwAQy6LzdZZflkvvxTiXOIp0FAL0wKQ,692
18
- lizard_ext/lizardgotocount.py,sha256=w2GWWwqVh4j7Fum41Wvg172b70JvtCm5BCzZUmmTlcM,514
19
- lizard_ext/lizardignoreassert.py,sha256=sqLwcnJQ06SYqIk901ib4NQ8ECwjIe_qL4T6z1wLXAk,644
20
- lizard_ext/lizardio.py,sha256=xQN-AgLGLKJarJkgfaqX_TKyupbb7GTcwPxrL2B1J1w,3357
21
- lizard_ext/lizardmccabe.py,sha256=RiO8ASmQUah4udOH8SbE2OOMxwShIPByW93TlFxXlQU,1274
22
- lizard_ext/lizardmodified.py,sha256=4Ld7yy1D2m2biMtx-g0DtjXwLa-9mG2togS2IRDAF3k,705
23
- lizard_ext/lizardnd.py,sha256=h4MaSsFAY5rK8kOSr61LkWntwJWV1KnhaEOWZgp3-c0,7496
24
- lizard_ext/lizardnonstrict.py,sha256=pPG22up2uh9rEkdRFtTWdiuOaiBNe0ZUjaZQpSTX5LE,394
25
- lizard_ext/lizardns.py,sha256=8pztUoRS_UWN24MawwxeHEJgYh49id5PWODUBb6O72U,4184
26
- lizard_ext/lizardoutside.py,sha256=FGm2tbBZ17-2OCgmQlD-vobUCfQKb0FAygf86eM3xuM,336
27
- lizard_ext/lizardstatementcount.py,sha256=xYk6ixSIItSE1BWQXzrWmduFgGhA3VR817SNKLffyVQ,1182
28
- lizard_ext/lizardwordcount.py,sha256=2QYXD7-AtkkgAbi9VSidunMbSsGQ7MKYb6IT-bS-cok,7575
29
- lizard_ext/version.py,sha256=gScBFBQFiyhdj77Gb-x1hY6wABdKwZlb_aaNdiiADQ0,181
30
- lizard_ext/xmloutput.py,sha256=-cbh0he4O_X-wX56gkv9AnSPNN0qvR7FACqlBeezUS4,5609
31
- lizard_languages/__init__.py,sha256=DniggHM3SOFlwkP8Tm4csEcisbf7_i1EvfoAkG9Atg0,1611
32
- lizard_languages/clike.py,sha256=_oDUbA1hEIPujKw3wyAtC1uFPvjmg4TBgKbHLa-S1wg,13597
33
- lizard_languages/code_reader.py,sha256=O0nZkI4xEHIWGgFBDwczj8-ay7aKllPnzRsblQtL3Gc,6874
34
- lizard_languages/csharp.py,sha256=EfFAIOIcJXUUhXTlZApXGSlzG34NZvHM9OSe6m7hpv0,2141
35
- lizard_languages/erlang.py,sha256=7YJS2cMyXDKEV_kpH8DzBARxFCFcjKuTOPSQ3K52auU,3860
36
- lizard_languages/fortran.py,sha256=KATDsnfjob5W3579A_VxbwrbTkK7Rx3p0eXdBgjx25I,8973
37
- lizard_languages/gdscript.py,sha256=KwlGoODilQnFgXvODpq_XlA6fV3hGbN9fd7bsiEUn78,637
38
- lizard_languages/go.py,sha256=sntz0jOEuj4klPipoTFd16UDK1fAUQfwK7YX_cLMZAc,1346
39
- lizard_languages/golike.py,sha256=vRIfjTVvc0VmJf27lTOLht55ZF1AQ9wn0Fvu-9WabWk,2858
40
- lizard_languages/java.py,sha256=HQBTZjUKbUJwgmtLYIzJrWtPpFP3ZdBP_NJK7YOXZC0,6424
41
- lizard_languages/javascript.py,sha256=vniCNMW-ea9Jpv6c8qCcjLVDYjT8VztjXigp5XRWt0E,317
42
- lizard_languages/js_style_regex_expression.py,sha256=Xgyogch4xElYtCG4EnBKvalHTl3tjRPcIIcIQRRd61I,1970
43
- lizard_languages/kotlin.py,sha256=v_o2orEzA5gB9vM_0h-E4QXjrc5Yum-0K6W6_laOThc,2844
44
- lizard_languages/lua.py,sha256=3nqBcunBzJrhv4Iqaf8xvbyqxZy3aSxJ-IiHimHFlac,1573
45
- lizard_languages/objc.py,sha256=2a1teLdaXZBtCeFiIZer1j_sVx9LZ1CbF2XfnqlvLmk,2319
46
- lizard_languages/perl.py,sha256=136w620eECe_t-kmlRUGrsZSxQNo2JQ_PZTSQfCSmHY,11987
47
- lizard_languages/php.py,sha256=UV40p8WzNC64NQ5qElPKzcFTjVt5kenLMz-eKYlcnMY,9940
48
- lizard_languages/plsql.py,sha256=17zf0AkDLFW7mA3ngUNrU7z6U6DkmA96CKOcEhYNC5Q,17137
49
- lizard_languages/python.py,sha256=AsL0SmQ73zhNS1iGi4Z8VtuUE0VjqBzo9W8W0mjqL0E,5790
50
- lizard_languages/r.py,sha256=IoyMhmFtUmTji6rm6-fqss_j_kvIHu3JjABRh6RNys0,12583
51
- lizard_languages/ruby.py,sha256=HL1ZckeuUUJU3QSVAOPsG_Zsl0C6X2PX5_VaWqclzkM,2277
52
- lizard_languages/rubylike.py,sha256=dAGZ2wqW8nqaESMU8HkeR9gwQ-q9fmZqE6AANvVZD1Q,3426
53
- lizard_languages/rust.py,sha256=WarDHnFZv99Yu3_C5DpZfLS8dVWz6AcOzo2dzLW94rA,817
54
- lizard_languages/scala.py,sha256=6Jr_TG945VYqB3o5weD7jN7S4beHt4aVj3r-fmKeMAM,1316
55
- lizard_languages/script_language.py,sha256=SKe45AbO6Z-axbN8KW_g7jf9g7YTXZ6dWzJj4ubDsM8,1172
56
- lizard_languages/solidity.py,sha256=Z0GD7U5bI5eUikdy7m_iKWeFD5yXRYq4r3zycscOhJQ,553
57
- lizard_languages/st.py,sha256=7fpOfNAoUjNY8RCHSYLufnOzZTUkKwjVvcyRyM1xP2Y,4160
58
- lizard_languages/swift.py,sha256=p8S2OAkQOx9YQ02yhoVXFkr7pMqUH1Nb3RVXPHRU_9M,2450
59
- lizard_languages/tnsdl.py,sha256=pGcalA_lHY362v2wwPS86seYBOOBBjvmU6vd4Yy3A9g,2803
60
- lizard_languages/tsx.py,sha256=1oOVCcz5yHkmYLYGhSarCMSXfGVasweklAqqapkuNR4,17160
61
- lizard_languages/ttcn.py,sha256=ygjw_raBmPF-4mgoM8m6CAdyEMpTI-n1kZJK1RL4Vxo,2131
62
- lizard_languages/typescript.py,sha256=unCDj040dY9fTOw9iIykqjt2j5tZWJ2Bm9fHYjOWY5I,14706
63
- lizard_languages/vue.py,sha256=KXUBUo2R1zNF8Pffrz_KsQEN44m5XFRMoGXylxKUeT0,1038
64
- lizard_languages/zig.py,sha256=NX1iyBstBuJFeAGBOAIaRfrmeBREne2HX6Pt4fXZZTQ,586
65
- lizard-1.19.0.dist-info/LICENSE.txt,sha256=05ZjgQ8Cl1dD9p0BhW-Txzkc5rhCogGJVEuf1GT2Y_M,1303
66
- lizard-1.19.0.dist-info/METADATA,sha256=DNAVbhrtdVrI5tn2rWZoSBwCfZ5ArhMQ0XNmHvOqbh4,16697
67
- lizard-1.19.0.dist-info/WHEEL,sha256=Kh9pAotZVRFj97E15yTA4iADqXdQfIVTHcNaZTjxeGM,110
68
- lizard-1.19.0.dist-info/entry_points.txt,sha256=pPMMwoHAltzGHqR2WeJQItLeeyR7pbX5R2S_POC-xoo,40
69
- lizard-1.19.0.dist-info/top_level.txt,sha256=5NTrTaOLhHuTzXaGcZPKfuaOgUv7WafNGe0Zl5aycpg,35
70
- lizard-1.19.0.dist-info/RECORD,,