Pseudo-tag fixes. Sigh.

This commit is contained in:
Jan Larres 2011-01-22 22:16:49 +13:00
parent 7bae0c5a69
commit 39beb53fc1

View File

@ -480,9 +480,9 @@ endfunction
" genereate a tag). Another example are anonymous
" namespaces/structs/enums/unions that also don't get a tag themselves. These
" tags are thus called 'pseudo-tags' in Tagbar.
" This is probably the most cryptic function since it has to deal with things
" that aren't actually there and several corner cases. Try not to think about
" it too much.
" This (in conjunction with ProcessPseudoTag) is probably the most cryptic
" function since it has to deal with things that aren't actually there and
" several corner cases. Try not to think about it too much.
function! s:AddChildren(tags, processedtags, curpath,
\ pscope, scope, depth, typeinfo)
let is_child = 'has_key(v:val.fields, a:scope)'
@ -501,39 +501,21 @@ function! s:AddChildren(tags, processedtags, curpath,
" 'curchildren' are children at the current depth
if !empty(curchildren)
for child in curchildren
let is_parent = 'has_key(a:typeinfo.kind2scope,
\ v:val.fields.kind) &&
\ a:typeinfo.kind2scope[v:val.fields.kind] == a:scope &&
\ s:GetFullTagPath(v:val, a:typeinfo) == child.fields[a:scope]'
let parentlist = filter(copy(a:processedtags), is_parent)
if !empty(parentlist)
call filter(a:processedtags, '!(' . is_parent . ')')
else
let parentlist = filter(copy(a:tags), is_parent)
if !empty(parentlist)
call filter(a:tags, '!(' . is_parent . ')')
endif
endif
let parentname = substitute(child.fields[a:scope],a:curpath, '', '')
let parentname = substitute(parentname,'^' . a:typeinfo.sro, '', '')
let parentpath = split(parentname, a:typeinfo.sro)
let maxpathlen = a:depth - 1 - len(split(a:curpath, a:typeinfo.sro))
let parentlist = s:ExtractParentList(a:tags, a:processedtags,
\ join(parentpath[:maxpathlen], a:typeinfo.sro),
\ a:scope, a:typeinfo)
" If we don't have a parent at this point it must be a pseudo-tag
if empty(parentlist)
let parentname = substitute(child.fields[a:scope],
\ a:curpath, '', '')
let parentname = substitute(parentname,
\ '^' . a:typeinfo.sro, '', '')
let parent = {}
let parent.name = parentname
let parent.fields = {}
let parent.fields.kind = a:typeinfo.scope2kind[a:scope]
let parent.fields.line = 0
if a:pscope != ''
let parentscope = substitute(a:curpath,
\ parentname, '', '')
let parentscope = substitute(parentscope,
\ a:typeinfo.sro . '$', '', '')
let parent.fields[a:pscope] = parentscope
endif
let parent.children = [child]
" If we don't have a parent at this point it must be a
" pseudo-tag, so create an entry for it
call s:ProcessPseudoTag(a:tags, a:processedtags, child,
\ a:curpath, parentpath, parentname,
\ a:pscope, a:scope, a:typeinfo)
else
let parent = parentlist[0]
if has_key(parent, 'children')
@ -541,9 +523,8 @@ function! s:AddChildren(tags, processedtags, curpath,
else
let parent.children = [child]
endif
call add(a:processedtags, parent)
endif
call add(a:processedtags, parent)
endfor
" Recursively add children
@ -579,23 +560,100 @@ function! s:AddChildren(tags, processedtags, curpath,
endif
endfunction
function! s:GetFullTagPath(tag, typeinfo)
let cur_scope = ''
for scope in a:typeinfo.scopes
if has_key(a:tag.fields, scope)
let cur_scope = scope
function! s:ProcessPseudoTag(tags, processedtags, child, curpath, parentpath,
\ parentname, pscope, scope, typeinfo)
" First check if the pseudo-tag is child of an existing tag.
let parentpathlen = len(a:parentpath)
let pseudoparentlist = []
for i in range(parentpathlen - 2, 0, -1)
let pseudoparentpath = a:parentpath[:i]
for scope in a:typeinfo.scopes
let pseudoparentlist = s:ExtractParentList(a:tags, a:processedtags,
\ join(pseudoparentpath, a:typeinfo.sro),
\ scope, a:typeinfo)
if !empty(pseudoparentlist)
break
endif
endfor
if !empty(pseudoparentlist)
break
endif
endfor
if cur_scope != ''
return a:tag.fields[cur_scope] . a:typeinfo.sro . a:tag.name
if !empty(pseudoparentlist)
" The pseudo-tag is child of an existing (real) tag -- so we have to
" add the real tag to the list of processed tags, create a pseudo-tag,
" add the pseudo-tag to the children of the real tag and add the
" /current/ tag ('child') to the children of the pseudo-tag. Yuck.
let pseudoparent = pseudoparentlist[0]
let parentname = substitute(a:parentname, pseudoparent.name, '', '')
let parentname = substitute(parentname, '^' . a:typeinfo.sro, '', '')
if has_key(pseudoparent, 'children')
let is_existingparent = 'v:val.name == parentname &&
\ v:val.fields.kind == a:typeinfo.scope2kind[a:scope]'
let existingparent = filter(copy(pseudoparent.children),
\ is_existingparent)
if !empty(existingparent)
call filter(pseudoparent.children,
\ '!(' . is_existingparent . ')')
let parent = existingparent[0]
call add(parent.children, a:child)
else
let parent = s:CreatePseudoTag(parentname, a:curpath, a:pscope,
\ a:scope, a:typeinfo)
let parent.children = [a:child]
endif
call add(pseudoparent.children, parent)
else
let parent = s:CreatePseudoTag(parentname, a:curpath, a:pscope,
\ a:scope, a:typeinfo)
let parent.children = [a:child]
let pseudoparent.children = [parent]
endif
call add(a:processedtags, pseudoparent)
else
return a:tag.name
let parent = s:CreatePseudoTag(a:parentname, a:curpath, a:pscope,
\ a:scope, a:typeinfo)
let parent.children = [a:child]
call add(a:processedtags, parent)
endif
endfunction
function! s:ExtractParentList(tags, processedtags, path, scope, typeinfo)
let is_parent = 'has_key(a:typeinfo.kind2scope, v:val.fields.kind) &&
\ a:typeinfo.kind2scope[v:val.fields.kind] == a:scope &&
\ v:val.name == a:path'
let parentlist = filter(copy(a:processedtags), is_parent)
if !empty(parentlist)
call filter(a:processedtags, '!(' . is_parent . ')')
else
let parentlist = filter(copy(a:tags), is_parent)
if !empty(parentlist)
call filter(a:tags, '!(' . is_parent . ')')
endif
endif
return parentlist
endfunction
function! s:CreatePseudoTag(name, curpath, pscope, scope, typeinfo)
let pseudotag = {}
let pseudotag.name = a:name
let pseudotag.fields = {}
let pseudotag.fields.kind = a:typeinfo.scope2kind[a:scope]
let pseudotag.fields.line = 0
if a:pscope != ''
let parentscope = substitute(a:curpath, a:name, '', '')
let parentscope = substitute(parentscope, a:typeinfo.sro . '$', '', '')
let pseudotag.fields[a:pscope] = parentscope
endif
return pseudotag
endfunction
function! s:PathMatches(scopename, curpath, sro)
let index = strridx(a:scopename, a:sro)
let parentpath = strpart(a:scopename, 0, index)
@ -948,6 +1006,9 @@ endfunction
function! s:ToggleHelp()
let s:short_help = !s:short_help
" Prevent highlighting from being off after adding/removing the help text
match none
if s:current_file == ''
call s:RenderContent(s:current_file, '')
else