starting to track local functions. A module without a starting doc comment is considered an error. A problem with tag warnings crashing ldoc was sorted out. A table or function comment at the end of file could cause a crash.
This commit is contained in:
parent
d2d7d6ac38
commit
74b52dacd1
21
doc.lua
21
doc.lua
|
@ -18,7 +18,8 @@ local known_tags = {
|
||||||
param = 'M', see = 'M', usage = 'M', ['return'] = 'M', field = 'M', author='M';
|
param = 'M', see = 'M', usage = 'M', ['return'] = 'M', field = 'M', author='M';
|
||||||
class = 'id', name = 'id', pragma = 'id', alias = 'id';
|
class = 'id', name = 'id', pragma = 'id', alias = 'id';
|
||||||
copyright = 'S', summary = 'S', description = 'S', release = 'S', license = 'S';
|
copyright = 'S', summary = 'S', description = 'S', release = 'S', license = 'S';
|
||||||
module = 'T', script = 'T',['function'] = 'T', table = 'T', section = 'T', type = 'T';
|
module = 'T', script = 'T',['function'] = 'T', lfunction = 'T',
|
||||||
|
table = 'T', section = 'T', type = 'T';
|
||||||
}
|
}
|
||||||
known_tags._alias = {}
|
known_tags._alias = {}
|
||||||
known_tags._project_level = {
|
known_tags._project_level = {
|
||||||
|
@ -78,10 +79,8 @@ function File:_init(filename)
|
||||||
end
|
end
|
||||||
|
|
||||||
function File:new_item(tags,line)
|
function File:new_item(tags,line)
|
||||||
local item = Item(tags)
|
local item = Item(tags,self,line)
|
||||||
self.items:append(item)
|
self.items:append(item)
|
||||||
item.file = self
|
|
||||||
item.lineno = line
|
|
||||||
return item
|
return item
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -92,6 +91,7 @@ function File:finish()
|
||||||
item:finish()
|
item:finish()
|
||||||
if doc.project_level(item.type) then
|
if doc.project_level(item.type) then
|
||||||
this_mod = item
|
this_mod = item
|
||||||
|
|
||||||
-- if name is 'package.mod', then mod_name is 'mod'
|
-- if name is 'package.mod', then mod_name is 'mod'
|
||||||
local package,mname = split_dotted_name(this_mod.name)
|
local package,mname = split_dotted_name(this_mod.name)
|
||||||
if not package then
|
if not package then
|
||||||
|
@ -168,7 +168,9 @@ function File:finish()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Item:_init(tags)
|
function Item:_init(tags,file,line)
|
||||||
|
self.file = file
|
||||||
|
self.lineno = line
|
||||||
self.summary = tags.summary
|
self.summary = tags.summary
|
||||||
self.description = tags.description
|
self.description = tags.description
|
||||||
tags.summary = nil
|
tags.summary = nil
|
||||||
|
@ -186,14 +188,14 @@ function Item:_init(tags)
|
||||||
elseif ttype == TAG_ID then
|
elseif ttype == TAG_ID then
|
||||||
if type(value) ~= 'string' then
|
if type(value) ~= 'string' then
|
||||||
-- such tags are _not_ multiple, e.g. name
|
-- such tags are _not_ multiple, e.g. name
|
||||||
self:error(tag..' cannot have multiple values')
|
self:error("'"..tag.."' cannot have multiple values")
|
||||||
else
|
else
|
||||||
self.tags[tag] = tools.extract_identifier(value)
|
self.tags[tag] = tools.extract_identifier(value)
|
||||||
end
|
end
|
||||||
elseif ttype == TAG_SINGLE then
|
elseif ttype == TAG_SINGLE then
|
||||||
self.tags[tag] = value
|
self.tags[tag] = value
|
||||||
else
|
else
|
||||||
self:warning ('unknown tag: '..tag)
|
self:warning ("unknown tag: '"..tag.."'")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -272,6 +274,11 @@ function Item:warning(msg)
|
||||||
io.stderr:write(name,':',self.lineno or '?',' ',msg,'\n')
|
io.stderr:write(name,':',self.lineno or '?',' ',msg,'\n')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Item:error(msg)
|
||||||
|
self:warning(msg)
|
||||||
|
os.exit(1)
|
||||||
|
end
|
||||||
|
|
||||||
-- resolving @see references. A word may be either a function in this module,
|
-- resolving @see references. A word may be either a function in this module,
|
||||||
-- or a module in this package. A MOD.NAME reference is within this package.
|
-- or a module in this package. A MOD.NAME reference is within this package.
|
||||||
-- Otherwise, the full qualified name must be used.
|
-- Otherwise, the full qualified name must be used.
|
||||||
|
|
58
ldoc.lua
58
ldoc.lua
|
@ -47,6 +47,7 @@ end
|
||||||
ModuleMap:add_kind('function','Functions','Parameters')
|
ModuleMap:add_kind('function','Functions','Parameters')
|
||||||
ModuleMap:add_kind('table','Tables','Fields')
|
ModuleMap:add_kind('table','Tables','Fields')
|
||||||
ModuleMap:add_kind('field','Fields')
|
ModuleMap:add_kind('field','Fields')
|
||||||
|
ModuleMap:add_kind('lfunction','Local Functions','Parameters')
|
||||||
|
|
||||||
|
|
||||||
class.ProjectMap(KindMap)
|
class.ProjectMap(KindMap)
|
||||||
|
@ -244,8 +245,10 @@ function Lua:find_module(tok,t,v)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Lua:function_follows(t,v)
|
function Lua:function_follows(t,v,tok)
|
||||||
return t == 'keyword' and v == 'function'
|
local is_local = t == 'keyword' and v == 'local'
|
||||||
|
if is_local then t,v = tnext(tok) end
|
||||||
|
return t == 'keyword' and v == 'function', is_local
|
||||||
end
|
end
|
||||||
|
|
||||||
function Lua:parse_function_header (tags,tok,toks)
|
function Lua:parse_function_header (tags,tok,toks)
|
||||||
|
@ -256,7 +259,11 @@ end
|
||||||
|
|
||||||
function Lua:parse_extra (tags,tok,toks)
|
function Lua:parse_extra (tags,tok,toks)
|
||||||
if tags.class == 'table' and not tags.fields then
|
if tags.class == 'table' and not tags.fields then
|
||||||
local res,t,v = self:search_for_token(tok,'{','{',tok())
|
local res
|
||||||
|
local stat,t,v = pcall(tok)
|
||||||
|
if not stat then return nil end
|
||||||
|
print('tok',t,v)
|
||||||
|
res,t,v = self:search_for_token(tok,'{','{',tok())
|
||||||
if not res then return nil,t,v end
|
if not res then return nil,t,v end
|
||||||
tags.formal_args = tools.get_parameters(toks,'}',function(s)
|
tags.formal_args = tools.get_parameters(toks,'}',function(s)
|
||||||
return s == ',' or s == ';'
|
return s == ',' or s == ';'
|
||||||
|
@ -303,7 +310,13 @@ local function parse_file(fname,lang)
|
||||||
local tok,f = lang.lexer(fname)
|
local tok,f = lang.lexer(fname)
|
||||||
local toks = tools.space_skip_getter(tok)
|
local toks = tools.space_skip_getter(tok)
|
||||||
|
|
||||||
function lineno () return lexer.lineno(tok) end
|
function lineno ()
|
||||||
|
while true do
|
||||||
|
local res = lexer.lineno(tok)
|
||||||
|
if type(res) == 'number' then return res end
|
||||||
|
if res == nil then return nil end
|
||||||
|
end
|
||||||
|
end
|
||||||
function filename () return fname end
|
function filename () return fname end
|
||||||
|
|
||||||
function F:warning (msg,kind)
|
function F:warning (msg,kind)
|
||||||
|
@ -350,24 +363,20 @@ local function parse_file(fname,lang)
|
||||||
|
|
||||||
if t == 'space' then t,v = tnext(tok) end
|
if t == 'space' then t,v = tnext(tok) end
|
||||||
|
|
||||||
local fun_follows,tags
|
local fun_follows, tags, is_local
|
||||||
if ldoc_comment or first_comment then
|
if ldoc_comment or first_comment then
|
||||||
comment = table.concat(comment)
|
comment = table.concat(comment)
|
||||||
fun_follows = lang:function_follows(t,v)
|
if not ldoc_comment and first_comment then
|
||||||
if fun_follows or comment:find '@' or first_comment then
|
F:error("first comment must be a doc comment!")
|
||||||
|
end
|
||||||
|
first_comment = false
|
||||||
|
fun_follows, is_local = lang:function_follows(t,v,tok)
|
||||||
|
if fun_follows or comment:find '@'then
|
||||||
tags = extract_tags(comment)
|
tags = extract_tags(comment)
|
||||||
-- handle the special case where the initial module comment was not
|
|
||||||
-- an ldoc style comment
|
|
||||||
if not ldoc_comment and first_comment and not tags.class then
|
|
||||||
tags.class = 'module'
|
|
||||||
ldoc_comment = true
|
|
||||||
F:warning 'Module doc comment assumed'
|
|
||||||
end
|
|
||||||
if doc.project_level(tags.class) then
|
if doc.project_level(tags.class) then
|
||||||
module_found = tags.name
|
module_found = tags.name
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
first_comment = false
|
|
||||||
end
|
end
|
||||||
-- some hackery necessary to find the module() call
|
-- some hackery necessary to find the module() call
|
||||||
if not module_found and ldoc_comment then
|
if not module_found and ldoc_comment then
|
||||||
|
@ -388,14 +397,21 @@ local function parse_file(fname,lang)
|
||||||
|
|
||||||
-- end of a block of document comments
|
-- end of a block of document comments
|
||||||
if ldoc_comment and tags then
|
if ldoc_comment and tags then
|
||||||
if fun_follows then -- parse the function definition
|
local line = t ~= nil and lineno() or 666
|
||||||
lang:parse_function_header(tags,tok,toks)
|
if t ~= nil then
|
||||||
else
|
if fun_follows then -- parse the function definition
|
||||||
lang:parse_extra(tags,tok,toks)
|
lang:parse_function_header(tags,tok,toks)
|
||||||
|
else
|
||||||
|
lang:parse_extra(tags,tok,toks)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if tags.class == 'function' and is_local then
|
||||||
|
tags.class = 'lfunction'
|
||||||
end
|
end
|
||||||
if tags.name then
|
if tags.name then
|
||||||
F:new_item(tags,lineno()).inferred = fun_follows
|
F:new_item(tags,line).inferred = fun_follows
|
||||||
end
|
end
|
||||||
|
if not t then break end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if t ~= 'comment' then t,v = tok() end
|
if t ~= 'comment' then t,v = tok() end
|
||||||
|
@ -606,7 +622,7 @@ local ldoc_dir = arg[0]:gsub('[^/\\]+$','')
|
||||||
if args.style == '!' then args.style = ldoc_dir end
|
if args.style == '!' then args.style = ldoc_dir end
|
||||||
if args.template == '!' then args.template = ldoc_dir end
|
if args.template == '!' then args.template = ldoc_dir end
|
||||||
|
|
||||||
local module_template,err = utils.readfile (path.join(args.style,templ))
|
local module_template,err = utils.readfile (path.join(args.template,templ))
|
||||||
if not module_template then quit(err) end
|
if not module_template then quit(err) end
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue