lizard 1.17.12__py2.py3-none-any.whl → 1.17.14__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.12
3
+ Version: 1.17.14
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/
@@ -28,6 +28,7 @@ Classifier: Programming Language :: Python :: 3.9
28
28
  Classifier: Programming Language :: Python :: 3.10
29
29
  Classifier: Programming Language :: Python :: 3.11
30
30
  License-File: LICENSE.txt
31
+ Requires-Dist: pygments
31
32
 
32
33
  |Web Site| Lizard
33
34
  =================
@@ -52,7 +53,7 @@ A list of supported languages:
52
53
  - Java
53
54
  - C# (C Sharp)
54
55
  - JavaScript (With ES6 and JSX)
55
- - TypeScript
56
+ - TypeScript (With TSX)
56
57
  - Objective-C
57
58
  - Swift
58
59
  - Python
@@ -68,6 +69,7 @@ A list of supported languages:
68
69
  - Kotlin
69
70
  - Solidity
70
71
  - Erlang
72
+ - Zig
71
73
 
72
74
  By default lizard will search for any source code that it knows and mix
73
75
  all the results together. This might not be what you want. You can use
@@ -385,5 +387,3 @@ Lizard is also used as a plugin for fastlane to help check code complexity and s
385
387
  - `European research project FASTEN (Fine-grained Analysis of SofTware Ecosystems as Networks, <http://fasten-project.eu/)>`_
386
388
  - `for a quality analyzer <https://github.com/fasten-project/quality-analyzer>`_
387
389
 
388
-
389
-
@@ -1,4 +1,4 @@
1
- lizard.py,sha256=KR3F6F-5GzGQP0GLxjWmpRRUsLbfL-Lthtz3jWLlyPY,38576
1
+ lizard.py,sha256=WfzR6yEkclgbV2CTpDZrwWDnmNUnXyd6BIL6LR--QWk,38609
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=IGTGICiK_IJcldRGDhd_jNDohxFWJEWYOVxkemaY20Q,3051
@@ -25,26 +25,27 @@ 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=vHwwcIFibVozQB9PB9t8W0GArqtRDBM3HzpcDelMWq8,182
28
+ lizard_ext/version.py,sha256=Q_IWUX-GJQsIg-nJXStY9pJaspkNNkBE5mLUB-v3UKw,182
29
29
  lizard_ext/xmloutput.py,sha256=-cbh0he4O_X-wX56gkv9AnSPNN0qvR7FACqlBeezUS4,5609
30
- lizard_languages/__init__.py,sha256=iIbCcjN1AzmVtqCB7caRcLWQ4CdQwyT0UAiRKCkVeL0,1273
31
- lizard_languages/clike.py,sha256=YgB0dHYdQ5Ae1pN00zcstkuXl94n8Ugo-aTYUNmJr7o,10723
32
- lizard_languages/code_reader.py,sha256=KTZ7v2MtaowH118yS2sd5GKgUW3hkLWUZ8YBiX3ZsL8,6180
30
+ lizard_languages/__init__.py,sha256=PsUTjwesQ_Kk2SLsaI2Sn7ePtWLEQs2XW6EOPJJybcA,1427
31
+ lizard_languages/clike.py,sha256=Lnwkma-jEu8FNVEPqTAKPkz1Hi0T_dP7H9Jyq0Bd0kQ,10725
32
+ lizard_languages/code_reader.py,sha256=sMkHfIjZTom3d5gINfm42vUY28kTOOdxEUboc7eRMUU,6211
33
33
  lizard_languages/csharp.py,sha256=lVi-g-0JjHagqDR5r-lRdi2BuCdtR5aer9CYY-Nzw44,478
34
- lizard_languages/erlang.py,sha256=AaPfIGq_phVi2hRUVHNrrmXiQSdlEktbSVOvPxORWf8,3822
35
- lizard_languages/fortran.py,sha256=iXxS44sNJ2_h-nvJC58Pz6AGDyVx2HdBEVF-EeYGn84,7327
34
+ lizard_languages/erlang.py,sha256=7YJS2cMyXDKEV_kpH8DzBARxFCFcjKuTOPSQ3K52auU,3860
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
39
  lizard_languages/java.py,sha256=mfXCRicmZFZFxPW7QuTOQtAKzOZD3d-uh4tiALcGdX4,1186
40
- lizard_languages/javascript.py,sha256=agcEwJbrY0tFt8rGWwsO2pH-MKXvKmt9BMlcKkUB9m4,4314
40
+ lizard_languages/javascript.py,sha256=dc_P3fS39S-5sefTNKPzi7Hype7WkM3rMKONpd1iklM,4143
41
41
  lizard_languages/js_style_language_states.py,sha256=2_dgrXLe113xEdfATByioohGquW428pPo9gI3I1duS4,4257
