File: gen_javadoc.py

package info (click to toggle)
opencv 2.3.1-11%2Bdeb7u1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 82,284 kB
  • sloc: xml: 493,314; cpp: 334,117; ansic: 108,641; java: 15,407; python: 14,061; sh: 107; makefile: 61
file content (220 lines) | stat: -rw-r--r-- 9,036 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
import os, sys, re, string, glob
allmodules = ["core", "flann", "imgproc", "ml", "highgui", "video", "features2d", "calib3d", "objdetect", "legacy", "contrib", "gpu", "androidcamera", "haartraining", "java", "python", "stitching", "traincascade", "ts"]
verbose = False
show_warnings = True
show_errors = True

class JavadocGenerator(object):
    def __init__(self, definitions = {}, javadoc_marker = "//javadoc:"):
        self.definitions = definitions
        self.javadoc_marker = javadoc_marker
        self.markers_processed = 0
        self.markers_documented = 0
        self.params_documented = 0
        self.params_undocumented = 0

    def parceJavadocMarker(self, line):
        assert line.lstrip().startswith(self.javadoc_marker)
        offset = line[:line.find(self.javadoc_marker)]
        line = line.strip()[len(self.javadoc_marker):]
        args_start = line.rfind("(")
        args_end = line.rfind(")")
        assert args_start * args_end > 0
        if args_start >= 0:
            assert args_start < args_end
            name = line[:args_start].strip()
            if name.startswith("java"):
                name = name[4:]
            return (name, offset,  filter(None, list(arg.strip() for arg in line[args_start+1:args_end].split(","))))
        name = line.strip()
        if name.startswith("java"):
            name = name[4:]
        return (name, offset, [])

    def document(self, infile, outfile):
        inf = open(infile, "rt")
        outf = open(outfile, "wt")
        module = os.path.splitext(os.path.basename(infile))[0].split("+")[0]
        if module not in allmodules:
            module = "unknown"
        try:
            for l in inf.readlines():
                org = l
                l = l.replace(" ", "").replace("\t", "")#remove all whitespace
                if l.startswith(self.javadoc_marker):
                    marker = self.parceJavadocMarker(l)
                    self.markers_processed += 1
                    decl = self.definitions.get(marker[0],None)
                    if decl:
                        javadoc = self.makeJavadoc(decl, marker[2])
                        if verbose:
                            print
                            print "Javadoc for \"%s\" File: %s (line %s)" % (decl["name"], decl["file"], decl["line"])
                            print javadoc
                        for line in javadoc.split("\n"):
                            outf.write(marker[1] + line + "\n")
                        self.markers_documented += 1
                    elif show_errors:
                        print >> sys.stderr, "gen_javadoc error: could not find documentation for %s (module: %s)" % (l.lstrip()[len(self.javadoc_marker):-1].strip(), module)
                else:
                    outf.write(org.replace("\t", "    ").rstrip()+"\n")
        except:
            inf.close()
            outf.close()
            os.remove(outfile)
            raise
        else:
            inf.close()
            outf.close()

    def ReformatForJavadoc(self, s):
        out = ""
        for term in s.split("\n"):
            if term.startswith("*") or term.startswith("#."):
                term = "  " + term
            if not term:
                out += " *\n"
            else:
                pos_start = 0
                pos_end = min(77, len(term)-1)
                while pos_start < pos_end:
                    if pos_end - pos_start == 77:
                        while pos_end >= pos_start+60:
                            if not term[pos_end].isspace():
                                pos_end -= 1
                            else:
                                break
                        if pos_end < pos_start+60:
                            pos_end = min(pos_start + 77, len(term)-1)
                            while pos_end < len(term):
                                if not term[pos_end].isspace():
                                    pos_end += 1
                                else:
                                    break
                    out += " * " + term[pos_start:pos_end+1].rstrip() + "\n"
                    pos_start = pos_end + 1
                    pos_end = min(pos_start + 77, len(term)-1)
        return out

    def getJavaName(self, decl):
        name = "org.opencv."
        name += decl["module"]
        if "class" in decl:
            name += "." + decl["class"]
        else:
            name += "." + decl["module"].capitalize()
        if "method" in decl:
            name += "." + decl["method"]
        return name

    def getDocURL(self, decl):
        url = "http://opencv.itseez.com/modules/"
        url += decl["module"]
        url += "/doc/"
        url += os.path.basename(decl["file"]).replace(".rst",".html")
        url += "#" + decl["name"].replace("::","-").replace("()","").replace("=","").strip().rstrip("_").replace(" ","-").replace("_","-").lower()
        return url

    def makeJavadoc(self, decl, args = None):
        doc = ""
        prefix = "/**\n"

        if decl.get("isclass", False):
            decl_type = "class"
        elif decl.get("isstruct", False):
            decl_type = "struct"
        elif "class" in decl:
            decl_type = "method"
        else:
            decl_type = "function"

        # brief goes first
        if "brief" in decl:
            doc += prefix + self.ReformatForJavadoc(decl["brief"])
            prefix = " *\n"
        elif "long" not in decl:
            if show_warnings:
                print >> sys.stderr, "gen_javadoc warning: no description for " + decl_type + " \"%s\" File: %s (line %s)" % (func["name"], func["file"], func["line"])
            doc += prefix + self.ReformatForJavadoc("This " + decl_type + " is undocumented")
            prefix = " *\n"
    
        # long goes after brief
        if "long" in decl:
            doc += prefix  + self.ReformatForJavadoc(decl["long"])
            prefix = " *\n"

        # @param tags
        if args and (decl_type == "method" or decl_type == "function"):
            documented_params = decl.get("params",{})
            for arg in args:
                arg_doc = documented_params.get(arg, None)
                if not arg_doc:
                    arg_doc = "a " + arg
                    if show_warnings:
                        print >> sys.stderr, "gen_javadoc warning: parameter \"%s\" of \"%s\" is undocumented. File: %s (line %s)" % (arg, decl["name"], decl["file"], decl["line"])
                    self.params_undocumented += 1
                else:
                    self.params_documented += 1
                doc += prefix + self.ReformatForJavadoc("@param " + arg + " " + arg_doc)
                prefix = ""
            prefix = " *\n"

        # @see tags
        # always link to documentation
        doc += prefix + " * @see <a href=\"" + self.getDocURL(decl) + "\">" + self.getJavaName(decl) + "</a>\n"
        prefix = ""
        # other links
        if "seealso" in decl:
            for see in decl["seealso"]:
                seedecl = self.definitions.get(see,None)
                if seedecl:
                    doc += prefix + " * @see " + self.getJavaName(seedecl) + "\n"
                else:
                    doc += prefix + " * @see " + see.replace("::",".") + "\n"
        prefix = " *\n"

        #doc += prefix + " * File: " + decl["file"] + " (line " + str(decl["line"]) + ")\n"

        return (doc + " */").replace("::",".")

    def printSummary(self):
        print
        print "Javadoc Generator Summary:"
        print "  Total markers:        %s" % self.markers_processed
        print "  Undocumented markers: %s" % (self.markers_processed - self.markers_documented)
        print "  Generated comments:   %s" % self.markers_documented

        print
        print "  Documented params:    %s" % self.params_documented
        print "  Undocumented params:  %s" % self.params_undocumented
        print

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print "Usage:\n", os.path.basename(sys.argv[0]), " <input dir1> [<input dir2> [...]]"
        exit(0)
   
    selfpath = os.path.dirname(os.path.abspath(sys.argv[0]))
    hdr_parser_path = os.path.join(selfpath, "../python/src2")
    
    sys.path.append(selfpath)
    sys.path.append(hdr_parser_path)
    import hdr_parser
    import rst_parser

    print "Parsing documentation..."
    parser = rst_parser.RstParser(hdr_parser.CppHeaderParser())
    for m in allmodules:
        parser.parse(m, os.path.join(selfpath, "../" + m))
        
    parser.printSummary()

    print "Generating javadoc comments..."
    generator = JavadocGenerator(parser.definitions)
    for i in range(1, len(sys.argv)):
        folder = os.path.abspath(sys.argv[i])
        for jfile in [f for f in glob.glob(os.path.join(folder,"*.java")) if not f.endswith("-jdoc.java")]:
            outfile = os.path.abspath(os.path.basename(jfile).replace(".java", "-jdoc.java"))
            generator.document(jfile, outfile)

    generator.printSummary()