lizard 1.17.13__tar.gz → 1.17.14__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 (97) hide show
  1. {lizard-1.17.13 → lizard-1.17.14}/PKG-INFO +3 -4
  2. {lizard-1.17.13 → lizard-1.17.14}/README.rst +2 -1
  3. {lizard-1.17.13 → lizard-1.17.14}/lizard.egg-info/PKG-INFO +3 -4
  4. {lizard-1.17.13 → lizard-1.17.14}/lizard.egg-info/SOURCES.txt +3 -0
  5. {lizard-1.17.13 → lizard-1.17.14}/lizard.egg-info/entry_points.txt +0 -1
  6. {lizard-1.17.13 → lizard-1.17.14}/lizard.py +3 -1
  7. {lizard-1.17.13 → lizard-1.17.14}/lizard_ext/version.py +1 -1
  8. {lizard-1.17.13 → lizard-1.17.14}/lizard_languages/__init__.py +6 -0
  9. {lizard-1.17.13 → lizard-1.17.14}/lizard_languages/clike.py +2 -2
  10. {lizard-1.17.13 → lizard-1.17.14}/lizard_languages/code_reader.py +12 -6
  11. {lizard-1.17.13 → lizard-1.17.14}/lizard_languages/erlang.py +10 -6
  12. {lizard-1.17.13 → lizard-1.17.14}/lizard_languages/fortran.py +91 -47
  13. {lizard-1.17.13 → lizard-1.17.14}/lizard_languages/javascript.py +1 -5
  14. lizard-1.17.14/lizard_languages/jsx.py +27 -0
  15. {lizard-1.17.13 → lizard-1.17.14}/lizard_languages/python.py +10 -6
  16. lizard-1.17.14/lizard_languages/tsx.py +44 -0
  17. {lizard-1.17.13 → lizard-1.17.14}/lizard_languages/typescript.py +26 -0
  18. lizard-1.17.14/lizard_languages/zig.py +25 -0
  19. {lizard-1.17.13 → lizard-1.17.14}/setup.cfg +3 -0
  20. {lizard-1.17.13 → lizard-1.17.14}/test/testLanguages.py +4 -0
  21. {lizard-1.17.13 → lizard-1.17.14}/LICENSE.txt +0 -0
  22. {lizard-1.17.13 → lizard-1.17.14}/lizard.egg-info/dependency_links.txt +0 -0
  23. {lizard-1.17.13 → lizard-1.17.14}/lizard.egg-info/requires.txt +0 -0
  24. {lizard-1.17.13 → lizard-1.17.14}/lizard.egg-info/top_level.txt +0 -0
  25. {lizard-1.17.13 → lizard-1.17.14}/lizard_ext/__init__.py +0 -0
  26. {lizard-1.17.13 → lizard-1.17.14}/lizard_ext/auto_open.py +0 -0
  27. {lizard-1.17.13 → lizard-1.17.14}/lizard_ext/csvoutput.py +0 -0
  28. {lizard-1.17.13 → lizard-1.17.14}/lizard_ext/default_ordered_dict.py +0 -0
  29. {lizard-1.17.13 → lizard-1.17.14}/lizard_ext/extension_base.py +0 -0
  30. {lizard-1.17.13 → lizard-1.17.14}/lizard_ext/htmloutput.py +0 -0
  31. {lizard-1.17.13 → lizard-1.17.14}/lizard_ext/keywords.py +0 -0
  32. {lizard-1.17.13 → lizard-1.17.14}/lizard_ext/lizardboolcount.py +0 -0
  33. {lizard-1.17.13 → lizard-1.17.14}/lizard_ext/lizardcomplextags.py +0 -0
  34. {lizard-1.17.13 → lizard-1.17.14}/lizard_ext/lizardcpre.py +0 -0
  35. {lizard-1.17.13 → lizard-1.17.14}/lizard_ext/lizarddependencycount.py +0 -0
  36. {lizard-1.17.13 → lizard-1.17.14}/lizard_ext/lizarddumpcomments.py +0 -0
  37. {lizard-1.17.13 → lizard-1.17.14}/lizard_ext/lizardduplicate.py +0 -0
  38. {lizard-1.17.13 → lizard-1.17.14}/lizard_ext/lizardduplicated_param_list.py +0 -0
  39. {lizard-1.17.13 → lizard-1.17.14}/lizard_ext/lizardexitcount.py +0 -0
  40. {lizard-1.17.13 → lizard-1.17.14}/lizard_ext/lizardgotocount.py +0 -0
  41. {lizard-1.17.13 → lizard-1.17.14}/lizard_ext/lizardignoreassert.py +0 -0
  42. {lizard-1.17.13 → lizard-1.17.14}/lizard_ext/lizardio.py +0 -0
  43. {lizard-1.17.13 → lizard-1.17.14}/lizard_ext/lizardmccabe.py +0 -0
  44. {lizard-1.17.13 → lizard-1.17.14}/lizard_ext/lizardmodified.py +0 -0
  45. {lizard-1.17.13 → lizard-1.17.14}/lizard_ext/lizardnd.py +0 -0
  46. {lizard-1.17.13 → lizard-1.17.14}/lizard_ext/lizardnonstrict.py +0 -0
  47. {lizard-1.17.13 → lizard-1.17.14}/lizard_ext/lizardns.py +0 -0
  48. {lizard-1.17.13 → lizard-1.17.14}/lizard_ext/lizardoutside.py +0 -0
  49. {lizard-1.17.13 → lizard-1.17.14}/lizard_ext/lizardstatementcount.py +0 -0
  50. {lizard-1.17.13 → lizard-1.17.14}/lizard_ext/lizardwordcount.py +0 -0
  51. {lizard-1.17.13 → lizard-1.17.14}/lizard_ext/xmloutput.py +0 -0
  52. {lizard-1.17.13 → lizard-1.17.14}/lizard_languages/csharp.py +0 -0
  53. {lizard-1.17.13 → lizard-1.17.14}/lizard_languages/gdscript.py +0 -0
  54. {lizard-1.17.13 → lizard-1.17.14}/lizard_languages/go.py +0 -0
  55. {lizard-1.17.13 → lizard-1.17.14}/lizard_languages/golike.py +0 -0
  56. {lizard-1.17.13 → lizard-1.17.14}/lizard_languages/java.py +0 -0
  57. {lizard-1.17.13 → lizard-1.17.14}/lizard_languages/js_style_language_states.py +0 -0
  58. {lizard-1.17.13 → lizard-1.17.14}/lizard_languages/js_style_regex_expression.py +0 -0
  59. {lizard-1.17.13 → lizard-1.17.14}/lizard_languages/kotlin.py +0 -0
  60. {lizard-1.17.13 → lizard-1.17.14}/lizard_languages/lua.py +0 -0
  61. {lizard-1.17.13 → lizard-1.17.14}/lizard_languages/objc.py +0 -0
  62. {lizard-1.17.13 → lizard-1.17.14}/lizard_languages/php.py +0 -0
  63. {lizard-1.17.13 → lizard-1.17.14}/lizard_languages/ruby.py +0 -0
  64. {lizard-1.17.13 → lizard-1.17.14}/lizard_languages/rubylike.py +0 -0
  65. {lizard-1.17.13 → lizard-1.17.14}/lizard_languages/rust.py +0 -0
  66. {lizard-1.17.13 → lizard-1.17.14}/lizard_languages/scala.py +0 -0
  67. {lizard-1.17.13 → lizard-1.17.14}/lizard_languages/script_language.py +0 -0
  68. {lizard-1.17.13 → lizard-1.17.14}/lizard_languages/solidity.py +0 -0
  69. {lizard-1.17.13 → lizard-1.17.14}/lizard_languages/swift.py +0 -0
  70. {lizard-1.17.13 → lizard-1.17.14}/lizard_languages/tnsdl.py +0 -0
  71. {lizard-1.17.13 → lizard-1.17.14}/lizard_languages/ttcn.py +0 -0
  72. {lizard-1.17.13 → lizard-1.17.14}/setup.py +0 -0
  73. {lizard-1.17.13 → lizard-1.17.14}/test/testApplication.py +0 -0
  74. {lizard-1.17.13 → lizard-1.17.14}/test/testAssertionExtension.py +0 -0
  75. {lizard-1.17.13 → lizard-1.17.14}/test/testBasicFunctionInfo.py +0 -0
  76. {lizard-1.17.13 → lizard-1.17.14}/test/testCOutsideComplexity.py +0 -0
  77. {lizard-1.17.13 → lizard-1.17.14}/test/testCPreprocessorExtension.py +0 -0
  78. {lizard-1.17.13 → lizard-1.17.14}/test/testCommentOptions.py +0 -0
  79. {lizard-1.17.13 → lizard-1.17.14}/test/testCyclomaticComplexity.py +0 -0
  80. {lizard-1.17.13 → lizard-1.17.14}/test/testExtension.py +0 -0
  81. {lizard-1.17.13 → lizard-1.17.14}/test/testFilesFilter.py +0 -0
  82. {lizard-1.17.13 → lizard-1.17.14}/test/testFunctionDependencyCount.py +0 -0
  83. {lizard-1.17.13 → lizard-1.17.14}/test/testFunctionExitCount.py +0 -0
  84. {lizard-1.17.13 → lizard-1.17.14}/test/testFunctionGotoCount.py +0 -0
  85. {lizard-1.17.13 → lizard-1.17.14}/test/testFunctionStatementCount.py +0 -0
  86. {lizard-1.17.13 → lizard-1.17.14}/test/testHelpers.py +0 -0
  87. {lizard-1.17.13 → lizard-1.17.14}/test/testMcCabe.py +0 -0
  88. {lizard-1.17.13 → lizard-1.17.14}/test/testNestedStructures.py +0 -0
  89. {lizard-1.17.13 → lizard-1.17.14}/test/testNestingDepth.py +0 -0
  90. {lizard-1.17.13 → lizard-1.17.14}/test/testOutput.py +0 -0
  91. {lizard-1.17.13 → lizard-1.17.14}/test/testOutputCSV.py +0 -0
  92. {lizard-1.17.13 → lizard-1.17.14}/test/testOutputFile.py +0 -0
  93. {lizard-1.17.13 → lizard-1.17.14}/test/testOutputHTML.py +0 -0
  94. {lizard-1.17.13 → lizard-1.17.14}/test/testTokenizer.py +0 -0
  95. {lizard-1.17.13 → lizard-1.17.14}/test/test_analyzer.py +0 -0
  96. {lizard-1.17.13 → lizard-1.17.14}/test/test_auto_open.py +0 -0
  97. {lizard-1.17.13 → lizard-1.17.14}/test/test_options.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lizard
