1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-02-03 07:40:05 +08:00
SpaceVim/bundle/vim-javacomplete2/autoload/javacomplete/parseradapter.vim
2022-11-02 00:34:34 +08:00

152 lines
7.7 KiB
VimL

" Vim completion script for java
" Maintainer: artur shaik <ashaihullin@gmail.com>
"
" Methods that calling internal parser
function! javacomplete#parseradapter#Parse(...)
let filename = a:0 == 0 ? '%' : a:1
let currentFilename = javacomplete#GetCurrentFileKey()
let changed = 0
if filename == '%' || currentFilename == filename
let props = get(g:JavaComplete_Files, currentFilename, {})
if get(props, 'changedtick', -1) != b:changedtick
let changed = 1
let props.changedtick = b:changedtick
let lines = getline('^', '$')
endif
else
let props = get(g:JavaComplete_Files, filename, {})
if get(props, 'modifiedtime', 0) != getftime(filename)
let changed = 1
let props.modifiedtime = getftime(filename)
if filename =~ '^__'
let lines = getline('^', '$')
else
let lines = readfile(filename)
endif
endif
endif
if changed
call java_parser#InitParser(lines)
call java_parser#SetLogLevel(0)
let props.unit = java_parser#compilationUnit()
if &ft == 'jsp'
return props
endif
let package = has_key(props.unit, 'package') ? props.unit.package . '.' : ''
call s:UpdateFQN(props.unit, package)
endif
if filename !~ '^__'
let g:JavaComplete_Files[filename] = props
endif
return props.unit
endfunction
" update fqn for toplevel types or nested types.
" not for local type or anonymous type
function! s:UpdateFQN(tree, qn)
if a:tree.tag == 'TOPLEVEL'
for def in a:tree.types
call s:UpdateFQN(def, a:qn)
endfor
elseif a:tree.tag == 'CLASSDEF'
let a:tree.fqn = a:qn . a:tree.name
for def in a:tree.defs
if type(def) != type([])
unlet def
continue
endif
if def.tag == 'CLASSDEF'
call s:UpdateFQN(def, a:tree.fqn . '.')
endif
endfor
endif
endfunction
" TreeVisitor {{{2
" parent argument exist for lambdas only
function! s:visitTree(tree, param, parent) dict
if type(a:tree) == type({})
exe get(self, get(a:tree, 'tag', ''), '')
elseif type(a:tree) == type([])
for tree in a:tree
call self.visit(tree, a:param, a:parent)
unlet tree
endfor
endif
endfunction
" we need to return to parent leafs to get lambda's arguments declaration
function! s:lambdaMeth(tree)
if a:tree.tag == 'APPLY'
return {'meth': a:tree.meth, 'stats': {}}
elseif a:tree.tag == 'VARDEF'
return {'stats': {'tag': a:tree.tag, 't': a:tree.t, 'name': a:tree.name, 'endpos': a:tree.endpos, 'n': a:tree.n, 'pos': a:tree.pos, 'm': a:tree.m}, 'meth': {}}
elseif a:tree.tag == 'RETURN'
return {'stats': {'tag': a:tree.tag, 'endpos': a:tree.endpos, 'pos': a:tree.pos}, 'meth': {}}
endif
return {'meth': {}, 'stats': {}}
endfunction
let s:TreeVisitor = {'visit': function('s:visitTree'),
\ 'lambdameth': function('s:lambdaMeth'),
\ 'TOPLEVEL' : 'call self.visit(a:tree.types, a:param, a:tree)',
\ 'BLOCK' : 'let stats = a:tree.stats | if stats == [] | call java_parser#GotoPosition(a:tree.pos) | let stats = java_parser#block().stats | endif | call self.visit(stats, a:param, a:tree)',
\ 'DOLOOP' : 'call self.visit(a:tree.body, a:param, a:tree) | call self.visit(a:tree.cond, a:param, a:tree)',
\ 'WHILELOOP' : 'call self.visit(a:tree.cond, a:param, a:tree) | call self.visit(a:tree.body, a:param, a:tree)',
\ 'FORLOOP' : 'call self.visit(a:tree.init, a:param, a:tree) | call self.visit(a:tree.cond, a:param, a:tree) | call self.visit(a:tree.step, a:param, a:tree) | call self.visit(a:tree.body, a:param, a:tree)',
\ 'FOREACHLOOP' : 'call self.visit(a:tree.var, a:param, a:tree) | call self.visit(a:tree.expr, a:param, a:tree) | call self.visit(a:tree.body, a:param, a:tree)',
\ 'LABELLED' : 'call self.visit(a:tree.body, a:param, a:tree)',
\ 'SWITCH' : 'call self.visit(a:tree.selector, a:param, a:tree) | call self.visit(a:tree.cases, a:param, a:tree)',
\ 'CASE' : 'call self.visit(a:tree.pat, a:param, a:tree) | call self.visit(a:tree.stats, a:param, a:tree)',
\ 'SYNCHRONIZED': 'call self.visit(a:tree.lock, a:param, a:tree) | call self.visit(a:tree.body, a:param, a:tree)',
\ 'TRY' : 'call self.visit(a:tree.params, a:param, a:tree) | call self.visit(a:tree.body, a:param, a:tree) | call self.visit(a:tree.catchers, a:param, a:tree) | call self.visit(a:tree.finalizer, a:param, a:tree) ',
\ 'RARROW' : 'call self.visit(a:tree.body, a:param, a:tree)',
\ 'CATCH' : 'call self.visit(a:tree.param,a:param, a:tree) | call self.visit(a:tree.body, a:param, a:tree)',
\ 'CONDEXPR' : 'call self.visit(a:tree.cond, a:param, a:tree) | call self.visit(a:tree.truepart, a:param, a:tree) | call self.visit(a:tree.falsepart, a:param, a:tree)',
\ 'IF' : 'call self.visit(a:tree.cond, a:param, a:tree) | call self.visit(a:tree.thenpart, a:param, a:tree) | if has_key(a:tree, "elsepart") | call self.visit(a:tree.elsepart, a:param, a:tree) | endif',
\ 'EXEC' : 'call self.visit(a:tree.expr, a:param, a:tree)',
\ 'APPLY' : 'call self.visit(a:tree.meth, a:param, a:tree) | call self.visit(a:tree.args, a:param, a:tree)',
\ 'NEWCLASS' : 'call self.visit(a:tree.def, a:param, a:tree)',
\ 'RETURN' : 'if has_key(a:tree, "expr") | call self.visit(a:tree.expr, a:param, a:tree) | endif',
\ 'LAMBDA' : 'call extend(a:tree, self.lambdameth(a:parent)) | call self.visit(a:tree.meth, a:param, a:tree) | call self.visit(a:tree.stats, a:param, a:tree) | call self.visit(a:tree.args, a:param, a:tree) | call self.visit(a:tree.body, a:param, a:tree)'
\}
let s:TV_CMP_POS = 'a:tree.pos <= a:param.pos && a:param.pos <= get(a:tree, "endpos", -1)'
let s:TV_CMP_POS_BODY = 'has_key(a:tree, "body") && a:tree.body.pos <= a:param.pos && a:param.pos <= get(a:tree.body, "endpos", -1)'
" Return a stack of enclosing types (including local or anonymous classes).
" Given the optional argument, return all (toplevel or static member) types besides enclosing types.
function! javacomplete#parseradapter#SearchTypeAt(tree, targetPos, ...)
let s:TreeVisitor.CLASSDEF = 'if a:param.allNonLocal || ' . s:TV_CMP_POS . ' | call add(a:param.result, a:tree) | call self.visit(a:tree.defs, a:param, a:tree) | endif'
let s:TreeVisitor.METHODDEF = 'if ' . s:TV_CMP_POS_BODY . ' | call self.visit(a:tree.body, a:param, a:tree) | endif'
let s:TreeVisitor.VARDEF = 'if has_key(a:tree, "init") && !a:param.allNonLocal && ' . s:TV_CMP_POS . ' | call self.visit(a:tree.init, a:param, a:tree) | endif'
let s:TreeVisitor.IDENT = ''
let result = []
call s:TreeVisitor.visit(a:tree, {'result': result, 'pos': a:targetPos, 'allNonLocal': a:0 == 0 ? 0 : 1}, {})
return result
endfunction
" a:1 match beginning
" return a stack of matching name
function! javacomplete#parseradapter#SearchNameInAST(tree, name, targetPos, fullmatch)
let comparator = a:fullmatch ? '==#' : '=~# "^" .'
let cmd = 'if a:tree.name ' .comparator. ' a:param.name | call add(a:param.result, a:tree) | endif'
let cmdPos = 'if a:tree.name ' .comparator. ' a:param.name && a:tree.pos <= a:param.pos | call add(a:param.result, a:tree) | endif'
let s:TreeVisitor.CLASSDEF = 'if ' . s:TV_CMP_POS . ' | ' . cmd . ' | call self.visit(a:tree.defs, a:param, a:tree) | endif'
let s:TreeVisitor.METHODDEF = cmd . ' | if ' . s:TV_CMP_POS_BODY . ' | call self.visit(a:tree.params, a:param, a:tree) | call self.visit(a:tree.body, a:param, a:tree) | endif'
let s:TreeVisitor.VARDEF = cmdPos . ' | if has_key(a:tree, "init") && ' . s:TV_CMP_POS . ' | call self.visit(a:tree.init, a:param, a:tree) | endif'
let s:TreeVisitor.IDENT = 'if a:parent.tag == "LAMBDA" && a:parent.body.pos <= a:param.pos | call add(a:param.result, a:parent) | endif'
let result = []
call s:TreeVisitor.visit(a:tree, {'result': result, 'pos': a:targetPos, 'name': a:name}, {})
return result
endfunction
" vim:set fdm=marker sw=2 nowrap: