lizard 1.17.13__tar.gz → 1.17.15__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. {lizard-1.17.13 → lizard-1.17.15}/PKG-INFO +4 -4
  2. {lizard-1.17.13 → lizard-1.17.15}/README.rst +3 -1
  3. {lizard-1.17.13 → lizard-1.17.15}/lizard.egg-info/PKG-INFO +4 -4
  4. {lizard-1.17.13 → lizard-1.17.15}/lizard.egg-info/SOURCES.txt +4 -0
  5. {lizard-1.17.13 → lizard-1.17.15}/lizard.egg-info/entry_points.txt +0 -1
  6. {lizard-1.17.13 → lizard-1.17.15}/lizard.py +8 -11
  7. {lizard-1.17.13 → lizard-1.17.15}/lizard_ext/csvoutput.py +11 -25
  8. {lizard-1.17.13 → lizard-1.17.15}/lizard_ext/version.py +1 -1
  9. {lizard-1.17.13 → lizard-1.17.15}/lizard_languages/__init__.py +8 -0
  10. {lizard-1.17.13 → lizard-1.17.15}/lizard_languages/clike.py +2 -2
  11. {lizard-1.17.13 → lizard-1.17.15}/lizard_languages/code_reader.py +14 -7
  12. {lizard-1.17.13 → lizard-1.17.15}/lizard_languages/erlang.py +10 -6
  13. {lizard-1.17.13 → lizard-1.17.15}/lizard_languages/fortran.py +91 -47
  14. lizard-1.17.15/lizard_languages/javascript.py +19 -0
  15. {lizard-1.17.13 → lizard-1.17.15}/lizard_languages/js_style_language_states.py +20 -21
  16. lizard-1.17.15/lizard_languages/js_style_regex_expression.py +53 -0
  17. lizard-1.17.13/lizard_languages/javascript.py → lizard-1.17.15/lizard_languages/jsx.py +20 -50
  18. {lizard-1.17.13 → lizard-1.17.15}/lizard_languages/python.py +10 -6
  19. {lizard-1.17.13 → lizard-1.17.15}/lizard_languages/script_language.py +1 -1
  20. lizard-1.17.15/lizard_languages/tsx.py +24 -0
  21. lizard-1.17.15/lizard_languages/typescript.py +124 -0
  22. lizard-1.17.15/lizard_languages/vue.py +34 -0
  23. lizard-1.17.15/lizard_languages/zig.py +25 -0
  24. {lizard-1.17.13 → lizard-1.17.15}/setup.cfg +3 -0
  25. {lizard-1.17.13 → lizard-1.17.15}/test/testLanguages.py +4 -0
  26. lizard-1.17.13/lizard_languages/js_style_regex_expression.py +0 -23
  27. lizard-1.17.13/lizard_languages/typescript.py +0 -49
  28. {lizard-1.17.13 → lizard-1.17.15}/LICENSE.txt +0 -0
  29. {lizard-1.17.13 → lizard-1.17.15}/lizard.egg-info/dependency_links.txt +0 -0
  30. {lizard-1.17.13 → lizard-1.17.15}/lizard.egg-info/requires.txt +0 -0
  31. {lizard-1.17.13 → lizard-1.17.15}/lizard.egg-info/top_level.txt +0 -0
  32. {lizard-1.17.13 → lizard-1.17.15}/lizard_ext/__init__.py +0 -0
  33. {lizard-1.17.13 → lizard-1.17.15}/lizard_ext/auto_open.py +0 -0
  34. {lizard-1.17.13 → lizard-1.17.15}/lizard_ext/default_ordered_dict.py +0 -0
  35. {lizard-1.17.13 → lizard-1.17.15}/lizard_ext/extension_base.py +0 -0
  36. {lizard-1.17.13 → lizard-1.17.15}/lizard_ext/htmloutput.py +0 -0
  37. {lizard-1.17.13 → lizard-1.17.15}/lizard_ext/keywords.py +0 -0
  38. {lizard-1.17.13 → lizard-1.17.15}/lizard_ext/lizardboolcount.py +0 -0
  39. {lizard-1.17.13 → lizard-1.17.15}/lizard_ext/lizardcomplextags.py +0 -0
  40. {lizard-1.17.13 → lizard-1.17.15}/lizard_ext/lizardcpre.py +0 -0
  41. {lizard-1.17.13 → lizard-1.17.15}/lizard_ext/lizarddependencycount.py +0 -0
  42. {lizard-1.17.13 → lizard-1.17.15}/lizard_ext/lizarddumpcomments.py +0 -0
  43. {lizard-1.17.13 → lizard-1.17.15}/lizard_ext/lizardduplicate.py +0 -0
  44. {lizard-1.17.13 → lizard-1.17.15}/lizard_ext/lizardduplicated_param_list.py +0 -0
  45. {lizard-1.17.13 → lizard-1.17.15}/lizard_ext/lizardexitcount.py +0 -0
  46. {lizard-1.17.13 → lizard-1.17.15}/lizard_ext/lizardgotocount.py +0 -0
  47. {lizard-1.17.13 → lizard-1.17.15}/lizard_ext/lizardignoreassert.py +0 -0
  48. {lizard-1.17.13 → lizard-1.17.15}/lizard_ext/lizardio.py +0 -0
  49. {lizard-1.17.13 → lizard-1.17.15}/lizard_ext/lizardmccabe.py +0 -0
  50. {lizard-1.17.13 → lizard-1.17.15}/lizard_ext/lizardmodified.py +0 -0
  51. {lizard-1.17.13 → lizard-1.17.15}/lizard_ext/lizardnd.py +0 -0
  52. {lizard-1.17.13 → lizard-1.17.15}/lizard_ext/lizardnonstrict.py +0 -0
  53. {lizard-1.17.13 → lizard-1.17.15}/lizard_ext/lizardns.py +0 -0
  54. {lizard-1.17.13 → lizard-1.17.15}/lizard_ext/lizardoutside.py +0 -0
  55. {lizard-1.17.13 → lizard-1.17.15}/lizard_ext/lizardstatementcount.py +0 -0
  56. {lizard-1.17.13 → lizard-1.17.15}/lizard_ext/lizardwordcount.py +0 -0
  57. {lizard-1.17.13 → lizard-1.17.15}/lizard_ext/xmloutput.py +0 -0
  58. {lizard-1.17.13 → lizard-1.17.15}/lizard_languages/csharp.py +0 -0
  59. {lizard-1.17.13 → lizard-1.17.15}/lizard_languages/gdscript.py +0 -0
  60. {lizard-1.17.13 → lizard-1.17.15}/lizard_languages/go.py +0 -0
  61. {lizard-1.17.13 → lizard-1.17.15}/lizard_languages/golike.py +0 -0
  62. {lizard-1.17.13 → lizard-1.17.15}/lizard_languages/java.py +0 -0
  63. {lizard-1.17.13 → lizard-1.17.15}/lizard_languages/kotlin.py +0 -0
  64. {lizard-1.17.13 → lizard-1.17.15}/lizard_languages/lua.py +0 -0
  65. {lizard-1.17.13 → lizard-1.17.15}/lizard_languages/objc.py +0 -0
  66. {lizard-1.17.13 → lizard-1.17.15}/lizard_languages/php.py +0 -0
  67. {lizard-1.17.13 → lizard-1.17.15}/lizard_languages/ruby.py +0 -0
  68. {lizard-1.17.13 → lizard-1.17.15}/lizard_languages/rubylike.py +0 -0
  69. {lizard-1.17.13 → lizard-1.17.15}/lizard_languages/rust.py +0 -0
  70. {lizard-1.17.13 → lizard-1.17.15}/lizard_languages/scala.py +0 -0
  71. {lizard-1.17.13 → lizard-1.17.15}/lizard_languages/solidity.py +0 -0
  72. {lizard-1.17.13 → lizard-1.17.15}/lizard_languages/swift.py +0 -0
  73. {lizard-1.17.13 → lizard-1.17.15}/lizard_languages/tnsdl.py +0 -0
  74. {lizard-1.17.13 → lizard-1.17.15}/lizard_languages/ttcn.py +0 -0
  75. {lizard-1.17.13 → lizard-1.17.15}/setup.py +0 -0
  76. {lizard-1.17.13 → lizard-1.17.15}/test/testApplication.py +0 -0
  77. {lizard-1.17.13 → lizard-1.17.15}/test/testAssertionExtension.py +0 -0
  78. {lizard-1.17.13 → lizard-1.17.15}/test/testBasicFunctionInfo.py +0 -0
  79. {lizard-1.17.13 → lizard-1.17.15}/test/testCOutsideComplexity.py +0 -0
  80. {lizard-1.17.13 → lizard-1.17.15}/test/testCPreprocessorExtension.py +0 -0
  81. {lizard-1.17.13 → lizard-1.17.15}/test/testCommentOptions.py +0 -0
  82. {lizard-1.17.13 → lizard-1.17.15}/test/testCyclomaticComplexity.py +0 -0
  83. {lizard-1.17.13 → lizard-1.17.15}/test/testExtension.py +0 -0
  84. {lizard-1.17.13 → lizard-1.17.15}/test/testFilesFilter.py +0 -0
  85. {lizard-1.17.13 → lizard-1.17.15}/test/testFunctionDependencyCount.py +0 -0
  86. {lizard-1.17.13 → lizard-1.17.15}/test/testFunctionExitCount.py +0 -0
  87. {lizard-1.17.13 → lizard-1.17.15}/test/testFunctionGotoCount.py +0 -0
  88. {lizard-1.17.13 → lizard-1.17.15}/test/testFunctionStatementCount.py +0 -0
  89. {lizard-1.17.13 → lizard-1.17.15}/test/testHelpers.py +0 -0
  90. {lizard-1.17.13 → lizard-1.17.15}/test/testMcCabe.py +0 -0
  91. {lizard-1.17.13 → lizard-1.17.15}/test/testNestedStructures.py +0 -0
  92. {lizard-1.17.13 → lizard-1.17.15}/test/testNestingDepth.py +0 -0
  93. {lizard-1.17.13 → lizard-1.17.15}/test/testOutput.py +0 -0
  94. {lizard-1.17.13 → lizard-1.17.15}/test/testOutputCSV.py +0 -0
  95. {lizard-1.17.13 → lizard-1.17.15}/test/testOutputFile.py +0 -0
  96. {lizard-1.17.13 → lizard-1.17.15}/test/testOutputHTML.py +0 -0
  97. {lizard-1.17.13 → lizard-1.17.15}/test/testTokenizer.py +0 -0
  98. {lizard-1.17.13 → lizard-1.17.15}/test/test_analyzer.py +0 -0
  99. {lizard-1.17.13 → lizard-1.17.15}/test/test_auto_open.py +0 -0
  100. {lizard-1.17.13 → lizard-1.17.15}/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.15
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,8 @@ 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
+ - VueJS
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
-
@@ -21,7 +21,8 @@ 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
+ - VueJS
25
26
  - Objective-C
26
27
  - Swift
27
28
  - Python
@@ -37,6 +38,7 @@ A list of supported languages:
37
38
  - Kotlin
38
39
  - Solidity
39
40
  - Erlang
41
+ - Zig
40
42
 
41
43
  By default lizard will search for any source code that it knows and mix
42
44
  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.15
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,8 @@ 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
+ - VueJS
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
-
@@ -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,11 @@ 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/vue.py
71
+ lizard_languages/zig.py
68
72
  test/testApplication.py
69
73
  test/testAssertionExtension.py
70
74
  test/testBasicFunctionInfo.py
@@ -1,3 +1,2 @@
1
1
  [console_scripts]
2
2
  lizard = lizard:main
3
-
@@ -298,8 +298,7 @@ class FunctionInfo(Nesting): # pylint: disable=R0902
298
298
  return self.name.split('::')[-1]
299
299
 
300
300
  location = property(lambda self:
301
- " %(name)s@%(start_line)s-%(end_line)s@%(filename)s"
302
- % self.__dict__)
301
+ f" {self.name}@{self.start_line}-{self.end_line}@{self.filename}")
303
302
 
304
303
  parameter_count = property(lambda self: len(self.parameters))
305
304
 
@@ -572,7 +571,9 @@ class FileAnalyzer(object): # pylint: disable=R0903
572
571
  for _ in reader(tokens, reader):
