Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 11 additions & 13 deletions autoload/phpcomplete.vim
Original file line number Diff line number Diff line change
Expand Up @@ -732,29 +732,27 @@ function! phpcomplete#CompleteUserClass(scontext, base, sccontent, classAccess)
let res = []

" limit based on context to static or normal methods
let static_con = ''
if a:scontext =~ '::'
if g:phpcomplete_relax_static_constraint == 1
let functions = filter(deepcopy(a:sccontent),
\ 'v:val =~ "^\\s*\\(static\\s\\+\\(' . a:classAccess . '\\)*\\|\\(' . a:classAccess . '\\s\\+\\)*static\\)\\s\\+function"')
let functions += filter(deepcopy(a:sccontent),
\ 'v:val =~ "^\\s*\\(' . a:classAccess . '\\s\\+\\)*function"')
else
let functions = filter(deepcopy(a:sccontent),
\ 'v:val =~ "^\\s*\\(static\\s\\+\\(' . a:classAccess . '\\)*\\|\\(' . a:classAccess . '\\s\\+\\)*static\\)\\s\\+function"')
let static_con = ''
else
let static_con = '\\(.*\\<static\\>\\)\\@='
endif
elseif a:scontext =~ '->'
let functions = filter(deepcopy(a:sccontent),
\ 'v:val =~ "^\\s*\\(' . a:classAccess . '\\s\\+\\)*function"')
let static_con = '\\(.*\\<static\\>\\)\\@!'
endif

let sfuncs = split(join(functions, ' '), 'function\s\+')
let functions = filter(deepcopy(a:sccontent),
\ 'v:val =~ "^\\s*\\(.*\\<' . a:classAccess . '\\>\\)\\@=' . static_con . '\\(public\\|protected\\|private\\|static\\|final\\|abstract\\|\\s\\)\\+function"')

let c_functions = {}
let c_doc = {}
for i in sfuncs
for i in functions
let f_name = matchstr(i,
\ '^&\?\zs[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*\ze')
\ 'function\s*&\?\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*\({\|$\)')
\ 'function\s*&\?[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*\s*(\zs.\{-}\ze)\_s*\({\|\_$\)')
if f_name != ''
let c_functions[f_name.'('] = f_args
if g:phpcomplete_parse_docblock_comments
Expand Down
125 changes: 125 additions & 0 deletions tests/CompleteUserClass2_test.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
fun! SetUp()
let g:fixture_class_content = readfile(expand('%:p:h').'/'.'fixtures/CompleteUserClass/user_extended.class.php')[2:]
let g:commented_fixture_class_content = readfile(expand('%:p:h').'/'.'fixtures/CompleteUserClass/commented_foo.class.php')[2:]
let g:phpcomplete_relax_static_constraint = 0
let g:phpcomplete_parse_docblock_comments = 0
endf

fun! TestCase_returns_everyting_instance_related_when_scope_is_in_class()
call SetUp()

let ret = phpcomplete#CompleteUserClass('$u->', '', g:fixture_class_content, '\\(public\\|private\\|protected\\)')
call VUAssertEquals([
\{'word': 'A_CONST', 'info': 'A_CONST', 'menu': '', 'kind': 'd'},
\{'word': '__construct(', 'info': '__construct()', 'menu': ')', 'kind': 'f'},
\{'word': 'final_private_method(', 'info': 'final_private_method($foo = null)', 'menu': '$foo = null)', 'kind': 'f'},
\{'word': 'private_method(', 'info': 'private_method($foo)', 'menu': '$foo)', 'kind': 'f'},
\{'word': 'private_property', 'info': '', 'menu': '', 'kind': 'v'},
\{'word': 'protected_method(', 'info': 'protected_method($foo)', 'menu': '$foo)', 'kind': 'f'},
\{'word': 'protected_property', 'info': '', 'menu': '', 'kind': 'v'},
\{'word': 'public_final_method(', 'info': 'public_final_method($foo, $anotherfoo = '''')', 'menu': '$foo, $anotherfoo = '''')', 'kind': 'f'},
\{'word': 'public_method(', 'info': 'public_method($foo)', 'menu': '$foo)', 'kind': 'f'},
\{'word': 'public_method_with_amp(', 'info': 'public_method_with_amp($foo)', 'menu': '$foo)', 'kind': 'f'},
\{'word': 'public_property1', 'info': '', 'menu': '', 'kind': 'v'},
\{'word': 'public_property2', 'info': '', 'menu': '', 'kind': 'v'}],
\ ret)
endfun

