3
3
" Maintainer: Dávid Szabó ( complex857 AT gmail DOT com )
4
4
" Previous Maintainer: Mikolaj Machowski ( mikmach AT wp DOT pl )
5
5
" URL: https://github.com/shawncplus/phpcomplete.vim
6
- " Last Change: 2015 Jul 13
6
+ " Last Change: 2016 Oct 10
7
7
"
8
8
" OPTIONS:
9
9
"
@@ -195,6 +195,8 @@ function! phpcomplete#CompletePHP(findstart, base) " {{{
195
195
" }}}
196
196
elseif context = ~? ' implements'
197
197
return phpcomplete#CompleteClassName (a: base , [' i' ], current_namespace, imports)
198
+ elseif context = ~? ' instanceof'
199
+ return phpcomplete#CompleteClassName (a: base , [' c' , ' n' ], current_namespace, imports)
198
200
elseif context = ~? ' extends\s\+.\+$' && a: base == ' '
199
201
return [' implements' ]
200
202
elseif context = ~? ' extends'
@@ -787,6 +789,8 @@ function! phpcomplete#CompleteClassName(base, kinds, current_namespace, imports)
787
789
788
790
if kinds == [' c' , ' i' ]
789
791
let filterstr = ' v:val =~? "\\(class\\|interface\\)\\s\\+[a-zA-Z_\\x7f-\\xff][a-zA-Z_0-9\\x7f-\\xff]*\\s*"'
792
+ elseif kinds == [' c' , ' n' ]
793
+ let filterstr = ' v:val =~? "\\(class\\|namespace\\)\\s\\+[a-zA-Z_\\x7f-\\xff][a-zA-Z_0-9\\x7f-\\xff]*\\s*"'
790
794
elseif kinds == [' c' ]
791
795
let filterstr = ' v:val =~? "class\\s\\+[a-zA-Z_\\x7f-\\xff][a-zA-Z_0-9\\x7f-\\xff]*\\s*"'
792
796
elseif kinds == [' i' ]
@@ -996,7 +1000,7 @@ function! phpcomplete#CompleteUserClass(context, base, sccontent, visibility) "
996
1000
let required_modifiers += [' static' ]
997
1001
endif
998
1002
let all_variable = filter (deepcopy (a: sccontent ),
999
- \ ' v:val =~ "^\\s*\\(var\\s\\+\\|public\\s\\+\\|protected\\s\\+\\|private\\s\\+\\|final\\s\\+\\|abstract\\s\\+\\|static\\s\\+\\)\\+\\$"' )
1003
+ \ ' v:val =~ "\\( ^\\s*\\(var\\s\\+\\|public\\s\\+\\|protected\\s\\+\\|private\\s\\+\\|final\\s\\+\\|abstract\\s\\+\\|static\\s\\+\\)\\+\\$\\|^\\s*\\(\\/\\|\\*\\)*\\s*@property\\s\\+\\S\\+\\s\\S\\{-}\\s*$\\) "' )
1000
1004
1001
1005
let variables = []
1002
1006
for i in all_variable
@@ -1160,6 +1164,14 @@ function! phpcomplete#GetTaglist(pattern) " {{{
1160
1164
endif
1161
1165
1162
1166
let tags = taglist (a: pattern )
1167
+ for tag in tags
1168
+ for prop in keys (tag )
1169
+ if prop == ' cmd' || prop == ' static' || prop == ' kind' || prop == ' builtin'
1170
+ continue
1171
+ endif
1172
+ let tag [prop] = substitute (tag [prop], ' \\\\' , ' \\' , ' g' )
1173
+ endfor
1174
+ endfor
1163
1175
let s: cache_tags [a: pattern ] = tags
1164
1176
let has_key = has_key (s: cache_tags , a: pattern )
1165
1177
let s: cache_tags_checksum = cache_checksum
@@ -1379,16 +1391,25 @@ function! phpcomplete#GetCallChainReturnType(classname_candidate, class_candidat
1379
1391
" Get Structured information of all classes and subclasses including namespace and includes
1380
1392
" try to find the method's return type in docblock comment
1381
1393
for classstructure in classcontents
1382
- let docblock_target_pattern = ' function\s\+&\?' .method.' \|\(public\|private\|protected\|var\).\+\$' .method
1394
+ let docblock_target_pattern = ' function\s\+&\?' .method.' \>\ |\(public\|private\|protected\|var\).\+\$' .method. ' \>\|@property.\+\$ ' .method. ' \> '
1383
1395
let doc_str = phpcomplete#GetDocBlock (split (classstructure.content, ' \n' ), docblock_target_pattern)
1384
1396
if doc_str != ' '
1385
1397
break
1386
1398
endif
1387
1399
endfor
1388
1400
if doc_str != ' '
1389
1401
let docblock = phpcomplete#ParseDocBlock (doc_str)
1390
- if has_key (docblock.return , ' type' ) || has_key (docblock.var , ' type' )
1391
- let type = has_key (docblock.return , ' type' ) ? docblock.return .type : docblock.var .type
1402
+ if has_key (docblock.return , ' type' ) || has_key (docblock.var , ' type' ) || len (docblock.properties) > 0
1403
+ let type = has_key (docblock.return , ' type' ) ? docblock.return .type : has_key (docblock.var , ' type' ) ? docblock.var .type : ' '
1404
+
1405
+ if type == ' '
1406
+ for property in docblock.properties
1407
+ if property.description = ~? method
1408
+ let type = property.type
1409
+ break
1410
+ endif
1411
+ endfor
1412
+ endif
1392
1413
1393
1414
" there's a namespace in the type, threat the type as FQCN
1394
1415
if type = ~ ' \\'
@@ -1554,6 +1575,9 @@ function! phpcomplete#GetClassName(start_line, context, current_namespace, impor
1554
1575
elseif get (methodstack, 0 ) = ~# function_invocation_pattern
1555
1576
let function_name = matchstr (methodstack[0 ], ' ^\s*\zs' .function_name_pattern)
1556
1577
let function_file = phpcomplete#GetFunctionLocation (function_name, a: current_namespace )
1578
+ if function_file == ' '
1579
+ let function_file = phpcomplete#GetFunctionLocation (function_name, ' \' )
1580
+ endif
1557
1581
1558
1582
if function_file == ' VIMPHP_BUILTINFUNCTION'
1559
1583
" built in function, grab the return type from the info string
@@ -1569,7 +1593,7 @@ function! phpcomplete#GetClassName(start_line, context, current_namespace, impor
1569
1593
let [class_candidate_namespace, function_imports] = phpcomplete#GetCurrentNameSpace (file_lines)
1570
1594
" try to expand the classname of the returned type with the context got from the function's source file
1571
1595
1572
- let [classname_candidate, unused ] = phpcomplete#ExpandClassName (classname_candidate, class_candidate_namespace, function_imports)
1596
+ let [classname_candidate, class_candidate_namespace ] = phpcomplete#ExpandClassName (classname_candidate, class_candidate_namespace, function_imports)
1573
1597
endif
1574
1598
endif
1575
1599
if classname_candidate != ' '
@@ -1650,9 +1674,10 @@ function! phpcomplete#GetClassName(start_line, context, current_namespace, impor
1650
1674
let sub_methodstack = phpcomplete#GetMethodStack (matchstr (line , ' ^\s*' .object.' \s*=&\?\s*\s\+\zs.*' ))
1651
1675
let [classname_candidate, class_candidate_namespace] = phpcomplete#GetCallChainReturnType (
1652
1676
\ classname,
1653
- \ a: current_namespace ,
1677
+ \ namespace_for_class ,
1654
1678
\ a: imports ,
1655
1679
\ sub_methodstack)
1680
+
1656
1681
return (class_candidate_namespace == ' \' || class_candidate_namespace == ' ' ) ? classname_candidate : class_candidate_namespace.' \' .classname_candidate
1657
1682
endif
1658
1683
endif
@@ -1783,6 +1808,9 @@ function! phpcomplete#GetClassName(start_line, context, current_namespace, impor
1783
1808
let [function_name, function_namespace] = phpcomplete#ExpandClassName (function_name, a: current_namespace , a: imports )
1784
1809
1785
1810
let function_file = phpcomplete#GetFunctionLocation (function_name, function_namespace)
1811
+ if function_file == ' '
1812
+ let function_file = phpcomplete#GetFunctionLocation (function_name, ' \' )
1813
+ endif
1786
1814
1787
1815
if function_file == ' VIMPHP_BUILTINFUNCTION'
1788
1816
" built in function, grab the return type from the info string
@@ -1798,7 +1826,7 @@ function! phpcomplete#GetClassName(start_line, context, current_namespace, impor
1798
1826
let classname_candidate = docblock.return .type
1799
1827
let [class_candidate_namespace, function_imports] = phpcomplete#GetCurrentNameSpace (file_lines)
1800
1828
" try to expand the classname of the returned type with the context got from the function's source file
1801
- let [classname_candidate, unused ] = phpcomplete#ExpandClassName (classname_candidate, class_candidate_namespace, function_imports)
1829
+ let [classname_candidate, class_candidate_namespace ] = phpcomplete#ExpandClassName (classname_candidate, class_candidate_namespace, function_imports)
1802
1830
break
1803
1831
endif
1804
1832
endif
@@ -1861,6 +1889,8 @@ function! phpcomplete#GetClassName(start_line, context, current_namespace, impor
1861
1889
for tag in tags
1862
1890
if tag .kind == ? ' v' && tag .cmd = ~? ' =\s*new\s\+\zs' .class_name_pattern.' \ze'
1863
1891
let classname = matchstr (tag .cmd, ' =\s*new\s\+\zs' .class_name_pattern.' \ze' )
1892
+ " unescape the classname, it would have "\" doubled since it is an ex command
1893
+ let classname = substitute (classname, ' \\\(\_.\)' , ' \1' , ' g' )
1864
1894
return classname
1865
1895
endif
1866
1896
endfor
@@ -2077,6 +2107,19 @@ function! phpcomplete#GetClassContentsStructure(file_path, file_lines, class_nam
2077
2107
endif
2078
2108
call searchpair (' {' , ' ' , ' }' , ' W' )
2079
2109
let class_closing_bracket_line = line (' .' )
2110
+
2111
+ " Include class docblock
2112
+ let doc_line = cfline - 1
2113
+ if getline (doc_line) = ~? ' ^\s*\*/'
2114
+ while doc_line != 0
2115
+ if getline (doc_line) = ~? ' ^\s*/\*\*'
2116
+ let cfline = doc_line
2117
+ break
2118
+ endif
2119
+ let doc_line -= 1
2120
+ endwhile
2121
+ endif
2122
+
2080
2123
let classcontent = join (getline (cfline, class_closing_bracket_line), " \n " )
2081
2124
2082
2125
let used_traits = []
@@ -2241,8 +2284,19 @@ function! phpcomplete#GetDocBlock(sccontent, search) " {{{
2241
2284
let line = a: sccontent [i ]
2242
2285
" search for a function declaration
2243
2286
if line = ~? a: search
2244
- let l = i - 1
2245
- " start backward serch for the comment block
2287
+ if line = ~? ' @property'
2288
+ let doc_line = i
2289
+ while doc_line != sccontent_len - 1
2290
+ if a: sccontent [doc_line] = ~? ' ^\s*\*/'
2291
+ let l = doc_line
2292
+ break
2293
+ endif
2294
+ let doc_line += 1
2295
+ endwhile
2296
+ else
2297
+ let l = i - 1
2298
+ endif
2299
+ " start backward search for the comment block
2246
2300
while l != 0
2247
2301
let line = a: sccontent [l ]
2248
2302
" if it's a one line docblock like comment and we can just return it right away
@@ -2263,7 +2317,7 @@ function! phpcomplete#GetDocBlock(sccontent, search) " {{{
2263
2317
return ' '
2264
2318
end
2265
2319
2266
- while l ! = 0
2320
+ while l > = 0
2267
2321
let line = a: sccontent [l ]
2268
2322
if line = ~? ' ^\s*/\*\*'
2269
2323
let comment_start = l
@@ -2297,9 +2351,10 @@ function! phpcomplete#ParseDocBlock(docblock) " {{{
2297
2351
\ ' return' : {},
2298
2352
\ ' throws' : [],
2299
2353
\ ' var' : {},
2354
+ \ ' properties' : [],
2300
2355
\ }
2301
2356
2302
- let res .description = substitute (matchstr (a: docblock , ' \zs\_.\{-}\ze\(@var\|@param\|@return\|$\)' ), ' \(^\_s*\|\_s*$\)' , ' ' , ' g' )
2357
+ let res .description = substitute (matchstr (a: docblock , ' \zs\_.\{-}\ze\(@type\|@ var\|@param\|@return\|$\)' ), ' \(^\_s*\|\_s*$\)' , ' ' , ' g' )
2303
2358
let docblock_lines = split (a: docblock , " \n " )
2304
2359
2305
2360
let param_lines = filter (copy (docblock_lines), ' v:val =~? "^@param"' )
@@ -2334,15 +2389,26 @@ function! phpcomplete#ParseDocBlock(docblock) " {{{
2334
2389
endif
2335
2390
endfor
2336
2391
2337
- let var_line = filter (copy (docblock_lines), ' v:val =~? "^@var"' )
2392
+ let var_line = filter (copy (docblock_lines), ' v:val =~? "^\\( @var\\|@type\\) "' )
2338
2393
if len (var_line) > 0
2339
- let var_parts = matchlist (var_line[0 ], ' @var\s\+\(\S\+\)\s*\(.*\)' )
2394
+ let var_parts = matchlist (var_line[0 ], ' \( @var\|@type\) \s\+\(\S\+\)\s*\(.*\)' )
2340
2395
let res [' var' ] = {
2341
2396
\ ' line' : var_parts[0 ],
2342
- \ ' type' : phpcomplete#GetTypeFromDocBlockParam (get (var_parts, 1 , ' ' )),
2343
- \ ' description' : get (var_parts, 2 , ' ' )}
2397
+ \ ' type' : phpcomplete#GetTypeFromDocBlockParam (get (var_parts, 2 , ' ' )),
2398
+ \ ' description' : get (var_parts, 3 , ' ' )}
2344
2399
endif
2345
2400
2401
+ let property_lines = filter (copy (docblock_lines), ' v:val =~? "^@property"' )
2402
+ for property_line in property_lines
2403
+ let parts = matchlist (property_line, ' \(@property\)\s\+\(\S\+\)\s*\(.*\)' )
2404
+ if len (parts) > 0
2405
+ call add (res .properties, {
2406
+ \ ' line' : parts[0 ],
2407
+ \ ' type' : phpcomplete#GetTypeFromDocBlockParam (get (parts, 2 , ' ' )),
2408
+ \ ' description' : get (parts, 3 , ' ' )})
2409
+ endif
2410
+ endfor
2411
+
2346
2412
return res
2347
2413
endfunction
2348
2414
" }}}
@@ -2498,6 +2564,7 @@ function! phpcomplete#GetCurrentNameSpace(file_lines) " {{{
2498
2564
let name = matchstr (name, ' \\\zs[^\\]\+\ze$' )
2499
2565
endif
2500
2566
endif
2567
+
2501
2568
" leading slash is not required use imports are always absolute
2502
2569
let imports[name] = {' name' : object, ' kind' : ' ' }
2503
2570
endfor
@@ -2533,6 +2600,7 @@ function! phpcomplete#GetCurrentNameSpace(file_lines) " {{{
2533
2600
elseif ! exists (' no_namespace_candidate' )
2534
2601
" save the first namespacless match to be used if no better
2535
2602
" candidate found later on
2603
+ let tag .namespace = namespace_for_classes
2536
2604
let no_namespace_candidate = tag
2537
2605
endif
2538
2606
endif
0 commit comments