在一個相當大的代碼庫中有幾層可以在vim或命令行中找到所有從基類派生的類類? grep是一個選項,但可以很慢,因爲grep不會編入索引。C++,cscope,ctags和vim:查找從這個類繼承的類
回答
無論是cscope的,也不CTAGS讓我們直接處理繼承,但它相對容易解決這個限制,因爲派生類也收錄。
cscope的
在cscope的,找 「C符號」 Foobar
通常列出了原班和類從它繼承。由於搜索是針對數據庫完成的,因此它閃電般快速。
或者,你可以使用cscope的egrep的搜索功能與像:.*Foobar
模式列出只類從Foobar
繼承。因此,即使我們沒有專門的「查找從這個類繼承的類」命令,我們也可以毫不費力地完成工作。
CTAGS
雖然CTAGS允許包括與--fields=+i
繼承信息,該信息不能直接在Vim中使用。但是,Vim解析了inherits
字段,因此可能會使用taglist()
構建一個快速且骯髒的解決方案。
ACK,AG
這兩個程序的工作或多或少如grep,但他們都朝源代碼中搜索目標,使他們比grep的速度真的。
在我的Vim的配置,:grep
設置爲運行ag
程序而不是默認的grep
所以,尋找從類光標下衍生會是什麼樣子類:
:grep :.*<C-r><C-w><CR>
下面是相關線路我的~/.vimrc
:
if executable("ag")
set grepprg=ag\ --nogroup\ --nocolor\ --ignore-case\ --column
set grepformat=%f:%l:%c:%m,%f:%l:%m
endif
我注意到一些使用':Ggrep'命令使用fugitive和vim的速度。這個改進要求代碼是一個git repo,這在我的文章中沒有提到,但是是另一種選擇。 – 2016-01-26 23:34:15
在lh-cpp中,我定義了命令:Children
。它依賴於ctags數據庫,因此它非常有限。
它需要兩個可選參數:要查找的命名空間(我沒有找到避免這種情況的方法)以及父類的名稱 - >:Children [!] {namespace} {parent-class}
。
該命令嘗試緩存儘可能多的信息。因此,當相關信息在ctags數據庫中發生變化時,必須更新緩存。它是通過敲打命令完成 - >:Children!
我不認爲vim是列出所有子類的正確工具。相反,我們最好使用doxygen爲源代碼生成文檔。雖然doxygen需要一些時間,但我們可以使用所有類的文檔/圖表,這是清晰和快速的。
儘管您正在使用圖形界面進行開發,但這仍然假設。有時候,我必須通過ssh使用minty(cygwins終端),這意味着開發者必須擁有一個web服務器來託管doxygen文件。 – 2014-09-04 17:30:14
是的,確切地說。已經提供SSH的Linux/Unix服務器很容易部署Web服務器,還建議在Web服務器中啓用PHP,在Doxygen頁面內部提供一個簡單的搜索引擎。 – Chandler 2014-09-06 11:22:39
Eclipse和SlickEdit都可以列出類的繼承樹,也可以列出重載方法的樹列表。這在Eclipse中被稱爲Type Hierarchy,當用OO語言進行編碼時,它是IDE中最有用的功能之一。 Doxygen真的很有用,但當你只需要快速瀏覽「Type Hierarchy」時,它就是一種矯枉過正。 – 2016-08-08 19:05:09
如果使用繼承信息(see the --fields option)構建帶有Exuberant CTags的標記文件,那麼以下腳本將起作用。它增加了一個:Inherits
命令,該命令可以採用類的名稱(例如:Inherits Foo
)或正則表達式。
與:tag
命令類似,您需要在正則表達式前面加上一個'\'字符來指示您搜索,例如, :Inherits \Foo.*
。
結果放到窗口的位置列表,你用瀏覽:ll
,:lne
,:lp
等VIM似乎並沒有允許腳本修改標籤列表這就是我喜歡。
如果你想知道爲什麼我不使用taglist()
,這是因爲taglist()
在大型標籤文件上的速度非常慢。原帖有一個使用taglist()
的版本,如果你很好奇,你可以瀏覽編輯歷史。
" Parse an Exuberant Ctags record using the same format as taglist()
"
" Throws CtagsParseErr if there is a general problem parsing the record
function! ParseCtagsRec(record, tag_dir)
let tag = {}
" Parse the standard fields
let sep_pos = stridx(a:record, "\t")
if sep_pos < 1
throw 'CtagsParseErr'
endif
let tag['name'] = a:record[:sep_pos - 1]
let tail = a:record[sep_pos + 1:]
let sep_pos = stridx(tail, "\t")
if sep_pos < 1
throw 'CtagsParseErr'
endif
" '/' will work as a path separator on most OS's, but there
" should really be an OS independent way to build paths.
let tag['filename'] = a:tag_dir.'/'.tail[:sep_pos - 1]
let tail = tail[sep_pos + 1:]
let sep_pos = stridx(tail, ";\"\t")
if sep_pos < 1
throw 'CtagsParseErr'
endif
let tag['cmd'] = tail[:sep_pos - 1]
" Parse the Exuberant Ctags extension fields
let extensions = tail[sep_pos + 3:]
for extension in split(extensions, '\t')
let sep_pos = stridx(extension, ':')
if sep_pos < 1
if has_key(tag, 'kind')
throw 'CtagsParseErr'
endif
let tag['kind'] = extension
else
let tag[extension[:sep_pos - 1]] = extension[sep_pos + 1:]
endif
endfor
return tag
endfunction
" Find all classes derived from a given class, or a regex (preceded by a '/')
" The results are placed in the current windows location list.
function! Inherits(cls_or_regex)
if a:cls_or_regex[0] == '/'
let regex = a:cls_or_regex[1:]
else
let regex = '\<'.a:cls_or_regex.'\>$'
endif
let loc_list = []
let tfiles = tagfiles()
let tag_count = 0
let found_count = 0
for file in tfiles
let tag_dir = fnamemodify(file, ':p:h')
try
for line in readfile(file)
let tag_count += 1
if tag_count % 10000 == 0
echo tag_count 'tags scanned,' found_count 'matching classes found. Still searching...'
redraw
endif
if line[0] == '!'
continue
endif
let tag = ParseCtagsRec(line, tag_dir)
if has_key(tag, 'inherits')
let baselist = split(tag['inherits'], ',\s*')
for base in baselist
if match(base, regex) != -1
let location = {}
let location['filename'] = tag['filename']
let cmd = tag['cmd']
if cmd[0] == '/' || cmd[0] == '?'
let location['pattern'] = cmd[1:-2]
else
let location['lnum'] = str2nr(cmd)
endif
call add(loc_list, location)
let found_count += 1
endif
endfor
endif
endfor
catch /^OptionErr$/
echo 'Parsing error: Failed to parse an option.'
return
catch /^CtagsParseErr$/
echo 'Parsing error: Tags files does not appear to be an Exuberant Ctags file.'
return
catch
echo 'Could not read tag file:' file
return
endtry
endfor
call setloclist(0, loc_list)
echo tag_count 'tags scanned,' found_count 'matching classes found.'
endfunction
command! -nargs=1 -complete=tag Inherits call Inherits('<args>')
- 1. 使用ctags和cscope
- 2. 查詢和繼承的類
- 3. C#類繼承
- 4. 繼承類。 C++
- 5. C#繼承類
- 6. 類繼承C++
- 7. c#繼承類
- 8. 從抽象類繼承C#
- 9. 從C++類繼承NSObject
- 10. 從protobuf繼承C++類
- 11. C++中的繼承(父類和子類)
- 12. C++模板類和繼承
- 13. C++泛型類和繼承
- 14. C#嵌套類和繼承
- 15. C++循環繼承和類
- 16. C++繼承和類成員
- 17. C#繼承和靜態類
- 18. C++類繼承和模板
- 19. 目標C類和繼承
- 20. c#類的繼承
- 21. C++類的繼承
- 22. 如何從另一個繼承類的繼承類的說話
- 23. C#:繼承一個子類,它從父
- 24. 從兩個類繼承在C#
- 25. 從兩個類繼承在C++
- 26. C#繼承。從基類派生類
- 27. 類繼承和模板類C++
- 28. 類和基類繼承在C#
- 29. FreeBSD使用cscope&ctags
- 30. C++/CLI:從一個CLR類繼承,多個C ++類
我不這麼認爲時,cscope和ctags的是基於正則表達式,但沒有類似語法IDE – 2014-09-04 02:35:10
你有沒有考慮[確認](http://beyondgrep.com/),將[Ag銀魔] (https://github.com/ggreer/the_silver_searcher)或[git grep](http://git-scm.com/docs/git-grep)?這些通常比grep快得多。 – 2014-09-04 04:54:07
我也對此感興趣。我目前使用Eclipse和SlickEdit來做到這一點。在Eclipse中,這個功能稱爲Type Hierarchy。有一個名爲eclim的項目,它將Eclipse的功能集成到Vim中,這是Vim中最接近我看到的,不幸的是,eclim吃了很多內存,並且在Windows中不斷崩潰,很可能是由於Eclipse而要求Eclipse精細化調整內存設置.. – 2016-08-08 19:10:24