fun! TestCase_returns_everyting_instance_related_when_scope_is_out_of_class()
call SetUp()

let ret = phpcomplete#CompleteUserClass('$u->', '', g:fixture_class_content, 'public')
call VUAssertEquals([
\{'word': 'A_CONST', 'info': 'A_CONST', 'menu': '', 'kind': 'd'},
\{'word': '__construct(', 'info': '__construct()', 'menu': ')', 'kind': 'f'},
\{'word': 'public_final_method(', 'info': 'public_final_method($foo, $anotherfoo = '''')', 'menu': '$foo, $anotherfoo = '''')', 'kind': 'f'},
\{'word': 'public_method(', 'info': 'public_method($foo)', 'menu': '$foo)', 'kind': 'f'},
\{'word': 'public_method_with_amp(', 'info': 'public_method_with_amp($foo)', 'menu': '$foo)', 'kind': 'f'},
\{'word': 'public_property1', 'info': '', 'menu': '', 'kind': 'v'},
\{'word': 'public_property2', 'info': '', 'menu': '', 'kind': 'v'}],
\ ret)
endfun

fun! TestCase_returns_everyting_static_when_scope_is_in_class()
call SetUp()

let ret = phpcomplete#CompleteUserClass('UserClass::', '', g:fixture_class_content, '\\(public\\|private\\|protected\\)')
call VUAssertEquals([
\ {'word': '$private_static_property', 'info': '', 'menu': '', 'kind': 'v'},
\ {'word': '$protected_static_property', 'info': '', 'menu': '', 'kind': 'v'},
\ {'word': '$public_static_property', 'info': '', 'menu': '', 'kind': 'v'},
\ {'word': 'A_CONST', 'info': 'A_CONST', 'menu': '', 'kind': 'd'},
\ {'word': 'final_static_public_method(', 'info': 'final_static_public_method()', 'menu': ')', 'kind': 'f'},
\ {'word': 'private_static_method(', 'info': 'private_static_method($foo)', 'menu': '$foo)', 'kind': 'f'},
\ {'word': 'protected_static_method(', 'info': 'protected_static_method($foo)', 'menu': '$foo)', 'kind': 'f'},
\ {'word': 'public_final_static_method(', 'info': 'public_final_static_method( $foo, $anotherfoo = array() )', 'menu': ' $foo, $anotherfoo = array() )', 'kind': 'f'},
\ {'word': 'public_static_method(', 'info': 'public_static_method($foo)', 'menu': '$foo)', 'kind': 'f'},
\ {'word': 'static_final_protected_method(', 'info': 'static_final_protected_method()', 'menu': ')', 'kind': 'f'},
\ {'word': 'static_public_method(', 'info': 'static_public_method($foo)', 'menu': '$foo)', 'kind': 'f'}],
\ ret)
endfun

fun! TestCase_filters_for_instane_level_prefix()
call SetUp()

let ret = phpcomplete#CompleteUserClass('$u->', 'public_', g:fixture_class_content, '\\(public\\|private\\|protected\\)')
call VUAssertEquals([
\ {'word': 'public_final_method(', 'info': 'public_final_method($foo, $anotherfoo = '''')', 'menu': '$foo, $anotherfoo = '''')', 'kind': 'f'},
\ {'word': 'public_method(', 'info': 'public_method($foo)', 'menu': '$foo)', 'kind': 'f'},
\ {'word': 'public_method_with_amp(', 'info': 'public_method_with_amp($foo)', 'menu': '$foo)', 'kind': 'f'},
\ {'word': 'public_property1', 'info': '', 'menu': '', 'kind': 'v'},
\ {'word': 'public_property2', 'info': '', 'menu': '', 'kind': 'v'}],
\ ret)
endfun

fun! TestCase_filters_for_static_property_names()
call SetUp()

let ret = phpcomplete#CompleteUserClass('UserClass::', '$private_', g:fixture_class_content, '\\(public\\|private\\|protected\\)')
call VUAssertEquals([
\ {'word': '$private_static_property', 'info': '', 'menu': '', 'kind': 'v'}],
\ ret)
endfun

fun! TestCase_returns_everyting_static_when_scope_is_out_of_class()
call SetUp()

