使用 Doxygen 和非 Doxygen 注释源代码创建文档
Create Documentation using Doxygen and non-Doxygen commented source code
我们在这里得到了一些像 10 年前的 C 和 C++ 代码,没有文档或手册。然而,头文件中的源代码记录得很好,但是要遍历所有文件以查找信息需要大量工作。它看起来像这样:
// Description description ....
//
// @param parameter 1 name:
// description of parameter 1
//
// @param parameter 2 name:
// description of parameter 2
//
Returntype Functionname(parameter1, parameter2);
使用 doxygen 向导可以创建文档,但所有注释都将丢失,因为它们的格式不是解析器可以理解的。
那是我不知道的格式吗?我可以教解析器做什么吗?还是其他软件使用的特殊格式?
我写了一个 python 脚本,将注释转换为解析器可以理解的格式。它不漂亮,也不安全,但对我们有用。
import re
import time
import os
import shutil
def convertHeaderDocumentation(file):
with open(file) as f:
lines = f.readlines()
lines = [line.rstrip('\n') for line in lines]
scanning = False
commentLines = []
convertedDocument = ""
declaration = ""
for line in lines:
if line == "" or \
line.strip().startswith("#"):
if len(commentLines) > 0:
convertedDocument += ''.join(el + "\n" for el in commentLines)
commentLines.clear()
convertedDocument += line + "\n"
continue
if line.strip().startswith('//'):
if not scanning:
commentLines.clear()
scanning = True
commentLines.append(line)
else:
if scanning:
if line.strip() != "":
declaration = line.strip()
match = re.search('\s*\w*\s*(\w+)\s+(\w+).*\((.*)[^)].*;', declaration)
if not match is None:
# check for function description
description = ""
for line in commentLines:
if line[2:].strip().startswith("@") or \
line[2:].strip() == "":
break
else:
description += line[2:].strip()
# scan for parameter description
parameters = []
parameter = ""
scanning = False
for line in commentLines:
# start scanning, if line starts with @
if line[2:].strip().startswith("@") and \
scanning == False :
# if present add to parameter lst
if parameter != "":
parameters.append(parameter)
scanning = True
parameter = line[2:].strip() + " "
continue
# stop scanning if an empty line is read
if line[2:].strip() == "":
scanning = False
# save if parameter is in buffer
if parameter != "":
parameters.append(parameter)
parameter = ""
if scanning == True and line[2:].strip() != "":
parameter += line[2:].strip()
convertedDocument += "/**\n"
convertedDocument += " * @fn " + declaration[:-1] + "\n"
convertedDocument += " *\n"
convertedDocument += " * @brief "
restLine = 80 - len(" * @brief ")
for index in range(0, len(description), restLine):
convertedDocument += description[index:index + restLine] + "\n * "
convertedDocument += "\n"
for parameter in parameters:
convertedDocument += " * " + parameter + "\n *\n"
convertedDocument += " * @return " + match.group(1) + "\n"
convertedDocument += " *\n"
convertedDocument += " * @date " + time.strftime("%d.%m.%Y") + "<br> parsed using python\n"
convertedDocument += " */\n"
convertedDocument += declaration + "\n\n"
commentLines.clear()
else :
convertedDocument += ''.join(el + "\n" for el in commentLines)
commentLines.clear();
return convertedDocument
projectDir = "path to source files goes here"
projectDir = os.abspath(projectDir)
parentProjectDir, projectDirName = os.path.split(projectDir)
convertedDir = os.path.join(parentProjectDir, "converted")
print(convertedDir)
for root, dirs, files in os.walk(projectDir):
# create directory structure if not present
tmpConvertedDir = os.path.join(convertedDir, root[len(projectDir) + 1:])
if not os.path.exists(tmpConvertedDir):
os.makedirs(tmpConvertedDir)
for file in files:
filename, fileextension = os.path.splitext(file)
# only copy/convert c++/c source files
if fileextension in {'.h','.c','.cpp'} :
newPath = os.path.join(tmpConvertedDir, file)
print(newPath)
# convert header files
if fileextension in {'.h'}:
#print("convert ", os.path.join(root, file), " to ", newPath)
converted = convertHeaderDocumentation(os.path.join(root, file))
with open(newPath, 'w') as f:
f.write(converted)
# copy source files
else:
print("copy ", os.path.join(root, file), " to ", newPath)
shutil.copyfile(os.path.join(root, file), newPath)
使用正则表达式捕捉函数声明有点棘手。对于我的情况
\s*\w*\s*(\w+)\s+(\w+).*\((.*)[^)].*;
工作得很好,但是如果没有任何额外的关键字,惰性量词对于返回类型 \s*\w*?\s*(\w+)\s+(\w+).*\((.*)[^)].*;
之前的关键字会更准确
给定的 projectDir 目录和子文件夹中的所有 C 和 C++ 文件如果是头文件则被转换,或者如果它们是源文件则只复制。因此创建了一个包含 copied/converted 文件的目录 ..\converted。
doxygen 向导使用生成的文件创建了足够的文档。也许这会对某人有所帮助:-)
我们在这里得到了一些像 10 年前的 C 和 C++ 代码,没有文档或手册。然而,头文件中的源代码记录得很好,但是要遍历所有文件以查找信息需要大量工作。它看起来像这样:
// Description description ....
//
// @param parameter 1 name:
// description of parameter 1
//
// @param parameter 2 name:
// description of parameter 2
//
Returntype Functionname(parameter1, parameter2);
使用 doxygen 向导可以创建文档,但所有注释都将丢失,因为它们的格式不是解析器可以理解的。
那是我不知道的格式吗?我可以教解析器做什么吗?还是其他软件使用的特殊格式?
我写了一个 python 脚本,将注释转换为解析器可以理解的格式。它不漂亮,也不安全,但对我们有用。
import re
import time
import os
import shutil
def convertHeaderDocumentation(file):
with open(file) as f:
lines = f.readlines()
lines = [line.rstrip('\n') for line in lines]
scanning = False
commentLines = []
convertedDocument = ""
declaration = ""
for line in lines:
if line == "" or \
line.strip().startswith("#"):
if len(commentLines) > 0:
convertedDocument += ''.join(el + "\n" for el in commentLines)
commentLines.clear()
convertedDocument += line + "\n"
continue
if line.strip().startswith('//'):
if not scanning:
commentLines.clear()
scanning = True
commentLines.append(line)
else:
if scanning:
if line.strip() != "":
declaration = line.strip()
match = re.search('\s*\w*\s*(\w+)\s+(\w+).*\((.*)[^)].*;', declaration)
if not match is None:
# check for function description
description = ""
for line in commentLines:
if line[2:].strip().startswith("@") or \
line[2:].strip() == "":
break
else:
description += line[2:].strip()
# scan for parameter description
parameters = []
parameter = ""
scanning = False
for line in commentLines:
# start scanning, if line starts with @
if line[2:].strip().startswith("@") and \
scanning == False :
# if present add to parameter lst
if parameter != "":
parameters.append(parameter)
scanning = True
parameter = line[2:].strip() + " "
continue
# stop scanning if an empty line is read
if line[2:].strip() == "":
scanning = False
# save if parameter is in buffer
if parameter != "":
parameters.append(parameter)
parameter = ""
if scanning == True and line[2:].strip() != "":
parameter += line[2:].strip()
convertedDocument += "/**\n"
convertedDocument += " * @fn " + declaration[:-1] + "\n"
convertedDocument += " *\n"
convertedDocument += " * @brief "
restLine = 80 - len(" * @brief ")
for index in range(0, len(description), restLine):
convertedDocument += description[index:index + restLine] + "\n * "
convertedDocument += "\n"
for parameter in parameters:
convertedDocument += " * " + parameter + "\n *\n"
convertedDocument += " * @return " + match.group(1) + "\n"
convertedDocument += " *\n"
convertedDocument += " * @date " + time.strftime("%d.%m.%Y") + "<br> parsed using python\n"
convertedDocument += " */\n"
convertedDocument += declaration + "\n\n"
commentLines.clear()
else :
convertedDocument += ''.join(el + "\n" for el in commentLines)
commentLines.clear();
return convertedDocument
projectDir = "path to source files goes here"
projectDir = os.abspath(projectDir)
parentProjectDir, projectDirName = os.path.split(projectDir)
convertedDir = os.path.join(parentProjectDir, "converted")
print(convertedDir)
for root, dirs, files in os.walk(projectDir):
# create directory structure if not present
tmpConvertedDir = os.path.join(convertedDir, root[len(projectDir) + 1:])
if not os.path.exists(tmpConvertedDir):
os.makedirs(tmpConvertedDir)
for file in files:
filename, fileextension = os.path.splitext(file)
# only copy/convert c++/c source files
if fileextension in {'.h','.c','.cpp'} :
newPath = os.path.join(tmpConvertedDir, file)
print(newPath)
# convert header files
if fileextension in {'.h'}:
#print("convert ", os.path.join(root, file), " to ", newPath)
converted = convertHeaderDocumentation(os.path.join(root, file))
with open(newPath, 'w') as f:
f.write(converted)
# copy source files
else:
print("copy ", os.path.join(root, file), " to ", newPath)
shutil.copyfile(os.path.join(root, file), newPath)
使用正则表达式捕捉函数声明有点棘手。对于我的情况
\s*\w*\s*(\w+)\s+(\w+).*\((.*)[^)].*;
工作得很好,但是如果没有任何额外的关键字,惰性量词对于返回类型 \s*\w*?\s*(\w+)\s+(\w+).*\((.*)[^)].*;
给定的 projectDir 目录和子文件夹中的所有 C 和 C++ 文件如果是头文件则被转换,或者如果它们是源文件则只复制。因此创建了一个包含 copied/converted 文件的目录 ..\converted。
doxygen 向导使用生成的文件创建了足够的文档。也许这会对某人有所帮助:-)