42
42
  lizard_languages/js_style_regex_expression.py,sha256=1d4eK5RR0GBAFg2eDb2cKA_YHIYlxjhG7PXAuMOKnRA,743
43
+ lizard_languages/jsx.py,sha256=trMT1ruo6Wi3kJB0qQYJL8Ms0GFEapqD9_SaTe0vCDk,785
43
44
  lizard_languages/kotlin.py,sha256=v_o2orEzA5gB9vM_0h-E4QXjrc5Yum-0K6W6_laOThc,2844
44
45
  lizard_languages/lua.py,sha256=3nqBcunBzJrhv4Iqaf8xvbyqxZy3aSxJ-IiHimHFlac,1573
45
46
  lizard_languages/objc.py,sha256=2a1teLdaXZBtCeFiIZer1j_sVx9LZ1CbF2XfnqlvLmk,2319
46
47
  lizard_languages/php.py,sha256=8OufyR2TIWyf3bXuTmp37Vwf_tEPF4YV5M3i5_jnguA,1377
47
- lizard_languages/python.py,sha256=JDXqQ7SEnNSXlbK5sMyUKwCFBTEto20Wg8_ZkzYisSI,3721
48
+ lizard_languages/python.py,sha256=5MwhyuzUqbUkhNyzeo_YsTRp4onMUVC19t61lLnDyjc,3761
48
49
  lizard_languages/ruby.py,sha256=gUrFsaS6ZJbjb9CixBHP9n0BxGOb8HsDEg7jJ2bz_80,2187
49
50
  lizard_languages/rubylike.py,sha256=dAGZ2wqW8nqaESMU8HkeR9gwQ-q9fmZqE6AANvVZD1Q,3426
50
51
  lizard_languages/rust.py,sha256=DG2RkR9JWwcD6gIw-BPzg-Yo_lxQtSvfgHioFWIQm9o,610
@@ -53,11 +54,13 @@ lizard_languages/script_language.py,sha256=FOzB9Rg5-XTnFDeeRRyIrp2rDomRDHhaPsxsx
53
54
  lizard_languages/solidity.py,sha256=Z0GD7U5bI5eUikdy7m_iKWeFD5yXRYq4r3zycscOhJQ,553
54
55
  lizard_languages/swift.py,sha256=p8S2OAkQOx9YQ02yhoVXFkr7pMqUH1Nb3RVXPHRU_9M,2450
55
56
  lizard_languages/tnsdl.py,sha256=pGcalA_lHY362v2wwPS86seYBOOBBjvmU6vd4Yy3A9g,2803
57
+ lizard_languages/tsx.py,sha256=Ey7IxFfF2nwt-MJisEO2FaIOl47m4EPf3jF6x62YTVA,1332
56
58
  lizard_languages/ttcn.py,sha256=ygjw_raBmPF-4mgoM8m6CAdyEMpTI-n1kZJK1RL4Vxo,2131
