summaryrefslogtreecommitdiff
path: root/.vim/autoload/omni/cpp/complete.vim
diff options
context:
space:
mode:
Diffstat (limited to '.vim/autoload/omni/cpp/complete.vim')
-rw-r--r--.vim/autoload/omni/cpp/complete.vim569
1 files changed, 569 insertions, 0 deletions
diff --git a/.vim/autoload/omni/cpp/complete.vim b/.vim/autoload/omni/cpp/complete.vim
new file mode 100644
index 0000000..a7e4edc
--- /dev/null
+++ b/.vim/autoload/omni/cpp/complete.vim
@@ -0,0 +1,569 @@
+" Description: Omni completion script for cpp files
+" Maintainer: Vissale NEANG
+" Last Change: 27 sept. 2007
+
+if v:version < 700
+ echohl WarningMsg
+ echomsg "omni#cpp#complete.vim: Please install vim 7.0 or higher for omni-completion"
+ echohl None
+ finish
+endif
+
+call omni#cpp#settings#Init()
+let s:OmniCpp_ShowScopeInAbbr = g:OmniCpp_ShowScopeInAbbr
+let s:OmniCpp_ShowPrototypeInAbbr = g:OmniCpp_ShowPrototypeInAbbr
+let s:OmniCpp_ShowAccess = g:OmniCpp_ShowAccess
+let s:szCurrentWorkingDir = getcwd()
+
+" Cache data
+let s:CACHE_TAG_POPUP_ITEMS = {}
+let s:CACHE_TAG_FILES = {}
+let s:CACHE_TAG_ENV = ''
+let s:CACHE_OVERLOADED_FUNCTIONS = {}
+
+" Has preview window?
+let s:hasPreviewWindow = match(&completeopt, 'preview')>=0
+let s:hasPreviewWindowOld = s:hasPreviewWindow
+
+" Popup item list
+let s:popupItemResultList = []
+
+" May complete indicator
+let s:bMayComplete = 0
+
+" Init mappings
+function! omni#cpp#complete#Init()
+ call omni#cpp#settings#Init()
+ set omnifunc=omni#cpp#complete#Main
+ inoremap <expr> <C-X><C-O> omni#cpp#maycomplete#Complete()
+ inoremap <expr> . omni#cpp#maycomplete#Dot()
+ inoremap <expr> > omni#cpp#maycomplete#Arrow()
+ inoremap <expr> : omni#cpp#maycomplete#Scope()
+endfunc
+
+" Find the start position of the completion
+function! s:FindStartPositionOfCompletion()
+ " Locate the start of the item, including ".", "->" and "[...]".
+ let line = getline('.')
+ let start = col('.') - 1
+
+ let lastword = -1
+ while start > 0
+ if line[start - 1] =~ '\w'
+ let start -= 1
+ elseif line[start - 1] =~ '\.'
+ " Searching for dot '.'
+ if lastword == -1
+ let lastword = start
+ endif
+ let start -= 1
+ elseif start > 1 && line[start - 2] == '-' && line[start - 1] == '>'
+ " Searching for '->'
+ if lastword == -1
+ let lastword = start
+ endif
+ let start -= 2
+ elseif start > 1 && line[start - 2] == ':' && line[start - 1] == ':'
+ " Searching for '::' for namespaces and class
+ if lastword == -1
+ let lastword = start
+ endif
+ let start -= 2
+ elseif line[start - 1] == ']'
+ " Skip over [...].
+ let n = 0
+ let start -= 1
+ while start > 0
+ let start -= 1
+ if line[start] == '['
+ if n == 0
+ break
+ endif
+ let n -= 1
+ elseif line[start] == ']' " nested []
+ let n += 1
+ endif
+ endwhile
+ else
+ break
+ endif
+ endwhile
+ if lastword==-1
+ " For completion on the current scope
+ let lastword = start
+ endif
+ return lastword
+endfunc
+
+" Returns if szKey1.szKey2 is in the cache
+" @return
+" - 0 = key not found
+" - 1 = szKey1.szKey2 found
+" - 2 = szKey1.[part of szKey2] found
+function! s:IsCached(cache, szKey1, szKey2)
+ " Searching key in the result cache
+ let szResultKey = a:szKey1 . a:szKey2
+ let result = [0, szResultKey]
+ if a:szKey2 != ''
+ let szKey = a:szKey2
+ while len(szKey)>0
+ if has_key(a:cache, a:szKey1 . szKey)
+ let result[1] = a:szKey1 . szKey
+ if szKey != a:szKey2
+ let result[0] = 2
+ else
+ let result[0] = 1
+ endif
+ break
+ endif
+ let szKey = szKey[:-2]
+ endwhile
+ else
+ if has_key(a:cache, szResultKey)
+ let result[0] = 1
+ endif
+ endif
+ return result
+endfunc
+
+" Extend a tag item to a popup item
+function! s:ExtendTagItemToPopupItem(tagItem, szTypeName)
+ let tagItem = a:tagItem
+
+ " Add the access
+ let szItemMenu = ''
+ let accessChar = {'public': '+','protected': '#','private': '-'}
+ if g:OmniCpp_ShowAccess
+ if has_key(tagItem, 'access') && has_key(accessChar, tagItem.access)
+ let szItemMenu = szItemMenu.accessChar[tagItem.access]
+ else
+ let szItemMenu = szItemMenu." "
+ endif
+ endif
+
+ " Formating optional menu string we extract the scope information
+ let szName = substitute(tagItem.name, '.*::', '', 'g')
+ let szItemWord = szName
+ let szAbbr = szName
+
+ if !g:OmniCpp_ShowScopeInAbbr
+ let szScopeOfTag = omni#cpp#utils#ExtractScope(tagItem)
+ let szItemMenu = szItemMenu.' '.szScopeOfTag[2:]
+ let szItemMenu = substitute(szItemMenu, '\s\+$', '', 'g')
+ else
+ let szAbbr = tagItem.name
+ endif
+ if g:OmniCpp_ShowAccess
+ let szItemMenu = substitute(szItemMenu, '^\s\+$', '', 'g')
+ else
+ let szItemMenu = substitute(szItemMenu, '\(^\s\+\)\|\(\s\+$\)', '', 'g')
+ endif
+
+ " Formating information for the preview window
+ if index(['f', 'p'], tagItem.kind[0])>=0
+ let szItemWord .= '('
+ if g:OmniCpp_ShowPrototypeInAbbr && has_key(tagItem, 'signature')
+ let szAbbr .= tagItem.signature
+ else
+ let szAbbr .= '('
+ endif
+ endif
+ let szItemInfo = ''
+ if s:hasPreviewWindow
+ let szItemInfo = omni#cpp#utils#GetPreviewWindowStringFromTagItem(tagItem)
+ endif
+
+ " If a function is a ctor we add a new key in the tagItem
+ if index(['f', 'p'], tagItem.kind[0])>=0
+ if match(szName, '^\~') < 0 && a:szTypeName =~ '\C\<'.szName.'$'
+ " It's a ctor
+ let tagItem['ctor'] = 1
+ elseif has_key(tagItem, 'access') && tagItem.access == 'friend'
+ " Friend function
+ let tagItem['friendfunc'] = 1
+ endif
+ endif
+
+ " Extending the tag item to a popup item
+ let tagItem['word'] = szItemWord
+ let tagItem['abbr'] = szAbbr
+ let tagItem['menu'] = szItemMenu
+ let tagItem['info'] = szItemInfo
+ let tagItem['dup'] = (s:hasPreviewWindow && index(['f', 'p', 'm'], tagItem.kind[0])>=0)
+ return tagItem
+endfunc
+
+" Get tag popup item list
+function! s:TagPopupList(szTypeName, szBase)
+ let result = []
+
+ " Searching key in the result cache
+ let cacheResult = s:IsCached(s:CACHE_TAG_POPUP_ITEMS, a:szTypeName, a:szBase)
+
+ " Building the tag query, we don't forget dtors when a:szBase==''
+ if a:szTypeName!=''
+ " Scope search
+ let szTagQuery = '^' . a:szTypeName . '::' . a:szBase . '\~\?\w\+$'
+ else
+ " Global search
+ let szTagQuery = '^' . a:szBase . '\w\+$'
+ endif
+
+ " If the result is already in the cache we return it
+ if cacheResult[0]
+ let result = s:CACHE_TAG_POPUP_ITEMS[ cacheResult[1] ]
+ if cacheResult[0] == 2
+ let result = filter(copy(result), 'v:val.name =~ szTagQuery' )
+ endif
+ return result
+ endif
+
+ try
+ " Getting tags
+ let result = omni#common#utils#TagList(szTagQuery)
+
+ " We extend tag items to popup items
+ call map(result, 's:ExtendTagItemToPopupItem(v:val, a:szTypeName)')
+
+ " We store the result in a cache
+ if cacheResult[1] != ''
+ let s:CACHE_TAG_POPUP_ITEMS[ cacheResult[1] ] = result
+ endif
+ catch /^TagList:UserInterrupt$/
+ endtry
+
+ return result
+endfunc
+
+" Find complete matches for a completion on the global scope
+function! s:SearchGlobalMembers(szBase)
+ if a:szBase != ''
+ let tagPopupList = s:TagPopupList('', a:szBase)
+ let tagPopupList = filter(copy(tagPopupList), g:omni#cpp#utils#szFilterGlobalScope)
+ call extend(s:popupItemResultList, tagPopupList)
+ endif
+endfunc
+
+" Search class, struct, union members
+" @param resolvedTagItem: a resolved tag item
+" @param szBase: string base
+" @return list of tag items extended to popup items
+function! s:SearchMembers(resolvedTagItem, szBase)
+ let result = []
+ if a:resolvedTagItem == {}
+ return result
+ endif
+
+ " Get type info without the starting '::'
+ let szTagName = omni#cpp#utils#ExtractTypeInfoFromTag(a:resolvedTagItem)[2:]
+
+ " Unnamed type case. A tag item representing an unnamed type is a variable
+ " ('v') a member ('m') or a typedef ('t')
+ if index(['v', 't', 'm'], a:resolvedTagItem.kind[0])>=0 && has_key(a:resolvedTagItem, 'typeref')
+ " We remove the 'struct:' or 'class:' etc...
+ let szTagName = substitute(a:resolvedTagItem.typeref, '^\w\+:', '', 'g')
+ endif
+
+ return copy(s:TagPopupList(szTagName, a:szBase))
+endfunc
+
+" Return if the tag env has changed
+function! s:HasTagEnvChanged()
+ if s:CACHE_TAG_ENV == &tags
+ return 0
+ else
+ let s:CACHE_TAG_ENV = &tags
+ return 1
+ endif
+endfunc
+
+" Return if a tag file has changed in tagfiles()
+function! s:HasATagFileOrTagEnvChanged()
+ if s:HasTagEnvChanged()
+ let s:CACHE_TAG_FILES = {}
+ return 1
+ endif
+
+ let result = 0
+ for tagFile in tagfiles()
+ if tagFile == ""
+ continue
+ endif
+
+ if has_key(s:CACHE_TAG_FILES, tagFile)
+ let currentFiletime = getftime(tagFile)
+ if currentFiletime > s:CACHE_TAG_FILES[tagFile]
+ " The file has changed, updating the cache
+ let s:CACHE_TAG_FILES[tagFile] = currentFiletime
+ let result = 1
+ endif
+ else
+ " We store the time of the file
+ let s:CACHE_TAG_FILES[tagFile] = getftime(tagFile)
+ let result = 1
+ endif
+ endfor
+ return result
+endfunc
+" Initialization
+call s:HasATagFileOrTagEnvChanged()
+
+" Filter same function signatures of base classes
+function! s:FilterOverloadedFunctions(tagPopupList)
+ let result = []
+ for tagPopupItem in a:tagPopupList
+ if has_key(tagPopupItem, 'kind') && index(['f', 'p'], tagPopupItem.kind[0])>=0 && has_key(tagPopupItem, 'signature')
+ if !has_key(s:CACHE_OVERLOADED_FUNCTIONS, tagPopupItem.word . tagPopupItem.signature)
+ let s:CACHE_OVERLOADED_FUNCTIONS[tagPopupItem.word . tagPopupItem.signature] = 1
+ call extend(result, [tagPopupItem])
+ endif
+ else
+ call extend(result, [tagPopupItem])
+ endif
+ endfor
+ return result
+endfunc
+
+" Access filter
+function! s:GetAccessFilter(szFilter, szAccessFilter)
+ let szFilter = a:szFilter
+ if g:OmniCpp_DisplayMode == 0
+ if a:szAccessFilter == 'public'
+ " We only get public members
+ let szFilter .= "&& v:val.access == 'public'"
+ elseif a:szAccessFilter == 'protected'
+ " We get public and protected members
+ let szFilter .= "&& v:val.access != 'private'"
+ endif
+ endif
+ return szFilter
+endfunc
+
+" Filter class members in the popup menu after a completion with -> or .
+function! s:FilterClassMembers(tagPopupList, szAccessFilter)
+ let szFilter = "(!has_key(v:val, 'friendfunc') && !has_key(v:val, 'ctor') && has_key(v:val, 'kind') && index(['m', 'p', 'f'], v:val.kind[0])>=0 && has_key(v:val, 'access'))"
+ call filter(a:tagPopupList, s:GetAccessFilter(szFilter, a:szAccessFilter))
+ call extend(s:popupItemResultList, s:FilterOverloadedFunctions(a:tagPopupList))
+endfunc
+
+" Filter class scope members in the popup menu after a completion with ::
+" We only display attribute and functions members that
+" have an access information. We also display nested
+" class, struct, union, and enums, typedefs
+function! s:FilterClassScopeMembers(tagPopupList, szAccessFilter)
+ let szFilter = "!has_key(v:val, 'friendfunc') && has_key(v:val, 'kind') && (index(['m', 'p', 'f'], v:val.kind[0])>=0 && has_key(v:val, 'access'))"
+ let szFilter = s:GetAccessFilter(szFilter, a:szAccessFilter)
+ let szFilter .= "|| index(['c','e','g','s','t','u'], v:val.kind[0])>=0"
+ call filter(a:tagPopupList, szFilter)
+ call extend(s:popupItemResultList, s:FilterOverloadedFunctions(a:tagPopupList))
+endfunc
+
+" Filter static class members in the popup menu
+function! s:FilterStaticClassMembers(tagPopupList, szAccessFilter)
+ let szFilter = "!has_key(v:val, 'friendfunc') && has_key(v:val, 'kind') && (index(['m', 'p', 'f'], v:val.kind[0])>=0 && has_key(v:val, 'access') && match(v:val.cmd, '\\Cstatic')!=-1)"
+ let szFilter = s:GetAccessFilter(szFilter, a:szAccessFilter)
+ let szFilter = szFilter . "|| index(['c','e','g','n','s','t','u','v'], v:val.kind[0])>=0"
+ call filter(a:tagPopupList, szFilter)
+ call extend(s:popupItemResultList, s:FilterOverloadedFunctions(a:tagPopupList))
+endfunc
+
+" Filter scope members in the popup menu
+function! s:FilterNamespaceScopeMembers(tagPopupList)
+ call extend(s:popupItemResultList, a:tagPopupList)
+endfunc
+
+" Init data at the start of completion
+function! s:InitComplete()
+ " Reset the popup item list
+ let s:popupItemResultList = []
+ let s:CACHE_OVERLOADED_FUNCTIONS = {}
+
+ " Reset includes cache when the current working directory has changed
+ let szCurrentWorkingDir = getcwd()
+ if s:szCurrentWorkingDir != szCurrentWorkingDir
+ let s:szCurrentWorkingDir = szCurrentWorkingDir
+ let g:omni#cpp#includes#CACHE_INCLUDES = {}
+ let g:omni#cpp#includes#CACHE_FILE_TIME = {}
+ endif
+
+ " Has preview window ?
+ let s:hasPreviewWindow = match(&completeopt, 'preview')>=0
+
+ let bResetCache = 0
+
+ " Reset tag env or tag files dependent caches
+ if s:HasATagFileOrTagEnvChanged()
+ let bResetCache = 1
+ endif
+
+ if (s:OmniCpp_ShowScopeInAbbr != g:OmniCpp_ShowScopeInAbbr)
+ \|| (s:OmniCpp_ShowPrototypeInAbbr != g:OmniCpp_ShowPrototypeInAbbr)
+ \|| (s:OmniCpp_ShowAccess != g:OmniCpp_ShowAccess)
+
+ let s:OmniCpp_ShowScopeInAbbr = g:OmniCpp_ShowScopeInAbbr
+ let s:OmniCpp_ShowPrototypeInAbbr = g:OmniCpp_ShowPrototypeInAbbr
+ let s:OmniCpp_ShowAccess = g:OmniCpp_ShowAccess
+ let bResetCache = 1
+ endif
+
+ if s:hasPreviewWindow != s:hasPreviewWindowOld
+ let s:hasPreviewWindowOld = s:hasPreviewWindow
+ let bResetCache = 1
+ endif
+
+ if bResetCache
+ let g:omni#cpp#namespaces#CacheResolve = {}
+ let s:CACHE_TAG_POPUP_ITEMS = {}
+ let g:omni#cpp#utils#CACHE_TAG_INHERITS = {}
+ call garbagecollect()
+ endif
+
+ " Check for updates
+ for szIncludeName in keys(g:omni#cpp#includes#CACHE_INCLUDES)
+ let fTime = getftime(szIncludeName)
+ let bNeedUpdate = 0
+ if has_key(g:omni#cpp#includes#CACHE_FILE_TIME, szIncludeName)
+ if fTime != g:omni#cpp#includes#CACHE_FILE_TIME[szIncludeName]
+ let bNeedUpdate = 1
+ endif
+ else
+ let g:omni#cpp#includes#CACHE_FILE_TIME[szIncludeName] = fTime
+ let bNeedUpdate = 1
+ endif
+
+ if bNeedUpdate
+ " We have to update include list and namespace map of this file
+ call omni#cpp#includes#GetList(szIncludeName, 1)
+ call omni#cpp#namespaces#GetMapFromBuffer(szIncludeName, 1)
+ endif
+ endfor
+
+ let s:bDoNotComplete = 0
+endfunc
+
+
+" This function is used for the 'omnifunc' option.
+function! omni#cpp#complete#Main(findstart, base)
+ if a:findstart
+ "call omni#common#debug#Start()
+
+ call s:InitComplete()
+
+ " Note: if s:bMayComplete==1 g:omni#cpp#items#data is build by MayComplete functions
+ if !s:bMayComplete
+ " If the cursor is in a comment we go out
+ if omni#cpp#utils#IsCursorInCommentOrString()
+ " Returning -1 is not enough we have to set a variable to let
+ " the second call of omni#cpp#complete knows that the
+ " cursor was in a comment
+ " Why is there a second call when the first call returns -1 ?
+ let s:bDoNotComplete = 1
+ return -1
+ endif
+
+ " We get items here (whend a:findstart==1) because GetItemsToComplete()
+ " depends on the cursor position.
+ " When a:findstart==0 the cursor position is modified
+ let g:omni#cpp#items#data = omni#cpp#items#Get(omni#cpp#utils#TokenizeCurrentInstruction())
+ endif
+
+ " Get contexts stack
+ let s:contextStack = omni#cpp#namespaces#GetContexts()
+
+ " Reinit of may complete indicator
+ let s:bMayComplete = 0
+ return s:FindStartPositionOfCompletion()
+ endif
+
+ " If the cursor is in a comment we return an empty result
+ if s:bDoNotComplete
+ let s:bDoNotComplete = 0
+ return []
+ endif
+
+ if len(g:omni#cpp#items#data)==0
+ " A) CURRENT_SCOPE_COMPLETION_MODE
+
+ " 1) Displaying data of each context
+ let szAccessFilter = 'all'
+ for szCurrentContext in s:contextStack
+ if szCurrentContext == '::'
+ continue
+ endif
+
+ let resolvedTagItem = omni#cpp#utils#GetResolvedTagItem(s:contextStack, omni#cpp#utils#CreateTypeInfo(szCurrentContext))
+ if resolvedTagItem != {}
+ " We don't search base classes because bases classes are
+ " already in the context stack
+ let tagPopupList = s:SearchMembers(resolvedTagItem, a:base)
+ if index(['c','s'], resolvedTagItem.kind[0])>=0
+ " It's a class or struct
+ call s:FilterClassScopeMembers(tagPopupList, szAccessFilter)
+ let szAccessFilter = 'protected'
+ else
+ " It's a namespace or union, we display all members
+ call s:FilterNamespaceScopeMembers(tagPopupList)
+ endif
+ endif
+ endfor
+
+ " 2) Displaying global scope members
+ if g:OmniCpp_GlobalScopeSearch
+ call s:SearchGlobalMembers(a:base)
+ endif
+ else
+ let typeInfo = omni#cpp#items#ResolveItemsTypeInfo(s:contextStack, g:omni#cpp#items#data)
+
+ if typeInfo != {}
+ if g:omni#cpp#items#data[-1].kind == 'itemScope'
+ " B) SCOPE_COMPLETION_MODE
+ if omni#cpp#utils#GetTypeInfoString(typeInfo)==''
+ call s:SearchGlobalMembers(a:base)
+ else
+ for resolvedTagItem in omni#cpp#utils#GetResolvedTags(s:contextStack, typeInfo)
+ let tagPopupList = s:SearchMembers(resolvedTagItem, a:base)
+ if index(['c','s'], resolvedTagItem.kind[0])>=0
+ let szTypeInfo = omni#cpp#utils#ExtractTypeInfoFromTag(resolvedTagItem)
+ if g:OmniCpp_DisplayMode==0
+ " We want to complete a class or struct
+ " If this class is a base class so we display all class members
+ if index(s:contextStack, szTypeInfo)<0
+ let szAccessFilter = 'public'
+ call s:FilterStaticClassMembers(tagPopupList, szAccessFilter)
+ else
+ let szAccessFilter = (s:contextStack[0] == szTypeInfo)? 'all' : 'protected'
+ call s:FilterClassScopeMembers(tagPopupList, szAccessFilter)
+ endif
+ else
+ if index(s:contextStack, szTypeInfo)<0
+ let szAccessFilter = 'public'
+ else
+ let szAccessFilter = (s:contextStack[0] == szTypeInfo)? 'all' : 'protected'
+ endif
+ call s:FilterClassScopeMembers(tagPopupList, szAccessFilter)
+ endif
+ else
+ " We want to complete a namespace
+ call s:FilterNamespaceScopeMembers(tagPopupList)
+ endif
+ endfor
+ endif
+ else
+ " C) CLASS_MEMBERS_COMPLETION_MODE
+ for resolvedTagItem in omni#cpp#utils#GetResolvedTags(s:contextStack, typeInfo)
+ let szTypeInfo = omni#cpp#utils#ExtractTypeInfoFromTag(resolvedTagItem)
+ if index(s:contextStack, szTypeInfo)<0
+ let szAccessFilter = 'public'
+ else
+ let szAccessFilter = (s:contextStack[0] == szTypeInfo)? 'all' : 'protected'
+ endif
+ call s:FilterClassMembers(s:SearchMembers(resolvedTagItem, a:base), szAccessFilter)
+ endfor
+ endif
+ endif
+ endif
+
+ "call omni#common#debug#End()
+
+ return s:popupItemResultList
+endfunc