Simone Margaritelli
Simone Margaritelli

Reputation: 4733

Any software to auto generate doxygen comment blocks?

I'm developing a large C++ program and I've now decided to document it with Doxygen. There are plenty of classes, methods, functions, macros and so on. Therefore I'm searching for software that would scan my source tree and insert Doxygen comment blocks on top of every "documentable item" to let me edit them later and add details such as method descriptions and so on.

Does any such software exist?

I'm under GNU/Linux with the Code::Blocks IDE, so no Visual Studio plugins are needed.

Upvotes: 17

Views: 23428

Answers (7)

RufusVS
RufusVS

Reputation: 4127

Check your editor. I have been using the CodeWright editor, and it has a feature called selective display. Configured properly I can press the icon, and only the first line of function definitions is displayed. Alternatively, you can use block collapse/expand in some other editors. Either way makes it easy to speedily navigate through your source code to headers/definitions, etc and then paste some boiler plate comment to be filled in later. I often use my own search tags, e.g. COMMENTME in my code that I can get back to with simple searches.

Upvotes: 0

user2827968
user2827968

Reputation:

There is also a free Doxygen generator for C++ that uses the macro explorer plugin for Visual Studio 2015, which can be found here: https://github.com/cppocl/visual_studio_macros

Upvotes: 0

user939719
user939719

Reputation: 29

The posting for genDoxygenC.py has numerous index/whitespace errors. Since Python program flow is dependent on proper indexing I am concerned that the inner block the addDoxygenComment method might not have been correct. Is there a chance you could post the actual source file to here?

Upvotes: 1

parasrish
parasrish

Reputation: 4152

There are some c/cpp parsers in python, that might be used for your specific purpose. However, I have never used those yet.

For a similar objective, I wrote a python script that adds "doxygen-headers" to the methods in the header-file majorly. I have used regular expression, and I have a version that adds "doxygen headers" in the source file for the method-definitions (use RE_M_DEFINITION, at method-lookup).

Code for your reference, as below:

genDoxygenC.py

#!/usr/bin/python

import os
import sys
import re

################################################################

RE_MULTI_LINE_PARAMS = ".*"

# could be used in header/source files, for method-definition extraction
RE_M_DEFINITION  = r'[A-Za-z0-9*]*\s*[A-Za-z0-9_*]+\s*[A-Za-z0-9_~:*]+\(.*\)\s*\{\s*.*?\s*\}'   #TODO:  this needs to be more generic to                                                        be able to parse for methods only
# used in header-files in major for method declaration extraction
RE_M_DECLERATION = r"[A-Za-z0-9*]*\s*[A-Za-z0-9_*]+\s+[A-Za-z0-9_~*]+\s*\(%s\)\s*;"%RE_MULTI_LINE_PARAMS

################################################################

# C/CPP CMD List
cmdList = ["for","if","while","switch","else"];

##########################
# exit errors enumerations
class EErrors() :
    IncorrectUsage, FileOpenError = range(2)

###################
# exception handler
def handleException(e, mssg) :
    if e == EErrors.IncorrectUsage :
        print "Usage : "+mssg
        elif e == EErrors.FileOpenError :
        print "Unable to open \"" + mssg + "\" file !"
    sys.exit(2)

###############################
# creates method doxygen header 
def frameDoxygenHeader(param_count, paramList) :
    commentStr = "/**\n * @brief \n"    
    if param_count > 0 :
        for param in paramList:
            commentStr = commentStr + " * @param \n"

    # comment for return values
    commentStr = commentStr + " * @return \n */ \n"

    return commentStr

##############################################
# adds the doxygen comments, on method lookup
def addDoxygenComment(file_name, funcList) :
    try:    
        fh = open(file_name, 'rb')
        f_old = open(file_name, 'r+') 
    except:
                handleException(EErrors.FileOpenError, file_name)

    f_new = open(out_file_name, "w")
    final_loc = 0
    next_split_loc = 0
    last_write_loc = 0
    fContent = str(f_old.read())
    for func in funcList:
        SEARCH_TEXT = func  
        print "SEARCH_TEXT "+SEARCH_TEXT
            fsize =  os.path.getsize(file_name)
            bsize = fsize
            word_len = len(SEARCH_TEXT)
        fh.seek(0)

        # doxygen comment header generation
        paramListStr = re.findall(r'\(.*\)', SEARCH_TEXT)
        paramListStr[0] = paramListStr[0].replace('(','')
        paramListStr[0] = paramListStr[0].replace(')','')
        paramList = paramListStr[0].split(",")
        comment_text = frameDoxygenHeader(len(paramList),paramList)

        while True:
                    found = 0
                    pr = fh.read(bsize)
                    pf = pr.find(SEARCH_TEXT, next_split_loc)
                    if pf > -1:
                            found = 1
                            pos_dec = fh.tell() - (bsize - pf)
                            fh.seek(pos_dec + word_len)
                            bsize = fsize - fh.tell()
                print "Case-I:"+str(fh.tell())
                    if fh.tell() < fsize:
                                   seek = fh.tell() - word_len + 1
                                   print "seek"+str(seek)
                       fh.seek(seek)
                                   if 1==found:
                                           final_loc = seek
                           next_split_loc = final_loc + word_len - 1
                                           print "loc: "+str(final_loc)
                       print "Case-IIa:"+str(fh.tell())
                    else:
                                   break

        # create file with doxygen comments
        if final_loc != -1 :
            #f_new.write(fContent[0:final_loc-1]);
            #not to miss the contents, between two methods          
            if last_write_loc < final_loc :
                f_new.write(fContent[last_write_loc:final_loc-1]);

            f_new.write(comment_text);
            f_new.write(fContent[final_loc-1:next_split_loc])
            last_write_loc = next_split_loc

            #reset values
            final_loc = -1
        else:
            print "method not found !!"

    # last of the file should not be missed either
    if last_write_loc < len(fContent) :
        f_new.write(fContent[last_write_loc:]);
    f_new.close()
    f_old.close()


