1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-02-03 09:50:04 +08:00
SpaceVim/bundle/vim-javacomplete2/autoload/javacomplete/newclass.vim
2022-11-02 00:34:34 +08:00

492 lines
16 KiB
VimL
Vendored

" Vim completion script for java
" Maintainer: artur shaik <ashaihullin@gmail.com>
"
" Classes generator
function! s:Log(log)
let log = type(a:log) == type("") ? a:log : string(a:log)
call javacomplete#logger#Log("[newclass] ". log)
endfunction
function! javacomplete#newclass#TemplatesCompletion(argLead, command, cursorPos)
call s:Log("arglead:[".a:argLead ."] cmdline:[" .a:command ."] cursorpos:[" .a:cursorPos ."]")
let result = []
let commandTokens = split(a:command, ':', 1)
let command = len(commandTokens) >= 1 ? commandTokens[-1] : a:command
call extend(result, s:FetchTemplatesByPrefix(command, 0))
return result
endfunction
function! javacomplete#newclass#Completion(argLead, command, cursorPos)
call s:Log("arglead:[".a:argLead ."] cmdline:[" .a:command ."] cursorpos:[" .a:cursorPos ."]")
let result = []
let commandTokens = split(a:command, ':', 1)
let command = len(commandTokens) >= 1 ? commandTokens[-1] : a:command
if command[0] == '/'
call extend(result, s:ClassnameCompletions(command[1:], s:GetCompleted(commandTokens), 0))
elseif command[0] == '['
call extend(result, s:FetchAvailableSubDirectories(command[1:], s:GetCompleted(commandTokens)))
elseif len(commandTokens) == 1
call extend(result, s:FetchTemplatesByPrefix(command, 1))
call extend(result, s:ClassnameCompletions(command, s:GetCompleted(commandTokens), 1))
elseif len(commandTokens) == 2
call extend(result, s:ClassnameCompletions(command, s:GetCompleted(commandTokens), 1))
call extend(result, s:ClassMethods(command, s:GetCompleted(commandTokens)))
elseif len(commandTokens) == 3
if commandTokens[1] =~ '[\[\]]'
call extend(result, s:ClassnameCompletions(command, s:GetCompleted(commandTokens), 1))
else
call extend(result, s:ClassMethods(command, s:GetCompleted(commandTokens)))
endif
else
call extend(result, s:ClassMethods(command, s:GetCompleted(commandTokens)))
endif
return result
endfunction
function! s:FetchTemplatesByPrefix(command, addSeparator)
let result = s:FetchTemplatesByPath(
\ g:JavaComplete_Home. '/plugin/res/gen__class_',
\ a:command,
\ a:addSeparator)
if isdirectory(g:JavaComplete_CustomTemplateDirectory)
call extend(result,
\ s:FetchTemplatesByPath(expand(g:JavaComplete_CustomTemplateDirectory). '/gen__class_',
\ a:command,
\ a:addSeparator))
endif
return result
endfunction
function! s:FetchTemplatesByPath(path, command, addSeparator)
let result = []
let cutLength = len(a:path)
for template in glob(a:path. a:command. '*.tpl', 0, 1)
call add(result, template[cutLength:-5]. (a:addSeparator == 1 ? ':' : ''))
endfor
return result
endfunction
function! s:ClassnameCompletions(command, completed, isRelative)
if stridx(a:command, ' ') < 0
return s:FetchAvailablePackages(a:command, a:completed, a:isRelative)
else
return s:FetchKeywords(a:command, a:completed, a:isRelative)
endif
endfunction
function! s:FetchAvailablePackages(command, completed, isRelative)
let result = []
let currentPath = split(expand('%:p:h'), g:FILE_SEP)
if a:isRelative == 0
let currentPackage = split(javacomplete#collector#GetPackageName(), '\.')
let sameSubpackageIdx = index(currentPath, currentPackage[0])
if sameSubpackageIdx >= 0
let currentPath = currentPath[:sameSubpackageIdx - 1]
if empty(a:command)
for p in currentPackage
call add(result, a:completed. '/'. p)
endfor
endif
endif
endif
let command = substitute(a:command, '\.', g:FILE_SEP, 'g')
let cutLength = len(join(currentPath, g:FILE_SEP)) + 2
for path in glob(g:FILE_SEP. join(currentPath, g:FILE_SEP). g:FILE_SEP. '**'. g:FILE_SEP. command. '*'. g:FILE_SEP, 1, 1)
let p = substitute(path[cutLength:], g:FILE_SEP, '.', 'g')
if a:isRelative == 0
let p = '/'. p
endif
call add(result, a:completed. p)
endfor
return result
endfunction
function! s:FetchKeywords(command, completed, isRelative)
let keywords = ['extends', 'implements']
let tokens = split(a:command, ' ', 1)
if len(tokens) > 1 && index(keywords, tokens[-2]) >= 0
return []
endif
let completed = a:completed. (a:isRelative == 0 ? '/' : '')
let completed = completed. join(tokens[:-2], ' ')
let result = []
for kw in keywords
if a:command =~ '\<'. kw. '\>'
\ || kw !~ '\<'. tokens[-1]. '*'
continue
endif
call add(result, completed. ' '. kw)
endfor
return result
endfunction
function! s:FetchAvailableSubDirectories(command, completed)
let result = []
let currentPath = split(expand('%:p:h'), g:FILE_SEP)
let currentPath = currentPath[:index(currentPath, 'src')]
let prePath = g:FILE_SEP. join(currentPath, g:FILE_SEP). g:FILE_SEP
let cutLength = len(prePath)
for path in glob(prePath. a:command. '*'. g:FILE_SEP, 0, 1)
call add(result, a:completed. '['. path[cutLength:-2]. ']')
endfor
return result
endfunction
function! s:ClassMethods(command, completed)
let keywords = ['constructor(', 'toString(', 'hashCode(', 'equals(']
let result = []
for kw in keywords
if kw !~ '\<'. a:command. '*'
continue
endif
call add(result, a:completed. kw)
endfor
return result
endfunction
function! s:GetCompleted(commandTokens)
let completed = join(a:commandTokens[:-2], ':')
if !empty(completed)
let completed = completed. ':'
endif
return completed
endfunction
function! javacomplete#newclass#CreateInFile()
let templates = s:FetchTemplatesByPrefix('', 0)
let message = join(templates, ', ')
let message .= "\nenter template name [default]: "
let userinput = input(message, '', 'customlist,javacomplete#newclass#TemplatesCompletion')
call s:Log("input: ". userinput)
let currentPath = split(expand('%:p:h'), g:FILE_SEP)
call filter(currentPath, 'empty(v:val) == 0')
if has('win32') && currentPath[0][-1:] ==':'
let currentPath = currentPath[1:]
endif
let data = {}
let data['path'] = ''
let data['current_path'] = g:FILE_SEP. join(currentPath, g:FILE_SEP)
let data['class'] = expand('%:t:r')
let data['package'] = s:DeterminePackage(currentPath)
if !empty(userinput)
let data['template'] = userinput
endif
call s:Log(data)
call s:CreateClass(data)
endfunction
function! s:DeterminePackage(currentPath)
let i = 0
while i < len(a:currentPath)
if a:currentPath[i] == 'java'
break
endif
let i += 1
endwhile
if i < len(a:currentPath)
let package = a:currentPath[i + 1:]
else
let rootPackage = input("\nenter your root package: ")
if empty(rootPackage)
return ''
endif
let i = 0
while i < len(a:currentPath)
if a:currentPath[i] == rootPackage
break
endif
let i += 1
endwhile
if i < len(a:currentPath)
let package = a:currentPath[i:]
else
return ''
endif
endif
return join(package, '.')
endfunction
function! javacomplete#newclass#CreateClass()
call javacomplete#Enable()
call javacomplete#Start()
let message = "enter new class name: "
let userinput = input(message, '', 'customlist,javacomplete#newclass#Completion')
if empty(userinput)
return
endif
call s:Log("input: ". userinput)
let currentPackage = split(javacomplete#collector#GetPackageName(), '\.')
let currentPath = split(expand('%:p:h'), g:FILE_SEP)
call filter(currentPath, 'empty(v:val) == 0')
if has('win32') && currentPath[0][-1:] ==':'
let currentPath = currentPath[1:]
endif
let data = s:ParseInput(
\ userinput, reverse(copy(currentPath)), currentPackage)
if type(data) != type({})
echom "\n"
echoerr "Error: could not parse input line"
return
endif
let data['current_path'] = g:FILE_SEP. join(currentPath, g:FILE_SEP). g:FILE_SEP
call s:CreateClass(data)
endfunction
function! s:CreateClass(data)
call s:Log("create class: ". string(a:data))
let path = a:data['current_path']
\ . g:FILE_SEP
\ . a:data['path']
if filewritable(path) != 2
call mkdir(path, 'p')
endif
let fileName = fnamemodify(path. g:FILE_SEP. a:data['class'], ":p")
let bufname = bufname('')
if getbufvar(bufname, "&mod") == 1 && getbufvar(bufname, "&hidden") == 0
execute ':vs'
endif
execute ':e '. fileName. '.java'
let fileSize = getfsize(fileName. '.java')
if (fileSize <= 0 && fileSize > -2) || (line('$') == 1 && getline(1) == '')
let options = {
\ 'name' : a:data['class'],
\ 'package' : a:data['package']
\ }
if has_key(a:data, 'fields')
let options['fields'] = a:data['fields']
endif
if has_key(a:data, 'extends')
let options['extends'] = a:data['extends']
endif
if has_key(a:data, 'implements')
let options['implements'] = a:data['implements']
endif
let isInterfaceTemplate = 0
if has_key(a:data, 'template')
if a:data['template'] == 'interface'
let isInterfaceTemplate = 1
endif
call javacomplete#generators#GenerateClass(options, a:data['template'])
else
call javacomplete#generators#GenerateClass(options)
endif
silent execute "normal! gg=G"
call search(a:data['class'])
silent execute "normal! j"
call javacomplete#imports#AddMissing()
if !isInterfaceTemplate
call javacomplete#generators#AbstractDeclaration()
endif
if has_key(a:data, 'methods')
let methods = a:data['methods']
let vars = s:GetVariables(get(a:data, 'fields', {}))
if has_key(methods, 'constructor')
let command = {'template': 'constructor', 'replace': {'type': 'same'}, 'fields' : []}
call s:InsertVars(command, methods['constructor'], vars)
call javacomplete#generators#GenerateByTemplate(command)
endif
if has_key(methods, 'toString')
let command = {'template': 'toString_StringBuilder', 'replace': {'type': 'similar'}, 'fields' : []}
if empty(methods['toString'])
call add(methods['toString'], '*')
endif
call s:InsertVars(command, methods['toString'], vars)
call javacomplete#generators#GenerateByTemplate(command)
endif
if has_key(methods, 'equals')
let command = {'template': 'equals', 'replace': {'type': 'similar'}, 'fields' : []}
if empty(methods['equals'])
call add(methods['equals'], '*')
endif
call s:InsertVars(command, methods['equals'], vars)
call javacomplete#generators#GenerateByTemplate(command)
endif
if has_key(methods, 'hashCode')
let command = {'template': 'hashCode', 'replace': {'type': 'similar'}, 'fields' : []}
if empty(methods['hashCode'])
call add(methods['hashCode'], '*')
endif
call s:InsertVars(command, methods['hashCode'], vars)
call javacomplete#generators#GenerateByTemplate(command)
endif
endif
if !isInterfaceTemplate
if has_key(a:data, 'fields')
call javacomplete#generators#Accessors()
endif
endif
endif
endfunction
function! s:InsertVars(command, method, vars)
for arg in a:method
if arg == '*'
let a:command['fields'] = values(a:vars)
break
endif
call add(a:command['fields'], a:vars[arg])
endfor
endfunction
function! s:GetVariables(fields)
let result = {}
for fieldIdx in keys(a:fields)
let field = a:fields[fieldIdx]
let var = {
\ 'name' : field['name'],
\ 'type' : field['type'],
\ 'static' : field['mod'] =~ '.*\<static\>.*',
\ 'final' : field['mod'] =~ '.*\<final\>.*',
\ 'isArray' : field['type'] =~# g:RE_ARRAY_TYPE
\ }
let result[fieldIdx] = var
endfor
return result
endfunction
function! s:ParseInput(userinput, currentPath, currentPackage)
let submatch = matchlist(a:userinput, '^\([A-Za-z0-9_]*:\)\=\(\[.\{-}\]:\)\=\(\%(\/\|\/\.\|\)'. g:RE_TYPE. '\)\(\s\+extends\s\+'. g:RE_TYPE. '\)\=\(\s\+implements\s\+'. g:RE_TYPE. '\)\=\((.\{-})\|\)\(:.*\)\=$')
if !empty(submatch)
let path = split(submatch[3], '\.')
let subdir = !empty(submatch[2]) ? submatch[2][1:-3] : ''
let classData = s:BuildPathData(path, subdir, a:currentPath, a:currentPackage)
if !empty(submatch[1])
let classData['template'] = submatch[1][:-2]
endif
if !empty(submatch[4])
let m = matchlist(submatch[4], '.*extends\s\+\('. g:RE_TYPE. '\)')
if !empty(m)
let classData['extends'] = m[1]
endif
endif
if !empty(submatch[5])
let m = matchlist(submatch[5], '.*implements\s\+\('. g:RE_TYPE. '\)')
if !empty(m)
let classData['implements'] = m[1]
endif
endif
if !empty(submatch[6])
let fieldsMap = s:ParseFields(submatch[6])
if type(fieldsMap) == type({})
let classData['fields'] = fieldsMap
endif
endif
if !empty(submatch[7])
let methodsMap = s:ParseMethods(submatch[7])
if !empty(methodsMap)
let classData['methods'] = methodsMap
endif
endif
return classData
endif
endfunction
function! s:ParseMethods(methods)
let methodsMap = {}
let methods = split(a:methods[1:], ':')
for method in methods
let bracketsIdx = stridx(method, '(')
if bracketsIdx > 0
let methodName = method[:bracketsIdx - 1]
let methodsMap[methodName] = []
let args = split(method[bracketsIdx + 1:-2], ',')
for arg in args
if arg != '*'
let arg = arg*1
endif
call add(methodsMap[methodName], arg)
endfor
else
let methodsMap[method] = []
endif
endfor
return methodsMap
endfunction
function! s:ParseFields(fields)
let fields = javacomplete#util#Trim(a:fields[1:-2])
if !empty(fields)
let fieldsList = split(fields, ',')
let fieldsMap = {}
let idx = 1
for field in fieldsList
let fieldMatch = matchlist(field, '^\s*\(\%('. g:RE_TYPE_MODS. '\s\+\)\+\)\=\('. g:RE_TYPE. '\)\s\+\('. g:RE_IDENTIFIER. '\).*$')
if !empty(fieldMatch)
let fieldMap = {}
let fieldMap['mod'] = empty(fieldMatch[1]) ?
\ 'private' : javacomplete#util#Trim(fieldMatch[1])
let fieldMap['type'] = fieldMatch[2]
let fieldMap['name'] = fieldMatch[3]
let fieldsMap[string(idx)] = fieldMap
let idx += 1
endif
endfor
return fieldsMap
endif
return 0
endfunction
function! s:BuildPathData(path, subdir, currentPath, currentPackage)
if !empty(a:subdir)
let idx = index(a:currentPath, 'src')
let newPath = repeat('..'. g:FILE_SEP, idx)
let newPath .= a:subdir. g:FILE_SEP. 'java'. g:FILE_SEP
let newPath .= join(a:currentPackage, g:FILE_SEP). g:FILE_SEP
else
let newPath = ''
endif
let path = a:path
if path[0] == '/' || path[0][0] == '/'
if path[0] == '/'
let path = path[1:]
else
let path[0] = path[0][1:]
endif
let sameSubpackageIdx = index(a:currentPath, a:currentPackage[0])
if sameSubpackageIdx < 0
return s:RelativePath(path, newPath, a:currentPath, a:currentPackage)
endif
let currentPath = a:currentPath[:sameSubpackageIdx]
let idx = index(currentPath, path[0])
if idx < 0
let newPath .= repeat('..'. g:FILE_SEP, len(currentPath))
let newPath .= join(path[:-2], g:FILE_SEP)
let newPackage = path[:-2]
else
let newPath .= idx > 0 ?
\ repeat('..'. g:FILE_SEP,
\ len(currentPath[:idx-1]))
\ :
\ ''
let newPath .= join(path[1:-2], g:FILE_SEP)
let newPackage = path[1:-2]
call extend(newPackage, reverse(currentPath)[:-idx-1], 0)
endif
return {
\ 'path' : newPath,
\ 'class' : path[-1],
\ 'package' : join(newPackage, '.')
\ }
else
return s:RelativePath(path, newPath, a:currentPath, a:currentPackage)
endif
endfunction
function! s:RelativePath(path, newPath, currentPath, currentPackage)
let newPackage = join(a:currentPackage + a:path[:-2], '.')
return {
\ 'path' : a:newPath. join(a:path[:-2], g:FILE_SEP),
\ 'class' : a:path[-1],
\ 'package' : newPackage
\ }
endfunction
" vim:set fdm=marker sw=2 nowrap: