lizard 1.17.15__py2.py3-none-any.whl → 1.17.16__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.17.15
3
+ Version: 1.17.16
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/
@@ -29,6 +29,7 @@ Classifier: Programming Language :: Python :: 3.10
29
29
  Classifier: Programming Language :: Python :: 3.11
30
30
  License-File: LICENSE.txt
31
31
  Requires-Dist: pygments
32
+ Requires-Dist: pathspec
32
33
 
33
34
  |Web Site| Lizard
34
35
  =================
@@ -138,6 +139,13 @@ Exclude anything in the tests folder:
138
139
 
139
140
  lizard mySource/ -x"./tests/*"
140
141
 
142
+ Use .gitignore file:
143
+
144
+ ::
145
+
146
+ lizard mySource/
147
+
148
+ If there is a .gitignore file in the given path, lizard will automatically use it as an additional filter to exclude files that match the gitignore patterns. This is useful when you want to analyze only the tracked files in your git repository.
141
149
 
142
150
  Options
143
151
  ~~~~~~~
@@ -1,4 +1,4 @@
1
- lizard.py,sha256=F6eF_WT_arglGadw__oqYk_NMgEVk-8idmybIrtd2OE,38568
1
+ lizard.py,sha256=m-wnNDtLaug8yvK65Ex1IMRTubo6uFQAfdcdRN9x5Mg,39927
2
2
  lizard_ext/__init__.py,sha256=Cz0pvH6QHyadK-rAeeEhQVsm0hW5M-fBQgV4FBaX9zk,500
3
3
  lizard_ext/auto_open.py,sha256=byD_RbeVhvSUhR2bJMRitvA3zcKEapFwv0-XaDJ6GFo,1096
4
4
  lizard_ext/csvoutput.py,sha256=43fhmo8kB85qcdujCwySGNuTC4FkKUPLqIApPeljPnA,2663
@@ -25,18 +25,18 @@ lizard_ext/lizardns.py,sha256=8pztUoRS_UWN24MawwxeHEJgYh49id5PWODUBb6O72U,4184
25
25
  lizard_ext/lizardoutside.py,sha256=FGm2tbBZ17-2OCgmQlD-vobUCfQKb0FAygf86eM3xuM,336
26
26
  lizard_ext/lizardstatementcount.py,sha256=xYk6ixSIItSE1BWQXzrWmduFgGhA3VR817SNKLffyVQ,1182
27
27
  lizard_ext/lizardwordcount.py,sha256=2QYXD7-AtkkgAbi9VSidunMbSsGQ7MKYb6IT-bS-cok,7575
28
- lizard_ext/version.py,sha256=bEnVphLi5lD3nsGDAkiBaNX1JY-mQDoiFcSVF8rk7zc,182
28
+ lizard_ext/version.py,sha256=s8Ej-6FrgTUH06Kp-lskbDvVReimxGKBZNzim7QUtbI,182
29
29
  lizard_ext/xmloutput.py,sha256=-cbh0he4O_X-wX56gkv9AnSPNN0qvR7FACqlBeezUS4,5609
30
30
  lizard_languages/__init__.py,sha256=2mvrPWMJVCq981kMjoAPEi2O07C8vo-vUWOG_wp7vKQ,1473
31
31
  lizard_languages/clike.py,sha256=Lnwkma-jEu8FNVEPqTAKPkz1Hi0T_dP7H9Jyq0Bd0kQ,10725
32
32
  lizard_languages/code_reader.py,sha256=P0PkE4QZBWOEj6cFHA4hj3hcLZLcGnqH31EmtltxlaE,6240
33
- lizard_languages/csharp.py,sha256=lVi-g-0JjHagqDR5r-lRdi2BuCdtR5aer9CYY-Nzw44,478
33
+ lizard_languages/csharp.py,sha256=EfFAIOIcJXUUhXTlZApXGSlzG34NZvHM9OSe6m7hpv0,2141
34
34
  lizard_languages/erlang.py,sha256=7YJS2cMyXDKEV_kpH8DzBARxFCFcjKuTOPSQ3K52auU,3860