let ret = phpcomplete#CompleteUserClass('UserClass::', '', g:fixture_class_content, 'public')
call VUAssertEquals([
\ {'word': '$public_static_property', 'info': '', 'menu': '', 'kind': 'v'},
\ {'word': 'A_CONST', 'info': 'A_CONST', 'menu': '', 'kind': 'd'},
\ {'word': 'final_static_public_method(', 'info': 'final_static_public_method()', 'menu': ')', 'kind': 'f'},
\ {'word': 'public_final_static_method(', 'info': 'public_final_static_method( $foo, $anotherfoo = array() )', 'menu': ' $foo, $anotherfoo = array() )', 'kind': 'f'},
\ {'word': 'public_static_method(', 'info': 'public_static_method($foo)', 'menu': '$foo)', 'kind': 'f'},
\ {'word': 'static_public_method(', 'info': 'static_public_method($foo)', 'menu': '$foo)', 'kind': 'f'}],
\ ret)
endfun

fun! TestCase_returns_non_explicit_static_methods_when_phpcomplete_relax_static_constraint_enabled()
call SetUp()
let g:phpcomplete_relax_static_constraint = 1
let ret = phpcomplete#CompleteUserClass('UserClass::', '', g:fixture_class_content, 'public')
call VUAssertEquals([
\ {'word': '$public_static_property', 'info': '', 'menu': '', 'kind': 'v'},
\ {'word': 'A_CONST', 'info': 'A_CONST', 'menu': '', 'kind': 'd'},
\ {'word': '__construct(', 'info': '__construct()', 'menu': ')', 'kind': 'f'},
\ {'word': 'final_static_public_method(', 'info': 'final_static_public_method()', 'menu': ')', 'kind': 'f'},
\ {'word': 'public_final_method(', 'info': 'public_final_method($foo, $anotherfoo = '''')', 'menu': '$foo, $anotherfoo = '''')', 'kind': 'f'},
\ {'word': 'public_final_static_method(', 'info': 'public_final_static_method( $foo, $anotherfoo = array() )', 'menu': ' $foo, $anotherfoo = array() )', 'kind': 'f'},
\ {'word': 'public_method(', 'info': 'public_method($foo)', 'menu': '$foo)', 'kind': 'f'},
\ {'word': 'public_method_with_amp(', 'info': 'public_method_with_amp($foo)', 'menu': '$foo)', 'kind': 'f'},
\ {'word': 'public_static_method(', 'info': 'public_static_method($foo)', 'menu': '$foo)', 'kind': 'f'},
\ {'word': 'static_public_method(', 'info': 'static_public_method($foo)', 'menu': '$foo)', 'kind': 'f'}],
\ ret)
endfun

fun! TestCase_returns_types_for_properties_and_return_types_from_docblock_comments()
call SetUp()
let g:phpcomplete_parse_docblock_comments = 1

let ret = phpcomplete#CompleteUserClass('$u->', 'commented', g:commented_fixture_class_content, 'public')
call VUAssertEquals([
\ {'word': 'commented_method(', 'info': "commented_method($foo, $bar, $baz = '')\n\nReturn:\n\tstring: description of return\n", 'menu': "$foo, $bar, $baz = '') | string", 'kind': 'f'},
\ {'word': 'commented_property', 'info': "Type:\n\tFoo\n", 'menu': 'Foo', 'kind': 'v'}],
\ ret)
endfun
70 changes: 70 additions & 0 deletions tests/fixtures/CompleteUserClass/user_extended.class.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

class UserClass {

const A_CONST = 'foo';

var $public_property1;
public $public_property2;
protected $protected_property;
private $private_property;

public static $public_static_property;
protected static $protected_static_property;
private static $private_static_property;

public function __construct() {
}

public function public_method($foo) {
}

public function &public_method_with_amp($foo)
{

}

public final function public_final_method($foo, $anotherfoo = '')
{

}

private function private_method($foo) {
}

final private function final_private_method($foo = null)
{

}

protected function protected_method($foo) {
}

public static function public_static_method($foo) {
}

static public function static_public_method($foo) {
}

public final static function public_final_static_method( $foo, $anotherfoo = array() )
{

}

final static public function final_static_public_method()
{

}

private static function private_static_method($foo) {
}

protected static function protected_static_method($foo) {
}

static final protected function static_final_protected_method()
{

}
}