使用Doxygen和非Doxygen评论源代码创建文档

时间:2017-08-10 13:17:15

标签: c++ c doxygen documentation-generation

我们在这里得到了一些像10年前的C和C ++代码,没有文档或手册。然而,源文件在头文件中记录得相当不错,但是在查找信息的所有文件中有很多工作要做。它看起来像这样:

var data = {"id":"27","kode":"1111","judul":"q","penulis":"q","penerbit":"q","tahun_terbit":"1","tgl_masuk":"2017-08-09","tgl_update":"2017-08-09"}

使用doxygen向导可以创建文档,但所有注释都会丢失,因为它们不会以解析器理解的方式格式化。

那是我不知道的格式吗?我可以教解析器怎么做?或者它是另一种软件使用的特殊格式?

1 个答案:

答案 0 :(得分:0)

我写了一个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 ++文件如果是头文件则转换,如果它们是源文件则只复制。因此,创建了一个目录.. \ converted,其中包含复制/转换的文件。

使用生成的文件doxygen向导创建了足够的文档。也许这会帮助某人: - )