35
35
  lizard_languages/fortran.py,sha256=KATDsnfjob5W3579A_VxbwrbTkK7Rx3p0eXdBgjx25I,8973
36
36
  lizard_languages/gdscript.py,sha256=KwlGoODilQnFgXvODpq_XlA6fV3hGbN9fd7bsiEUn78,637
37
37
  lizard_languages/go.py,sha256=dSbWxtWve7KSRW5i9w4DxhODtJ72EcBNrgp-7Xhn0Sg,465
38
38
  lizard_languages/golike.py,sha256=vRIfjTVvc0VmJf27lTOLht55ZF1AQ9wn0Fvu-9WabWk,2858
39
- lizard_languages/java.py,sha256=mfXCRicmZFZFxPW7QuTOQtAKzOZD3d-uh4tiALcGdX4,1186
39
+ lizard_languages/java.py,sha256=N9V1nbK_kGN4T2A1xpU1f9wZxGL6UEwVuOCA7D_tjPQ,3036
40
40
  lizard_languages/javascript.py,sha256=sGZeTqFqCjcl87ncR-Rmj-HTp-4s4ptoTMxeDgc8Jvw,522
41
41
  lizard_languages/js_style_language_states.py,sha256=Ie0eA15rd0gfahdNzUlSkQa-o_j5idTIB82JU32c378,4165
42
42
  lizard_languages/js_style_regex_expression.py,sha256=Xgyogch4xElYtCG4EnBKvalHTl3tjRPcIIcIQRRd61I,1970
@@ -59,9 +59,9 @@ lizard_languages/ttcn.py,sha256=ygjw_raBmPF-4mgoM8m6CAdyEMpTI-n1kZJK1RL4Vxo,2131
59
59
  lizard_languages/typescript.py,sha256=c_Kez4pOGMXhdo6q3HT-clEJDP7LuRIbBkkJSipComU,3568
60
60
  lizard_languages/vue.py,sha256=KXUBUo2R1zNF8Pffrz_KsQEN44m5XFRMoGXylxKUeT0,1038
61
61
  lizard_languages/zig.py,sha256=NX1iyBstBuJFeAGBOAIaRfrmeBREne2HX6Pt4fXZZTQ,586
62
- lizard-1.17.15.dist-info/LICENSE.txt,sha256=05ZjgQ8Cl1dD9p0BhW-Txzkc5rhCogGJVEuf1GT2Y_M,1303
63
- lizard-1.17.15.dist-info/METADATA,sha256=P5tZ8sJtxBdTVX6qYePWJc_NuXcA7QI3yp4gomL0lgA,15428
64
- lizard-1.17.15.dist-info/WHEEL,sha256=Kh9pAotZVRFj97E15yTA4iADqXdQfIVTHcNaZTjxeGM,110
65
- lizard-1.17.15.dist-info/entry_points.txt,sha256=ZBqPhu-J3NoGGW5vn2Gfyoo0vdVlgBgM-wlNm0SGYUQ,39
66
- lizard-1.17.15.dist-info/top_level.txt,sha256=5NTrTaOLhHuTzXaGcZPKfuaOgUv7WafNGe0Zl5aycpg,35
67
- lizard-1.17.15.dist-info/RECORD,,
62
+ lizard-1.17.16.dist-info/LICENSE.txt,sha256=05ZjgQ8Cl1dD9p0BhW-Txzkc5rhCogGJVEuf1GT2Y_M,1303
63
+ lizard-1.17.16.dist-info/METADATA,sha256=m4ndIad8zK__BY3lidM_6WBys_A7GQY0TNDWFq8XIk8,15745
64
+ lizard-1.17.16.dist-info/WHEEL,sha256=Kh9pAotZVRFj97E15yTA4iADqXdQfIVTHcNaZTjxeGM,110
65
+ lizard-1.17.16.dist-info/entry_points.txt,sha256=ZBqPhu-J3NoGGW5vn2Gfyoo0vdVlgBgM-wlNm0SGYUQ,39
66
+ lizard-1.17.16.dist-info/top_level.txt,sha256=5NTrTaOLhHuTzXaGcZPKfuaOgUv7WafNGe0Zl5aycpg,35
67
+ lizard-1.17.16.dist-info/RECORD,,
lizard.py CHANGED
@@ -896,14 +896,43 @@ def md5_hash_file(full_path_name):
896
896
  def get_all_source_files(paths, exclude_patterns, lans):
