# HG changeset patch # User Bram Moolenaar # Date 1437596579 -7200 # Node ID ad7ee058c03b0edecb2f9e478e588f698fa59c05 # Parent 4d8542ea435e0bdccd028b21018880ccbcbe5b3d Correct optwin script, update PHP complete. diff --git a/runtime/autoload/phpcomplete.vim b/runtime/autoload/phpcomplete.vim --- a/runtime/autoload/phpcomplete.vim +++ b/runtime/autoload/phpcomplete.vim @@ -3,7 +3,7 @@ " Maintainer: Dávid Szabó ( complex857 AT gmail DOT com ) " Previous Maintainer: Mikolaj Machowski ( mikmach AT wp DOT pl ) " URL: https://github.com/shawncplus/phpcomplete.vim -" Last Change: 2015 Jul 03 +" Last Change: 2015 Jul 13 " " OPTIONS: " @@ -318,7 +318,7 @@ function! phpcomplete#CompleteGeneral(ba \ '^&\?\zs[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*\ze') if f_name =~? '^'.substitute(a:base, '\\', '\\\\', 'g') let f_args = matchstr(i, - \ '^&\?[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*\s*(\zs.\{-}\ze)\_s*\({\|$\)') + \ '^&\?[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*\s*(\zs.\{-}\ze)\_s*\(;\|{\|$\)') let int_functions[f_name.'('] = f_args.')' endif endfor @@ -646,7 +646,7 @@ function! phpcomplete#CompleteUnknownCla let f_name = matchstr(i, \ '^&\?\zs[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*\ze') let f_args = matchstr(i, - \ '^&\?[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*\s*(\zs.\{-}\ze)\_s*\({\|$\)') + \ '^&\?[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*\s*(\zs.\{-}\ze)\_s*\(;\|{\|$\)') let int_functions[f_name.'('] = f_args.')' endfor @@ -981,7 +981,7 @@ function! phpcomplete#CompleteUserClass( let f_name = matchstr(i, \ 'function\s*&\?\zs[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*\ze') let f_args = matchstr(i, - \ 'function\s*&\?[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*\s*(\zs.\{-}\ze)\_s*\({\|\_$\)') + \ 'function\s*&\?[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*\s*(\zs.\{-}\ze)\_s*\(;\|{\|\_$\)') if f_name != '' && stridx(f_name, '__') != 0 let c_functions[f_name.'('] = f_args if g:phpcomplete_parse_docblock_comments @@ -1379,8 +1379,8 @@ function! phpcomplete#GetCallChainReturn " Get Structured information of all classes and subclasses including namespace and includes " try to find the method's return type in docblock comment for classstructure in classcontents - let doclock_target_pattern = 'function\s\+&\?'.method.'\|\(public\|private\|protected\|var\).\+\$'.method - let doc_str = phpcomplete#GetDocBlock(split(classstructure.content, '\n'), doclock_target_pattern) + let docblock_target_pattern = 'function\s\+&\?'.method.'\|\(public\|private\|protected\|var\).\+\$'.method + let doc_str = phpcomplete#GetDocBlock(split(classstructure.content, '\n'), docblock_target_pattern) if doc_str != '' break endif @@ -1701,9 +1701,11 @@ function! phpcomplete#GetClassName(start " try to find the next non-comment or string ";" char let start_col = match(line, '^\s*'.object.'\C\s*=\zs&\?\s\+\(clone\)\?\s*'.variable_name_pattern) let filelines = reverse(copy(lines)) - let [pos, char] = s:getNextCharWithPos(filelines, [a:start_line - i - 1, start_col]) + let [pos, char] = s:getNextCharWithPos(filelines, [len(filelines) - i, start_col]) let chars_read = 1 let last_pos = pos + " function_boundary == 0 if we are not in a function + let real_lines_offset = len(function_boundary) == 1 ? 1 : function_boundary[0][0] " read while end of the file while char != 'EOF' && chars_read < 1000 let last_pos = pos @@ -1711,7 +1713,11 @@ function! phpcomplete#GetClassName(start let chars_read += 1 " we got a candidate if char == ';' - let synIDName = synIDattr(synID(pos[0] + 1, pos[1] + 1, 0), 'name') + " pos values is relative to the function's lines, + " line 0 need to be offsetted with the line number + " where te function was started to get the line number + " in real buffer terms + let synIDName = synIDattr(synID(real_lines_offset + pos[0], pos[1] + 1, 0), 'name') " it's not a comment or string, end search if synIDName !~? 'comment\|string' break @@ -1719,7 +1725,7 @@ function! phpcomplete#GetClassName(start endif endwhile - let prev_context = phpcomplete#GetCurrentInstruction(last_pos[0] + 1, last_pos[1], b:phpbegin) + let prev_context = phpcomplete#GetCurrentInstruction(real_lines_offset + last_pos[0], last_pos[1], b:phpbegin) if prev_context == '' " cannot get previous context give up return @@ -1739,13 +1745,14 @@ function! phpcomplete#GetClassName(start " assignment for the variable in question with a function on the right hand side if line =~# '^\s*'.object.'\s*=&\?\s*'.function_invocation_pattern - " try to find the next non-comment or string ";" char let start_col = match(line, '\C^\s*'.object.'\s*=\zs&\?\s*'.function_invocation_pattern) - let filelines = reverse(lines) - let [pos, char] = s:getNextCharWithPos(filelines, [a:start_line - i - 1, start_col]) + let filelines = reverse(copy(lines)) + let [pos, char] = s:getNextCharWithPos(filelines, [len(filelines) - i, start_col]) let chars_read = 1 let last_pos = pos + " function_boundary == 0 if we are not in a function + let real_lines_offset = len(function_boundary) == 1 ? 1 : function_boundary[0][0] " read while end of the file while char != 'EOF' && chars_read < 1000 let last_pos = pos @@ -1753,7 +1760,11 @@ function! phpcomplete#GetClassName(start let chars_read += 1 " we got a candidate if char == ';' - let synIDName = synIDattr(synID(pos[0] + 1, pos[1] + 1, 0), 'name') + " pos values is relative to the function's lines, + " line 0 need to be offsetted with the line number + " where te function was started to get the line number + " in real buffer terms + let synIDName = synIDattr(synID(real_lines_offset + pos[0], pos[1] + 1, 0), 'name') " it's not a comment or string, end search if synIDName !~? 'comment\|string' break @@ -1761,7 +1772,7 @@ function! phpcomplete#GetClassName(start endif endwhile - let prev_context = phpcomplete#GetCurrentInstruction(last_pos[0] + 1, last_pos[1], b:phpbegin) + let prev_context = phpcomplete#GetCurrentInstruction(real_lines_offset + last_pos[0], last_pos[1], b:phpbegin) if prev_context == '' " cannot get previous context give up return @@ -1864,6 +1875,9 @@ function! phpcomplete#GetClassLocation(c if has_key(g:php_builtin_classes, tolower(a:classname)) && (a:namespace == '' || a:namespace == '\') return 'VIMPHP_BUILTINOBJECT' endif + if has_key(g:php_builtin_interfaces, tolower(a:classname)) && (a:namespace == '' || a:namespace == '\') + return 'VIMPHP_BUILTINOBJECT' + endif if a:namespace == '' || a:namespace == '\' let search_namespace = '\' @@ -2048,9 +2062,18 @@ function! phpcomplete#GetClassContentsSt let content = join(getline(cfline, endline), "\n") " Catch extends if content =~? 'extends' - let extends_class = matchstr(content, 'class\_s\+'.a:class_name.'\_s\+extends\_s\+\zs'.class_name_pattern.'\ze') + let extends_string = matchstr(content, '\(class\|interface\)\_s\+'.a:class_name.'\_.\+extends\_s\+\zs\('.class_name_pattern.'\(,\|\_s\)*\)\+\ze\(extends\|{\)') + let extended_classes = map(split(extends_string, '\(,\|\_s\)\+'), 'substitute(v:val, "\\_s\\+", "", "g")') else - let extends_class = '' + let extended_classes = '' + endif + + " Catch implements + if content =~? 'implements' + let implements_string = matchstr(content, 'class\_s\+'.a:class_name.'\_.\+implements\_s\+\zs\('.class_name_pattern.'\(,\|\_s\)*\)\+\ze') + let implemented_interfaces = map(split(implements_string, '\(,\|\_s\)\+'), 'substitute(v:val, "\\_s\\+", "", "g")') + else + let implemented_interfaces = [] endif call searchpair('{', '', '}', 'W') let class_closing_bracket_line = line('.') @@ -2108,8 +2131,11 @@ function! phpcomplete#GetClassContentsSt \ }) let all_extends = used_traits - if extends_class != '' - call add(all_extends, extends_class) + if len(extended_classes) > 0 + call extend(all_extends, extended_classes) + endif + if len(implemented_interfaces) > 0 + call extend(all_extends, implemented_interfaces) endif if len(all_extends) > 0 for class in all_extends @@ -2119,7 +2145,12 @@ function! phpcomplete#GetClassContentsSt endif let classlocation = phpcomplete#GetClassLocation(class, namespace) if classlocation == "VIMPHP_BUILTINOBJECT" - let result += [phpcomplete#GenerateBuiltinClassStub(g:php_builtin_classes[tolower(class)])] + if has_key(g:php_builtin_classes, tolower(class)) + let result += [phpcomplete#GenerateBuiltinClassStub('class', g:php_builtin_classes[tolower(class)])] + endif + if has_key(g:php_builtin_interfaces, tolower(class)) + let result += [phpcomplete#GenerateBuiltinClassStub('interface', g:php_builtin_interfaces[tolower(class)])] + endif elseif classlocation != '' && filereadable(classlocation) let full_file_path = fnamemodify(classlocation, ':p') let result += phpcomplete#GetClassContentsStructure(full_file_path, readfile(full_file_path), class) @@ -2144,43 +2175,53 @@ function! phpcomplete#GetClassContents(c endfunction " }}} -function! phpcomplete#GenerateBuiltinClassStub(class_info) " {{{ - let re = 'class '.a:class_info['name']." {" - for [name, initializer] in items(a:class_info.constants) - let re .= "\n\tconst ".name." = ".initializer.";" - endfor - for [name, info] in items(a:class_info.properties) - let re .= "\n\t// @var $".name." ".info.type - let re .= "\n\tpublic $".name.";" - endfor - for [name, info] in items(a:class_info.static_properties) - let re .= "\n\t// @var ".name." ".info.type - let re .= "\n\tpublic static ".name." = ".info.initializer.";" - endfor - for [name, info] in items(a:class_info.methods) - if name =~ '^__' - continue - endif - let re .= "\n\t/**" - let re .= "\n\t * ".name - let re .= "\n\t *" - let re .= "\n\t * @return ".info.return_type - let re .= "\n\t */" - let re .= "\n\tpublic function ".name."(".info.signature."){" - let re .= "\n\t}" - endfor - for [name, info] in items(a:class_info.static_methods) - let re .= "\n\t/**" - let re .= "\n\t * ".name - let re .= "\n\t *" - let re .= "\n\t * @return ".info.return_type - let re .= "\n\t */" - let re .= "\n\tpublic static function ".name."(".info.signature."){" - let re .= "\n\t}" - endfor +function! phpcomplete#GenerateBuiltinClassStub(type, class_info) " {{{ + let re = a:type.' '.a:class_info['name']." {" + if has_key(a:class_info, 'constants') + for [name, initializer] in items(a:class_info.constants) + let re .= "\n\tconst ".name." = ".initializer.";" + endfor + endif + if has_key(a:class_info, 'properties') + for [name, info] in items(a:class_info.properties) + let re .= "\n\t// @var $".name." ".info.type + let re .= "\n\tpublic $".name.";" + endfor + endif + if has_key(a:class_info, 'static_properties') + for [name, info] in items(a:class_info.static_properties) + let re .= "\n\t// @var ".name." ".info.type + let re .= "\n\tpublic static ".name." = ".info.initializer.";" + endfor + endif + if has_key(a:class_info, 'methods') + for [name, info] in items(a:class_info.methods) + if name =~ '^__' + continue + endif + let re .= "\n\t/**" + let re .= "\n\t * ".name + let re .= "\n\t *" + let re .= "\n\t * @return ".info.return_type + let re .= "\n\t */" + let re .= "\n\tpublic function ".name."(".info.signature."){" + let re .= "\n\t}" + endfor + endif + if has_key(a:class_info, 'static_methods') + for [name, info] in items(a:class_info.static_methods) + let re .= "\n\t/**" + let re .= "\n\t * ".name + let re .= "\n\t *" + let re .= "\n\t * @return ".info.return_type + let re .= "\n\t */" + let re .= "\n\tpublic static function ".name."(".info.signature."){" + let re .= "\n\t}" + endfor + endif let re .= "\n}" - return { 'class': a:class_info['name'], + return { a:type : a:class_info['name'], \ 'content': re, \ 'namespace': '', \ 'imports': {}, @@ -2204,8 +2245,11 @@ function! phpcomplete#GetDocBlock(sccont " start backward serch for the comment block while l != 0 let line = a:sccontent[l] - " if comment end found save line position and end search - if line =~? '^\s*\*/' + " if it's a one line docblock like comment and we can just return it right away + if line =~? '^\s*\/\*\*.\+\*\/\s*$' + return substitute(line, '\v^\s*(\/\*\*\s*)|(\s*\*\/)\s*$', '', 'g') + "... or if comment end found save line position and end search + elseif line =~? '^\s*\*/' let comment_end = l break " ... or the line doesn't blank (only whitespace or nothing) end search @@ -2227,6 +2271,7 @@ function! phpcomplete#GetDocBlock(sccont endif let l -= 1 endwhile + " no docblock comment start found if comment_start == -1 return '' @@ -2388,7 +2433,15 @@ function! phpcomplete#GetCurrentNameSpac break endif let block_end_pos = searchpairpos('{', '', '}\|\%$', 'W', 'synIDattr(synID(line("."), col("."), 0), "name") =~? "string\\|comment"') - silent! exec block_start_pos[0].','.block_end_pos[0].'d' + + if block_end_pos != [0, 0] + " end of the block found, just delete it + silent! exec block_start_pos[0].','.block_end_pos[0].'d _' + else + " block pair not found, use block start as beginning and the end + " of the buffer instead + silent! exec block_start_pos[0].',$d _' + endif endwhile normal! G diff --git a/runtime/optwin.vim b/runtime/optwin.vim --- a/runtime/optwin.vim +++ b/runtime/optwin.vim @@ -1,7 +1,7 @@ " These commands create the option window. " " Maintainer: Bram Moolenaar -" Last Change: 2015 Jul 21 +" Last Change: 2015 Jul 22 " If there already is an option window, jump to that one. if bufwinnr("option-window") > 0 @@ -706,7 +706,7 @@ call BinOptionG("eb", &eb) call append("$", "visualbell\tuse a visual bell instead of beeping") call BinOptionG("vb", &vb) call append("$", "belloff\tdo not ring the bell for these reasons") -call OptionG("beolloff", &beolloff) +call OptionG("belloff", &belloff) if has("multi_lang") call append("$", "helplang\tlist of preferred languages for finding help") call OptionG("hlg", &hlg)