X-Git-Url: https://git.archive.openwrt.org/?p=project%2Fluci.git;a=blobdiff_plain;f=contrib%2Fluadoc%2Flua%2Fluadoc%2Ftaglet%2Fstandard.lua;h=f55ea720427f41e2a99d1d281cf728eb1cab093e;hp=334f4a24dd00cd91a65c3ce8407447d1e2a19b07;hb=7528812494f1408d3f6db6deb8455d56362c05b6;hpb=dba6854d65a9ff859e1a7782f048cecfdd2513ca diff --git a/contrib/luadoc/lua/luadoc/taglet/standard.lua b/contrib/luadoc/lua/luadoc/taglet/standard.lua index 334f4a24d..f55ea7204 100644 --- a/contrib/luadoc/lua/luadoc/taglet/standard.lua +++ b/contrib/luadoc/lua/luadoc/taglet/standard.lua @@ -55,7 +55,7 @@ local function check_function (line) return { name = id, private = (l == "local"), - param = util.split("%s*,%s*", param), + param = { } --util.split("%s*,%s*", param), } end end) @@ -73,12 +73,12 @@ end -- Checks if the line contains a module definition. -- @param line string with line text -- @param currentmodule module already found, if any --- @return the name of the defined module, or nil if there is no module +-- @return the name of the defined module, or nil if there is no module -- definition local function check_module (line, currentmodule) line = util.trim(line) - + -- module"x.y" -- module'x.y' -- module[[x.y]] @@ -96,10 +96,42 @@ local function check_module (line, currentmodule) return currentmodule end +-- Patterns for constant recognition +local constant_patterns = { + "^()%s*([A-Z][A-Z0-9_]*)%s*=", + "^%s*(local%s)%s*([A-Z][A-Z0-9_]*)%s*=", +} + ------------------------------------------------------------------------------- --- Extracts summary information from a description. The first sentence of each --- doc comment should be a summary sentence, containing a concise but complete --- description of the item. It is important to write crisp and informative +-- Checks if the line contains a constant definition +-- @param line string with line text +-- @return constant information or nil if no constant definition found + +local function check_constant (line) + line = util.trim(line) + + local info = table.foreachi(constant_patterns, function (_, pattern) + local r, _, l, id = string.find(line, pattern) + if r ~= nil then + return { + name = id, + private = (l == "local"), + } + end + end) + + -- TODO: remove these assert's? + if info ~= nil then + assert(info.name, "constant name undefined") + end + + return info +end + +------------------------------------------------------------------------------- +-- Extracts summary information from a description. The first sentence of each +-- doc comment should be a summary sentence, containing a concise but complete +-- description of the item. It is important to write crisp and informative -- initial sentences that can stand on their own -- @param description text with item description -- @return summary string or nil if description is nil @@ -107,16 +139,16 @@ end local function parse_summary (description) -- summary is never nil... description = description or "" - + -- append an " " at the end to make the pattern work in all cases description = description.." " - -- read until the first period followed by a space or tab + -- read until the first period followed by a space or tab local summary = string.match(description, "(.-%.)[%s\t]") - + -- if pattern did not find the first sentence, summary is the whole description summary = summary or description - + return summary end @@ -151,7 +183,7 @@ end -- @param block block with comment field -- @return block parameter -local function parse_comment (block, first_line) +local function parse_comment (block, first_line, modulename) -- get the first non-empty line of code local code = table.foreachi(block.code, function(_, line) @@ -167,16 +199,21 @@ local function parse_comment (block, first_line) return line end end) - + -- parse first line of code if code ~= nil then local func_info = check_function(code) local module_name = check_module(code) + local const_info = check_constant(code) if func_info then block.class = "function" block.name = func_info.name block.param = func_info.param block.private = func_info.private + elseif const_info then + block.class = "constant" + block.name = const_info.name + block.private = const_info.private elseif module_name then block.class = "module" block.name = module_name @@ -192,16 +229,16 @@ local function parse_comment (block, first_line) -- parse @ tags local currenttag = "description" local currenttext - + table.foreachi(block.comment, function (_, line) line = util.trim_comment(line) - + local r, _, tag, text = string.find(line, "@([_%w%.]+)%s+(.*)") if r ~= nil then -- found new tag, add previous one, and start a new one -- TODO: what to do with invalid tags? issue an error? or log a warning? tags.handle(currenttag, block, currenttext) - + currenttag = tag currenttext = text else @@ -214,8 +251,12 @@ local function parse_comment (block, first_line) -- extracts summary information from the description block.summary = parse_summary(block.description) assert(string.sub(block.description, 1, 1) ~= " ", string.format("`%s'", block.description)) - - return block + + if block.name and block.class == "module" then + modulename = block.name + end + + return block, modulename end ------------------------------------------------------------------------------- @@ -239,9 +280,9 @@ local function parse_block (f, line, modulename, first) -- reached end of comment, read the code below it -- TODO: allow empty lines line, block.code, modulename = parse_code(f, line, modulename) - + -- parse information in block comment - block = parse_comment(block, first) + block, modulename = parse_comment(block, first, modulename) return line, block, modulename else @@ -250,10 +291,10 @@ local function parse_block (f, line, modulename, first) end end -- reached end of file - + -- parse information in block comment - block = parse_comment(block, first) - + block, modulename = parse_comment(block, first, modulename) + return line, block, modulename end @@ -263,58 +304,78 @@ end -- @param doc table with documentation -- @return table with documentation -function parse_file (filepath, doc) - local blocks = {} - local modulename = nil - +function parse_file (filepath, doc, handle, prev_line, prev_block, prev_modname) + local blocks = { prev_block } + local modulename = prev_modname + -- read each line - local f = io.open(filepath, "r") + local f = handle or io.open(filepath, "r") local i = 1 - local line = f:read() + local line = prev_line or f:read() local first = true while line ~= nil do + if string.find(line, "^[\t ]*%-%-%-") then -- reached a luadoc block - local block - line, block, modulename = parse_block(f, line, modulename, first) - table.insert(blocks, block) + local block, newmodname + line, block, newmodname = parse_block(f, line, modulename, first) + + if modulename and newmodname and newmodname ~= modulename then + doc = parse_file( nil, doc, f, line, block, newmodname ) + else + table.insert(blocks, block) + modulename = newmodname + end else -- look for a module definition - modulename = check_module(line, modulename) - + local newmodname = check_module(line, modulename) + + if modulename and newmodname and newmodname ~= modulename then + parse_file( nil, doc, f ) + else + modulename = newmodname + end + -- TODO: keep beginning of file somewhere - + line = f:read() end first = false i = i + 1 end - f:close() - -- store blocks in file hierarchy - assert(doc.files[filepath] == nil, string.format("doc for file `%s' already defined", filepath)) - table.insert(doc.files, filepath) - doc.files[filepath] = { - type = "file", - name = filepath, - doc = blocks, --- functions = class_iterator(blocks, "function"), --- tables = class_iterator(blocks, "table"), - } --- - local first = doc.files[filepath].doc[1] - if first and modulename then - doc.files[filepath].author = first.author - doc.files[filepath].copyright = first.copyright - doc.files[filepath].description = first.description - doc.files[filepath].release = first.release - doc.files[filepath].summary = first.summary + + if not handle then + f:close() + end + + if filepath then + -- store blocks in file hierarchy + assert(doc.files[filepath] == nil, string.format("doc for file `%s' already defined", filepath)) + table.insert(doc.files, filepath) + doc.files[filepath] = { + type = "file", + name = filepath, + doc = blocks, + -- functions = class_iterator(blocks, "function"), + -- tables = class_iterator(blocks, "table"), + } + -- + local first = doc.files[filepath].doc[1] + if first and modulename then + doc.files[filepath].author = first.author + doc.files[filepath].copyright = first.copyright + doc.files[filepath].description = first.description + doc.files[filepath].release = first.release + doc.files[filepath].summary = first.summary + end end -- if module definition is found, store in module hierarchy if modulename ~= nil then if modulename == "..." then - modulename = string.gsub (filepath, "%.lua$", "") - modulename = string.gsub (modulename, "/", ".") + assert( filepath, "Can't determine name for virtual module from filepatch" ) + modulename = string.gsub (filepath, "%.lua$", "") + modulename = string.gsub (modulename, "/", ".") end if doc.modules[modulename] ~= nil then -- module is already defined, just add the blocks @@ -336,14 +397,14 @@ function parse_file (filepath, doc) release = first and first.release, summary = "", } - + -- find module description for m in class_iterator(blocks, "module")() do doc.modules[modulename].description = util.concat( - doc.modules[modulename].description, + doc.modules[modulename].description, m.description) doc.modules[modulename].summary = util.concat( - doc.modules[modulename].summary, + doc.modules[modulename].summary, m.summary) if m.author then doc.modules[modulename].author = m.author @@ -361,7 +422,7 @@ function parse_file (filepath, doc) doc.modules[modulename].description = doc.modules[modulename].description or (first and first.description) or "" doc.modules[modulename].summary = doc.modules[modulename].summary or (first and first.summary) or "" end - + -- make functions table doc.modules[modulename].functions = {} for f in class_iterator(blocks, "function")() do @@ -370,7 +431,7 @@ function parse_file (filepath, doc) doc.modules[modulename].functions[f.name] = f end end - + -- make tables table doc.modules[modulename].tables = {} for t in class_iterator(blocks, "table")() do @@ -379,31 +440,42 @@ function parse_file (filepath, doc) doc.modules[modulename].tables[t.name] = t end end - end - - -- make functions table - doc.files[filepath].functions = {} - for f in class_iterator(blocks, "function")() do - if f and f.name then - table.insert(doc.files[filepath].functions, f.name) - doc.files[filepath].functions[f.name] = f + + -- make constants table + doc.modules[modulename].constants = {} + for c in class_iterator(blocks, "constant")() do + if c and c.name then + table.insert(doc.modules[modulename].constants, c.name) + doc.modules[modulename].constants[c.name] = c + end end end - - -- make tables table - doc.files[filepath].tables = {} - for t in class_iterator(blocks, "table")() do - if t and t.name then - table.insert(doc.files[filepath].tables, t.name) - doc.files[filepath].tables[t.name] = t + + if filepath then + -- make functions table + doc.files[filepath].functions = {} + for f in class_iterator(blocks, "function")() do + if f and f.name then + table.insert(doc.files[filepath].functions, f.name) + doc.files[filepath].functions[f.name] = f + end + end + + -- make tables table + doc.files[filepath].tables = {} + for t in class_iterator(blocks, "table")() do + if t and t.name then + table.insert(doc.files[filepath].tables, t.name) + doc.files[filepath].tables[t.name] = t + end end end - + return doc end ------------------------------------------------------------------------------- --- Checks if the file is terminated by ".lua" or ".luadoc" and calls the +-- Checks if the file is terminated by ".lua" or ".luadoc" and calls the -- function that does the actual parsing -- @param filepath full path of the file to parse -- @param doc table with documentation @@ -417,12 +489,12 @@ function file (filepath, doc) return true end end) - + if valid then logger:info(string.format("processing file `%s'", filepath)) doc = parse_file(filepath, doc) end - + return doc end @@ -437,7 +509,7 @@ function directory (path, doc) local fullpath = path .. "/" .. f local attr = posix.stat(fullpath) assert(attr, string.format("error stating file `%s'", fullpath)) - + if attr.type == "regular" then doc = file(fullpath, doc) elseif attr.type == "directory" and f ~= "." and f ~= ".." then @@ -465,7 +537,7 @@ end function start (files, doc) assert(files, "file list not specified") - + -- Create an empty document, or use the given one doc = doc or { files = {}, @@ -473,18 +545,18 @@ function start (files, doc) } assert(doc.files, "undefined `files' field") assert(doc.modules, "undefined `modules' field") - + table.foreachi(files, function (_, path) local attr = posix.stat(path) assert(attr, string.format("error stating path `%s'", path)) - + if attr.type == "regular" then doc = file(path, doc) elseif attr.type == "directory" then doc = directory(path, doc) end end) - + -- order arrays alphabetically recsort(doc.files) recsort(doc.modules)