3
- Version: 1.17.13
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/
@@ -52,7 +52,7 @@ A list of supported languages:
52
52
  - Java
53
53
  - C# (C Sharp)
54
54
  - JavaScript (With ES6 and JSX)
55
- - TypeScript
55
+ - TypeScript (With TSX)
56
56
  - Objective-C
57
57
  - Swift
58
58
  - Python
@@ -68,6 +68,7 @@ A list of supported languages:
68
68
  - Kotlin
69
69
  - Solidity
70
70
  - Erlang
71
+ - Zig
71
72
 
72
73
  By default lizard will search for any source code that it knows and mix
73
74
  all the results together. This might not be what you want. You can use
@@ -385,5 +386,3 @@ Lizard is also used as a plugin for fastlane to help check code complexity and s
385
386
  - `European research project FASTEN (Fine-grained Analysis of SofTware Ecosystems as Networks, <http://fasten-project.eu/)>`_
386
387
  - `for a quality analyzer <https://github.com/fasten-project/quality-analyzer>`_
387
388
 
388
-
389
-
@@ -21,7 +21,7 @@ A list of supported languages:
21
21
  - Java
22
22
  - C# (C Sharp)
23
23
  - JavaScript (With ES6 and JSX)
24
- - TypeScript
24
+ - TypeScript (With TSX)
25
25
  - Objective-C