57
- lizard_languages/typescript.py,sha256=yjUTVDkiONbg2v089pZC4wrCJSo1J5NVbQzbCfF4k6s,1547
58
- lizard-1.17.12.dist-info/LICENSE.txt,sha256=05ZjgQ8Cl1dD9p0BhW-Txzkc5rhCogGJVEuf1GT2Y_M,1303
59
- lizard-1.17.12.dist-info/METADATA,sha256=449xh2XT8PSdqHs1N-nAQVoyKRFp7bYdJGtUNVK5SMc,15379
60
- lizard-1.17.12.dist-info/WHEEL,sha256=fS9sRbCBHs7VFcwJLnLXN1MZRR0_TVTxvXKzOnaSFs8,110
61
- lizard-1.17.12.dist-info/entry_points.txt,sha256=pPMMwoHAltzGHqR2WeJQItLeeyR7pbX5R2S_POC-xoo,40
62
- lizard-1.17.12.dist-info/top_level.txt,sha256=5NTrTaOLhHuTzXaGcZPKfuaOgUv7WafNGe0Zl5aycpg,35
63
- lizard-1.17.12.dist-info/RECORD,,
59
+ lizard_languages/typescript.py,sha256=fyJeimadxFXqtfTt8MyVzAg6XqpVZeFJ1qp8RGurXbk,2594
60
+ lizard_languages/zig.py,sha256=NX1iyBstBuJFeAGBOAIaRfrmeBREne2HX6Pt4fXZZTQ,586
61
+ lizard-1.17.14.dist-info/LICENSE.txt,sha256=05ZjgQ8Cl1dD9p0BhW-Txzkc5rhCogGJVEuf1GT2Y_M,1303
62
+ lizard-1.17.14.dist-info/METADATA,sha256=RhLjrf5029-qdpfH3yGvH35sEaktWyHVmypIZHzhniA,15419
63
+ lizard-1.17.14.dist-info/WHEEL,sha256=Kh9pAotZVRFj97E15yTA4iADqXdQfIVTHcNaZTjxeGM,110
64
+ lizard-1.17.14.dist-info/entry_points.txt,sha256=ZBqPhu-J3NoGGW5vn2Gfyoo0vdVlgBgM-wlNm0SGYUQ,39
65
+ lizard-1.17.14.dist-info/top_level.txt,sha256=5NTrTaOLhHuTzXaGcZPKfuaOgUv7WafNGe0Zl5aycpg,35
66
+ lizard-1.17.14.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.44.0)
2
+ Generator: bdist_wheel (0.45.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py2-none-any
5
5
  Tag: py3-none-any
@@ -1,3 +1,2 @@
1
1
  [console_scripts]
2
2
  lizard = lizard:main
3
-
lizard.py CHANGED
@@ -572,7 +572,9 @@ class FileAnalyzer(object): # pylint: disable=R0903
572
572
  for _ in reader(tokens, reader):
573
573
  pass
574
574
  except RecursionError as e:
575
- sys.stderr.write("[skip] fail to process '%s' with RecursionError - %s\n" % (filename, e))
575
+ sys.stderr.write(
576
+ "[skip] fail to process '%s' with RecursionError - %s\n" %
577
+ (filename, e))
576
578
  return context.fileinfo
577
579
 
578
580
 
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.12"
6
+ version = "1.17.14"
@@ -1,5 +1,6 @@
1
1
  ''' programming languages of lizard '''
2
2
 
3
+ from lizard_languages.zig import ZigReader
3
4
  from .clike import CLikeReader
4
5
  from .erlang import ErlangReader
5
6
  from .java import JavaReader
@@ -20,6 +21,8 @@ from .rust import RustReader
20
21
  from .typescript import TypeScriptReader
21
22
  from .fortran import FortranReader
22
23
  from .solidity import SolidityReader
24
+ from .jsx import JSXReader
25
+ from .tsx import TSXReader
23
26
 
24
27
 
25
28
  def languages():
@@ -44,6 +47,9 @@ def languages():
44
47
  KotlinReader,
45
48
  SolidityReader,
46
49
  ErlangReader,
50
+ ZigReader,
51
+ JSXReader,
52
+ TSXReader,
47
53
  ]
48
54
 
49
55
 
lizard_languages/clike.py CHANGED
@@ -182,7 +182,7 @@ class CLikeStates(CodeStateMachine):
182
182
  self.context.add_to_function_name(' ' + token)
183
183
 
184
184
  def _state_name_with_space(self, token):
185
- self._state = self._state_operator\
185
+ self._state = self._state_operator \
186
186
  if token == 'operator' else self._state_function
187
187
  self.context.add_to_function_name(token)
188
188
 
@@ -196,7 +196,7 @@ class CLikeStates(CodeStateMachine):
196
196
  else:
197
197
  self.next(self._state_global)
198
198
  elif len(self.bracket_stack) == 1:
199
- if token != 'void': # void is a reserved keyword, meaning no parameters
199
+ if token != 'void': # void is a reserved keyword, meaning no parameters
200
200
  self.context.parameter(token)
201
201
  return
202
202
  self.context.add_to_long_function_name(token)
@@ -114,14 +114,16 @@ class CodeReader:
114
114
  if not token_class:
115
115
  token_class = create_token
116
116
 
117
- def _generate_tokens(source, add, flags=re.NOFLAG):
117
+ def _generate_tokens(source, add, flags=0):
118
118
  # DO NOT put any sub groups in the regex. Good for performance
119
119
  _until_end = r"(?:\\\n|[^\n])*"
