File: DocCheck.jl

package info (click to toggle)
julia 0.3.2-2
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 17,868 kB
  • ctags: 13,696
  • sloc: ansic: 102,603; lisp: 86,819; sh: 12,179; cpp: 8,793; makefile: 3,069; ruby: 1,594; python: 936; pascal: 697; xml: 532; java: 510; f90: 403; asm: 102; perl: 77; sql: 6
file content (196 lines) | stat: -rw-r--r-- 7,723 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
# Julia utilities for checking documentation

# This file contains a number of functions for checking julia documentation
#
# isdeprecated(v)         :  test if v is deprecated
# isdocumented(v)         :  true if v is documented
# undefined_exports(m)    :  returns a list of undefined exports in module m
# undocumented(m)         :  returns a list of undocumented exports in module m
# undocumented_by_file(m) :  returns a dictionary of undocumented exports, 
#                            with file, function, and line number information
# undocumented_rst(m)     :  produce a list of undocumented function suitable for
#                            pasting into github issue #2242

module DocCheck

import Base.Help: init_help, FUNCTION_DICT, MODULE_DICT
import Base: argtype_decl, uncompressed_ast

export isdeprecated, isdocumented, undefined_exports, undocumented, undocumented_by_file, undocumented_rst,
       gen_undocumented_template

isdeprecated(m::Module, v) = try endswith(functionloc(eval(m, v))[1], "deprecated.jl") catch return false end
isdeprecated(v)            = try endswith(functionloc(eval(v))[1], "deprecated.jl") catch return false end

isdocumented(v) = (s=string(v); haskey(FUNCTION_DICT, s) || haskey(MODULE_DICT, s))


modfuncjoin(m::String, f::String) = beginswith(f, '@') ? "@$m.$(f[2:end])" : "$m.$f"
modfuncjoin(m, f) = modfuncjoin(string(m), string(f))

# return a list of undefined exports in a module
undefined_exports(m::Module) = sort(filter(x->!isdefined(x), names(m)))
undefined_exports() = undefined(Base)

# Check for exported names that aren't documented,
# and return a Dict with (fn::Symbol, fullname::String) pairs
function undocumented(m::Module)
    init_help()
    undoc = Dict{Symbol, Array}()
    for v in sort(names(m))
        if isdefined(m,v) && !isdocumented(v) && !isdeprecated(m,v)
            ms = modfuncjoin(m,v)
            haskey(undoc, v) ? push!(undoc[v], ms) : (undoc[v] = [ms])
        end
    end
    undoc
end
undocumented() = undocumented(Base)

# Check for exported names that aren't documented, and
# return the file, function names, and line numbers, if available
function undocumented_by_file(m::Module)
    init_help()
    undocf = Dict{String, Dict}()
    for (f,_) in undocumented(m)
        s = string(f)
        try
            for (file, line) in functionlocs(eval(f))
                if beginswith(file, JULIA_HOME)
                    file = replace(file, JULIA_HOME, "\$JULIA_HOME", 1)
                end
                if !haskey(undocf, file)
                    undocf[file] = Dict{String, Vector{Integer}}()
                end
                if !haskey(undocf[file], s)
                    undocf[file][s] = [line]
                else
                    push!(undocf[file][s], line)
                end
            end
        catch
            if !haskey(undocf, "UNKNOWN_FILE")
                undocf["UNKNOWN_FILE"] = Dict{String, Vector{Integer}}()
            end
            undocf["UNKNOWN_FILE"][s] = Integer[-1]
        end
    end
    undocf
end
undocumented_by_file() = undocumented_by_file(Base)


# Unlike the above functions, this version parses base/exports.jl,
# because that file groups the functions in a more systematic manner.
# The output can be pasted into https://github.com/JuliaLang/julia/issues/2242
# This also only works with Base functions; the other "undocumented*"
# functions are more general.