897
897
  '''
898
898
  Function counts md5 hash for the given file and checks if it isn't a
899
- duplicate using set of hashes for previous files '''
899
+ duplicate using set of hashes for previous files.
900
+
901
+ If a .gitignore file is found in any of the given paths, it will be used
902
+ to filter out files that match the gitignore patterns.
903
+ '''
900
904
  hash_set = set()
905
+ gitignore_spec = None
906
+ base_path = None
907
+
908
+ def _load_gitignore():
909
+ nonlocal gitignore_spec, base_path
910
+ try:
911
+ import pathspec
912
+ for path in paths:
913
+ gitignore_path = os.path.join(path, '.gitignore')
914
+ if os.path.exists(gitignore_path):
915
+ with open(gitignore_path, 'r') as gitignore_file:
916
+ # Read lines and strip whitespace and empty lines
917
+ patterns = [line.strip() for line in gitignore_file.readlines()]
918
+ patterns = [p for p in patterns if p and not p.startswith('#')]
919
+ gitignore_spec = pathspec.PathSpec.from_lines('gitwildmatch', patterns)
920
+ base_path = path
921
+ break
922
+ except ImportError:
923
+ pass
901
924
 
902
925
  def _support(reader):
903
926
  return not lans or set(lans).intersection(
904
927
  reader.language_names)
905
928
 
906
929
  def _validate_file(pathname):
930
+ if gitignore_spec is not None and base_path is not None:
931
+ rel_path = os.path.relpath(pathname, base_path)
932
+ # Normalize path separators for consistent matching
933
+ rel_path = rel_path.replace(os.sep, '/')
934
+ if gitignore_spec.match_file(rel_path):
935
+ return False
907
936
  return (
908
937
  pathname in paths or (
909
938
  get_reader_for(pathname) and
@@ -926,6 +955,7 @@ def get_all_source_files(paths, exclude_patterns, lans):
926
955
  for filename in files:
927
956
  yield os.path.join(root, filename)
928
957
 
958
+ _load_gitignore()
929
959
  return filter(_validate_file, all_listed_files(paths))
930
960
 
931
961
 
@@ -967,7 +997,7 @@ def parse_args(argv):
967
997
  if inferred_printer:
968
998
  if not opt.printer:
969
999
  opt.printer = inferred_printer
970
- else:
1000
+ elif opt.printer != inferred_printer:
971
1001
  msg = "Warning: overriding output file extension.\n"
972
1002
  sys.stderr.write(msg)
973
1003
  return opt
lizard_ext/version.py CHANGED
@@ -3,4 +3,4 @@
3
3
  #
4
4
  # pylint: disable=missing-docstring,invalid-name
5
5
 
6
- version = "1.17.15"
6
+ version = "1.17.16"
@@ -2,7 +2,7 @@
2
2
  Language parser for C Sharp
3
3
  '''
4
4
 
5
- from .clike import CLikeReader
5
+ from .clike import CLikeReader, CLikeStates, CLikeNestingStackStates
6
6
 
7
7
 
8
8
  class CSharpReader(CLikeReader):
@@ -14,7 +14,49 @@ class CSharpReader(CLikeReader):
14
14
  _conditions = set(['if', 'for', 'while', '&&', '||', '?', 'catch',
15
15
  'case', '??'])
16
16
 
17
+ def __init__(self, context):
18
+ super(CSharpReader, self).__init__(context)
19
+ self.parallel_states = [
20
+ CSharpStates(context),
21
+ CLikeNestingStackStates(context)
22
+ ]
23
+
17
24
  @staticmethod
18
25
  def generate_tokens(source_code, addition='', token_class=None):
19
26
  return CLikeReader.generate_tokens(
20
27
  source_code, r"|(?:\?\?)", token_class)