26
26
  - Swift
27
27
  - Python
@@ -37,6 +37,7 @@ A list of supported languages:
37
37
  - Kotlin
38
38
  - Solidity
39
39
  - Erlang
40
+ - Zig
40
41
 
41
42
  By default lizard will search for any source code that it knows and mix
42
43
  all the results together. This might not be what you want. You can use
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lizard
3
- Version: 1.17.13
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/
@@ -52,7 +52,7 @@ A list of supported languages:
52
52
  - Java
53
53
  - C# (C Sharp)
54
54
  - JavaScript (With ES6 and JSX)
55
- - TypeScript
55
+ - TypeScript (With TSX)
56
56
  - Objective-C
57
57
  - Swift
58
58
  - Python
@@ -68,6 +68,7 @@ A list of supported languages:
68
68
  - Kotlin
69
69
  - Solidity
70
70
  - Erlang
71
+ - Zig
71
72
 
72
73
  By default lizard will search for any source code that it knows and mix
73
74
  all the results together. This might not be what you want. You can use
@@ -385,5 +386,3 @@ Lizard is also used as a plugin for fastlane to help check code complexity and s
385
386
  - `European research project FASTEN (Fine-grained Analysis of SofTware Ecosystems as Networks, <http://fasten-project.eu/)>`_