573
572
  pass
574
573
  except RecursionError as e:
575
- sys.stderr.write("[skip] fail to process '%s' with RecursionError - %s\n" % (filename, e))
574
+ sys.stderr.write(
575
+ "[skip] fail to process '%s' with RecursionError - %s\n" %
576
+ (filename, e))
576
577
  return context.fileinfo
577
578
 
578
579
 
@@ -721,17 +722,13 @@ class OutputScheme(object):
721
722
  if e.get("avg_caption", None)])
722
723
 
723
724
  def clang_warning_format(self):
724
- return (
725
- "{f.filename}:{f.start_line}: warning: {f.name} has " +
726
- ", ".join([
727
- "{{f.{ext[value]}}} {caption}"
728
- .format(ext=e, caption=e['caption'].strip())
729
- for e in self.items[:-1]
730
- ]))
725
+ return ("{f.filename}:{f.start_line}: warning: {f.name} has {f.nloc} NLOC, "
726
+ "{f.cyclomatic_complexity} CCN, {f.token_count} token, {f.parameter_count} PARAM, "
727
+ "{f.length} length, {f.max_nesting_depth} ND")
731
728
 
732
729
  def msvs_warning_format(self):
733
730
  return (
734
- "{f.filename}({f.start_line}): warning: {f.name} has " +
731
+ "{f.filename}({f.start_line}): warning: {f.name} ({f.long_name}) has " +
735
732
  ", ".join([
736
733
  "{{f.{ext[value]}}} {caption}"
737
734
  .format(ext=e, caption=e['caption'].strip())
@@ -36,9 +36,9 @@ def csv_output(result, options):
36
36
  if options.verbose:
37
37
  extension_caption = ""
38
38
  for caption in extension_captions:
39
- extension_caption = "{},{}".format(extension_caption, caption)
40
- print("NLOC,CCN,token,PARAM,length,location,file,function," +
41
- "long_name,start,end{}".format(extension_caption))
39
+ extension_caption = f"{extension_caption},{caption}"
40
+ print(f"NLOC,CCN,token,PARAM,length,location,file,function," +
41
+ f"long_name,start,end{extension_caption}")
42
42
 
43
43
  for source_file in result:
44
44
  if source_file:
@@ -46,25 +46,11 @@ def csv_output(result, options):
46
46
  if source_function:
47
47
  extension_string = ''
48
48
  for variable in extension_variables:
49
- extension_string = '{},{}'.\
50
- format(extension_string,
51
- source_function.__getattribute__(variable))
52
- print('{},{},{},{},{},"{}","{}","{}","{}",{},{}{}'.format(
53
- source_function.nloc,
54
- source_function.cyclomatic_complexity,
55
- source_function.token_count,
56
- len(source_function.parameters),
57
- source_function.length,
58
- "{}@{}-{}@{}".format(
59
- source_function.name.replace("\"", "'"),
60
- source_function.start_line,
61
- source_function.end_line,
62
- source_file.filename
63
- ),
64
- source_file.filename,
65
- source_function.name.replace("\"", "'"),
66
- source_function.long_name.replace("\"", "'"),
67
- source_function.start_line,
68
- source_function.end_line,
69
- extension_string
70
- ))
49
+ extension_string = f"{extension_string},{source_function.__getattribute__(variable)}"
50
+ print(f"{source_function.nloc},{source_function.cyclomatic_complexity},"
51
+ f"{source_function.token_count},{len(source_function.parameters)},"
52
+ f'{source_function.length},"{source_function.name.replace(chr(34), chr(39))}@'
53
+ f'{source_function.start_line}-{source_function.end_line}@{source_file.filename}",'
54
+ f'"{source_file.filename}","{source_function.name.replace(chr(34), chr(39))}",'
55
+ f'"{source_function.long_name.replace(chr(34), chr(39))}",'
56
+ f"{source_function.start_line},{source_function.end_line}{extension_string}")
@@ -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.15"
@@ -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,9 @@ 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
26
+ from .vue import VueReader
23
27
 
24
28
 
25
29
  def languages():
@@ -44,6 +48,10 @@ def languages():
44
48
  KotlinReader,
45
49
  SolidityReader,
46
50
  ErlangReader,
51
+ ZigReader,
52
+ JSXReader,
53
+ TSXReader,
54
+ VueReader,
47
55
  ]
48
56
 
49
57
 
@@ -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)
@@ -8,7 +8,7 @@ from functools import reduce
8
8
  from operator import or_
9
9
 
10
10
 
11
- class CodeStateMachine(object):
11
+ class CodeStateMachine:
12
12
  """ the state machine """
13
13
  # pylint: disable=R0903
14
14
  # pylint: disable=R0902
@@ -50,6 +50,7 @@ class CodeStateMachine(object):
50
50
  self.next(self.saved_state)
51
51
  if self.callback:
52
52
  self.callback()
53
+ self.callback = None
53
54
  self.last_token = token
54
55
  if self.to_exit:
55
56
  return True
@@ -117,11 +118,13 @@ class CodeReader:
117
118
  def _generate_tokens(source, add, flags=0):
118
119
  # DO NOT put any sub groups in the regex. Good for performance
119
120
  _until_end = r"(?:\\\n|[^\n])*"
120
- combined_symbols = ["<<=", ">>=", "||", "&&", "===", "!==",
121
- "==", "!=", "<=", ">=", "->", "=>",
122
- "++", "--", '+=', '-=',
123
- "+", "-", '*', '/',
124
- '*=', '/=', '^=', '&=', '|=', "..."]
121
+ combined_symbols = [
122
+ "<<=", ">>=", "||", "&&", "===", "!==",
123
+ "==", "!=", "<=", ">=", "->", "=>",
124
+ "++", "--", '+=', '-=',
125
+ "+", "-", '*', '/',
126
+ '*=', '/=', '^=', '&=', '|=', "..."
127
+ ]
125
128
  token_pattern = re.compile(
126
129
  r"(?:" +
127
130
  r"\/\*.*?\*\/" +
@@ -171,8 +174,12 @@ class CodeReader:
171
174
  pattern = re.compile(r'\(\?[aiLmsux]+\)')
172
175
  re_flags = ''.join(opt[2:-1] for opt in pattern.findall(addition))
173
176
  flags = reduce(or_, (flag_dict[flag] for flag in re_flags), 0)
177
+ cleaned_addition = pattern.sub('', addition)
174
178
 
175
- return _generate_tokens(source_code, pattern.sub('', addition), flags=flags)
179
+ return _generate_tokens(
180
+ source_code,
181
+ cleaned_addition,
182
+ flags=flags)
176
183
 
177
184
  def __call__(self, tokens, reader):
178
185
  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)
@@ -0,0 +1,19 @@
1
+ '''
2
+ Language parser for JavaScript
3
+ '''
4
+
5
+ from .code_reader import CodeReader
6
+ from .clike import CCppCommentsMixin
7
+ from .js_style_regex_expression import js_style_regex_expression
8
+ from .js_style_language_states import JavaScriptStyleLanguageStates
9
+ from .typescript import TypeScriptReader, JSTokenizer
10
+
11
+
12
+ class JavaScriptReader(TypeScriptReader):
13
+ # pylint: disable=R0903
14
+
15
+ ext = ['js']
16
+ language_names = ['javascript', 'js']
17
+
18
+ def __init__(self, context):
19
+ super(JavaScriptReader, self).__init__(context)