Search code examples
c#documentationdoxygenstatic-methodscall-graph

Doxygen does not generate links to methods without explicit classname


I am using Doxygen 1.8.9.1 to generate some html docs for my C# code. The problem is Doxygen does not seem to understand method calls to methods in the same Class unless you explicitly type the class name before the method name.

In this example class I have 2 identical static methods and 1 method which calls them both; one with just the method name and one with the class name included. When I generate the docs only someStaticMethod2 is linked to somecaller. someStaticMethod does not link to anything.

public class Class1 {

    static void someStaticMethod() {
    }

    static void someStaticMethod2() {
    }

    void somecaller() {
        someStaticMethod();
        Class1.someStaticMethod2();
    }

}

In my Doxygen config I have ticked every "extract" option I can see i.e.

EXTRACT_ALL            = YES
EXTRACT_PRIVATE        = YES
EXTRACT_STATIC         = YES
EXTRACT_LOCAL_CLASSES  = YES
EXTRACT_LOCAL_METHODS  = YES
EXTRACT_ANON_NSPACES   = YES

I have looked at related questions but they do not have answers..

Any ideas?
Thanks
Tom


Solution

  • As a quick work-around I made this Doxygen input filter using python. It assumes you have a .cs source file with one main class containing the static methods. Its a bit of a kludge as it doesn't do proper syntax parsing but it works for me ;)

    It takes the .cs input file, gets the class name and prepends it to any static function calls found within the class to replace calls like someStaticMethod to Class1.someStaticMethod

    To use just add this like to Doxygen config:
    FILTER_PATTERNS = *.cs=DocPreprocess.bat

    where the bat file is just a wrapper for the python script like this:

    @echo off
    cd %~dp0
    C:\WinPython-64bit-2.7.6.4\python-2.7.6.amd64\python.exe DocPreprocess.py %1
    

    just make sure the bat file is on the path or in the Doxygen startup folder.

    DocPreprocess.py

    import re
    import sys
    
    original = open(sys.argv[1],"rb").read();
    
    #remove quoted sections and char literal braces
    regex = re.compile('"([^"]*)"', re.IGNORECASE)
    buffer = regex.sub("", original).replace("'{'","").replace("'}'","")
    
    #remove comments 
    newbuffer = ""
    for l in buffer.splitlines():
        code,_,comment = l.partition(r"//")
        newbuffer += code
    
    buffer = " ".join(newbuffer.split())
    
    #get static functions and main class name
    depth = 0
    classname = ""
    classdepth = 0
    funcs = []
    while True:
        nopen = buffer.find("{")
        nclose = buffer.find("}")
        
        if nclose==-1 and nopen>-1: nclose=nopen+1
        if nclose>-1 and nopen==-1: nopen=nclose+1
        if nclose==-1 and nopen==-1: break
        
        if nopen < nclose:
            chunk,_,buffer = buffer.partition("{")
            depth+=1
        else:
            chunk,_,buffer = buffer.partition("}")
            depth-=1
            
        chunk = chunk.strip()
            
        if "public class" in chunk and classname == "":
            classname = chunk.split()[-1]
            classdepth = depth
            
        if classdepth and depth > classdepth and  "static" in chunk and chunk.endswith(")"):
            funcs.append(chunk.rpartition("(")[0].split()[-1])
    
    #replace
    fixed = ""
    for l in original.splitlines():
        words = l.split()
        stripped = l.strip()
        
        if "static" in words[0:3] or stripped.startswith("//") or stripped.startswith("#"): 
            #ignore function defs and comments
            fixed += l + "\n"
            continue
            
        for f in funcs:
            newname = classname+"."+f
            l=l.replace(newname,"[[TEMPTOKEN]]")
            l=l.replace(f,newname)
            l=l.replace("[[TEMPTOKEN]]",newname)
            
        fixed += l + "\n"
        
    #output fixed file to stdout
    print fixed
    

    This is only a hack to get what I wanted, I would still really like to see a real solution to make Doxygen do this automatically.

    Thanks
    Tom