lizard 1.17.15__tar.gz → 1.17.17__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.15 → lizard-1.17.17}/PKG-INFO +8 -1
- {lizard-1.17.15 → lizard-1.17.17}/README.rst +7 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard.egg-info/PKG-INFO +8 -1
- {lizard-1.17.15 → lizard-1.17.17}/lizard.egg-info/requires.txt +1 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard.py +32 -2
- {lizard-1.17.15 → lizard-1.17.17}/lizard_ext/version.py +1 -1
- lizard-1.17.17/lizard_languages/csharp.py +62 -0
- lizard-1.17.17/lizard_languages/java.py +142 -0
- lizard-1.17.17/lizard_languages/javascript.py +15 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_languages/jsx.py +17 -3
- {lizard-1.17.15 → lizard-1.17.17}/lizard_languages/ruby.py +3 -2
- {lizard-1.17.15 → lizard-1.17.17}/lizard_languages/tsx.py +1 -2
- {lizard-1.17.15 → lizard-1.17.17}/lizard_languages/typescript.py +9 -5
- {lizard-1.17.15 → lizard-1.17.17}/setup.py +1 -1
- {lizard-1.17.15 → lizard-1.17.17}/test/testFilesFilter.py +31 -0
- {lizard-1.17.15 → lizard-1.17.17}/test/testOutput.py +1 -1
- lizard-1.17.17/test/testOutputFile.py +117 -0
- lizard-1.17.15/lizard_languages/csharp.py +0 -20
- lizard-1.17.15/lizard_languages/java.py +0 -44
- lizard-1.17.15/lizard_languages/javascript.py +0 -19
- lizard-1.17.15/test/testOutputFile.py +0 -58
- {lizard-1.17.15 → lizard-1.17.17}/LICENSE.txt +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard.egg-info/SOURCES.txt +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard.egg-info/dependency_links.txt +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard.egg-info/entry_points.txt +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard.egg-info/top_level.txt +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_ext/__init__.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_ext/auto_open.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_ext/csvoutput.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_ext/default_ordered_dict.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_ext/extension_base.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_ext/htmloutput.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_ext/keywords.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_ext/lizardboolcount.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_ext/lizardcomplextags.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_ext/lizardcpre.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_ext/lizarddependencycount.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_ext/lizarddumpcomments.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_ext/lizardduplicate.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_ext/lizardduplicated_param_list.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_ext/lizardexitcount.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_ext/lizardgotocount.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_ext/lizardignoreassert.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_ext/lizardio.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_ext/lizardmccabe.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_ext/lizardmodified.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_ext/lizardnd.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_ext/lizardnonstrict.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_ext/lizardns.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_ext/lizardoutside.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_ext/lizardstatementcount.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_ext/lizardwordcount.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_ext/xmloutput.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_languages/__init__.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_languages/clike.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_languages/code_reader.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_languages/erlang.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_languages/fortran.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_languages/gdscript.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_languages/go.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_languages/golike.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_languages/js_style_language_states.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_languages/js_style_regex_expression.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_languages/kotlin.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_languages/lua.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_languages/objc.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_languages/php.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_languages/python.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_languages/rubylike.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_languages/rust.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_languages/scala.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_languages/script_language.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_languages/solidity.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_languages/swift.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_languages/tnsdl.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_languages/ttcn.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_languages/vue.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/lizard_languages/zig.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/setup.cfg +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/test/testApplication.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/test/testAssertionExtension.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/test/testBasicFunctionInfo.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/test/testCOutsideComplexity.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/test/testCPreprocessorExtension.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/test/testCommentOptions.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/test/testCyclomaticComplexity.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/test/testExtension.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/test/testFunctionDependencyCount.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/test/testFunctionExitCount.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/test/testFunctionGotoCount.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/test/testFunctionStatementCount.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/test/testHelpers.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/test/testLanguages.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/test/testMcCabe.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/test/testNestedStructures.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/test/testNestingDepth.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/test/testOutputCSV.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/test/testOutputHTML.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/test/testTokenizer.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/test/test_analyzer.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/test/test_auto_open.py +0 -0
- {lizard-1.17.15 → lizard-1.17.17}/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.17
|
|
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/
|
|
@@ -137,6 +137,13 @@ Exclude anything in the tests folder:
|
|
|
137
137
|
|
|
138
138
|
lizard mySource/ -x"./tests/*"
|
|
139
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.
|
|
140
147
|
|
|
141
148
|
Options
|
|
142
149
|
~~~~~~~
|
|
@@ -106,6 +106,13 @@ Exclude anything in the tests folder:
|
|
|
106
106
|
|
|
107
107
|
lizard mySource/ -x"./tests/*"
|
|
108
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.
|
|
109
116
|
|
|
110
117
|
Options
|
|
111
118
|
~~~~~~~
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: lizard
|
|
3
|
-
Version: 1.17.
|
|
3
|
+
Version: 1.17.17
|
|
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/
|
|
@@ -137,6 +137,13 @@ Exclude anything in the tests folder:
|
|
|
137
137
|
|
|
138
138
|
lizard mySource/ -x"./tests/*"
|
|
139
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.
|
|
140
147
|
|
|
141
148
|
Options
|
|
142
149
|
~~~~~~~
|
|
@@ -896,14 +896,43 @@ def md5_hash_file(full_path_name):
|
|
|
896
896
|
def get_all_source_files(paths, exclude_patterns, lans):
|
|
897
897
|
'''
|
|
898
898
|
Function counts md5 hash for the given file and checks if it isn't a
|
|
899
|
-
duplicate using set of hashes for previous files
|
|
899
|
+
duplicate using set of hashes for previous files.
|
|
900
|
+
|
|
901
|
+
If a .gitignore file is found in any of the given paths, it will be used
|
|
902
|
+
to filter out files that match the gitignore patterns.
|
|
903
|
+
'''
|
|
900
904
|
hash_set = set()
|
|
905
|
+
gitignore_spec = None
|
|
906
|
+
base_path = None
|
|
907
|
+
|
|
908
|
+
def _load_gitignore():
|
|
909
|
+
nonlocal gitignore_spec, base_path
|
|
910
|
+
try:
|
|
911
|
+
import pathspec
|
|
912
|
+
for path in paths:
|
|
913
|
+
gitignore_path = os.path.join(path, '.gitignore')
|
|
914
|
+
if os.path.exists(gitignore_path):
|
|
915
|
+
with open(gitignore_path, 'r') as gitignore_file:
|
|
916
|
+
# Read lines and strip whitespace and empty lines
|
|
917
|
+
patterns = [line.strip() for line in gitignore_file.readlines()]
|
|
918
|
+
patterns = [p for p in patterns if p and not p.startswith('#')]
|
|
919
|
+
gitignore_spec = pathspec.PathSpec.from_lines('gitwildmatch', patterns)
|
|
920
|
+
base_path = path
|
|
921
|
+
break
|
|
922
|
+
except ImportError:
|
|
923
|
+
pass
|
|
901
924
|
|
|
902
925
|
def _support(reader):
|
|
903
926
|
return not lans or set(lans).intersection(
|
|
904
927
|
reader.language_names)
|
|
905
928
|
|
|
906
929
|
def _validate_file(pathname):
|
|
930
|
+
if gitignore_spec is not None and base_path is not None:
|
|
931
|
+
rel_path = os.path.relpath(pathname, base_path)
|
|
932
|
+
# Normalize path separators for consistent matching
|
|
933
|
+
rel_path = rel_path.replace(os.sep, '/')
|
|
934
|
+
if gitignore_spec.match_file(rel_path):
|
|
935
|
+
return False
|
|
907
936
|
return (
|
|
908
937
|
pathname in paths or (
|
|
909
938
|
get_reader_for(pathname) and
|
|
@@ -926,6 +955,7 @@ def get_all_source_files(paths, exclude_patterns, lans):
|
|
|
926
955
|
for filename in files:
|
|
927
956
|
yield os.path.join(root, filename)
|
|
928
957
|
|
|
958
|
+
_load_gitignore()
|
|
929
959
|
return filter(_validate_file, all_listed_files(paths))
|
|
930
960
|
|
|
931
961
|
|
|
@@ -967,7 +997,7 @@ def parse_args(argv):
|
|
|
967
997
|
if inferred_printer:
|
|
968
998
|
if not opt.printer:
|
|
969
999
|
opt.printer = inferred_printer
|
|
970
|
-
|
|
1000
|
+
elif opt.printer != inferred_printer:
|
|
971
1001
|
msg = "Warning: overriding output file extension.\n"
|
|
972
1002
|
sys.stderr.write(msg)
|
|
973
1003
|
return opt
|
|
@@ -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,142 @@
|
|
|
1
|
+
'''
|
|
2
|
+
Language parser for Java
|
|
3
|
+
'''
|
|
4
|
+
|
|
5
|
+
from lizard_languages.code_reader import CodeStateMachine
|
|
6
|
+
from .clike import CLikeReader, CLikeStates, CLikeNestingStackStates
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class JavaReader(CLikeReader):
|
|
10
|
+
# pylint: disable=R0903
|
|
11
|
+
|
|
12
|
+
ext = ['java']
|
|
13
|
+
language_names = ['java']
|
|
14
|
+
|
|
15
|
+
def __init__(self, context):
|
|
16
|
+
super(JavaReader, self).__init__(context)
|
|
17
|
+
self.parallel_states = [
|
|
18
|
+
JavaStates(context),
|
|
19
|
+
CLikeNestingStackStates(context)]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class JavaStates(CLikeStates): # pylint: disable=R0903
|
|
23
|
+
def __init__(self, context):
|
|
24
|
+
super(JavaStates, self).__init__(context)
|
|
25
|
+
self.class_name = None
|
|
26
|
+
self.is_record = False
|
|
27
|
+
self.in_record_constructor = False
|
|
28
|
+
|
|
29
|
+
def _state_old_c_params(self, token):
|
|
30
|
+
if token == '{':
|
|
31
|
+
self._state_dec_to_imp(token)
|
|
32
|
+
|
|
33
|
+
def _state_imp(self, token):
|
|
34
|
+
def callback():
|
|
35
|
+
self.next(self._state_global)
|
|
36
|
+
self.sub_state(JavaFunctionBodyStates(self.context), callback, token)
|
|
37
|
+
|
|
38
|
+
def try_new_function(self, name):
|
|
39
|
+
# Don't create a function for record compact constructor
|
|
40
|
+
if self.is_record and name == self.class_name:
|
|
41
|
+
self.in_record_constructor = True
|
|
42
|
+
self._state = self._state_record_compact_constructor
|
|
43
|
+
return
|
|
44
|
+
self.context.try_new_function(name)
|
|
45
|
+
self._state = self._state_function
|
|
46
|
+
if self.class_name and self.context.current_function:
|
|
47
|
+
self.context.current_function.name = f"{self.class_name}::{name}"
|
|
48
|
+
|
|
49
|
+
def _try_start_a_class(self, token):
|
|
50
|
+
if token in ("class", "record", "enum"):
|
|
51
|
+
self.class_name = None
|
|
52
|
+
self.is_record = token == "record"
|
|
53
|
+
self.in_record_constructor = False
|
|
54
|
+
self._state = self._state_class_declaration
|
|
55
|
+
return True
|
|
56
|
+
|
|
57
|
+
def _state_global(self, token):
|
|
58
|
+
if token == '@':
|
|
59
|
+
self._state = self._state_decorator
|
|
60
|
+
return
|
|
61
|
+
if self._try_start_a_class(token):
|
|
62
|
+
return
|
|
63
|
+
if not self.in_record_constructor: # Only process as potential function if not in record constructor
|
|
64
|
+
super(JavaStates, self)._state_global(token)
|
|
65
|
+
|
|
66
|
+
def _state_decorator(self, _):
|
|
67
|
+
self._state = self._state_post_decorator
|
|
68
|
+
|
|
69
|
+
def _state_post_decorator(self, token):
|
|
70
|
+
if token == '.':
|
|
71
|
+
self._state = self._state_decorator
|
|
72
|
+
else:
|
|
73
|
+
self._state = self._state_global
|
|
74
|
+
self._state(token)
|
|
75
|
+
|
|
76
|
+
def _state_class_declaration(self, token):
|
|
77
|
+
if token == '{':
|
|
78
|
+
def callback():
|
|
79
|
+
self._state = self._state_global
|
|
80
|
+
self.sub_state(JavaClassBodyStates(self.class_name, self.is_record, self.context), callback, token)
|
|
81
|
+
elif token == '(': # Record parameters
|
|
82
|
+
self._state = self._state_record_parameters
|
|
83
|
+
elif token[0].isalpha():
|
|
84
|
+
if not self.class_name: # Only set class name if not already set
|
|
85
|
+
self.class_name = token
|
|
86
|
+
|
|
87
|
+
def _state_record_parameters(self, token):
|
|
88
|
+
if token == ')':
|
|
89
|
+
self._state = self._state_class_declaration
|
|
90
|
+
|
|
91
|
+
def _state_record_compact_constructor(self, token):
|
|
92
|
+
if token == '{':
|
|
93
|
+
self._state = self._state_record_constructor_body
|
|
94
|
+
return
|
|
95
|
+
self._state = self._state_global
|
|
96
|
+
self._state(token)
|
|
97
|
+
|
|
98
|
+
def _state_record_constructor_body(self, token):
|
|
99
|
+
if token == '}':
|
|
100
|
+
self.in_record_constructor = False
|
|
101
|
+
self._state = self._state_global
|
|
102
|
+
|
|
103
|
+
class JavaFunctionBodyStates(JavaStates):
|
|
104
|
+
def __init__(self, context):
|
|
105
|
+
super(JavaFunctionBodyStates, self).__init__(context)
|
|
106
|
+
|
|
107
|
+
@CodeStateMachine.read_inside_brackets_then("{}", "_state_dummy")
|
|
108
|
+
@CodeStateMachine.read_inside_brackets_then("()", "_state_dummy")
|
|
109
|
+
def _state_global(self, token):
|
|
110
|
+
if token == "new":
|
|
111
|
+
self.next(self._state_new)
|
|
112
|
+
self._try_start_a_class(token)
|
|
113
|
+
if self.br_count == 0:
|
|
114
|
+
self.statemachine_return()
|
|
115
|
+
|
|
116
|
+
def _state_dummy(self, _):
|
|
117
|
+
pass
|
|
118
|
+
|
|
119
|
+
def _state_new(self, token):
|
|
120
|
+
self.next(self._state_new_parameters)
|
|
121
|
+
|
|
122
|
+
def _state_new_parameters(self, token):
|
|
123
|
+
if token == "(":
|
|
124
|
+
self.sub_state(JavaFunctionBodyStates(self.context), None, token)
|
|
125
|
+
return
|
|
126
|
+
if token == "{":
|
|
127
|
+
def callback():
|
|
128
|
+
self.next(self._state_global)
|
|
129
|
+
self.sub_state(JavaClassBodyStates("(anonymous)", False, self.context), callback, token)
|
|
130
|
+
return
|
|
131
|
+
self.next(self._state_global)
|
|
132
|
+
|
|
133
|
+
class JavaClassBodyStates(JavaStates):
|
|
134
|
+
def __init__(self, class_name, is_record, context):
|
|
135
|
+
super(JavaClassBodyStates, self).__init__(context)
|
|
136
|
+
self.class_name = class_name
|
|
137
|
+
self.is_record = is_record
|
|
138
|
+
|
|
139
|
+
def _state_global(self, token):
|
|
140
|
+
super()._state_global(token)
|
|
141
|
+
if token == '}':
|
|
142
|
+
self.statemachine_return()
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
'''
|
|
2
|
+
Language parser for JavaScript
|
|
3
|
+
'''
|
|
4
|
+
|
|
5
|
+
from .typescript import TypeScriptReader
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class JavaScriptReader(TypeScriptReader):
|
|
9
|
+
# pylint: disable=R0903
|
|
10
|
+
|
|
11
|
+
ext = ['js', 'cjs', 'mjs']
|
|
12
|
+
language_names = ['javascript', 'js']
|
|
13
|
+
|
|
14
|
+
def __init__(self, context):
|
|
15
|
+
super(JavaScriptReader, self).__init__(context)
|
|
@@ -8,6 +8,20 @@ from .code_reader import CodeReader
|
|
|
8
8
|
from .js_style_regex_expression import js_style_regex_expression
|
|
9
9
|
|
|
10
10
|
|
|
11
|
+
class TSXTokenizer(JSTokenizer):
|
|
12
|
+
def __init__(self):
|
|
13
|
+
super().__init__()
|
|
14
|
+
|
|
15
|
+
def process_token(self, token):
|
|
16
|
+
if token == "<":
|
|
17
|
+
from .jsx import XMLTagWithAttrTokenizer # Import only when needed
|
|
18
|
+
self.sub_tokenizer = XMLTagWithAttrTokenizer()
|
|
19
|
+
return
|
|
20
|
+
|
|
21
|
+
for tok in super().process_token(token):
|
|
22
|
+
yield tok
|
|
23
|
+
|
|
24
|
+
|
|
11
25
|
class JSXMixin:
|
|
12
26
|
'''Base mixin class for JSX/TSX shared functionality'''
|
|
13
27
|
@staticmethod
|
|
@@ -17,7 +31,7 @@ class JSXMixin:
|
|
|
17
31
|
r"|(?:\$\w+)" + \
|
|
18
32
|
r"|(?:\<\/\w+\>)" + \
|
|
19
33
|
r"|`.*?`"
|
|
20
|
-
js_tokenizer =
|
|
34
|
+
js_tokenizer = TSXTokenizer()
|
|
21
35
|
for token in CodeReader.generate_tokens(
|
|
22
36
|
source_code, addition, token_class):
|
|
23
37
|
for tok in js_tokenizer(token):
|
|
@@ -102,7 +116,7 @@ class XMLTagWithAttrTokenizer(Tokenizer):
|
|
|
102
116
|
self.state = self._after_tag
|
|
103
117
|
elif token == "{":
|
|
104
118
|
self.cache.append("}")
|
|
105
|
-
self.sub_tokenizer =
|
|
119
|
+
self.sub_tokenizer = TSXTokenizer()
|
|
106
120
|
self.state = self._after_tag
|
|
107
121
|
|
|
108
122
|
def _body(self, token):
|
|
@@ -116,7 +130,7 @@ class XMLTagWithAttrTokenizer(Tokenizer):
|
|
|
116
130
|
return self.flush()
|
|
117
131
|
|
|
118
132
|
if token == '{':
|
|
119
|
-
self.sub_tokenizer =
|
|
133
|
+
self.sub_tokenizer = TSXTokenizer()
|
|
120
134
|
return self.flush()
|
|
121
135
|
|
|
122
136
|
|
|
@@ -9,11 +9,12 @@ from .script_language import ScriptLanguageMixIn
|
|
|
9
9
|
|
|
10
10
|
class MyToken(str):
|
|
11
11
|
def __new__(cls, value, *_):
|
|
12
|
-
|
|
12
|
+
val = value.group(0) if hasattr(value, 'group') else value
|
|
13
|
+
return super(MyToken, cls).__new__(cls, val)
|
|
13
14
|
|
|
14
15
|
def __init__(self, value):
|
|
15
16
|
super(MyToken, self).__init__()
|
|
16
|
-
self.begin = value.start()
|
|
17
|
+
self.begin = value.start() if hasattr(value, 'start') else 0
|
|
17
18
|
|
|
18
19
|
|
|
19
20
|
class RubyReader(RubylikeReader):
|
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
Language parser for TSX
|
|
3
3
|
'''
|
|
4
4
|
|
|
5
|
-
from .typescript import TypeScriptReader
|
|
5
|
+
from .typescript import TypeScriptReader
|
|
6
6
|
from .jsx import JSXMixin
|
|
7
|
-
from .code_reader import CodeReader
|
|
8
7
|
from .js_style_regex_expression import js_style_regex_expression
|
|
9
8
|
|
|
10
9
|
|
|
@@ -37,10 +37,6 @@ class JSTokenizer(Tokenizer):
|
|
|
37
37
|
self.depth = 1
|
|
38
38
|
|
|
39
39
|
def process_token(self, token):
|
|
40
|
-
if token == "<":
|
|
41
|
-
from .jsx import XMLTagWithAttrTokenizer # Import only when needed
|
|
42
|
-
self.sub_tokenizer = XMLTagWithAttrTokenizer()
|
|
43
|
-
return
|
|
44
40
|
if token == "{":
|
|
45
41
|
self.depth += 1
|
|
46
42
|
elif token == "}":
|
|
@@ -115,10 +111,18 @@ class TypeScriptTypeAnnotationStates(CodeStateMachine):
|
|
|
115
111
|
self.next(self._state_simple_type, token)
|
|
116
112
|
|
|
117
113
|
def _state_simple_type(self, token):
|
|
118
|
-
|
|
114
|
+
print(token)
|
|
115
|
+
if token == '<':
|
|
116
|
+
print(token)
|
|
117
|
+
self.next(self._state_generic_type, token)
|
|
118
|
+
elif token in '{=;':
|
|
119
119
|
self.saved_token = token
|
|
120
120
|
self.statemachine_return()
|
|
121
121
|
|
|
122
122
|
@CodeStateMachine.read_inside_brackets_then("{}")
|
|
123
123
|
def _inline_type_annotation(self, _):
|
|
124
124
|
self.statemachine_return()
|
|
125
|
+
|
|
126
|
+
@CodeStateMachine.read_inside_brackets_then("<>")
|
|
127
|
+
def _state_generic_type(self, token):
|
|
128
|
+
self.statemachine_return()
|
|
@@ -95,7 +95,7 @@ setup(
|
|
|
95
95
|
packages=['lizard_ext', 'lizard_languages'],
|
|
96
96
|
#data_files=[('lizard_ext', [])],
|
|
97
97
|
py_modules=['lizard'],
|
|
98
|
-
install_requires=['pygments'],
|
|
98
|
+
install_requires=['pygments', 'pathspec'],
|
|
99
99
|
entry_points={'console_scripts': ['lizard = lizard:main']},
|
|
100
100
|
author='Terry Yin',
|
|
101
101
|
author_email='terry@odd-e.com',
|
|
@@ -126,3 +126,34 @@ class TestFilesFilter(unittest.TestCase):
|
|
|
126
126
|
else:
|
|
127
127
|
file_names = ["./f1.cpp", "./f2.cpp"]
|
|
128
128
|
self.assertEqual(file_names, list(files))
|
|
129
|
+
|
|
130
|
+
@patch.object(os.path, "exists")
|
|
131
|
+
@patch.object(os.path, "relpath")
|
|
132
|
+
@patch.object(os, "walk")
|
|
133
|
+
@patch("builtins.open", create=True)
|
|
134
|
+
def test_gitignore_filter(self, mock_open, mock_os_walk, mock_relpath, mock_exists):
|
|
135
|
+
mock_os_walk.return_value = (['.',
|
|
136
|
+
None,
|
|
137
|
+
['temp.c', 'node_modules/file.js', 'useful.cpp']], )
|
|
138
|
+
|
|
139
|
+
def exists_side_effect(path):
|
|
140
|
+
return path.endswith('.gitignore')
|
|
141
|
+
mock_exists.side_effect = exists_side_effect
|
|
142
|
+
|
|
143
|
+
def relpath_side_effect(path, start):
|
|
144
|
+
# Return paths in a normalized format
|
|
145
|
+
if path.startswith('./'):
|
|
146
|
+
path = path[2:]
|
|
147
|
+
return path.replace(os.sep, '/')
|
|
148
|
+
mock_relpath.side_effect = relpath_side_effect
|
|
149
|
+
|
|
150
|
+
mock_file = mock_open.return_value.__enter__.return_value
|
|
151
|
+
mock_file.readlines.return_value = ["node_modules/\n", "*.c\n"]
|
|
152
|
+
mock_file.read.return_value = "node_modules/\n*.c\n"
|
|
153
|
+
|
|
154
|
+
files = get_all_source_files(["dir"], [], [])
|
|
155
|
+
if which_system() == "Windows":
|
|
156
|
+
file_names = [".\\useful.cpp"]
|
|
157
|
+
else:
|
|
158
|
+
file_names = ["./useful.cpp"]
|
|
159
|
+
self.assertEqual(file_names, list(files))
|
|
@@ -125,7 +125,7 @@ class TestAllOutput(StreamStdoutTestCase):
|
|
|
125
125
|
def test_should_not_print_extension_results_when_not_implemented(self):
|
|
126
126
|
file_infos = []
|
|
127
127
|
option = Mock(CCN=15, number = 0, thresholds={}, extensions = [object()], whitelist='')
|
|
128
|
-
|
|
128
|
+
print_result_with_scheme(file_infos, option)
|
|
129
129
|
|
|
130
130
|
def test_print_result(self):
|
|
131
131
|
file_infos = [FileInformation('f1.c', 1, []), FileInformation('f2.c', 1, [])]
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
from os.path import join
|
|
2
|
+
from shutil import rmtree
|
|
3
|
+
from tempfile import mkdtemp
|
|
4
|
+
import unittest
|
|
5
|
+
from lizard import html_output, print_xml, parse_args, main
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TestFileOutputArgParsing(unittest.TestCase):
|
|
9
|
+
|
|
10
|
+
def test_short(self):
|
|
11
|
+
args = parse_args(["lizard", "-o test_file"])
|
|
12
|
+
self.assertEqual("test_file", args.output_file.strip())
|
|
13
|
+
|
|
14
|
+
def test_long(self):
|
|
15
|
+
args = parse_args(["lizard", "--output_file", "test_file"])
|
|
16
|
+
self.assertEqual("test_file", args.output_file.strip())
|
|
17
|
+
|
|
18
|
+
def test_standalone(self):
|
|
19
|
+
args = parse_args(["lizard", "--output_file", "test_file.html"])
|
|
20
|
+
self.assertEqual(html_output, args.printer)
|
|
21
|
+
|
|
22
|
+
def test_override(self):
|
|
23
|
+
args = parse_args(["lizard", "--output_file test_file.html", "--xml"])
|
|
24
|
+
self.assertEqual(print_xml, args.printer)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class TestFileOutputIntegration(unittest.TestCase):
|
|
28
|
+
|
|
29
|
+
def setUp(self):
|
|
30
|
+
self.tmp_dir = mkdtemp()
|
|
31
|
+
print("Tmp directory '{}' created.\n".format(self.tmp_dir))
|
|
32
|
+
|
|
33
|
+
def tearDown(self):
|
|
34
|
+
rmtree(self.tmp_dir)
|
|
35
|
+
print("Tmp directory '{}' deleted.\n".format(self.tmp_dir))
|
|
36
|
+
|
|
37
|
+
def output_test(self, file_name, expected_first_line):
|
|
38
|
+
path = join(self.tmp_dir, file_name)
|
|
39
|
+
args = ["lizard", "--verbose", "--output_file", path, "test/data"]
|
|
40
|
+
main(args)
|
|
41
|
+
first_line = open(path, 'r').readline().strip('\n')
|
|
42
|
+
self.assertEqual(first_line, expected_first_line)
|
|
43
|
+
|
|
44
|
+
def test_default(self):
|
|
45
|
+
header = "================================================"
|
|
46
|
+
self.output_test("test", header)
|
|
47
|
+
|
|
48
|
+
def test_csv(self):
|
|
49
|
+
header = "NLOC,CCN,token,PARAM,length,location,file,function,long_name,start,end"
|
|
50
|
+
self.output_test("test.csv", header)
|
|
51
|
+
|
|
52
|
+
def test_html(self):
|
|
53
|
+
header = "<!DOCTYPE HTML PUBLIC"
|
|
54
|
+
self.output_test("test.html", header)
|
|
55
|
+
|
|
56
|
+
def test_xml(self):
|
|
57
|
+
header = "<?xml version=\"1.0\" ?>"
|
|
58
|
+
self.output_test("test.xml", header)
|
|
59
|
+
|
|
60
|
+
def test_html_output_with_extension(self):
|
|
61
|
+
"""Test that using --html with .html extension works correctly without warnings"""
|
|
62
|
+
path = join(self.tmp_dir, "test.html")
|
|
63
|
+
args = ["lizard", "--length", "75", "--CCN", "20", "--arguments", "3",
|
|
64
|
+
"--warnings_only", "--sort", "cyclomatic_complexity", "--html",
|
|
65
|
+
"--output_file", path, "test/data"]
|
|
66
|
+
|
|
67
|
+
# Capture stdout to check for warnings
|
|
68
|
+
import sys
|
|
69
|
+
from io import StringIO
|
|
70
|
+
stdout = StringIO()
|
|
71
|
+
old_stdout = sys.stdout
|
|
72
|
+
sys.stdout = stdout
|
|
73
|
+
|
|
74
|
+
try:
|
|
75
|
+
main(args)
|
|
76
|
+
output = stdout.getvalue()
|
|
77
|
+
self.assertNotIn("Warning: overriding output file extension", output,
|
|
78
|
+
"Should not show extension warning when using .html extension with --html")
|
|
79
|
+
|
|
80
|
+
# Verify the file exists and has HTML content
|
|
81
|
+
with open(path, 'r') as f:
|
|
82
|
+
content = f.read()
|
|
83
|
+
self.assertTrue(content.startswith("<!DOCTYPE HTML PUBLIC"),
|
|
84
|
+
"Output file should contain HTML content")
|
|
85
|
+
finally:
|
|
86
|
+
sys.stdout = old_stdout
|
|
87
|
+
|
|
88
|
+
def test_html_extension_warning(self):
|
|
89
|
+
"""Test that using --html with .html extension works correctly without warnings,
|
|
90
|
+
but using a different format with .html extension shows a warning"""
|
|
91
|
+
path = join(self.tmp_dir, "test.html")
|
|
92
|
+
|
|
93
|
+
# Capture stderr to check for warnings
|
|
94
|
+
import sys
|
|
95
|
+
from io import StringIO
|
|
96
|
+
stderr = StringIO()
|
|
97
|
+
old_stderr = sys.stderr
|
|
98
|
+
sys.stderr = stderr
|
|
99
|
+
|
|
100
|
+
try:
|
|
101
|
+
# First test: --html with .html extension should not warn
|
|
102
|
+
args = ["lizard", "--html", "--output_file", path, "test/data"]
|
|
103
|
+
main(args)
|
|
104
|
+
output = stderr.getvalue()
|
|
105
|
+
self.assertNotIn("Warning: overriding output file extension", output,
|
|
106
|
+
"Should not show warning when format matches extension")
|
|
107
|
+
stderr.truncate(0)
|
|
108
|
+
stderr.seek(0)
|
|
109
|
+
|
|
110
|
+
# Second test: --xml with .html extension should warn
|
|
111
|
+
args = ["lizard", "--xml", "--output_file", path, "test/data"]
|
|
112
|
+
main(args)
|
|
113
|
+
output = stderr.getvalue()
|
|
114
|
+
self.assertIn("Warning: overriding output file extension", output,
|
|
115
|
+
"Should show warning when format doesn't match extension")
|
|
116
|
+
finally:
|
|
117
|
+
sys.stderr = old_stderr
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
'''
|
|
2
|
-
Language parser for C Sharp
|
|
3
|
-
'''
|
|
4
|
-
|
|
5
|
-
from .clike import CLikeReader
|
|
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
|
-
@staticmethod
|
|
18
|
-
def generate_tokens(source_code, addition='', token_class=None):
|
|
19
|
-
return CLikeReader.generate_tokens(
|
|
20
|
-
source_code, r"|(?:\?\?)", token_class)
|
|
@@ -1,44 +0,0 @@
|
|
|
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 _state_old_c_params(self, token):
|
|
23
|
-
if token == '{':
|
|
24
|
-
self._state_dec_to_imp(token)
|
|
25
|
-
|
|
26
|
-
def try_new_function(self, name):
|
|
27
|
-
self.context.try_new_function(name)
|
|
28
|
-
self._state = self._state_function
|
|
29
|
-
|
|
30
|
-
def _state_global(self, token):
|
|
31
|
-
if token == '@':
|
|
32
|
-
self._state = self._state_decorator
|
|
33
|
-
return
|
|
34
|
-
super(JavaStates, self)._state_global(token)
|
|
35
|
-
|
|
36
|
-
def _state_decorator(self, _):
|
|
37
|
-
self._state = self._state_post_decorator
|
|
38
|
-
|
|
39
|
-
def _state_post_decorator(self, token):
|
|
40
|
-
if token == '.':
|
|
41
|
-
self._state = self._state_decorator
|
|
42
|
-
else:
|
|
43
|
-
self._state = self._state_global
|
|
44
|
-
self._state(token)
|
|
@@ -1,19 +0,0 @@
|
|
|
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)
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
from os.path import join
|
|
2
|
-
from shutil import rmtree
|
|
3
|
-
from tempfile import mkdtemp
|
|
4
|
-
import unittest
|
|
5
|
-
from lizard import html_output, print_xml, parse_args, main
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class TestFileOutputArgParsing(unittest.TestCase):
|
|
9
|
-
|
|
10
|
-
def test_short(self):
|
|
11
|
-
args = parse_args(["lizard", "-o test_file"])
|
|
12
|
-
self.assertEqual("test_file", args.output_file.strip())
|
|
13
|
-
|
|
14
|
-
def test_long(self):
|
|
15
|
-
args = parse_args(["lizard", "--output_file", "test_file"])
|
|
16
|
-
self.assertEqual("test_file", args.output_file.strip())
|
|
17
|
-
|
|
18
|
-
def test_standalone(self):
|
|
19
|
-
args = parse_args(["lizard", "--output_file", "test_file.html"])
|
|
20
|
-
self.assertEqual(html_output, args.printer)
|
|
21
|
-
|
|
22
|
-
def test_override(self):
|
|
23
|
-
args = parse_args(["lizard", "--output_file test_file.html", "--xml"])
|
|
24
|
-
self.assertEqual(print_xml, args.printer)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
class TestFileOutputIntegration(unittest.TestCase):
|
|
28
|
-
|
|
29
|
-
def setUp(self):
|
|
30
|
-
self.tmp_dir = mkdtemp()
|
|
31
|
-
print("Tmp directory '{}' created.\n".format(self.tmp_dir))
|
|
32
|
-
|
|
33
|
-
def tearDown(self):
|
|
34
|
-
rmtree(self.tmp_dir)
|
|
35
|
-
print("Tmp directory '{}' deleted.\n".format(self.tmp_dir))
|
|
36
|
-
|
|
37
|
-
def output_test(self, file_name, expected_first_line):
|
|
38
|
-
path = join(self.tmp_dir, file_name)
|
|
39
|
-
args = ["lizard", "--verbose", "--output_file", path, "test/data"]
|
|
40
|
-
main(args)
|
|
41
|
-
first_line = open(path, 'r').readline().strip('\n')
|
|
42
|
-
self.assertEqual(first_line, expected_first_line)
|
|
43
|
-
|
|
44
|
-
def test_default(self):
|
|
45
|
-
header = "================================================"
|
|
46
|
-
self.output_test("test", header)
|
|
47
|
-
|
|
48
|
-
def test_csv(self):
|
|
49
|
-
header = "NLOC,CCN,token,PARAM,length,location,file,function,long_name,start,end"
|
|
50
|
-
self.output_test("test.csv", header)
|
|
51
|
-
|
|
52
|
-
def test_html(self):
|
|
53
|
-
header = "<!DOCTYPE HTML PUBLIC"
|
|
54
|
-
self.output_test("test.html", header)
|
|
55
|
-
|
|
56
|
-
def test_xml(self):
|
|
57
|
-
header = "<?xml version=\"1.0\" ?>"
|
|
58
|
-
self.output_test("test.xml", header)
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|