" Vim completion script for java " Maintainer: artur shaik " " Utility functions function! s:Log(log) let log = type(a:log) == type("") ? a:log : string(a:log) call javacomplete#logger#Log("[util] ". log) endfunction " TODO: search pair used in string, like " 'create(ao.fox("("), new String).foo().' function! javacomplete#util#GetMatchedIndexEx(str, idx, one, another) let pos = a:idx while 0 <= pos && pos < len(a:str) let pos = match(a:str, '['. a:one . escape(a:another, ']') .']', pos+1) if pos != -1 if a:str[pos] == a:one let pos = javacomplete#util#GetMatchedIndexEx(a:str, pos, a:one, a:another) elseif a:str[pos] == a:another break endif endif endwhile return 0 <= pos && pos < len(a:str) ? pos : -3 endfunction " set string literal empty, remove comments, trim begining or ending spaces " test case: ' sb. /* block comment*/ append( "stringliteral" ) // comment ' function! javacomplete#util#Prune(str, ...) if a:str =~ '^\s*$' | return '' | endif let str = substitute(a:str, '"\(\\\(["\\''ntbrf]\)\|[^"]\)*"', '""', 'g') let str = substitute(str, '\/\/.*', '', 'g') let str = javacomplete#util#RemoveBlockComments(str) let str = javacomplete#util#Trim(str) return a:0 > 0 ? str : str . ' ' endfunction " Given argument, replace block comments with spaces of same number function! javacomplete#util#RemoveBlockComments(str, ...) let result = a:str let ib = match(result, '\/\*') let ie = match(result, '\*\/') while ib != -1 && ie != -1 && ib < ie let result = strpart(result, 0, ib) . (a:0 == 0 ? ' ' : repeat(' ', ie-ib+2)) . result[ie+2: ] let ib = match(result, '\/\*') let ie = match(result, '\*\/') endwhile return result endfunction function! javacomplete#util#Trim(str) let str = substitute(a:str, '^\s*', '', '') return substitute(str, '\s*$', '', '') endfunction fu! javacomplete#util#SplitAt(str, index) return [strpart(a:str, 0, a:index+1), strpart(a:str, a:index+1)] endfu function! javacomplete#util#SearchPairBackward(str, idx, one, another) let idx = a:idx let n = 0 while idx >= 0 let idx -= 1 if a:str[idx] == a:one if n == 0 break endif let n -= 1 elseif a:str[idx] == a:another " nested let n += 1 endif endwhile return idx endfunction function! javacomplete#util#CountDims(str) if match(a:str, '[[\]]') == -1 return 0 endif " int[] -> [I, String[] -> let dims = len(matchstr(a:str, '^[\+')) if dims == 0 let idx = len(a:str)-1 while idx >= 0 && a:str[idx] == ']' let dims += 1 let idx = javacomplete#util#SearchPairBackward(a:str, idx, '[', ']')-1 endwhile endif return dims endfu function! javacomplete#util#Index(list, expr, key) let i = 0 while i < len(a:list) if get(a:list[i], a:key, '') == a:expr return i endif let i += 1 endwhile return -1 endfunction function! javacomplete#util#KeepCursor(cmd) let lnum_old = line('.') let col_old = col('.') exe a:cmd call cursor(lnum_old, col_old) endfunction function! javacomplete#util#InCommentOrLiteral(line, col) if has("syntax") && &ft != 'jsp' return synIDattr(synID(a:line, a:col, 1), "name") =~? '\(Comment\|String\|Character\)' endif endfunction function! javacomplete#util#InComment(line, col) if has("syntax") && &ft != 'jsp' return synIDattr(synID(a:line, a:col, 1), "name") =~? 'comment' endif endfunction fu! javacomplete#util#GotoUpperBracket() let searched = 0 while (!searched) call search('[{}]', 'bW') if getline('.')[col('.')-1] == '}' normal! % else let searched = 1 endif endwhile endfu function! javacomplete#util#GetClassNameWithScope(...) let offset = a:0 > 0 ? a:1 : col('.') let curline = getline('.') let word_l = offset - 1 while curline[word_l - 1] =~ '[\.:@A-Za-z0-9_]' let word_l -= 1 if curline[word_l] == '@' break endif endwhile let word_r = word_l while curline[word_r] =~ '[@A-Za-z0-9_]' let word_r += 1 endwhile return curline[word_l : word_r - 1] endfunction function! s:MemberCompare(m1, m2) return a:m1['n'] == a:m2['n'] ? 0 : a:m1['n'] > a:m2['n'] ? 1 : -1 endfunction function! javacomplete#util#Sort(ci) let ci = a:ci if has_key(ci, 'fields') call sort(ci['fields'], 's:MemberCompare') endif if has_key(ci, 'methods') call sort(ci['methods'], 's:MemberCompare') endif return ci endfunction function! javacomplete#util#CleanFQN(fqnDeclaration) let start = 0 let fqnDeclaration = a:fqnDeclaration let result = matchlist(fqnDeclaration, '\<'. g:RE_IDENTIFIER. '\%(\s*\.\s*\('. g:RE_IDENTIFIER. '\)\)*', start) while !empty(result) if len(result[1]) > 0 if result[0][-1:-1] == '$' let result[0] = result[0][:-2]. '\$' endif let fqnDeclaration = substitute(fqnDeclaration, result[0], result[1], '') let shift = result[1] else let shift = result[0] endif if shift[-1:-1] == '$' let shift = shift[:-2]. '\$' endif let start = match(fqnDeclaration, shift, start) + len(shift) let result = matchlist(fqnDeclaration, '\<'. g:RE_IDENTIFIER. '\%(\s*\.\s*\('. g:RE_IDENTIFIER. '\)\)*', start) endwhile return fqnDeclaration endfunction function! javacomplete#util#FindFile(what, ...) abort let direction = a:0 > 0 ? a:1 : ';' let old_suffixesadd = &suffixesadd try let &suffixesadd = '' return findfile(a:what, escape(expand('.'), '*[]?{}, ') . direction) finally let &suffixesadd = old_suffixesadd endtry endfunction function! javacomplete#util#GlobPathList(path, pattern, suf, depth) if v:version > 704 || v:version == 704 && has('patch279') let pathList = globpath(a:path, a:pattern, a:suf, 1) else let pathList = split(globpath(a:path, a:pattern, a:suf), "\n") endif if a:depth > 0 let depths = [] for i in range(1, a:depth) call add(depths, repeat("*".g:FILE_SEP, i)) endfor for i in depths call extend(pathList, javacomplete#util#GlobPathList(a:path, i. a:pattern, 0, 0)) endfor endif return pathList endfunction function! javacomplete#util#IsWindows() abort return has("win32") || has("win64") || has("win16") || has("dos32") || has("dos16") endfunction function! s:JobVimOnCloseHandler(channel) let job = s:asyncJobs[s:ChannelId(a:channel)] let info = job_info(job['job']) let Handler = function(job['handler']) call call(Handler, [info['exitval'], 'exit']) endfunction function! s:JobVimOnErrorHandler(channel, text) let job = s:asyncJobs[s:ChannelId(a:channel)] let Handler = function(job['handler']) call call(Handler, [[a:text], 'stderr']) endfunction function! s:JobVimOnCallbackHandler(channel, text) let job = s:asyncJobs[s:ChannelId(a:channel)] let Handler = function(job['handler']) call call(Handler, [[a:text], 'stdout']) endfunction function! s:JobNeoVimResponseHandler(jobId, data, event) let job = s:asyncJobs[a:jobId] let Handler = function(job['handler']) call call(Handler, [a:data, a:event]) endfunction function! s:ChannelId(channel) return matchstr(a:channel, '\d\+') endfunction function! s:NewJob(id, handler) let s:asyncJobs = get(s:, 'asyncJobs', {}) let s:asyncJobs[a:id] = {} let s:asyncJobs[a:id]['handler'] = a:handler endfunction function! javacomplete#util#RunSystem(command, shellName, handler) call s:Log("running command: ". string(a:command)) if has('nvim') if exists('*jobstart') let callbacks = { \ 'on_stdout': function('s:JobNeoVimResponseHandler'), \ 'on_stderr': function('s:JobNeoVimResponseHandler'), \ 'on_exit': function('s:JobNeoVimResponseHandler') \ } let jobId = jobstart(a:command, extend({'shell': a:shellName}, callbacks)) call s:NewJob(jobId, a:handler) return endif elseif exists('*job_start') let options = { \ 'out_cb' : function('s:JobVimOnCallbackHandler'), \ 'err_cb' : function('s:JobVimOnErrorHandler'), \ 'close_cb' : function('s:JobVimOnCloseHandler') \ } if has('win32') && type(a:command) == 3 let a:command[0] = exepath(a:command[0]) endif let job = job_start(a:command, options) let jobId = s:ChannelId(job_getchannel(job)) call s:NewJob(jobId, a:handler) let s:asyncJobs[jobId]['job'] = job return endif if type(a:command) == type([]) let ret = system(join(a:command, " ")) else let ret = system(a:command) endif for l in split(ret, "\n") call call(a:handler, [[l], "stdout"]) endfor call call(a:handler, ["0", "exit"]) endfunction function! javacomplete#util#Base64Encode(str) JavacompletePy import base64 JavacompletePy import vim JavacompletePy content = vim.eval('a:str') if sys.version_info.major == 2 else bytes(vim.eval('a:str'), 'utf-8') JavacompletePy b64 = base64.b64encode(content) JavacompletePy vim.command("let base64 = '%s'" % (b64 if sys.version_info.major == 2 else b64.decode('utf-8'))) return base64 endfunction function! javacomplete#util#RemoveFile(file) if filewritable(a:file) if g:JavaComplete_IsWindows silent exe '!rmdir /s /q "'. a:file. '"' else silent exe '!rm -r "'. a:file. '"' endif silent redraw! endif endfunction if exists('*uniq') function! javacomplete#util#uniq(list) abort return uniq(a:list) endfunction else function! javacomplete#util#uniq(list) abort let i = len(a:list) - 1 while 0 < i if a:list[i] ==# a:list[i - 1] call remove(a:list, i) let i -= 2 else let i -= 1 endif endwhile return a:list endfunction endif function! javacomplete#util#GetBase(extra) let base = expand(g:JavaComplete_BaseDir. g:FILE_SEP. "javacomplete2". g:FILE_SEP. a:extra) if !isdirectory(base) call mkdir(base, "p") endif return base endfunction function! javacomplete#util#RemoveEmptyClasses(classes) return filter(a:classes, 'v:val !~ "^$"') endfunction function! javacomplete#util#GetRegularClassesDict() if exists('s:RegularClassesDict') return s:RegularClassesDict endif let path = javacomplete#util#GetBase('cache'). g:FILE_SEP. 'regular_classes_'. g:JavaComplete_ProjectKey. '.dat' if filereadable(path) let classes = readfile(path) else let classes = [] endif let classes = javacomplete#util#RemoveEmptyClasses(javacomplete#util#uniq(sort(extend(classes, g:JavaComplete_RegularClasses)))) let dict = {} for class in classes call extend(dict, {split(class,'\.')[-1] : class}) endfor let s:RegularClassesDict = dict return s:RegularClassesDict endfunction function! javacomplete#util#SaveRegularClassesList(classesDict) let path = javacomplete#util#GetBase('cache'). g:FILE_SEP. 'regular_classes_'. g:JavaComplete_ProjectKey. '.dat' call writefile(values(a:classesDict), path) unlet s:RegularClassesDict endfunction function! javacomplete#util#IsStatic(modifier) return a:modifier[strlen(a:modifier)-4] endfunction function! javacomplete#util#IsBuiltinType(name) return index(g:J_PRIMITIVE_TYPES, a:name) >= 0 endfunction function! javacomplete#util#IsKeyword(name) return index(g:J_KEYWORDS, a:name) >= 0 endfunction function! javacomplete#util#HasKeyword(name) return a:name =~# g:RE_KEYWORDS endfunction function! javacomplete#util#CheckModifier(modifier, condition) if type(a:condition) == type([]) for condition in a:condition if condition <= len(a:modifier) if a:modifier[-condition : -condition] == '1' return 1 endif endif endfor return 0 else if a:condition <= len(a:modifier) return a:modifier[-a:condition : -a:condition] == '1' endif return 0 endif endfunction function! javacomplete#util#GenMethodParamsDeclaration(method) if has_key(a:method, 'p') let match = matchlist(a:method.d, '^\(.*(\)') if len(match) > 0 let d = match[1] let match = matchlist(a:method.d, '.*)\(.*\)$') let throws = len(match) > 0 ? substitute(match[1], ',', ', ', 'g') : '' let ds = [] let paramNames = [] for p in a:method.p let repeats = count(a:method.p, p) > 1 ? 1 : 0 if index(g:J_PRIMITIVE_TYPES, p) >= 0 let var = p[0] else let p = javacomplete#util#CleanFQN(p) let var = tolower(p[0]). p[1:] endif let match = matchlist(var, '^\([a-zA-Z0-9]\+\)\A*') let countVar = count(paramNames, match[1]) + repeats call add(paramNames, match[1]) call add(ds, p. ' '. match[1]. (countVar > 0 ? countVar : "")) endfor return d. join(ds, ', '). ')'. throws endif endif return a:method.d endfunction function! javacomplete#util#GetClassPackage(class) let lastDot = strridx(a:class, '.') if lastDot > 0 return a:class[0:lastDot - 1] endif return a:class endfunction " vim:set fdm=marker sw=2 nowrap: