diff runtime/autoload/phpcomplete.vim @ 6153:1e8ebf870720

Updated runtime files.
author Bram Moolenaar <bram@vim.org>
date Fri, 22 Aug 2014 19:21:47 +0200
parents 92751673cc37
children 47b1887483da
line wrap: on
line diff
--- 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:  2014 May 30
+" Last Change:  2014 Jul 24
 "
 "	OPTIONS:
 "
@@ -277,7 +277,7 @@ endfunction
 " }}}
 
 function! phpcomplete#CompleteGeneral(base, current_namespace, imports) " {{{
-	" Complete everything else -
+	" Complete everything
 	"  + functions,  DONE
 	"  + keywords of language DONE
 	"  + defines (constant definitions), DONE
@@ -949,12 +949,11 @@ function! phpcomplete#CompleteUserClass(
 		endif
 	endfor
 
-	let jvars = join(variables, ' ')
-	let svars = split(jvars, '\$')
+	let static_vars = split(join(variables, ' '), '\$')
 	let c_variables = {}
 
 	let var_index = 0
-	for i in svars
+	for i in static_vars
 		let c_var = matchstr(i,
 					\ '^\zs[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*\ze')
 		if c_var != ''
@@ -1083,7 +1082,6 @@ endfunction
 " }}}
 
 function! phpcomplete#GetTaglist(pattern) " {{{
-
 	let cache_checksum = ''
 	if g:phpcomplete_cache_taglists == 1
 		" build a string with  format of "<tagfile>:<mtime>$<tagfile2>:<mtime2>..."
@@ -1447,6 +1445,7 @@ function! phpcomplete#GetClassName(start
 	" Get class name
 	" Class name can be detected in few ways:
 	" @var $myVar class
+	" @var class $myVar
 	" in the same line (php 5.4 (new Class)-> syntax)
 	" line above
 	" or line in tags file
@@ -1525,6 +1524,11 @@ function! phpcomplete#GetClassName(start
 		let object_is_array = (object =~ '\v^[^[]+\[' ? 1 : 0)
 		let object = matchstr(object, variable_name_pattern)
 
+		let function_boundary = phpcomplete#GetCurrentFunctionBoundaries()
+		let search_end_line = max([1, function_boundary[0][0]])
+		" -1 makes us ignore the current line (where the completion was invoked
+		let lines = reverse(getline(search_end_line, line('.') - 1))
+
 		" check Constant lookup
 		let constant_object = matchstr(a:context, '\zs'.class_name_pattern.'\ze::')
 		if constant_object != ''
@@ -1533,21 +1537,20 @@ function! phpcomplete#GetClassName(start
 
 		if classname_candidate == ''
 			" scan the file backwards from current line for explicit type declaration (@var $variable Classname)
-			let i = 1 " start from the current line - 1
-			while i < a:start_line
-				let line = getline(a:start_line - i)
+			for line in lines
 				" in file lookup for /* @var $foo Class */
 				if line =~# '@var\s\+'.object.'\s\+'.class_name_pattern
 					let classname_candidate = matchstr(line, '@var\s\+'.object.'\s\+\zs'.class_name_pattern.'\(\[\]\)\?')
 					let [classname_candidate, class_candidate_namespace] = phpcomplete#ExpandClassName(classname_candidate, a:current_namespace, a:imports)
 					break
-				elseif line !~ '^\s*$'
-					" type indicator comments should be next to the variable
-					" non empty lines break the search
+				endif
+				" in file lookup for /* @var Class $foo */
+				if line =~# '@var\s\+'.class_name_pattern.'\s\+'.object
+					let classname_candidate = matchstr(line, '@var\s\+\zs'.class_name_pattern.'\(\[\]\)\?\ze'.'\s\+'.object)
+					let [classname_candidate, class_candidate_namespace] = phpcomplete#ExpandClassName(classname_candidate, a:current_namespace, a:imports)
 					break
 				endif
-				let i += 1
-			endwhile
+			endfor
 		endif
 
 		if classname_candidate != ''
@@ -1555,12 +1558,9 @@ function! phpcomplete#GetClassName(start
 			" return absolute classname, without leading \
 			return (class_candidate_namespace == '\' || class_candidate_namespace == '') ? classname_candidate : class_candidate_namespace.'\'.classname_candidate
 		endif