#############################################
#############################################
# main execution of the code starts from here
#############################################
argc = len(sys.argv)
if (argc == 1 or argc >2)  :
    handleException(EErrors.IncorrectUsage, "genDoxygenC.py <cpp source file>")
else :
    # Correct Input as per USAGE.
    fname = sys.argv[1]
    out_file_name = fname+'.doxygen'
    fcontent=''
    try:
        # read file
        fh = open(fname)
        fcontent = fh.read()
    #   print fcontent
    except:
        handleException(EErrors.FileOpenError, fname)

    # lookup for methods in file
    funcList = re.findall(RE_M_DECLERATION, fcontent, re.VERBOSE)
    fh.close()

    funcListCopy = funcList
    for fStr in funcListCopy :
        fStr = fStr.lstrip()
        startW = fStr.partition(' ')[0]
        startW = fStr.partition('(')[0]
        #print startW
        if startW in cmdList :
            # invalid method extraction
            funcList.remove(fStr)   

    # process valid methods-list for doxygen header
    addDoxygenComment(fname, funcList)
    #print funcList

Usage :: ./genDoxygenC.py file.h

This will generate

file.h.doxygen

and then, you can probably check the doxygen-headers-added-file, with original-header-file using any diff-tool.

Example : meld file.h file.h.doxygen

Note:: The script might skip constructors, with new versions definitions/declarations like;

S() : n(7)) {};

Upvotes: 1

Renato Coelho
Renato Coelho

Reputation: 21

Ok, so this is an old post, but I just had the same problem and I've found doxymacs. It integrates nicely with emacs and generates doxymacs comments for your functions and files. After putting the .el file in your emacs path you can add a hook to make it available whenever you open a C/C++ file "(add-hook 'c-mode-common-hook'doxymacs-mode)" and comment the functions with C-c d f and the files with C-c d i, there are other comment types available, just check the project page: http://doxymacs.sourceforge.net/

Upvotes: 2

Matthieu M.
Matthieu M.

Reputation: 299730

I am quite perplex here.

What is the goal of automatically generating comments ?

Comments are meant to bring additional value:

/**
 * \brief: finds the person based on its name
 * \param: name, the name of the person
 * \result: the person
 */
Person findPerson(Name name);

Is nothing but code clutter that clog my valuable screen estate. And that's about as much as can be generated automatically unfortunately... Notice in particular that I have no idea of what happens if ever the function does not find the person, which certainly seems likely: does it abort ? throws ? (what... ?) returns a default constructed object ?

On the other hand:

///
/// Try an exact match approach to begin with
/// Uses the double metaphone algorithm
///   if none was found as we have
///   a western european clientele
///
Person findPerson(Name name)
{
}

is much more interesting!

  • Now I know what is this strange collection of if that seems to be performing some kind of sound recognition...
  • I know its name so I can look it up on Internet to check its implementation (functionality)
  • And I know why it was selected and thus when I should reevaluate its use (fits a western european clientele so if we develop on arabic market it'll need adaptation...)

Unfortunately, that's not going to be generated automatically.

Upvotes: 6

Joris Timmermans
Joris Timmermans

Reputation: 10968

You can set Doxygen to extract non-documented items as well - that may do what you want without adding ANY comment blocks to the code yet.

After that you can create templates / macros (depends on your IDE) to create pre-formatted blocks for each type of item, as you slowly work through the code documenting items one by one.

[edit] If you're using Visual Studio, some introspection is available on the classes and other constructs in the file, that may help. Alternatively take a look at Doxycomment - it might be some of what you want.

Upvotes: 2

Related Questions