Skip to content

Commit f7b34e3

Browse files
committed
#25 fixed paths after re-structure
1 parent 389888a commit f7b34e3

3 files changed

Lines changed: 284 additions & 3 deletions

File tree

tools/documentation_level_check.py

Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
1+
#!/usr/bin/python3
2+
# Copyright 2021 Covidien LP.
3+
# All Rights Reserved. The information contained herein is confidential
4+
# property of Covidien. The use, copying, transfer or disclosure of such
5+
# information is prohibited except by written agreement with Covidien.
6+
7+
import re
8+
9+
# Separator for documentation file.
10+
SEPARATOR_LENGTH = 40
11+
# Skipping line if it starts with:
12+
WORDS_TO_SKIP = ["#", "using ", "typedef "]
13+
14+
15+
class DocumentationChecker:
16+
17+
def __init__(self, source_file):
18+
self.__lines = []
19+
self.__all_entities = 0
20+
self.__commented_entities = 0
21+
self.__file_errors = []
22+
self.__source_file = source_file
23+
24+
def check_file(self):
25+
"""
26+
Checks how many doxygen lines are supposed to be in file, and how many there are
27+
:return: errors list with expected and actual results, documentation level percentage
28+
"""
29+
with open(self.__source_file, "r", encoding='utf-8') as f:
30+
# Looping through all lines in file. Breaking if line was not found
31+
while True:
32+
line = self.get_next_line(f)
33+
if not line:
34+
break
35+
36+
if "class " in line or "struct " in line:
37+
self.check_one_class(line, f)
38+
self.__lines = []
39+
continue
40+
41+
if "enum " in line:
42+
self.__all_entities += 1
43+
if any("///" in l and "\\brief" in l for l in self.__lines):
44+
self.__commented_entities += 1
45+
else:
46+
expected = "/// \\brief [enum description]/n (Maybe use enum class instead)"
47+
self.add_error(expected)
48+
self.__lines = []
49+
50+
elif "union " in line:
51+
self.__all_entities += 1
52+
if any("///" in l and "\\brief" in l for l in self.__lines):
53+
self.__commented_entities += 1
54+
else:
55+
expected = "/// \\brief [union description]/n (Unions shouldn't be used at all))"
56+
self.add_error(expected)
57+
self.__lines = []
58+
59+
elif line.startswith("const") and ("(" not in line.split("=")[0] or "(" not in line.split("{")[0]):
60+
self.__all_entities += 1
61+
if any("///" in l for l in self.__lines):
62+
self.__commented_entities += 1
63+
else:
64+
expected = "/// [const description]"
65+
self.add_error(expected)
66+
self.__lines = []
67+
68+
elif "(" in line:
69+
self.check_one_function(line, f)
70+
self.__lines = []
71+
continue
72+
73+
if "{" in line and "}" not in line:
74+
curly_brackets = 1
75+
while curly_brackets != 0:
76+
line = f.readline()
77+
if "{" in line:
78+
curly_brackets += 1
79+
if "}" in line:
80+
curly_brackets -= 1
81+
82+
if self.__all_entities == 0:
83+
percent = 1
84+
else:
85+
percent = self.__commented_entities / self.__all_entities
86+
if percent < 0.7:
87+
print('documentation check for file ' + self.__source_file.split('/Tests/')[1] + ' failed')
88+
else:
89+
print('documentation check for file ' + self.__source_file.split('/Tests/')[1] + ' is OK')
90+
return self.__file_errors, percent
91+
92+
def check_one_class(self, line, f):
93+
if ";" in line:
94+
return
95+
self.__all_entities += 1
96+
97+
class_name = line.split("class ")
98+
if len(class_name) == 1:
99+
class_name = line.split("struct ")
100+
class_name = class_name[1]
101+
class_name = re.sub('[{:}\n]', ' ', class_name)
102+
class_name = class_name.split(" ")[0]
103+
104+
if any("///" in l and "\\brief" in l for l in self.__lines):
105+
self.__commented_entities += 1
106+
else:
107+
expected = "/// \\brief [class/struct description]"
108+
self.add_error(expected)
109+
self.__lines = []
110+
111+
# Looping through class fields looking for functions
112+
while "{" not in line:
113+
line = f.readline()
114+
if "}" not in line:
115+
curly_brackets = 1
116+
while curly_brackets != 0:
117+
line = self.get_next_line(f)
118+
119+
if "class " in line or "struct " in line:
120+
self.check_one_class(line, f)
121+
self.__lines = []
122+
continue
123+
124+
if "(" in line:
125+
self.check_one_function(line, f, class_name)
126+
self.__lines = []
127+
continue
128+
129+
if "{" in line:
130+
curly_brackets += 1
131+
if "}" in line:
132+
curly_brackets -= 1
133+
134+
def check_one_function(self, line, f, class_name=""):
135+
136+
function_desc = line.split("(", 1)
137+
function_desc[0] = function_desc[0].strip()
138+
139+
# Skipping lambdas
140+
if "=" not in function_desc[0] and re.search(r'[^\W\d]', function_desc[0]):
141+
# Skipping function call but not a declaration
142+
if function_desc[0].count(" ") != 0 or (not class_name or class_name not in function_desc[0]):
143+
expected = ""
144+
self.__all_entities += 1
145+
if any("///" in l and "\\brief" in l for l in self.__lines):
146+
self.__commented_entities += 1
147+
else:
148+
expected = "/// \\brief [function description]\n\n"
149+
150+
function_params = function_desc[1]
151+
round_brackets = 1 + function_params.count("(") - function_params.count(")")
152+
while round_brackets != 0:
153+
function_params += f.readline()
154+
round_brackets = 1 + function_params.count("(") - function_params.count(")")
155+
function_params = function_params.rsplit(")", 1)[0]
156+
if not (function_params.strip() == ""):
157+
function_params = function_params.split(",")
158+
self.__all_entities += len(function_params)
159+
commented_params = sum("\\param" in l for l in self.__lines)
160+
self.__commented_entities += commented_params
161+
if commented_params != len(function_params):
162+
for i in range(len(function_params)):
163+
expected += "/// \\param [parameter description]\n\n"
164+
165+
if function_desc[0].count(" ") > 0 and "void " not in function_desc[0]:
166+
self.__all_entities += 1
167+
if any("///" in l and "\\return" in l for l in self.__lines):
168+
self.__commented_entities += 1
169+
else:
170+
expected += "/// \\return [return description]"
171+
172+
if expected:
173+
self.add_error(expected)
174+
175+
while ";" not in line and "{" not in line:
176+
line = f.readline()
177+
178+
if "{" in line and "}" not in line:
179+
curly_brackets = 1
180+
while curly_brackets != 0:
181+
line = f.readline()
182+
if "{" in line:
183+
curly_brackets += 1
184+
if "}" in line:
185+
curly_brackets -= 1
186+
187+
def get_next_line(self, f):
188+
line = f.readline()
189+
while line:
190+
if "namespace " in line:
191+
while "{" not in line and ";" not in line:
192+
line = f.readline()
193+
line = f.readline()
194+
continue
195+
196+
line = line.replace("static ", '')
197+
line = line.replace("extern ", '')
198+
line = line.replace("virtual ", '')
199+
line = line.replace("volatile ", '')
200+
line = line.replace("register ", '')
201+
line = line.strip()
202+
203+
# Deleting quoted text.
204+
line = re.sub("[\"].*[\"]", "", line)
205+
206+
if any(line.startswith(word) for word in WORDS_TO_SKIP):
207+
self.__lines = []
208+
line = f.readline()
209+
continue
210+
211+
if line.startswith("template"):
212+
triangle_brackets = line.count("<") - line.count(">")
213+
while triangle_brackets != 0:
214+
line = f.readline()
215+
triangle_brackets += line.count("<") - line.count(">")
216+
line = f.readline()
217+
218+
self.__lines.append(line)
219+
if "//" in line:
220+
line = f.readline()
221+
continue
222+
223+
if not line:
224+
line = f.readline()
225+
continue
226+
227+
break
228+
return line
229+
230+
def add_error(self, expected):
231+
self.__file_errors.append('==' * SEPARATOR_LENGTH)
232+
self.__file_errors.append('FILE: {}'.format(self.__source_file))
233+
self.__file_errors.append('==' * SEPARATOR_LENGTH)
234+
235+
self.__file_errors.append('Valid doxygen line not found\n')
236+
self.__file_errors.append('Expected: "{}"\n'.format(expected))
237+
238+
self.__file_errors.append('Actual: ')
239+
self.__file_errors.append('"""')
240+
for line in self.__lines[-3:]:
241+
self.__file_errors.append(line)
242+
self.__file_errors.append('...')
243+
self.__file_errors.append('"""')
244+
245+
246+
def check_one_file(source_file):
247+
d = DocumentationChecker(source_file)
248+
return d.check_file()
249+
250+
251+
def documentation_check(dir_to_check, exclude_dirs, common_dirs):
252+
extensions = ('.h')
253+
test_files_to_check = get_tests_code_files(dir_to_check, extensions=extensions, exclude_dirs=exclude_dirs, common_dirs=common_dirs)
254+
common_files_to_check = get_common_code_files(dir_to_check, extensions=extensions, exclude_dirs=exclude_dirs, common_dirs=common_dirs)
255+
results = { 'test_code' : {}, 'common_code' : {} }
256+
extended_results = { 'test_code' : {}, 'common_code' : {} }
257+
for test_file in test_files_to_check:
258+
if test_file.endswith("-inl.h"):
259+
continue
260+
errors, percent = documentation_level_check.check_one_file(test_file)
261+
if errors:
262+
results['test_code'][test_file.split('/Tests/')[1]] = errors
263+
if percent < 0.7:
264+
extended_results['test_code'][test_file.split('/Tests/')[1]] = "Fail"
265+
else:
266+
extended_results['test_code'][test_file.split('/Tests/')[1]] = "Pass"
267+
else:
268+
extended_results['test_code'][test_file.split('/Tests/')[1]] = "Pass"
269+
for common_file in common_files_to_check:
270+
if common_file.endswith("-inl.h"):
271+
continue
272+
errors, percent = documentation_level_check.check_one_file(common_file)
273+
if errors:
274+
results['common_code'][common_file.split('/Tests/')[1]] = errors
275+
if percent < 0.7:
276+
extended_results['common_code'][common_file.split('/Tests/')[1]] = "Fail"
277+
else:
278+
extended_results['common_code'][common_file.split('/Tests/')[1]] = "Pass"
279+
else:
280+
extended_results['common_code'][common_file.split('/Tests/')[1]] = "Pass"
281+
return results, extended_results

tools/format_fix.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
find test -regex '.*\.\(cpp\|h\|cc\|cxx\)' -exec clang-format-17 -i {} \;
2-
find src -regex '.*\.\(cpp\|h\|cc\|cxx\)' -exec clang-format-17 -i {} \;
1+
find tests -regex '.*\.\(cpp\|h\|cc\|cxx\)' -exec clang-format-17 -i {} \;
2+
find src -regex '.*\.\(cpp\|h\|cc\|cxx\)' -exec clang-format-17 -i {} \;

tools/format_fix_cmake.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
cmake-format -i CMakeLists.txt
22
cmake-format -i src/CMakeLists.txt
3-
cmake-format -i test/CMakeLists.txt
3+
cmake-format -i tests/CMakeLists.txt

0 commit comments

Comments
 (0)