-
 		" scan the file backwards from the current line
 		let i = 1
-		while i < a:start_line " {{{
-			let line = getline(a:start_line - i)
-
+		for line in lines " {{{
 			" do in-file lookup of $var = new Class
 			if line =~# '^\s*'.object.'\s*=\s*new\s\+'.class_name_pattern && !object_is_array
 				let classname_candidate = matchstr(line, object.'\c\s*=\s*new\s*\zs'.class_name_pattern.'\ze')
@@ -1722,7 +1722,7 @@ function! phpcomplete#GetClassName(start
 			endif
 
 			let i += 1
-		endwhile " }}}
+		endfor " }}}
 
 		if classname_candidate != ''
 			let [classname_candidate, class_candidate_namespace] = phpcomplete#GetCallChainReturnType(classname_candidate, class_candidate_namespace, class_candidate_imports, methodstack)
@@ -1962,7 +1962,9 @@ function! phpcomplete#GetClassContentsSt
 			let namespace = '\'
 		endif
 		let classlocation = phpcomplete#GetClassLocation(extends_class, namespace)
-		if classlocation != '' && filereadable(classlocation)
+		if classlocation == "VIMPHP_BUILTINOBJECT"
+			let result += [phpcomplete#GenerateBuiltinClassStub(g:php_builtin_classes[tolower(extends_class)])]
+		elseif classlocation != '' && filereadable(classlocation)
 			let full_file_path = fnamemodify(classlocation, ':p')
 			let result += phpcomplete#GetClassContentsStructure(full_file_path, readfile(full_file_path), extends_class)
 		elseif tolower(current_namespace) == tolower(namespace)
@@ -1985,6 +1987,51 @@ 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
+	let re .= "\n}"
+
+	return { 'class': a:class_info['name'],
+				\ 'content': re,
+				\ 'namespace': '',
+				\ 'imports': {},
+				\ 'file': 'VIMPHP_BUILTINOBJECT',
+				\ 'mtime': 0,
+				\ }
+endfunction " }}}
+
 function! phpcomplete#GetDocBlock(sccontent, search) " {{{
 	let i = 0
 	let l = 0
@@ -2307,6 +2354,40 @@ function! phpcomplete#GetCurrentNameSpac
 endfunction
 " }}}
 
+function! phpcomplete#GetCurrentFunctionBoundaries() " {{{
+	let old_cursor_pos = [line('.'), col('.')]
+	let current_line_no = old_cursor_pos[0]
+	let function_pattern = '\c\(.*\%#\)\@!\_^\s*\zs\(abstract\s\+\|final\s\+\|private\s\+\|protected\s\+\|public\s\+\|static\s\+\)*function\_.\{-}(\_.\{-})\_.\{-}{'
+
+	let func_start_pos = searchpos(function_pattern, 'Wbc')
+	if func_start_pos == [0, 0]
+		call cursor(old_cursor_pos[0], old_cursor_pos[1])
+		return 0
+	endif
+
+	" get the line where the function declaration actually started
+	call search('\cfunction\_.\{-}(\_.\{-})\_.\{-}{', 'Wce')
+
+	" get the position of the function block's closing "}"
+	let func_end_pos = searchpairpos('{', '', '}', 'W')
+	if func_end_pos == [0, 0]
+		" there is a function start but no end found, assume that we are in a
+		" function but the user did not typed the closing "}" yet and the
+		" function runs to the end of the file
+		let func_end_pos = [line('$'), len(getline(line('$')))]
+	endif
+
+	" Decho func_start_pos[0].' <= '.current_line_no.' && '.current_line_no.' <= '.func_end_pos[0]
+	if func_start_pos[0] <= current_line_no && current_line_no <= func_end_pos[0]
+		call cursor(old_cursor_pos[0], old_cursor_pos[1])
+		return [func_start_pos, func_end_pos]
+	endif
+
+	call cursor(old_cursor_pos[0], old_cursor_pos[1])
+	return 0
+endfunction
+" }}}
+
 function! phpcomplete#ExpandClassName(classname, current_namespace, imports) " {{{
 	" if there's an imported class, just use that class's information
 	if has_key(a:imports, a:classname) && (a:imports[a:classname].kind == 'c' || a:imports[a:classname].kind == 'i')