120
- combined_symbols = ["<<=", ">>=", "||", "&&", "===", "!==",
121
- "==", "!=", "<=", ">=", "->", "=>",
122
- "++", "--", '+=', '-=',
123
- "+", "-", '*', '/',
124
- '*=', '/=', '^=', '&=', '|=', "..."]
120
+ combined_symbols = [
121
+ "<<=", ">>=", "||", "&&", "===", "!==",
122
+ "==", "!=", "<=", ">=", "->", "=>",
123
+ "++", "--", '+=', '-=',
124
+ "+", "-", '*', '/',
125
+ '*=', '/=', '^=', '&=', '|=', "..."
126
+ ]
125
127
  token_pattern = re.compile(
126
128
  r"(?:" +
127
129
  r"\/\*.*?\*\/" +
@@ -170,9 +172,13 @@ class CodeReader:
170
172
 
171
173
  pattern = re.compile(r'\(\?[aiLmsux]+\)')
172
174
  re_flags = ''.join(opt[2:-1] for opt in pattern.findall(addition))
173
- flags = reduce(or_, (flag_dict[flag] for flag in re_flags), re.NOFLAG)
175
+ flags = reduce(or_, (flag_dict[flag] for flag in re_flags), 0)
176
+ cleaned_addition = pattern.sub('', addition)
174
177
 
175
- return _generate_tokens(source_code, pattern.sub('', addition), flags=flags)
178
+ return _generate_tokens(
179
+ source_code,
180
+ cleaned_addition,
181
+ flags=flags)
176
182
 
177
183
  def __call__(self, tokens, reader):
178
184
  self.context = reader.context
@@ -26,8 +26,12 @@ class ErlangReader(CodeReader):
26
26
 
27
27
  @staticmethod
28
28
  def generate_tokens(source_code, addition='', token_class=None):
29
- return map(lambda x: x[1], filter(lambda x: x[0] != py_token.Whitespace,
30
- lex(source_code, lexer=lexers.get_lexer_by_name('erlang'))))
29
+ lexer = lexers.get_lexer_by_name('erlang')
30
+ tokens = lex(source_code, lexer=lexer)
31
+ return map(
32
+ lambda x: x[1],
33
+ filter(lambda x: x[0] != py_token.Whitespace, tokens)
34
+ )
31
35
 
32
36
 
33
37
  class ErlangStates(CodeStateMachine):
@@ -77,8 +81,8 @@ class ErlangStates(CodeStateMachine):
77
81
  if token == '-':
78
82
  self.punctuated = True
79
83
  elif token == '>' and self.punctuated:
80
- if len(self.context.stacked_functions) <= 1 or \
81
- self.context.current_function.name == 'fun':
84
+ if (len(self.context.stacked_functions) <= 1 or
85
+ self.context.current_function.name == 'fun'):
82
86
  self.next(self._state_func_first_line, token)
83
87
  else:
84
88
  self.func_match_failed(token)
@@ -93,8 +97,8 @@ class ErlangStates(CodeStateMachine):
93
97
 
94
98
  def _state_nested_end(self, token):
95
99
  if token == '.' or token == ',':
96
- if len(self.context.stacked_functions) > 1 \
97
- and self.context.stacked_functions[-1].name == 'fun':
100
+ if (len(self.context.stacked_functions) > 1 and
101
+ self.context.stacked_functions[-1].name == 'fun'):
98
102
  self.statemachine_return()
99
103
  return
100
104
 
@@ -6,57 +6,65 @@ import re
6
6
  from .code_reader import CodeStateMachine, CodeReader
7
7
 
8
8
 
9
- # pylint: disable=R0903
10
- class FortranCommentsMixin(object):
9
+ class FortranCommentsMixin:
11
10
  @staticmethod
12
11
  def get_comment_from_token(token):
13
12
  if token.startswith('!'):
14
13
  return token[1:]
15
14
 
16
15
 
17
- # pylint: disable=R0903
18
16
  class FortranReader(CodeReader, FortranCommentsMixin):
19
- ''' This is the reader for Fortran. '''
17
+ '''This is the reader for Fortran.'''
20
18
 
21
19
  ext = ['f70', 'f90', 'f95', 'f03', 'f08', 'f', 'for', 'ftn', 'fpp']
22
20
  language_names = ['fortran']
23
- _conditions = set((
21
+
22
+ # Conditions need to have all the cases because the matching is case-insensitive
23
+ # and is not done here.
24
+ _conditions = {
24
25
  'IF', 'DO', '.AND.', '.OR.', 'CASE',
25
- 'if', 'do', '.and.', '.or.', 'case'))
26
- _blocks = ['PROGRAM', 'MODULE', 'SUBROUTINE', 'FUNCTION', 'TYPE', 'INTERFACE', 'BLOCK', 'IF', 'DO', 'FORALL', 'WHERE', 'SELECT', 'ASSOCIATE']
26
+ 'if', 'do', '.and.', '.or.', 'case'
27
+ }
28
+ _blocks = [
29
+ 'PROGRAM', 'MODULE', 'SUBMODULE', 'SUBROUTINE', 'FUNCTION', 'TYPE',
30
+ 'INTERFACE', 'BLOCK', 'IF', 'DO', 'FORALL', 'WHERE', 'SELECT', 'ASSOCIATE'
31
+ ]
27
32
 
28
33
  def __init__(self, context):
29
- super(FortranReader, self).__init__(context)
34
+ super().__init__(context)
30
35
  self.macro_disabled = False
31
36
  self.parallel_states = [FortranStates(context, self)]
32
37
 
33
38
  @staticmethod
34
39
  def generate_tokens(source_code, addition='', token_class=None):
35
40
  _until_end = r'(?:\\\n|[^\n])*'
36
- return CodeReader.generate_tokens(
37
- source_code,
41
+ block_endings = '|'.join(r'END\s*{0}'.format(_) for _ in FortranReader._blocks)
42
+ # Include all patterns and the (?i) flag in addition
43
+ addition = (
38
44
  r'(?i)'
39
- r'\/\/' +
40
- r'|\#' + _until_end +
41
- r'|\!' + _until_end +
42
- r'|^\*' + _until_end +
43
- r'|\.OR\.' +
44
- r'|\.AND\.' +
45
- r'|ELSE +IF' +
46
- ''.join(r'|END[ \t]+{0}'.format(_) for _ in FortranReader._blocks) +
47
- addition,
48
- token_class)
45
+ r'\/\/|'
46
+ r'\#' + _until_end + r'|'
47
+ r'\!' + _until_end + r'|'
48
+ r'^\*' + _until_end + r'|'
49
+ r'\.OR\.|'
50
+ r'\.AND\.|'
51
+ r'ELSE\s+IF|'
52
+ r'MODULE\s+PROCEDURE|'
53
+ + block_endings + addition
54
+ )
55
+ return CodeReader.generate_tokens(
56
+ source_code, addition=addition, token_class=token_class)
49
57
 
50
58
  def preprocess(self, tokens):
51
59
  macro_depth = 0
52
60
  new_line = True
53
61
  for token in tokens:
54
- if new_line and token[0].upper() in ('c', 'C', '*'):
55
- token = '!'+token[1:]
62
+ if new_line and token[0].upper() in ('C', '*'):
63
+ token = '!' + token[1:]
56
64
  new_line = token == '\n'
57
- macro = re.match(r'#\s*(\w+)', token)
58
- if macro:
59
- macro = macro.group(1).lower()
65
+ macro_match = re.match(r'#\s*(\w+)', token)
66
+ if macro_match:
67
+ macro = macro_match.group(1).lower()
60
68
  if macro in ('if', 'ifdef', 'ifndef', 'elif'):
61
69
  self.context.add_condition()
62
70
  if macro_depth > 0:
@@ -66,22 +74,29 @@ class FortranReader(CodeReader, FortranCommentsMixin):
66
74
  macro_depth -= 1
67
75
  elif macro in ('else', 'elif'):
68
76
  macro_depth += 1
69
- # In order to don't mess the nesting,
70
- # only the first branch of #if #elif #else
71
- # is read by the FortranStateMachine
77
+ # Only the first branch of #if #elif #else is read
72
78
  self.macro_disabled = macro_depth != 0
73
79
  elif not token.isspace() or token == '\n':
74
80
  yield token
75
81
 
76
- # pylint: disable=R0903
82
+
77
83
  class FortranStates(CodeStateMachine):
78
- # pylint: disable=line-too-long
79
- # pylint: disable=protected-access
80
- _ends = re.compile('(?:'+'|'.join(r'END\s*{0}'.format(_) for _ in FortranReader._blocks)+')', re.I)
84
+ _ends = re.compile(
85
+ '|'.join(r'END\s*{0}'.format(_) for _ in FortranReader._blocks), re.I)
86
+
87
+ # Define token groups to eliminate duplication
88
+ IGNORE_NEXT_TOKENS = {'%', '::', 'SAVE', 'DATA'}
89
+ IGNORE_VAR_TOKENS = {'INTEGER', 'REAL', 'COMPLEX', 'LOGICAL', 'CHARACTER'}
90
+ RESET_STATE_TOKENS = {'RECURSIVE', 'ELEMENTAL'}
91
+ FUNCTION_NAME_TOKENS = {'SUBROUTINE', 'FUNCTION'}
92
+ NESTING_KEYWORDS = {'FORALL', 'WHERE', 'SELECT', 'INTERFACE', 'ASSOCIATE'}
93
+ PROCEDURE_TOKENS = {'PROCEDURE', 'MODULE PROCEDURE'}
81
94
 
82
95
  def __init__(self, context, reader):
83
- super(FortranStates, self).__init__(context)
96
+ super().__init__(context)
84
97
  self.reader = reader
98
+ self.last_token = None
99
+ self.in_interface = False
85
100
 
86
101
  def __call__(self, token, reader=None):
87
102
  if self.reader.macro_disabled:
@@ -96,28 +111,35 @@ class FortranStates(CodeStateMachine):
96
111
 
97
112
  def _state_global(self, token):
98
113
  token_upper = token.upper()
99
- if token_upper in ('%', '::', 'SAVE', 'DATA'):
114
+ if token_upper in self.IGNORE_NEXT_TOKENS:
100
115
  self._state = self._ignore_next
101
- elif token_upper in ('INTEGER', 'REAL','COMPLEX','LOGICAL', 'CHARACTER'):
116
+ elif token_upper in self.IGNORE_VAR_TOKENS:
102
117
  self._state = self._ignore_var
103
118
  elif token == '(':
104
119
  self.next(self._ignore_expr, token)
105
- elif token_upper in ('PROGRAM',):
120
+ elif token_upper in self.RESET_STATE_TOKENS:
121
+ self.reset_state()
122
+ elif token_upper in self.FUNCTION_NAME_TOKENS:
123
+ self._state = self._function_name
124
+ elif token_upper == 'PROGRAM':
106
125
  self._state = self._namespace
107
126
  elif token_upper == 'MODULE':
127
+ self._state = self._module_or_procedure
128
+ elif token_upper == 'SUBMODULE':
108
129
  self._state = self._module
109
- elif token_upper in ('SUBROUTINE', 'FUNCTION'):
110
- self._state = self._function_name
130
+ self._module(token)
111
131
  elif token_upper == 'TYPE':
112
132
  self._state = self._type
113
133
  elif token_upper == 'IF':
114
134
  self._state = self._if
115
- elif token_upper in ('BLOCK',):
135
+ elif token_upper == 'BLOCK':
116
136
  self._state = self._ignore_if_paren
117
- elif token_upper in ('DO',):
137
+ elif token_upper == 'DO':
118
138
  self._state = self._ignore_if_label
119
- elif token_upper in ('FORALL', 'WHERE', 'SELECT', 'INTERFACE', 'ASSOCIATE'):
139
+ elif token_upper in self.NESTING_KEYWORDS:
120
140
  self.context.add_bare_nesting()
141
+ if token_upper == 'INTERFACE':
142
+ self.in_interface = True
121
143
  elif token_upper == 'ELSE':
122
144
  self.context.pop_nesting()
123
145
  self.context.add_bare_nesting()
@@ -127,6 +149,9 @@ class FortranStates(CodeStateMachine):
127
149
  self.context.add_condition()
128
150
  self._state = self._if
129
151
  elif token_upper == 'END' or self._ends.match(token):
152
+ end_token_upper = token_upper.replace(' ', '')
153
+ if end_token_upper.startswith('ENDINTERFACE'):
154
+ self.in_interface = False
130
155
  self.context.pop_nesting()
131
156
 
132
157
  def reset_state(self, token=None):
@@ -134,12 +159,11 @@ class FortranStates(CodeStateMachine):
134
159
  if token is not None:
135
160
  self._state_global(token)
136
161
 
137
- # pylint: disable=unused-argument
138
162
  def _ignore_next(self, token):
139
163
  self.reset_state()
140
164
 
141
165
  def _ignore_var(self, token):
142
- if token.upper() in ('SUBROUTINE', 'FUNCTION'):
166
+ if token.upper() in self.FUNCTION_NAME_TOKENS:
143
167
  self.reset_state(token)
144
168
  else:
145
169
  self.reset_state()
@@ -152,7 +176,7 @@ class FortranStates(CodeStateMachine):
152
176
  self.reset_state()
153
177
 
154
178
  def _ignore_if_label(self, token):
155
- if all(char in "0123456789" for char in token):
179
+ if token.isdigit():
156
180
  self.reset_state()
157
181
  else:
158
182
  self.context.add_bare_nesting()
@@ -184,11 +208,24 @@ class FortranStates(CodeStateMachine):
184
208
  self.reset_state(token)
185
209
 
186
210
  def _module(self, token):
187
- if token.upper() == 'PROCEDURE':
188
- self.reset_state()
211
+ if token.upper() in self.FUNCTION_NAME_TOKENS:
212
+ self._state = self._function_name
213
+ elif token.upper() in self.PROCEDURE_TOKENS:
214
+ self._state = self._procedure
189
215
  else:
190
216
  self._namespace(token)
191
217
 
218
+ def _procedure(self, token):
219
+ # Start a new function regardless of context
220
+ if self.last_token and self.last_token.upper() == 'MODULE':
221
+ # For "module procedure" case, use the current token as function name
222
+ self.context.restart_new_function(token)
223
+ else:
224
+ # For standalone "procedure" case
225
+ self.context.restart_new_function(token)
226
+ self.context.add_bare_nesting()
227
+ self.reset_state()
228
+
192
229
  def _type(self, token):
193
230
  if token in (',', '::') or token[0].isalpha():
194
231
  self._namespace(token)
@@ -210,8 +247,15 @@ class FortranStates(CodeStateMachine):
210
247
  pass
211
248
 
212
249
  def _if_then(self, token):
213
- if token.upper() == 'THEN':
250
+ token_upper = token.upper()
251
+ if token_upper == 'THEN':
214
252
  self.context.add_bare_nesting()
215
253
  self.reset_state()
216
254
  else:
217
255
  self.reset_state(token)
256
+
257
+ def _module_or_procedure(self, token):
258
+ if token.upper() == 'PROCEDURE':
259
+ self._state = self._procedure
260
+ else:
261
+ self._module(token)
@@ -11,7 +11,7 @@ from .js_style_language_states import JavaScriptStyleLanguageStates
11
11
  class JavaScriptReader(CodeReader, CCppCommentsMixin):
12
12
  # pylint: disable=R0903
13
13
 
14
- ext = ['js', 'jsx']
14
+ ext = ['js']
15
15
  language_names = ['javascript', 'js']
16
16
 
17
17
  @staticmethod
@@ -19,7 +19,6 @@ class JavaScriptReader(CodeReader, CCppCommentsMixin):
19
19
  def generate_tokens(source_code, addition='', token_class=None):
20
20
  addition = addition +\
21
21
  r"|(?:\$\w+)" + \
22
- r"|(?:\<\/\w+\>)" + \
23
22
  r"|`.*?`"
24
23
  js_tokenizer = JSTokenizer()
25
24
  for token in CodeReader.generate_tokens(
@@ -69,9 +68,6 @@ class JSTokenizer(Tokenizer):
69
68
  self.depth -= 1
70
69
  if self.depth == 0:
71
70
  self.stop()
72
- # {} in JSX is not listed as token
73
- # otherwise it will be regarded
74
- # as JS object
75
71
  return
76
72
  yield token
77
73
 
@@ -0,0 +1,27 @@
1
+ '''
2
+ Language parser for JSX
3
+ '''
4
+
5
+ from .javascript import JavaScriptReader, JSTokenizer, XMLTagWithAttrTokenizer, isidentifier
6
+ from .code_reader import CodeReader
7
+ from .js_style_regex_expression import js_style_regex_expression
8
+
9
+
10
+ class JSXReader(JavaScriptReader):
11
+ # pylint: disable=R0903
12
+
13
+ ext = ['jsx']
14
+ language_names = ['jsx']
15
+
16
+ @staticmethod
17
+ @js_style_regex_expression
18
+ def generate_tokens(source_code, addition='', token_class=None):
19
+ addition = addition +\
20
+ r"|(?:\$\w+)" + \
21
+ r"|(?:\<\/\w+\>)" + \
22
+ r"|`.*?`"
23
+ js_tokenizer = JSTokenizer()
24
+ for token in CodeReader.generate_tokens(
25
+ source_code, addition, token_class):
26
+ for tok in js_tokenizer(token):
27
+ yield tok
@@ -13,7 +13,7 @@ class PythonIndents: # pylint: disable=R0902
13
13
  self.indents = [0]
14
14
  self.context = context
15
15
 
16
- def set_nesting(self, spaces, token = ""):
16
+ def set_nesting(self, spaces, token=""):
17
17
  while self.indents[-1] > spaces and (not token.startswith(")")):
18
18
  self.indents.pop()
19
19
  self.context.pop_nesting()
@@ -29,8 +29,10 @@ class PythonReader(CodeReader, ScriptLanguageMixIn):
29
29
 
30
30
  ext = ['py']
31
31
  language_names = ['python']
32
- _conditions = set(['if', 'for', 'while', 'and', 'or',
33
- 'elif', 'except', 'finally'])
32
+ _conditions = set([
33
+ 'if', 'for', 'while', 'and', 'or',
34
+ 'elif', 'except', 'finally'
35
+ ])
34
36
 
35
37
  def __init__(self, context):
36
38
  super(PythonReader, self).__init__(context)
@@ -39,8 +41,9 @@ class PythonReader(CodeReader, ScriptLanguageMixIn):
39
41
  @staticmethod
40
42
  def generate_tokens(source_code, addition='', token_class=None):
41
43
  return ScriptLanguageMixIn.generate_common_tokens(
42
- source_code,
43
- r"|\'\'\'.*?\'\'\'" + r'|\"\"\".*?\"\"\"', token_class)
44
+ source_code,
45
+ r"|\'\'\'.*?\'\'\'" + r'|\"\"\".*?\"\"\"',
46
+ token_class)
44
47
 
45
48
  def preprocess(self, tokens):
46
49
  indents = PythonIndents(self.context)
@@ -54,7 +57,8 @@ class PythonReader(CodeReader, ScriptLanguageMixIn):
54
57
  else:
55
58
  if not token.startswith('#'):
56
59
  current_function = self.context.current_function
57
- if current_function.name == '*global*' or current_function.long_name.endswith(')'):
60
+ if (current_function.name == '*global*' or
61
+ current_function.long_name.endswith(')')):
58
62
  indents.set_nesting(current_leading_spaces, token)
59
63
  reading_leading_space = False
60
64
  else:
@@ -0,0 +1,44 @@
1
+ '''
2
+ Language parser for TSX
3
+ '''
4
+
5
+ from .typescript import TypeScriptReader, TypeScriptStates
6
+ from .javascript import JSTokenizer, XMLTagWithAttrTokenizer, isidentifier
7
+ from .code_reader import CodeReader
8
+ from .js_style_regex_expression import js_style_regex_expression
9
+
10
+
11
+ class TSXReader(TypeScriptReader):
12
+ # pylint: disable=R0903
13
+
14
+ ext = ['tsx']
15
+ language_names = ['tsx']
16
+
17
+ @staticmethod
18
+ @js_style_regex_expression
19
+ def generate_tokens(source_code, addition='', token_class=None):
20
+ addition = addition +\
21
+ r"|(?:\$\w+)" + \
22
+ r"|(?:\<\/\w+\>)" + \
23
+ r"|`.*?`"
24
+ js_tokenizer = JSTokenizer()
25
+ for token in CodeReader.generate_tokens(
26
+ source_code, addition, token_class):
27
+ for tok in js_tokenizer(token):
28
+ yield tok
29
+
30
+ def __init__(self, context):
31
+ super(TSXReader, self).__init__(context)
32
+ self.parallel_states = [TSXStates(context)]
33
+
34
+
35
+ class TSXStates(TypeScriptStates):
36
+ def _expecting_func_opening_bracket(self, token):
37
+ if token == '<':
38
+ self.next(self._expecting_jsx)
39
+ return
40
+ super(TSXStates, self)._expecting_func_opening_bracket(token)
41
+
42
+ def _expecting_jsx(self, token):
43
+ if token == '>':
44
+ self.next(self._expecting_func_opening_bracket)
@@ -31,6 +31,30 @@ class TypeScriptReader(CodeReader, CCppCommentsMixin):
31
31
 
32
32
  class TypeScriptStates(JavaScriptStyleLanguageStates):
33
33
 
34
+ def _state_global(self, token):
35
+ if token == ':':
36
+ # When we see a type annotation in global state, store the last tokens
37
+ # but don't treat it as a function name yet
38
+ self._potential_name = self.last_tokens
39
+ self.next(self._type_annotation)
40
+ return
41
+ if token == '=>':
42
+ # For arrow functions, we want to treat them as anonymous
43
+ self.function_name = ''
44
+ self._state = self._arrow_function
45
+ return
46
+ super(TypeScriptStates, self)._state_global(token)
47
+
48
+ def _type_annotation(self, token):
49
+ if token == '=':
50
+ # We're back to an assignment, restore the potential name
51
+ if hasattr(self, '_potential_name'):
52
+ self.last_tokens = self._potential_name
53
+ delattr(self, '_potential_name')
54
+ self.next(self._state_global, token)
55
+ else:
56
+ self.next(self._type_annotation)
57
+
34
58
  def _expecting_func_opening_bracket(self, token):
35
59
  if token == ':':
36
60
  self.next(self._expecting_default)
@@ -47,3 +71,5 @@ class TypeScriptStates(JavaScriptStyleLanguageStates):
47
71
  self.next(self._state_global)
48
72
  elif token == '{':
49
73
  self.next(self._expecting_func_opening_bracket, token)
74
+ elif token == '=':
75
+ self.next(self._state_global, token)
@@ -0,0 +1,25 @@
1
+ """
2
+ Language parser for Zig
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ from .clike import CCppCommentsMixin
8
+ from .code_reader import CodeReader
9
+ from .golike import GoLikeStates
10
+
11
+
12
+ class ZigReader(CodeReader, CCppCommentsMixin):
13
+ ext = ["zig"]
14
+ language_names = ["zig"]
15
+ _conditions = {"if", "for", "while", "and", "or", "orelse", "try", "catch", "=>"}
16
+
17
+ def __init__(self, context):
18
+ super().__init__(context)
19
+ self.parallel_states = [ZigStates(context)]
20
+
21
+
22
+ class ZigStates(GoLikeStates):
23
+ FUNC_KEYWORD = "fn"
24
+
25
+ _type_definition = GoLikeStates._state_global