# Based on code by @jihao
function _undocumented_rst()
    init_help()
    depdoc = havecount = total = 0
    out = String["The following exports are not documented:"]
    undoc_exports = Set()
    exports=[strip(x) for x in split(replace(open(readall, "$JULIA_HOME/../../base/exports.jl"),",",""),"\n")]
    for line in exports
        if search(line, "deprecated")!=0:-1; continue end
        if haskey(MODULE_DICT, line); havecount+=1; total+=1; continue end
        if length(line)>1
            if line[1]=='#'
               if line[2]!= ' ' continue end
            else
               s = symbol(line) # for submodules: string(:Sort) == "Base.Sort"
               if !isdefined(s) continue end
               if haskey(FUNCTION_DICT, line) || haskey(MODULE_DICT, line)
                  m = eval(symbol(getkey(MODULE_DICT, line, "Base")))
                  isdeprecated(m,s) && continue
                  havecount+=1; total+=1; continue
               end
               push!(undoc_exports, line)
               if line[1]=='@'; line = line[2:end] end
               line=string("- [ ] ", line)
               total+=1
            end
        end
        push!(out, line)
    end

    append!(out, String["", "Documented and deprecated functions/exports (please update docs)", ""])

    deprecated=[strip(x) for x in split(replace(open(readall, "$JULIA_HOME/../../base/deprecated.jl"),",",""),"\n")]
    for line in deprecated
        if beginswith(line, "@deprecated")
            fn = split(line, r" +")[2]
            if haskey(MODULE_DICT, fn); push!(out, string("- [ ] ", fn)); depdoc += 1 end
        elseif beginswith(line, "export")
            for fn in split(line, r"[ ,]+")[2:end]
                if haskey(MODULE_DICT, fn); push!(out, string("- [ ]", fn)); depdoc += 1 end
            end
        end
    end
    prepend!(out, String["$havecount/$total exports have been documented",
                         "(Additionally, $depdoc deprecated functions are still documentated)",
                         ""])
    (join(out, "\n"), undoc_exports)
end

undocumented_rst() = println(_undocumented_rst()[1])

function gen_undocumented_template(outfile = "$JULIA_HOME/../../doc/UNDOCUMENTED.rst")
    out = open(outfile, "w")
    init_help()
    println(out, ".. currentmodule:: Base")
    println(out)
    exports=[strip(x) for x in split(replace(open(readall, "$JULIA_HOME/../../base/exports.jl"),",",""),"\n")]
    for line in exports
        if search(line, "deprecated")!=0:-1; continue end
        if haskey(MODULE_DICT, line); continue end
        if length(line)>1
            if line[1]=='#'
                if line[2]!= ' ' continue end
                println(out)
                println(out, line[3:end])
                println(out, repeat("-", length(line)-2))
                println(out)
                continue
            else
                s = symbol(line) # for submodules: string(:Sort) == "Base.Sort"
                if !isdefined(s) continue end
                if haskey(FUNCTION_DICT, line) || haskey(MODULE_DICT, line)
                    continue
                end
                if line[1]=='@'; line = line[2:end] end
                sym = try eval(symbol(line)) catch :() end
                if isa(sym, Function)
                    mt = methods(sym)
                    if length(mt) == 1  # easy case
                        m = mt.defs
                        li = m.func.code
                        e = uncompressed_ast(li)
                        argnames = e.args[1]
                        decls = map(argtype_decl, argnames, {m.sig...})
                        args = join(decls, ",")
                        line = line * "($args)"
                    else
                        line = line * "(...)"
                    end
                    println(out, ".. function:: "*line)
                    println(out)
                    println(out, "   UNDOCUMENTED")
                    println(out)
                elseif isa(sym, Module)
                    println(out, ".. module:: "*line)
                    println(out)
                    println(out, "   UNDOCUMENTED (may not appear in helpdb.jl)")
                    println(out)
                end
            end
        end
    end

    close(out)
    nothing
end

end