lizard 1.17.14__tar.gz → 1.17.16__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.
- {lizard-1.17.14 → lizard-1.17.16}/PKG-INFO +9 -1
- {lizard-1.17.14 → lizard-1.17.16}/README.rst +8 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard.egg-info/PKG-INFO +9 -1
- {lizard-1.17.14 → lizard-1.17.16}/lizard.egg-info/SOURCES.txt +1 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard.egg-info/requires.txt +1 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard.py +37 -12
- {lizard-1.17.14 → lizard-1.17.16}/lizard_ext/csvoutput.py +11 -25
- {lizard-1.17.14 → lizard-1.17.16}/lizard_ext/version.py +1 -1
- {lizard-1.17.14 → lizard-1.17.16}/lizard_languages/__init__.py +2 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_languages/code_reader.py +2 -1
- lizard-1.17.16/lizard_languages/csharp.py +62 -0
- lizard-1.17.16/lizard_languages/java.py +89 -0
- lizard-1.17.16/lizard_languages/javascript.py +19 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_languages/js_style_language_states.py +20 -21
- lizard-1.17.16/lizard_languages/js_style_regex_expression.py +53 -0
- lizard-1.17.14/lizard_languages/javascript.py → lizard-1.17.16/lizard_languages/jsx.py +21 -47
- {lizard-1.17.14 → lizard-1.17.16}/lizard_languages/script_language.py +1 -1
- lizard-1.17.16/lizard_languages/tsx.py +24 -0
- lizard-1.17.16/lizard_languages/typescript.py +124 -0
- lizard-1.17.16/lizard_languages/vue.py +34 -0
- {lizard-1.17.14 → lizard-1.17.16}/setup.py +1 -1
- {lizard-1.17.14 → lizard-1.17.16}/test/testFilesFilter.py +31 -0
- {lizard-1.17.14 → lizard-1.17.16}/test/testOutput.py +1 -1
- lizard-1.17.16/test/testOutputFile.py +117 -0
- lizard-1.17.14/lizard_languages/csharp.py +0 -20
- lizard-1.17.14/lizard_languages/java.py +0 -44
- lizard-1.17.14/lizard_languages/js_style_regex_expression.py +0 -23
- lizard-1.17.14/lizard_languages/jsx.py +0 -27
- lizard-1.17.14/lizard_languages/tsx.py +0 -44
- lizard-1.17.14/lizard_languages/typescript.py +0 -75
- lizard-1.17.14/test/testOutputFile.py +0 -58
- {lizard-1.17.14 → lizard-1.17.16}/LICENSE.txt +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard.egg-info/dependency_links.txt +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard.egg-info/entry_points.txt +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard.egg-info/top_level.txt +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_ext/__init__.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_ext/auto_open.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_ext/default_ordered_dict.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_ext/extension_base.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_ext/htmloutput.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_ext/keywords.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_ext/lizardboolcount.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_ext/lizardcomplextags.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_ext/lizardcpre.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_ext/lizarddependencycount.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_ext/lizarddumpcomments.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_ext/lizardduplicate.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_ext/lizardduplicated_param_list.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_ext/lizardexitcount.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_ext/lizardgotocount.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_ext/lizardignoreassert.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_ext/lizardio.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_ext/lizardmccabe.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_ext/lizardmodified.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_ext/lizardnd.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_ext/lizardnonstrict.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_ext/lizardns.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_ext/lizardoutside.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_ext/lizardstatementcount.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_ext/lizardwordcount.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_ext/xmloutput.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_languages/clike.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_languages/erlang.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_languages/fortran.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_languages/gdscript.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_languages/go.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_languages/golike.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_languages/kotlin.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_languages/lua.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_languages/objc.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_languages/php.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_languages/python.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_languages/ruby.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_languages/rubylike.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_languages/rust.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_languages/scala.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_languages/solidity.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_languages/swift.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_languages/tnsdl.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_languages/ttcn.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/lizard_languages/zig.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/setup.cfg +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/test/testApplication.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/test/testAssertionExtension.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/test/testBasicFunctionInfo.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/test/testCOutsideComplexity.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/test/testCPreprocessorExtension.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/test/testCommentOptions.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/test/testCyclomaticComplexity.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/test/testExtension.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/test/testFunctionDependencyCount.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/test/testFunctionExitCount.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/test/testFunctionGotoCount.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/test/testFunctionStatementCount.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/test/testHelpers.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/test/testLanguages.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/test/testMcCabe.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/test/testNestedStructures.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/test/testNestingDepth.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/test/testOutputCSV.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/test/testOutputHTML.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/test/testTokenizer.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/test/test_analyzer.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/test/test_auto_open.py +0 -0
- {lizard-1.17.14 → lizard-1.17.16}/test/test_options.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: lizard
|
|
3
|
-
Version: 1.17.
|
|
3
|
+
Version: 1.17.16
|
|
4
4
|
Summary: A code analyzer without caring the C/C++ header files. It works with Java, C/C++, JavaScript, Python, Ruby, Swift, Objective C. Metrics includes cyclomatic complexity number etc.
|
|
5
5
|
Home-page: http://www.lizard.ws
|
|
6
6
|
Download-URL: https://pypi.python.org/lizard/
|
|
@@ -53,6 +53,7 @@ A list of supported languages:
|
|
|
53
53
|
- C# (C Sharp)
|
|
54
54
|
- JavaScript (With ES6 and JSX)
|
|
55
55
|
- TypeScript (With TSX)
|
|
56
|
+
- VueJS
|
|
56
57
|
- Objective-C
|
|
57
58
|
- Swift
|
|
58
59
|
- Python
|
|
@@ -136,6 +137,13 @@ Exclude anything in the tests folder:
|
|
|
136
137
|
|
|
137
138
|
lizard mySource/ -x"./tests/*"
|
|
138
139
|
|
|
140
|
+
Use .gitignore file:
|
|
141
|
+
|
|
142
|
+
::
|
|
143
|
+
|
|
144
|
+
lizard mySource/
|
|
145
|
+
|
|
146
|
+
If there is a .gitignore file in the given path, lizard will automatically use it as an additional filter to exclude files that match the gitignore patterns. This is useful when you want to analyze only the tracked files in your git repository.
|
|
139
147
|
|
|
140
148
|
Options
|
|
141
149
|
~~~~~~~
|
|
@@ -22,6 +22,7 @@ A list of supported languages:
|
|
|
22
22
|
- C# (C Sharp)
|
|
23
23
|
- JavaScript (With ES6 and JSX)
|
|
24
24
|
- TypeScript (With TSX)
|
|
25
|
+
- VueJS
|
|
25
26
|
- Objective-C
|
|
26
27
|
- Swift
|
|
27
28
|
- Python
|
|
@@ -105,6 +106,13 @@ Exclude anything in the tests folder:
|
|
|
105
106
|
|
|
106
107
|
lizard mySource/ -x"./tests/*"
|
|
107
108
|
|
|
109
|
+
Use .gitignore file:
|
|
110
|
+
|
|
111
|
+
::
|
|
112
|
+
|
|
113
|
+
lizard mySource/
|
|
114
|
+
|
|
115
|
+
If there is a .gitignore file in the given path, lizard will automatically use it as an additional filter to exclude files that match the gitignore patterns. This is useful when you want to analyze only the tracked files in your git repository.
|
|
108
116
|
|
|
109
117
|
Options
|
|
110
118
|
~~~~~~~
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: lizard
|
|
3
|
-
Version: 1.17.
|
|
3
|
+
Version: 1.17.16
|
|
4
4
|
Summary: A code analyzer without caring the C/C++ header files. It works with Java, C/C++, JavaScript, Python, Ruby, Swift, Objective C. Metrics includes cyclomatic complexity number etc.
|
|
5
5
|
Home-page: http://www.lizard.ws
|
|
6
6
|
Download-URL: https://pypi.python.org/lizard/
|
|
@@ -53,6 +53,7 @@ A list of supported languages:
|
|
|
53
53
|
- C# (C Sharp)
|
|
54
54
|
- JavaScript (With ES6 and JSX)
|
|
55
55
|
- TypeScript (With TSX)
|
|
56
|
+
- VueJS
|
|
56
57
|
- Objective-C
|
|
57
58
|
- Swift
|
|
58
59
|
- Python
|
|
@@ -136,6 +137,13 @@ Exclude anything in the tests folder:
|
|
|
136
137
|
|
|
137
138
|
lizard mySource/ -x"./tests/*"
|
|
138
139
|
|
|
140
|
+
Use .gitignore file:
|
|
141
|
+
|
|
142
|
+
::
|
|
143
|
+
|
|
144
|
+
lizard mySource/
|
|
145
|
+
|
|
146
|
+
If there is a .gitignore file in the given path, lizard will automatically use it as an additional filter to exclude files that match the gitignore patterns. This is useful when you want to analyze only the tracked files in your git repository.
|
|
139
147
|
|
|
140
148
|
Options
|
|
141
149
|
~~~~~~~
|
|
@@ -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
|
-
"
|
|
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
|
|
|
@@ -723,17 +722,13 @@ class OutputScheme(object):
|
|
|
723
722
|
if e.get("avg_caption", None)])
|
|
724
723
|
|
|
725
724
|
def clang_warning_format(self):
|
|
726
|
-
return (
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
"{{f.{ext[value]}}} {caption}"
|
|
730
|
-
.format(ext=e, caption=e['caption'].strip())
|
|
731
|
-
for e in self.items[:-1]
|
|
732
|
-
]))
|
|
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")
|
|
733
728
|
|
|
734
729
|
def msvs_warning_format(self):
|
|
735
730
|
return (
|
|
736
|
-
"{f.filename}({f.start_line}): warning: {f.name} has " +
|
|
731
|
+
"{f.filename}({f.start_line}): warning: {f.name} ({f.long_name}) has " +
|
|
737
732
|
", ".join([
|
|
738
733
|
"{{f.{ext[value]}}} {caption}"
|
|
739
734
|
.format(ext=e, caption=e['caption'].strip())
|
|
@@ -901,14 +896,43 @@ def md5_hash_file(full_path_name):
|
|
|
901
896
|
def get_all_source_files(paths, exclude_patterns, lans):
|
|
902
897
|
'''
|
|
903
898
|
Function counts md5 hash for the given file and checks if it isn't a
|
|
904
|
-
duplicate using set of hashes for previous files
|
|
899
|
+
duplicate using set of hashes for previous files.
|
|
900
|
+
|
|
901
|
+
If a .gitignore file is found in any of the given paths, it will be used
|
|
902
|
+
to filter out files that match the gitignore patterns.
|
|
903
|
+
'''
|
|
905
904
|
hash_set = set()
|
|
905
|
+
gitignore_spec = None
|
|
906
|
+
base_path = None
|
|
907
|
+
|
|
908
|
+
def _load_gitignore():
|
|
909
|
+
nonlocal gitignore_spec, base_path
|
|
910
|
+
try:
|
|
911
|
+
import pathspec
|
|
912
|
+
for path in paths:
|
|
913
|
+
gitignore_path = os.path.join(path, '.gitignore')
|
|
914
|
+
if os.path.exists(gitignore_path):
|
|
915
|
+
with open(gitignore_path, 'r') as gitignore_file:
|
|
916
|
+
# Read lines and strip whitespace and empty lines
|
|
917
|
+
patterns = [line.strip() for line in gitignore_file.readlines()]
|
|
918
|
+
patterns = [p for p in patterns if p and not p.startswith('#')]
|
|
919
|
+
gitignore_spec = pathspec.PathSpec.from_lines('gitwildmatch', patterns)
|
|
920
|
+
base_path = path
|
|
921
|
+
break
|
|
922
|
+
except ImportError:
|
|
923
|
+
pass
|
|
906
924
|
|
|
907
925
|
def _support(reader):
|
|
908
926
|
return not lans or set(lans).intersection(
|
|
909
927
|
reader.language_names)
|
|
910
928
|
|
|
911
929
|
def _validate_file(pathname):
|
|
930
|
+
if gitignore_spec is not None and base_path is not None:
|
|
931
|
+
rel_path = os.path.relpath(pathname, base_path)
|
|
932
|
+
# Normalize path separators for consistent matching
|
|
933
|
+
rel_path = rel_path.replace(os.sep, '/')
|
|
934
|
+
if gitignore_spec.match_file(rel_path):
|
|
935
|
+
return False
|
|
912
936
|
return (
|
|
913
937
|
pathname in paths or (
|
|
914
938
|
get_reader_for(pathname) and
|
|
@@ -931,6 +955,7 @@ def get_all_source_files(paths, exclude_patterns, lans):
|
|
|
931
955
|
for filename in files:
|
|
932
956
|
yield os.path.join(root, filename)
|
|
933
957
|
|
|
958
|
+
_load_gitignore()
|
|
934
959
|
return filter(_validate_file, all_listed_files(paths))
|
|
935
960
|
|
|
936
961
|
|
|
@@ -972,7 +997,7 @@ def parse_args(argv):
|
|
|
972
997
|
if inferred_printer:
|
|
973
998
|
if not opt.printer:
|
|
974
999
|
opt.printer = inferred_printer
|
|
975
|
-
|
|
1000
|
+
elif opt.printer != inferred_printer:
|
|
976
1001
|
msg = "Warning: overriding output file extension.\n"
|
|
977
1002
|
sys.stderr.write(msg)
|
|
978
1003
|
return opt
|
|
@@ -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 = "{},{}"
|
|
40
|
-
print("NLOC,CCN,token,PARAM,length,location,file,function," +
|
|
41
|
-
"long_name,start,end{}"
|
|
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
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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}")
|
|
@@ -23,6 +23,7 @@ from .fortran import FortranReader
|
|
|
23
23
|
from .solidity import SolidityReader
|
|
24
24
|
from .jsx import JSXReader
|
|
25
25
|
from .tsx import TSXReader
|
|
26
|
+
from .vue import VueReader
|
|
26
27
|
|
|
27
28
|
|
|
28
29
|
def languages():
|
|
@@ -50,6 +51,7 @@ def languages():
|
|
|
50
51
|
ZigReader,
|
|
51
52
|
JSXReader,
|
|
52
53
|
TSXReader,
|
|
54
|
+
VueReader,
|
|
53
55
|
]
|
|
54
56
|
|
|
55
57
|
|
|
@@ -8,7 +8,7 @@ from functools import reduce
|
|
|
8
8
|
from operator import or_
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
class CodeStateMachine
|
|
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
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
'''
|
|
2
|
+
Language parser for C Sharp
|
|
3
|
+
'''
|
|
4
|
+
|
|
5
|
+
from .clike import CLikeReader, CLikeStates, CLikeNestingStackStates
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class CSharpReader(CLikeReader):
|
|
9
|
+
# pylint: disable=R0903
|
|
10
|
+
|
|
11
|
+
ext = ['cs']
|
|
12
|
+
language_names = ['csharp']
|
|
13
|
+
|
|
14
|
+
_conditions = set(['if', 'for', 'while', '&&', '||', '?', 'catch',
|
|
15
|
+
'case', '??'])
|
|
16
|
+
|
|
17
|
+
def __init__(self, context):
|
|
18
|
+
super(CSharpReader, self).__init__(context)
|
|
19
|
+
self.parallel_states = [
|
|
20
|
+
CSharpStates(context),
|
|
21
|
+
CLikeNestingStackStates(context)
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
@staticmethod
|
|
25
|
+
def generate_tokens(source_code, addition='', token_class=None):
|
|
26
|
+
return CLikeReader.generate_tokens(
|
|
27
|
+
source_code, r"|(?:\?\?)", token_class)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class CSharpStates(CLikeStates):
|
|
31
|
+
def __init__(self, context):
|
|
32
|
+
super(CSharpStates, self).__init__(context)
|
|
33
|
+
self.in_primary_constructor = False
|
|
34
|
+
self.class_name = None
|
|
35
|
+
|
|
36
|
+
def try_new_function(self, name):
|
|
37
|
+
if not self.in_primary_constructor:
|
|
38
|
+
super(CSharpStates, self).try_new_function(name)
|
|
39
|
+
if self.class_name and self.context.current_function:
|
|
40
|
+
self.context.current_function.name = f"{self.class_name}::{name}"
|
|
41
|
+
|
|
42
|
+
def _state_global(self, token):
|
|
43
|
+
if token in ("class", "struct", "record"):
|
|
44
|
+
self.class_name = None
|
|
45
|
+
self._state = self._state_class_declaration
|
|
46
|
+
else:
|
|
47
|
+
super(CSharpStates, self)._state_global(token)
|
|
48
|
+
|
|
49
|
+
def _state_class_declaration(self, token):
|
|
50
|
+
if token == '(': # Primary constructor
|
|
51
|
+
self.in_primary_constructor = True
|
|
52
|
+
self._state = self._state_primary_constructor
|
|
53
|
+
elif token == '{':
|
|
54
|
+
self._state = self._state_global
|
|
55
|
+
elif token[0].isalpha():
|
|
56
|
+
if not self.class_name: # Only set class name if not already set
|
|
57
|
+
self.class_name = token
|
|
58
|
+
|
|
59
|
+
@CLikeStates.read_inside_brackets_then("()", "_state_class_declaration")
|
|
60
|
+
def _state_primary_constructor(self, _):
|
|
61
|
+
"""Skip primary constructor parameters without counting them as a function"""
|
|
62
|
+
self.in_primary_constructor = False
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
'''
|
|
2
|
+
Language parser for Java
|
|
3
|
+
'''
|
|
4
|
+
|
|
5
|
+
from .clike import CLikeReader, CLikeStates, CLikeNestingStackStates
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class JavaReader(CLikeReader):
|
|
9
|
+
# pylint: disable=R0903
|
|
10
|
+
|
|
11
|
+
ext = ['java']
|
|
12
|
+
language_names = ['java']
|
|
13
|
+
|
|
14
|
+
def __init__(self, context):
|
|
15
|
+
super(JavaReader, self).__init__(context)
|
|
16
|
+
self.parallel_states = [
|
|
17
|
+
JavaStates(context),
|
|
18
|
+
CLikeNestingStackStates(context)]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class JavaStates(CLikeStates): # pylint: disable=R0903
|
|
22
|
+
def __init__(self, context):
|
|
23
|
+
super(JavaStates, self).__init__(context)
|
|
24
|
+
self.class_name = None
|
|
25
|
+
self.is_record = False
|
|
26
|
+
self.in_record_constructor = False
|
|
27
|
+
|
|
28
|
+
def _state_old_c_params(self, token):
|
|
29
|
+
if token == '{':
|
|
30
|
+
self._state_dec_to_imp(token)
|
|
31
|
+
|
|
32
|
+
def try_new_function(self, name):
|
|
33
|
+
# Don't create a function for record compact constructor
|
|
34
|
+
if self.is_record and name == self.class_name:
|
|
35
|
+
self.in_record_constructor = True
|
|
36
|
+
self._state = self._state_record_compact_constructor
|
|
37
|
+
return
|
|
38
|
+
self.context.try_new_function(name)
|
|
39
|
+
self._state = self._state_function
|
|
40
|
+
if self.class_name and self.context.current_function:
|
|
41
|
+
self.context.current_function.name = f"{self.class_name}::{name}"
|
|
42
|
+
|
|
43
|
+
def _state_global(self, token):
|
|
44
|
+
if token == '@':
|
|
45
|
+
self._state = self._state_decorator
|
|
46
|
+
return
|
|
47
|
+
if token in ("class", "record", "enum"):
|
|
48
|
+
self.class_name = None
|
|
49
|
+
self.is_record = token == "record"
|
|
50
|
+
self.in_record_constructor = False
|
|
51
|
+
self._state = self._state_class_declaration
|
|
52
|
+
return
|
|
53
|
+
if not self.in_record_constructor: # Only process as potential function if not in record constructor
|
|
54
|
+
super(JavaStates, self)._state_global(token)
|
|
55
|
+
|
|
56
|
+
def _state_decorator(self, _):
|
|
57
|
+
self._state = self._state_post_decorator
|
|
58
|
+
|
|
59
|
+
def _state_post_decorator(self, token):
|
|
60
|
+
if token == '.':
|
|
61
|
+
self._state = self._state_decorator
|
|
62
|
+
else:
|
|
63
|
+
self._state = self._state_global
|
|
64
|
+
self._state(token)
|
|
65
|
+
|
|
66
|
+
def _state_class_declaration(self, token):
|
|
67
|
+
if token == '{':
|
|
68
|
+
self._state = self._state_global
|
|
69
|
+
elif token == '(': # Record parameters
|
|
70
|
+
self._state = self._state_record_parameters
|
|
71
|
+
elif token[0].isalpha():
|
|
72
|
+
if not self.class_name: # Only set class name if not already set
|
|
73
|
+
self.class_name = token
|
|
74
|
+
|
|
75
|
+
def _state_record_parameters(self, token):
|
|
76
|
+
if token == ')':
|
|
77
|
+
self._state = self._state_class_declaration
|
|
78
|
+
|
|
79
|
+
def _state_record_compact_constructor(self, token):
|
|
80
|
+
if token == '{':
|
|
81
|
+
self._state = self._state_record_constructor_body
|
|
82
|
+
return
|
|
83
|
+
self._state = self._state_global
|
|
84
|
+
self._state(token)
|
|
85
|
+
|
|
86
|
+
def _state_record_constructor_body(self, token):
|
|
87
|
+
if token == '}':
|
|
88
|
+
self.in_record_constructor = False
|
|
89
|
+
self._state = self._state_global
|
|
@@ -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)
|
|
@@ -11,8 +11,18 @@ class JavaScriptStyleLanguageStates(CodeStateMachine): # pylint: disable=R0903
|
|
|
11
11
|
self.last_tokens = ''
|
|
12
12
|
self.function_name = ''
|
|
13
13
|
self.started_function = None
|
|
14
|
+
self.as_object = False
|
|
14
15
|
|
|
15
16
|
def _state_global(self, token):
|
|
17
|
+
if self.as_object:
|
|
18
|
+
if token == ':':
|
|
19
|
+
self.function_name = self.last_tokens
|
|
20
|
+
return
|
|
21
|
+
elif token == '(':
|
|
22
|
+
self._function(self.last_tokens)
|
|
23
|
+
self.next(self._function, token)
|
|
24
|
+
return
|
|
25
|
+
|
|
16
26
|
if token in '.':
|
|
17
27
|
self._state = self._field
|
|
18
28
|
self.last_tokens += token
|
|
@@ -29,11 +39,11 @@ class JavaScriptStyleLanguageStates(CodeStateMachine): # pylint: disable=R0903
|
|
|
29
39
|
self.function_name = self.last_tokens
|
|
30
40
|
elif token == "(":
|
|
31
41
|
self.sub_state(
|
|
32
|
-
|
|
42
|
+
self.__class__(self.context))
|
|
33
43
|
elif token in '{':
|
|
34
44
|
if self.started_function:
|
|
35
45
|
self.sub_state(
|
|
36
|
-
|
|
46
|
+
self.__class__(self.context),
|
|
37
47
|
self._pop_function_from_stack)
|
|
38
48
|
else:
|
|
39
49
|
self.read_object()
|
|
@@ -46,7 +56,12 @@ class JavaScriptStyleLanguageStates(CodeStateMachine): # pylint: disable=R0903
|
|
|
46
56
|
self.last_tokens = token
|
|
47
57
|
|
|
48
58
|
def read_object(self):
|
|
49
|
-
|
|
59
|
+
def callback():
|
|
60
|
+
self.next(self._state_global)
|
|
61
|
+
|
|
62
|
+
object_reader = self.__class__(self.context)
|
|
63
|
+
object_reader.as_object = True
|
|
64
|
+
self.sub_state(object_reader, callback)
|
|
50
65
|
|
|
51
66
|
def statemachine_before_return(self):
|
|
52
67
|
self._pop_function_from_stack()
|
|
@@ -63,16 +78,14 @@ class JavaScriptStyleLanguageStates(CodeStateMachine): # pylint: disable=R0903
|
|
|
63
78
|
return
|
|
64
79
|
|
|
65
80
|
self.sub_state(
|
|
66
|
-
|
|
67
|
-
callback)
|
|
81
|
+
self.__class__(self.context), callback)
|
|
68
82
|
|
|
69
83
|
def _expecting_statement_or_block(self, token):
|
|
70
84
|
def callback():
|
|
71
85
|
self.next(self._state_global)
|
|
72
86
|
if token == "{":
|
|
73
87
|
self.sub_state(
|
|
74
|
-
|
|
75
|
-
callback)
|
|
88
|
+
self.__class__(self.context), callback)
|
|
76
89
|
else:
|
|
77
90
|
self.next(self._state_global, token)
|
|
78
91
|
|
|
@@ -116,17 +129,3 @@ class JavaScriptStyleLanguageStates(CodeStateMachine): # pylint: disable=R0903
|
|
|
116
129
|
if token != '{':
|
|
117
130
|
self.started_function = None
|
|
118
131
|
self.next(self._state_global, token)
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
class ES6ObjectStates(JavaScriptStyleLanguageStates): # pylint: disable=R0903
|
|
122
|
-
def __init__(self, context):
|
|
123
|
-
super(ES6ObjectStates, self).__init__(context)
|
|
124
|
-
|
|
125
|
-
def _state_global(self, token):
|
|
126
|
-
if token == ':':
|
|
127
|
-
self.function_name = self.last_tokens
|
|
128
|
-
elif token == '(':
|
|
129
|
-
self._function(self.last_tokens)
|
|
130
|
-
self.next(self._function, token)
|
|
131
|
-
else:
|
|
132
|
-
super(ES6ObjectStates, self)._state_global(token)
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
'''
|
|
2
|
+
generate token with javascript style regular expression.
|
|
3
|
+
'''
|
|
4
|
+
|
|
5
|
+
import re
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def js_style_regex_expression(func):
|
|
9
|
+
def generate_tokens_with_regex(source_code, addition='', token_class=None):
|
|
10
|
+
regx_regx = r"\/(\S*?[^\s\\]\/)+?(igm)*"
|
|
11
|
+
regx_pattern = re.compile(regx_regx)
|
|
12
|
+
tokens = list(func(source_code, addition, token_class))
|
|
13
|
+
result = []
|
|
14
|
+
i = 0
|
|
15
|
+
while i < len(tokens):
|
|
16
|
+
token = tokens[i]
|
|
17
|
+
if token == '/':
|
|
18
|
+
# Check if this could be a regex pattern
|
|
19
|
+
is_regex = False
|
|
20
|
+
if i == 0:
|
|
21
|
+
is_regex = True
|
|
22
|
+
elif i > 0:
|
|
23
|
+
prev_token = tokens[i-1].strip()
|
|
24
|
+
if prev_token and prev_token[-1] in '=,({[?:!&|;':
|
|
25
|
+
is_regex = True
|
|
26
|
+
|
|
27
|
+
if is_regex:
|
|
28
|
+
# This is likely a regex pattern start
|
|
29
|
+
regex_tokens = [token]
|
|
30
|
+
i += 1
|
|
31
|
+
while i < len(tokens) and not tokens[i].endswith('/'):
|
|
32
|
+
regex_tokens.append(tokens[i])
|
|
33
|
+
i += 1
|
|
34
|
+
if i < len(tokens):
|
|
35
|
+
regex_tokens.append(tokens[i])
|
|
36
|
+
i += 1
|
|
37
|
+
# Check for regex flags
|
|
38
|
+
if i < len(tokens) and re.match(r'^[igm]+$', tokens[i]):
|
|
39
|
+
regex_tokens.append(tokens[i])
|
|
40
|
+
i += 1
|
|
41
|
+
combined = ''.join(regex_tokens)
|
|
42
|
+
if regx_pattern.match(combined):
|
|
43
|
+
result.append(combined)
|
|
44
|
+
else:
|
|
45
|
+
result.extend(regex_tokens)
|
|
46
|
+
else:
|
|
47
|
+
# This is a division operator
|
|
48
|
+
result.append(token)
|
|
49
|
+
else:
|
|
50
|
+
result.append(token)
|
|
51
|
+
i += 1
|
|
52
|
+
return result
|
|
53
|
+
return generate_tokens_with_regex
|