28
+
29
+
30
+ class CSharpStates(CLikeStates):
31
+ def __init__(self, context):
32
+ super(CSharpStates, self).__init__(context)
33
+ self.in_primary_constructor = False
34
+ self.class_name = None
35
+
36
+ def try_new_function(self, name):
37
+ if not self.in_primary_constructor:
38
+ super(CSharpStates, self).try_new_function(name)
39
+ if self.class_name and self.context.current_function:
40
+ self.context.current_function.name = f"{self.class_name}::{name}"
41
+
42
+ def _state_global(self, token):
43
+ if token in ("class", "struct", "record"):
44
+ self.class_name = None
45
+ self._state = self._state_class_declaration
46
+ else:
47
+ super(CSharpStates, self)._state_global(token)
48
+
49
+ def _state_class_declaration(self, token):
50
+ if token == '(': # Primary constructor
51
+ self.in_primary_constructor = True
52
+ self._state = self._state_primary_constructor
53
+ elif token == '{':
54
+ self._state = self._state_global
55
+ elif token[0].isalpha():
56
+ if not self.class_name: # Only set class name if not already set
57
+ self.class_name = token
58
+
59
+ @CLikeStates.read_inside_brackets_then("()", "_state_class_declaration")
60
+ def _state_primary_constructor(self, _):
61
+ """Skip primary constructor parameters without counting them as a function"""
62
+ self.in_primary_constructor = False
lizard_languages/java.py CHANGED
@@ -19,19 +19,39 @@ class JavaReader(CLikeReader):
19
19
 
20
20
 
21
21
  class JavaStates(CLikeStates): # pylint: disable=R0903
22
+ def __init__(self, context):
23
+ super(JavaStates, self).__init__(context)
24
+ self.class_name = None
25
+ self.is_record = False
26
+ self.in_record_constructor = False
27
+
22
28
  def _state_old_c_params(self, token):
23
29
  if token == '{':
24
30
  self._state_dec_to_imp(token)
25
31
 
26
32
  def try_new_function(self, name):
33
+ # Don't create a function for record compact constructor
34
+ if self.is_record and name == self.class_name:
35
+ self.in_record_constructor = True
36
+ self._state = self._state_record_compact_constructor
37
+ return
27
38
  self.context.try_new_function(name)
28
39
  self._state = self._state_function
40
+ if self.class_name and self.context.current_function:
41
+ self.context.current_function.name = f"{self.class_name}::{name}"
29
42
 
30
43
  def _state_global(self, token):
31
44
  if token == '@':
32
45
  self._state = self._state_decorator
33
46
  return
34
- super(JavaStates, self)._state_global(token)
47
+ if token in ("class", "record", "enum"):
48
+ self.class_name = None
49
+ self.is_record = token == "record"
50
+ self.in_record_constructor = False
51
+ self._state = self._state_class_declaration
52
+ return
53
+ if not self.in_record_constructor: # Only process as potential function if not in record constructor
54
+ super(JavaStates, self)._state_global(token)
35
55
 
36
56
  def _state_decorator(self, _):
37
57
  self._state = self._state_post_decorator
@@ -42,3 +62,28 @@ class JavaStates(CLikeStates): # pylint: disable=R0903
42
62
  else:
43
63
  self._state = self._state_global
44
64
  self._state(token)
65
+
66
+ def _state_class_declaration(self, token):
67
+ if token == '{':
68
+ self._state = self._state_global
69
+ elif token == '(': # Record parameters
70
+ self._state = self._state_record_parameters
71
+ elif token[0].isalpha():
72
+ if not self.class_name: # Only set class name if not already set
73
+ self.class_name = token
74
+
75
+ def _state_record_parameters(self, token):
76
+ if token == ')':
77
+ self._state = self._state_class_declaration
78
+
79
+ def _state_record_compact_constructor(self, token):
80
+ if token == '{':
81
+ self._state = self._state_record_constructor_body
82
+ return
83
+ self._state = self._state_global
84
+ self._state(token)
85
+
86
+ def _state_record_constructor_body(self, token):
87
+ if token == '}':
88
+ self.in_record_constructor = False
89
+ self._state = self._state_global