386
387
  - `for a quality analyzer <https://github.com/fasten-project/quality-analyzer>`_
387
388
 
388
-
389
-
@@ -50,6 +50,7 @@ lizard_languages/java.py
50
50
  lizard_languages/javascript.py
51
51
  lizard_languages/js_style_language_states.py
52
52
  lizard_languages/js_style_regex_expression.py
53
+ lizard_languages/jsx.py
53
54
  lizard_languages/kotlin.py
54
55
  lizard_languages/lua.py
55
56
  lizard_languages/objc.py
@@ -63,8 +64,10 @@ lizard_languages/script_language.py
63
64
  lizard_languages/solidity.py
64
65
  lizard_languages/swift.py
65
66
  lizard_languages/tnsdl.py
67
+ lizard_languages/tsx.py
66
68
  lizard_languages/ttcn.py
67
69
  lizard_languages/typescript.py
70
+ lizard_languages/zig.py
68
71
  test/testApplication.py
69
72
  test/testAssertionExtension.py
70
73
  test/testBasicFunctionInfo.py
@@ -1,3 +1,2 @@
1
1
  [console_scripts]
2
2
  lizard = lizard:main
3
-
@@ -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
 
@@ -3,4 +3,4 @@
3
3
  #
4
4
  # pylint: disable=missing-docstring,invalid-name
5
5
 
6
- version = "1.17.13"
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
 
@@ -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)
@@ -117,11 +117,13 @@ class CodeReader:
117
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"\/\*.*?\*\/" +
@@ -171,8 +173,12 @@ class CodeReader:
171
173
  pattern = re.compile(r'\(\?[aiLmsux]+\)')
172
174
  re_flags = ''.join(opt[2:-1] for opt in pattern.findall(addition))
173
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
@@ -4,6 +4,9 @@ universal = 1
4
4
  [tool:pytest]
5
5
  python_files = test*
6
6
 
7
+ [pycodestyle]
8
+ max-line-length = 120
9
+
7
10
  [egg_info]
8
11
  tag_build =
9
12
  tag_date = 0
@@ -1,6 +1,7 @@
1
1
  import unittest
2
2
  from lizard_languages import get_reader_for, CLikeReader, JavaReader, ObjCReader, JavaScriptReader, ScalaReader,\
3
3
  GDScriptReader, SolidityReader, ErlangReader
4
+ from lizard_languages.zig import ZigReader
4
5
 
5
6
 
6
7
  class TestLanguageChooser(unittest.TestCase):
@@ -36,3 +37,6 @@ class TestLanguageChooser(unittest.TestCase):
36
37
 
37
38
  def test_erlang(self):
38
39
  self.assertEqual(ErlangReader, get_reader_for("a.erl"))
40
+
41
+ def test_zig(self):
42
+ self.assertEqual(ZigReader, get_reader_for("a.zig"))
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