1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-04-14 15:19:12 +08:00

fix(lang#php): use old phpcomplete

close https://github.com/SpaceVim/SpaceVim/issues/4519
This commit is contained in:
wsdjeg 2022-02-06 21:21:00 +08:00
parent c1bb72ba85
commit 1c57952d25
329 changed files with 77906 additions and 1 deletions

View File

@ -59,7 +59,11 @@ function! SpaceVim#layers#lang#php#plugins() abort
if SpaceVim#layers#lsp#check_filetype('php')
call add(plugins, ['phpactor/phpactor', {'on_ft' : 'php', 'build' : 'composer install --no-dev -o'}])
else
call add(plugins, ['shawncplus/phpcomplete.vim', { 'on_ft' : 'php'}])
if exists('*popup_create')
call add(plugins, [g:_spacevim_root_dir . 'bundle/phpcomplete.vim', {'merged' : 0}])
else
call add(plugins, [g:_spacevim_root_dir . 'bundle/phpcomplete.vim-vim7', {'merged' : 0}])
endif
endif
return plugins
endfunction

View File

@ -0,0 +1,4 @@
misc/dist_builtin.vim
tests/log.txt-*
**/DBG
bin/tags

View File

@ -0,0 +1,10 @@
language: bash
before_script:
- sudo apt-get update -qq
- sudo apt-get install -y vim
- sudo apt-get install -y bash
- git clone https://github.com/complex857/vimunit vimunit
script:
- cd tests/; bash runtests.sh

View File

@ -0,0 +1,50 @@
## Beginner's Guide
phpcomplete.vim complements Vim's built-in omnicomplete functions. It relies on Vim's access to a `tags` file.
A `tags` file is a metadata file that can describe your code and the relationships between its elements, like Classes, Interfaces, Methods, etc.
phpcomplete.vim does **not** generate that file for you, so before using phpcomplete.vim, you'll need to generate it for your PHP project on your own.
### Generating a `tags` file
First, you'll need a program that can parse your PHP project and output a tags file. There are a few choices for doing so and they're outlined here: [Getting Better Tags](https://github.com/shawncplus/phpcomplete.vim/wiki/Getting-better-tags).
Once you have a `ctags` or `phpctags` program installed, make sure it's in your `$PATH` ([relevant StackExchange post](https://unix.stackexchange.com/questions/26047/how-to-correctly-add-a-path-to-path)).
The rest of this guide will assume you're using `phpctags`; if you're using something else, substitute the `phpctags` command with `ctags`.
Now we're ready to generate our tags file. First, change directories to your project root, then you'll run the command to generate a `tags` file. Like so:
```sh
$ cd /path/to/your/project
$ phpctags -R
```
This should output a `tags` file in the current directory.
You may want to add that file to your `.gitignore`. If you're working with non-Vim users, you can try adding it to `.git/info/exclude` so as not to pollute your project's `.gitignore` with your Vim-specific rules.
**Note**: If you're using `phpctags` and your project is large enough, `phpctags` might run out of memory. If that happens, it will silently fail by not outputting a `tags` file at all. You can try replacing the command above with: `phpctags --memory=-1 -R` to give `phpctags` unlimited memory.
### Making sure Vim can read your `tags` file
By default, Vim will look for your `tags` file in your `cwd` under the following files: `./tags,tags`, this default behaviour is usually good enough.
The file lookup is controlled by the option `tags`. Some plugins like fugitive will add your project's `.git/tags` file to this list. If for some reason you need to add an another path you can do it like this:
```
set tags+=./some/path/to/extra/tags
```
See more under `:help 'tags'`
### Getting completions
Once you have everything set up above, you can finally get completions! The command to get Vim to open up suggestions is `<ctrl-x><ctrl-o>`.
That means hitting the <kbd>CTRL</kbd>+<kbd>x</kbd> keys at the same time, then hitting <kbd>CTRL</kbd>+<kbd>o</kbd> right after.
If there are multiple suggestions, you can use <kbd>CTRL</kbd>+<kbd>n</kbd> to scroll down the list and <kbd>CTRL</kbd>+<kbd>p</kbd> to scroll up the list.
Hitting <kbd>TAB</kbd> will complete the word under your cursor with your selection.
**That's it, enjoy!**

View File

@ -0,0 +1,147 @@
## About
Improved PHP omni-completion. Based on the default phpcomplete.vim.
[![Build Status](https://travis-ci.org/shawncplus/phpcomplete.vim.svg?branch=master)](https://travis-ci.org/shawncplus/phpcomplete.vim)
## Features
* Correct restriction of static or standard methods based on context ( show only static methods with `::` and only standard with `->`)
* Real support for `self::` and `$this->` with the aforementioned context restriction
* Constant variable completion (not just `define(VARIABLE, 1)` but `const VARIABLE = 1`)
* Better class detection:
- Recognize `/* @var $yourvar YourClass */` type mark comments
- Recognize `$instance = new Class;` class instantiations
- Recognize `$instance = Class::getInstance();` singleton instances
- Recognize `$date = DateTime::createFromFormat(...)` built-in class return types
- Recognize type hinting in function prototypes
- Recognize types in `@param` lines in function docblocks
- Recognize `$object = SomeClass::staticCall(...)` return types from docblocks
- Recognize array of objects via docblock like `$foo[42]->` or for variables created in `foreach`
* Displays docblock info in the preview for methods and properties
* Updated built-in class support with constants, methods and properties
* Updated list of PHP constants
* Updated list of built-in PHP functions
* Namespace support ( **Requires** [patched ctags](https://github.com/shawncplus/phpcomplete.vim/wiki/Getting-better-tags) )
* Enhanced jump-to-definition on <kbd>ctrl</kbd>+<kbd>]</kbd>
## Install
### Pathogen
1. Install the [pathogen.vim](https://github.com/tpope/vim-pathogen) plugin, [follow the instructions here](https://github.com/tpope/vim-pathogen#installation)
2. Clone the repository under your `~/.vim/bundle/` directory:
cd ~/.vim/bundle
git clone git://github.com/shawncplus/phpcomplete.vim.git
### Vundle
1. Install and configure the [Vundle](https://github.com/gmarik/vundle) plugin manager, [follow the instructions here](https://github.com/gmarik/vundle#quick-start)
2. Add the following line to your `.vimrc`:
Plugin 'shawncplus/phpcomplete.vim'
3. Source your `.vimrc` with `:so %` or otherwise reload your vim
4. Run the `:PluginInstall` commmand
## Usage
If you're new to auto-completion in Vim, we recommend reading our ["Beginner's Guide"](GUIDE.md).
## ctags
In order to support some php features introduced in PHP 5.3 you will have to use
a ctags binary that can generate the appropriate tags files. Most unix like systems
have a ctags version built in that's really outdated. Please read the "[getting better tags](https://github.com/shawncplus/phpcomplete.vim/wiki/Getting-better-tags)" wiki page for more information.
## Options
**let g:phpcomplete\_relax\_static\_constraint = 1/0 [default 0]** <br>
Enables completion for non-static methods when completing for static context (`::`).
This generates `E_STRICT` level warning, but php calls these methods nontheless.
**let g:phpcomplete\_complete\_for\_unknown\_classes = 1/0 [default 0]** <br>
Enables completion of variables and functions in "everything under the sun" fashion
when completing for an instance or static class context but the code can't tell the class
or locate the file that it lives in.
The completion list generated this way is only filtered by the completion base
and generally not much more accurate then simple keyword completion.
**let g:phpcomplete\_search\_tags\_for\_variables = 1/0 [default 0]** <br>
Enables use of tags when the plugin tries to find variables.
When enabled the plugin will search for the variables in the tag files with kind 'v',
lines like `$some_var = new Foo;` but these usually yield highly inaccurate results and
can be fairly slow.
**let g:phpcomplete\_min\_num\_of\_chars\_for\_namespace\_completion = n [default 1]** *Requires [patched ctags](https://github.com/shawncplus/phpcomplete.vim/wiki/Getting-better-tags)* <br>
This option controls the number of characters the user needs to type before
the tags will be searched for namespaces and classes in typed out namespaces in
"use ..." context. Setting this to 0 is not recommended because that means the code
have to scan every tag, and vim's taglist() function runs extremly slow with a
"match everything" pattern.<br>
**let g:phpcomplete\_parse\_docblock\_comments = 1/0 [default 0]**<br>
When enabled the preview window's content will include information
extracted from docblock comments of the completions.
Enabling this option will add return types to the completion menu for functions too.
**let g:phpcomplete\_cache\_taglists = 1/0 [default 1]**<br>
When enabled the taglist() lookups will be cached and subsequent searches
for the same pattern will not check the tagfiles any more, thus making the
lookups faster. Cache expiration is based on the mtimes of the tag files.
**let g:phpcomplete_enhance_jump_to_definition = 1/0 [default 1]<br>**
When enabled the `<C-]>` will be mapped to `phpcomplete#JumpToDefinition()`
which will try to make a more educated guess of the current
symbol's location than simple tag search. If the symbol's location
cannot be found the original `<C-]>` functionality will be invoked
**let g:phpcomplete\_mappings = {..} <br>**
Defines the mappings for the enhanced jump-to-definition.
**Recognized keys:**
- **jump\_to\_def**: Jumps to the definition in the current buffer
- **jump\_to\_def\_split**: Jumps to the definition in a new split buffer
- **jump\_to\_def\_vsplit**: Jumps to the definition in a new vertical split buffer
- **jump\_to\_def\_tabnew**: Jumps to the definition in a new tab buffer
You change any of them like this in your `vimrc`:
let g:phpcomplete_mappings = {
\ 'jump_to_def': ',g',
\ 'jump_to_def_tabnew': ',t',
\ }
The keys you don't specify will be mapped to the defaults:
let g:phpcomplete_mappings = {
\ 'jump_to_def': '<C-]>',
\ 'jump_to_def_split': '<C-W><C-]>',
\ 'jump_to_def_vsplit': '<C-W><C-\>',
\ 'jump_to_def_tabnew': '<C-W><C-[>',
\}
**let g:phpcomplete\_add\_function\_extensions = [...]**<br>
**let g:phpcomplete\_add\_class\_extensions = [...]**<br>
**let g:phpcomplete\_add\_interface\_extensions = [...]**<br>
**let g:phpcomplete\_add\_constant\_extensions = [...]**<br>
**let g:phpcomplete\_remove\_function\_extensions = [...]**<br>
**let g:phpcomplete\_remove\_class\_extensions = [...]**<br>
**let g:phpcomplete\_remove\_interface\_extensions = [...]**<br>
**let g:phpcomplete\_remove\_constant\_extensions = [...]**<br>
Built-in functions, classes, interfaces and constatns are grouped together by the extension.
Only the enabled extensions will be loaded for the plugin, the defaultly enabled ones can be
found in.
g:phpcomplete_active_function_extensions
g:phpcomplete_active_class_extensions
g:phpcomplete_active_interface_extensions
g:phpcomplete_active_constant_extensions
If you want to enable an extension that is disabled you can add it to the enabled lists
in your vimrc. Let's say you want to have the mongo extension's classes and functions
to be completed by the plugin, you can add it like this (in your `.vimrc`):
let g:phpcomplete_add_class_extensions = ['mongo']
let g:phpcomplete_add_function_extensions = ['mongo']
If you want to disable an otherwise enabled one, use the ..._remove_... version of these options:
let g:phpcomplete_remove_function_extensions = ['xslt_php_4']
let g:phpcomplete_remove_constant_extensions = ['xslt_php_4']
For the available extension files, check the [`misc/available_extensions`](https://github.com/shawncplus/phpcomplete.vim/blob/master/misc/available_extensions). file

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -0,0 +1,175 @@
<?php
/**
* Create dictionaries for phpcomlete.vim to use in autocompletion
*
* Uses the offical PHP documentation html files to extract function
* and method names with parameter signatures. The extracted info
* dumped into vim dictionaries that phpcomlete.vim plugin loads in
* for omnicomplete.
*/
require_once __DIR__.'/'.'generator/tools.php';
require_once __DIR__.'/'.'generator/constants.php';
require_once __DIR__.'/'.'generator/functions.php';
require_once __DIR__.'/'.'generator/classes.php';
$dist_enabled_function_extensions = array(
'math', 'strings', 'apache', 'arrays', 'php_options_info', 'classes_objects',
'urls', 'filesystem', 'variable_handling', 'calendar',
'function_handling', 'directories', 'date_time', 'network', 'spl',
'misc', 'curl', 'error_handling', 'dom', 'program_execution',
'mail', 'fastcgi_process_manager', 'filter', 'fileinfo', 'output_control',
'gd', 'iconv', 'json', 'libxml', 'multibyte_string', 'mssql',
'mysql', 'mysqli', 'password_hashing', 'postgresql',
'pcre', 'sessions', 'streams', 'simplexml', 'xmlwriter', 'zip',
);
$dist_enabled_class_extensions = array(
'spl', 'predefined_interfaces_and_classes', 'curl', 'date_time', 'directories',
'dom', 'predefined_exceptions', 'libxml', 'mysqli', 'pdo', 'phar', 'streams',
'sessions', 'simplexml', 'spl_types', 'xmlreader', 'zip',
);
$dist_enabled_interface_extensions = array(
'predefined_interfaces_and_classes', 'spl', 'date_time', 'json',
);
$dist_enabled_constant_extensions = array(
'common', 'arrays', 'calendar', 'curl', 'date_time', 'libxml', 'mysqli', 'spl',
'unknow', 'directories', 'dom', 'command_line_usage', 'handling_file_uploads',
'fileinfo', 'filesystem', 'filter', 'php_options_info', 'strings',
'error_handling', 'math', 'network', 'urls', 'gd', 'json', 'multibyte_string',
'mssql', 'mysql', 'output_control', 'password_hashing', 'postgresql',
'pcre', 'program_execution', 'sessions', 'variable_handling', 'misc',
'streams','iconv', 'phpini_directives', 'types', 'pdo',
'list_of_reserved_words', 'php_type_comparison_tables',
);
function main($argv){
if (count($argv) < 3) {
usage($argv);
return 1;
}
if (!is_dir($argv[1])) {
fprintf(STDERR, "Error: Invalid php_doc_path. {$argv[1]} is not a directory\n\n");
usage($argv);
return 1;
}
if (!is_readable($argv[1])) {
fprintf(STDERR, "Error: Invalid php_doc_path. {$argv[1]} is not readalbe\n\n");
usage($argv);
return 1;
}
if (!is_dir($argv[2])) {
fprintf(STDERR, "Error: Invalid plugin_path. {$argv[2]} is not a directory\n\n");
usage($argv);
return 1;
}
if (!is_dir($argv[2].'/misc')) {
fprintf(STDERR, "Error: Invalid plugin_path. {$argv[2]}/misc is not a directory\n\n");
usage($argv);
return 1;
}
$extensions = get_extension_names($argv[1]);
libxml_use_internal_errors(true);
$function_files = glob("{$argv[1]}/function.*.html");
$functions = extract_function_signatures($function_files, $extensions);
$extra_function_files = list_procedural_style_files("{$argv[1]}");
$functions = extract_function_signatures($extra_function_files, $extensions, $functions);
$class_files = glob("{$argv[1]}/class.*.html", GLOB_BRACE);
list($classes, $interfaces) = extract_class_signatures($class_files, $extensions);
// unfortunately constants are really everywhere, the *constants.html almost there ok but leaves out
// pages like filter.filters.sanitize.html
$constant_files = glob("{$argv[1]}/*.html");
list($constants, $class_constants) = extract_constant_names($constant_files, $extensions);
// some class constants like PDO::* are not defined in the class synopsis
// but they show up with the other constatns so we add them to the extracted classes
inject_class_constants($interfaces, $class_constants, false);
inject_class_constants($classes, $class_constants, false);
$meta_outfile = $argv[2].'/misc/available_extensions';
file_put_contents($meta_outfile, "Available function extensions:\n");
file_put_contents($meta_outfile, join("\n", array_map(function($ext_name){ return "\t".filenameize($ext_name); }, array_keys($functions))), FILE_APPEND);
file_put_contents($meta_outfile, "\n\nAvailable Class extensions:\n", FILE_APPEND);
file_put_contents($meta_outfile, join("\n", array_map(function($ext_name){ return "\t".filenameize($ext_name); }, array_keys($classes))), FILE_APPEND);
file_put_contents($meta_outfile, "\n\nAvailable Interface extensions:\n", FILE_APPEND);
file_put_contents($meta_outfile, join("\n", array_map(function($ext_name){ return "\t".filenameize($ext_name); }, array_keys($interfaces))), FILE_APPEND);
file_put_contents($meta_outfile, "\n\nAvailable Constant extensions:\n", FILE_APPEND);
file_put_contents($meta_outfile, join("\n", array_map(function($ext_name){ return "\t".filenameize($ext_name); }, array_keys($constants))), FILE_APPEND);
$outfile = $argv[2].'/misc/builtin.vim';
file_put_contents(
$outfile,
"let g:phpcomplete_builtin = {\n"
."\ 'functions':{},\n"
."\ 'classes':{},\n"
."\ 'interfaces':{},\n"
."\ 'constants':{},\n"
."\ }\n"
);
write_function_signatures_to_vim_hash($functions, $outfile, 'functions');
print "\nextracted ".array_sum(array_map(function($a){ return count($a); }, $functions))." built-in function";
write_class_signatures_to_vim_hash($classes, $outfile, 'classes');
print "\nextracted ".array_sum(array_map(function($a){ return count($a); }, $classes))." built-in class";
write_class_signatures_to_vim_hash($interfaces, $outfile, 'interfaces');
print "\nextracted ".array_sum(array_map(function($a){ return count($a); }, $interfaces))." built-in interface";
write_constant_names_to_vim_hash($constants, $outfile, 'constants');
print "\nextracted ".array_sum(array_map(function($a){ return count($a); }, $constants))." built-in constants";
$dist_outfile = $argv[2].'/misc/dist_builtin.vim';
file_put_contents(
$dist_outfile,
"let g:phpcomplete_builtin = {\n"
."\ 'functions':{},\n"
."\ 'classes':{},\n"
."\ 'interfaces':{},\n"
."\ 'constants':{},\n"
."\ }\n"
);
global $dist_enabled_function_extensions;
global $dist_enabled_class_extensions;
global $dist_enabled_interface_extensions;
global $dist_enabled_constant_extensions;
write_function_signatures_to_vim_hash($functions, $dist_outfile, 'functions', $dist_enabled_function_extensions, false);
write_class_signatures_to_vim_hash($classes, $dist_outfile, 'classes', $dist_enabled_class_extensions, false);
write_class_signatures_to_vim_hash($interfaces, $dist_outfile, 'interfaces', $dist_enabled_interface_extensions, false);
write_constant_names_to_vim_hash($constants, $dist_outfile, 'constants', $dist_enabled_constant_extensions, false);
return 0;
}
function usage($argv) {
fprintf(STDERR,
"USAGE:\n".
"\tphp {$argv[0]} <php_doc_path> <plugin_path>\n".
"\n".
"php_doc_path:\n".
"\tPath to a directory containing the\n".
"\textracted Many HTML files version of the documentation.\n".
"\tDownload from here: http://www.php.net/download-docs.php\n".
"\n".
"plugin_path:\n".
"\tPath to the plugins root, example: ~/.vim/bundle/phpcomplete.vim/\n"
);
}
return main($argv);

View File

@ -0,0 +1,411 @@
<?php
function extract_class_signatures($files, $extensions) {
$class_signatures = array();
$interface_signatures = array();
foreach ($files as $file) {
$doc = new DOMDocument;
$doc->loadHTMLFile($file);
$xpath = new DOMXpath($doc);
list($classname, $is_interface) = extract_class_name($xpath, $file);
if (empty($classname)) {
// no usual class synopsis found inside the file, just skip this class
continue;
}
$fields = extract_class_fields($xpath, $classname, $file);
$methods = extract_class_methods($xpath, $classname, $file);
$extension_name = get_extension_name($file, $extensions);
if ($extension_name === null){
continue;
}
if (!isset($class_signatures[$extension_name][$classname])) {
if ($is_interface) {
if (!isset($interface_signatures[$extension_name])) {
$interface_signatures[$extension_name] = array();
}
$interface_signatures[$extension_name][$classname] = array(
'constants' => $fields['constants'],
'properties' => $fields['properties'],
'static_properties' => $fields['static_properties'],
'methods' => $methods['methods'],
'static_methods' => $methods['static_methods'],
);
} else {
if (!isset($class_signatures[$extension_name])) {
$class_signatures[$extension_name] = array();
}
$class_signatures[$extension_name][$classname] = array(
'constants' => $fields['constants'],
'properties' => $fields['properties'],
'static_properties' => $fields['static_properties'],
'methods' => $methods['methods'],
'static_methods' => $methods['static_methods'],
);
}
} else {
// there are some duplicate class names in extensions, use only the first one
}
}
return array($class_signatures, $interface_signatures);
}
function extract_class_fields($xpath, $classname, $file) {
$re = array(
'constants' => array(),
'properties' => array(),
'static_properties' => array(),
);
$field_nodes = $xpath->query('//div[@class="classsynopsis"]//div[contains(@class, "fieldsynopsis")]');
foreach ($field_nodes as $field_node) {
// fields look like: <var class="varname"><a href="">$<var class="varname">y</var></a></var>
$property_node = $xpath->query('var[@class="varname"]//var[@class="varname"]/..', $field_node);
if ($property_node->length) {
$property_info = handle_class_property($xpath, $field_node, $file);
if (in_array('static', $property_info['modifiers'])) {
$re['static_properties'][$property_info['name']] = $property_info;
} else {
$re['properties'][$property_info['name']] = $property_info;
}
continue;
}
// constants look like: <var class="fieldsynopsis_varname"><a href="#"><var class="varname">W3C</var></a></var>
$constant_node = $xpath->query('*[@class="modifier" and text() = "const"]/..', $field_node);
if ($constant_node->length) {
$constant_info = handle_class_const($xpath, $field_node, $file);
$re['constants'][$constant_info['name']] = $constant_info;
continue;
}
}
array_map('ksort', $re);
return $re;
}
function extract_class_methods($xpath, $classname, $file) {
$re = array(
'methods' => array(),
'static_methods' => array(),
);
$method_nodes = $xpath->query('//div[@class="classsynopsis"]//div[contains(@class, "constructorsynopsis") or contains(@class, "methodsynopsis")]');
foreach ($method_nodes as $method_node) {
$method_info = handle_method_def($xpath, $classname, $method_node, $file);
if ($method_info === null) {
continue;
}
if (in_array('static', $method_info['modifiers'])) {
$re['static_methods'][$method_info['name']] = $method_info;
} else {
$re['methods'][$method_info['name']] = $method_info;
}
}
array_map('ksort', $re);
return $re;
}
function handle_method_def($xpath, $classname, $node, $file) {
$re = array(
'name' => '',
'return_type' => '',
'modifiers' => array(),
'params' => array(),
);
$type = $xpath->query('*[@class="type"]', $node);
$methodparams = $xpath->query('*[@class="methodparam"]', $node);
$name = $xpath->query('*[@class="methodname"]/*[@class="methodname"]', $node);
if ($name->length === 0) {
// methods that don't have manual pages will look like <span class="methodname"><strong> ... </strong></span>
$name = $xpath->query('*[@class="methodname"]/strong', $node);
// if even that failed, just give up
if ($name->length === 0) {
var_dump($node->textContent);
fwrite(STDERR, "\nextraction error, cant find method name in $file\n");
exit;
}
}
// chop of class name from the inherited method names
$name = preg_replace('/^[\w\\\\]+::/', '', trim($name->item(0)->textContent));
$re['name'] = $name;
// constructors and destructors dont have return types
if ($type->length === 0 && !($name == '__construct' || $name == '__destruct' || $name == '__wakeup' || $name == $classname)) {
// var_dump($name);
// var_dump($xpath->document->saveHTML($node));
fwrite(STDERR, "WARNING: extraction error, cant find return type in $file\n");
return null;
}
$re['return_type'] = $type->length ? trim($type->item(0)->textContent) : null;
$modifiers = $xpath->query('*[@class="modifier"]', $node);
foreach ($modifiers as $modifier) {
$re['modifiers'][] = trim($modifier->textContent);
}
$params = array();
$optional = false;
foreach ($methodparams as $param_node) {
if (!$optional
&& $param_node->previousSibling->nodeType == XML_TEXT_NODE
&& strpos($param_node->previousSibling->textContent, '[') !== false) {
$optional = true;
}
$paramtype = $xpath->query('*[@class="type"]', $param_node);
$paramname = $xpath->query('*[contains(@class, "parameter")]', $param_node);
$paramdefault = $xpath->query('*[@class="initializer"]', $param_node);
if ($paramname->length) {
// regular parameter
$param = array(
'type' => trim($paramtype->item(0)->textContent),
'name' => trim($paramname->item(0)->textContent),
'optional' => $optional,
);
if ($paramdefault->length) {
$param['default'] = trim($paramdefault->item(0)->textContent, "=\n\r ");
$param['optional'] = $optional;
}
$params[] = $param;
}
}
$re['params'] = $params;
return $re;
}
function extract_class_name($xpath) {
$is_interface = false;
$class = $xpath->query('//div[@class="classsynopsis"]/div[@class="classsynopsisinfo"]/*[@class="ooclass"]/*[@class="classname"]')->item(0);
if (!$class) {
return array(false, $is_interface);
}
$classname = trim($class->textContent);
$title = $xpath->query('//div[@class="classsynopsis"]/preceding-sibling::h2[@class="title"]')->item(0);
if ($title && stripos(trim($title->textContent), 'interface') === 0) {
$is_interface = true;
}
$title2 = $xpath->query('//div[@class="reference"]/h1[@class="title"]')->item(0);
if ($title2 && preg_match('/interface$/i', trim($title2->textContent))) {
$is_interface = true;
}
return array($classname, $is_interface);
}
function handle_class_property($xpath, $node, $file) {
$re = array(
'name' => '',
'modifiers' => array(),
'initializer' => '',
'type' => '',
);
$type = $xpath->query('*[@class="type"]', $node)->item(0);
if ($type) {
$re['type'] = trim($type->textContent);
}
$initializer = $xpath->query('*[@class="initializer"]', $node)->item(0);
if ($initializer) {
$re['initializer'] = trim($initializer->textContent, "= ");
}
$modifiers = $xpath->query('*[@class="modifier"]', $node);
foreach ($modifiers as $modifier) {
$re['modifiers'][] = trim($modifier->textContent);
}
$name = $xpath->query('var[@class="varname"]', $node)->item(0);
if (!$name) {
print $xpath->document->saveHTML($node);
fwrite(STDERR, "\nextraction error, cant find field name in $file\n");
exit;
}
if (in_array('static', $re['modifiers'])) {
$re['name'] = trim($name->textContent);
} else {
$re['name'] = trim($name->textContent, '$ ');
}
return $re;
}
function handle_class_const($xpath, $node, $file) {
$re = array(
'name' => '',
'initializer' => '',
);
$name = $xpath->query('var//var[@class="varname"]', $node)->item(0);
if (!$name) {
print $xpath->document->saveHTML($node);
fwrite(STDERR, "\nextraction error, cant find const name in $file\n");
exit;
}
$re['name'] = trim($name->textContent);
$initializer = $xpath->query('*[@class="initializer"]', $node)->item(0);
if ($initializer) {
$re['initializer'] = trim($initializer->textContent, "= ");
}
return $re;
}
function write_class_signatures_to_vim_hash($signatures, $outpath, $keyname, $enabled_extensions = null, $prettyprint = true) {
$fd = fopen($outpath, 'a');
if (!empty($enabled_extensions)) {
$enabled_extensions = array_flip($enabled_extensions);
}
foreach ($signatures as $extension_name => $classes) {
if (empty($classes)) {
continue;
}
if ($enabled_extensions && !isset($enabled_extensions[filenameize($extension_name)])) {
continue;
}
if ($prettyprint) {
fwrite($fd, "let g:phpcomplete_builtin['".$keyname."']['".filenameize($extension_name)."'] = {\n");
} else {
fwrite($fd, "let g:phpcomplete_builtin['".$keyname."']['".filenameize($extension_name)."']={");
}
foreach ($classes as $classname => $class_info) {
if ($prettyprint) {
fwrite($fd, "\\'".strtolower($classname)."': {\n");
} else {
fwrite($fd, "'".strtolower($classname)."':{");
}
if ($prettyprint) {
fwrite($fd, "\\ 'name': '".vimstring_escape($classname)."',\n");
} else {
fwrite($fd, "'name':'".vimstring_escape($classname)."',");
}
if (!empty($class_info['constants'])) {
if ($prettyprint) {
fwrite($fd, "\\ 'constants': {\n");
} else {
fwrite($fd, "'constants':{");
}
foreach ($class_info['constants'] as $constant => $constant_info) {
if ($prettyprint) {
fwrite($fd, "\\ '{$constant}': '".vimstring_escape($constant_info['initializer'])."',\n");
} else {
fwrite($fd, "'{$constant}':'".vimstring_escape($constant_info['initializer'])."',");
}
}
// closing constants
if ($prettyprint) {
fwrite($fd, "\\ },\n");
} else {
fwrite($fd, "},");
}
}
if (!empty($class_info['properties'])) {
if ($prettyprint) {
fwrite($fd, "\\ 'properties': {\n");
} else {
fwrite($fd, "'properties': {");
}
foreach ($class_info['properties'] as $property => $property_info) {
if ($prettyprint) {
fwrite($fd, "\\ '{$property}': { 'initializer': '".vimstring_escape($property_info['initializer'])."', 'type': '".vimstring_escape($property_info['type'])."'},\n");
} else {
fwrite($fd, "'{$property}':{'initializer':'".vimstring_escape($property_info['initializer'])."','type':'".vimstring_escape($property_info['type'])."'},");
}
}
// closing properties
if ($prettyprint) {
fwrite($fd, "\\ },\n");
} else {
fwrite($fd, "},");
}
}
if (!empty($class_info['static_properties'])) {
if ($prettyprint) {
fwrite($fd, "\\ 'static_properties': {\n");
} else {
fwrite($fd, "'static_properties':{");
}
foreach ($class_info['static_properties'] as $property => $property_info) {
if ($prettyprint) {
fwrite($fd, "\\ '{$property}': { 'initializer': '".vimstring_escape($property_info['initializer'])."', 'type': '".vimstring_escape($property_info['type'])."'},\n");
} else {
fwrite($fd, "'{$property}':{ 'initializer':'".vimstring_escape($property_info['initializer'])."','type':'".vimstring_escape($property_info['type'])."'},");
}
}
// closing static_properties
if ($prettyprint) {
fwrite($fd, "\\ },\n");
} else {
fwrite($fd, "},");
}
}
if (!empty($class_info['methods'])) {
if ($prettyprint) {
fwrite($fd, "\\ 'methods': {\n");
} else {
fwrite($fd, "'methods':{");
}
foreach ($class_info['methods'] as $methodname => $method_info) {
if ($prettyprint) {
fwrite($fd, "\\ '{$methodname}': { 'signature': '".format_method_signature($method_info)."', 'return_type': '".vimstring_escape($method_info['return_type'])."'},\n");
} else {
fwrite($fd, "'{$methodname}':{'signature':'".format_method_signature($method_info)."','return_type':'".vimstring_escape($method_info['return_type'])."'},");
}
}
// closing methods
if ($prettyprint) {
fwrite($fd, "\\ },\n");
} else {
fwrite($fd, "},");
}
}
if (!empty($class_info['static_methods'])) {
if ($prettyprint) {
fwrite($fd, "\\ 'static_methods': {\n");
} else {
fwrite($fd, "'static_methods':{");
}
foreach ($class_info['static_methods'] as $methodname => $method_info) {
if ($prettyprint) {
fwrite($fd, "\\ '{$methodname}': { 'signature': '".format_method_signature($method_info)."', 'return_type': '".vimstring_escape($method_info['return_type'])."'},\n");
} else {
fwrite($fd, "'{$methodname}':{'signature':'".format_method_signature($method_info)."','return_type':'".vimstring_escape($method_info['return_type'])."'},");
}
}
// closing static_methods
if ($prettyprint) {
fwrite($fd, "\\ },\n");
} else {
fwrite($fd, "},");
}
}
// closing the class
if ($prettyprint) {
fwrite($fd, "\\},\n");
} else {
fwrite($fd, "},");
}
}
// closing the extension
if ($prettyprint) {
fwrite($fd, "\\}\n");
} else {
fwrite($fd, "}\n");
}
}
fclose($fd);
}

View File

@ -0,0 +1,115 @@
<?php
function extract_constant_names($files, $extensions) {
$constants = array();
$class_constants = array();
foreach ($files as $file) {
$doc = new DOMDocument;
$doc->loadHTMLFile($file);
$xpath = new DOMXpath($doc);
// Unfortunately, the constatns are not marked with classes in code,
// only a <strong><code>UPPERCASE_LETTER</code></strong> seem to be universal among them
// xpath1 doesn't have uppercase so but fortunetly the alphabet is pretty limited
// so translate() will do for uppercasing content so we only select full uppercased contents
$nodes = $xpath->query('//strong/code[translate(text(), "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ") = text()]');
foreach ($nodes as $node) {
// regexp lifted from http://php.net/manual/en/language.constants.php added ":" so we can pick up class constants
if (preg_match('/^[a-zA-Z_\x7f-\xff][:a-zA-Z0-9_\x7f-\xff]*$/', trim($node->textContent))) {
$constant = trim($node->textContent);
// these are so common they are in almost every file,
// to trim down the number of non-empty extensions we handle them elsewhere
if (strpos($constant, 'E_') === 0 || strpos($constant, '__') === 0 || in_array($constant, array('NULL', 'TRUE', 'FALSE'))) {
$constants['common'][$constant] = true;
continue;
}
$extension_name = get_extension_name($file, $extensions);
if ($extension_name === null){
continue;
}
if (strpos($constant, "::") !== false) {
if (!isset($class_constants[$extension_name])) {
$class_constants[$extension_name] = array();
}
$class_constants[$extension_name][$constant] = true;
} else {
if (!isset($constants[$extension_name])) {
$constants[$extension_name] = array();
}
$constants[$extension_name][$constant] = true;
}
}
}
}
return array($constants, $class_constants);
}
function inject_class_constants(&$class_groups, $class_constant_groups, $generate_warnings = true) {
// a lowercaseclassname => LowerCaseClassName map
$classnames = array();
foreach ($class_groups as $extension => $classes) {
$classnames = array_merge($classnames, array_combine(array_map('strtolower', array_keys($classes)), array_keys($classes)));
}
foreach ($class_constant_groups as $const_extension => $class_constants) {
foreach ($class_constants as $constant => $__not_used) {
list($classname, $constantname) = explode('::', $constant);
$lowercase_classname = strtolower($classname);
if (!isset($classnames[$lowercase_classname])) {
if ($generate_warnings) {
fwrite(STDERR, "\nNOTICE: can't place class constant: '{$constant}', no such class found: '{$classname} ({$lowercase_classname})'");
}
continue;
}
$classname = $classnames[$lowercase_classname];
foreach ($class_groups as $class_extension => $classes) {
if (isset($classes[$classname])) {
$class_groups[$class_extension][$classname]['constants'][$constantname] = array('initializer' => '');
continue 2;
}
}
// this line only reached if the previous loop fails to place the constatn
if ($generate_warnings) {
fwrite(STDERR, "\nNOTICE: can't place class constant: '{$constant}', no such class found: '{$classname}' 2");
}
}
}
}
function write_constant_names_to_vim_hash($constant_groups, $outpath, $keyname, $enabled_extensions = null, $prettyprint = true) {
$fd = fopen($outpath, 'a');
if (!empty($enabled_extensions)) {
$enabled_extensions = array_flip($enabled_extensions);
}
foreach ($constant_groups as $extension_name => $constants) {
if (empty($constants)) {
continue;
}
if ($enabled_extensions && !isset($enabled_extensions[filenameize($extension_name)])) {
continue;
}
if ($prettyprint) {
fwrite($fd, "let g:phpcomplete_builtin['".$keyname."']['".filenameize($extension_name)."'] = {\n");
} else {
fwrite($fd, "let g:phpcomplete_builtin['".$keyname."']['".filenameize($extension_name)."']={");
}
foreach ($constants as $constant => $__not_used) {
if ($prettyprint) {
fwrite($fd, "\\ '{$constant}': '',\n");
} else {
fwrite($fd, "'{$constant}':'',");
}
}
if ($prettyprint) {
fwrite($fd, "\\ }\n");
} else {
fwrite($fd, "}\n");
}
}
fclose($fd);
}

View File

@ -0,0 +1,180 @@
<?php
function extract_function_signatures($files, $extensions, $signatures = array()) {
foreach ($files as $file) {
$extension_name = get_extension_name($file, $extensions);
if ($extension_name === null){
continue;
}
if (!isset($signatures[$extension_name])) {
$signatures[$extension_name] = array();
}
$doc = new DOMDocument;
$doc->loadHTMLFile($file);
$xpath = new DOMXpath($doc);
$removed_warning = $xpath->query('//div[contains(@id, "-refsynopsisdiv")]/div[@class="warning"]');
if ($removed_warning->length > 0 && preg_match('/REMOVED\s+in\s+PHP\s+7\.\d+\.\d+/i', $removed_warning->item(0)->textContent)) {
continue;
}
$nodes = $xpath->query('//div[contains(@class, "methodsynopsis")]');
if ($nodes->length == 0) {
// no signature found, maybe its an alias?
$nodes = $xpath->query('//div[contains(@class, "description")]/p[@class="simpara"][contains(text(), "This function is an alias of:")]');
if ($nodes->length) {
$signatures[$extension_name][] = handle_func_alias($xpath, $nodes, $file);
}
} else if ($nodes->length == 1) {
if (!preg_match('/\w+::\w+/', $nodes->item(0)->textContent)) {
$signatures[$extension_name][] = handle_func_def($xpath, $nodes->item(0), $file);
} else {
fwrite(STDERR, "WARNING: Only class-like function definition found in ".$file."\n");
continue;
}
} else if ($nodes->length > 1) {
// more than one signature for a single function name
// maybe its a procedural style of a method like xmlwriter_text -> XMLWriter::text
// search for the first non object style synopsis and extract from that
foreach ($nodes as $node) {
if (!preg_match('/\w+::\w+/', $node->textContent)) {
$signatures[$extension_name][] = handle_func_def($xpath, $node, $file);
break;
}
}
}
}
return $signatures;
}
function list_procedural_style_files($dir) {
$files = array();
$dir = rtrim($dir, '/');
$dh = opendir($dir);
$doc = new DOMDocument();
while (false !== ($filename = readdir($dh))) {
if (preg_match('/\.html$/', $filename)) {
$doc->loadHTMLFile($dir.'/'.$filename);
$xpath = new DOMXPath($doc);
$nodes = $xpath->query('//p[contains(@class, "para") and contains(translate(text(), "P", "p"), "procedural style")]');
if ($nodes && $nodes->length !== 0) {
$files[] = $dir.'/'.$filename;
}
}
}
return array_unique($files);
}
function handle_func_def($xpath, $nodes, $file) {
$type = $xpath->query('span[@class="type"]', $nodes);
$methodname = $xpath->query('*[@class="methodname"]/*', $nodes);
$methodparams = $xpath->query('*[@class="methodparam"]', $nodes);
if ($type->length === 0) {
fwrite(STDERR, "WARNING: can't find return type in ".$file."\n");
$return_type = 'void';
} else {
$return_type = trim($type->item(0)->textContent);
}
if ($methodname->length === 0) {
fwrite(STDERR, "Extraction error, can't find method name in ".$file."\n");
exit;
}
$params = array();
$optional = false;
foreach ($methodparams as $param) {
if (!$optional
&& $param->previousSibling->nodeType == XML_TEXT_NODE
&& strpos($param->previousSibling->textContent, '[') !== false) {
$optional = true;
}
$paramtype = $xpath->query('*[@class="type"]', $param);
$paramname = $xpath->query('*[contains(@class, "parameter")]', $param);
$paramdefault = $xpath->query('*[@class="initializer"]', $param);
if ($paramname->length) {
// regular parameter
$p = array(
'type' => $paramtype->item(0)->textContent,
'name' => $paramname->item(0)->textContent,
'optional' => $optional,
);
if ($paramdefault->length) {
$p['default'] = trim($paramdefault->item(0)->textContent, "=\r\n ");
$p['optional'] = true;
}
$params[] = $p;
}
}
$full_signature = preg_replace('/\s+/', ' ', trim(str_replace(array("\n", "\t", "\r"), "", $nodes->textContent)));
return array(
'type' => 'function',
'full_signature' => $full_signature,
'return_type' => $return_type,
'name' => trim($methodname->item(0)->textContent),
'params' => $params
);
}
function handle_func_alias($xpath, $nodes, $file) {
$methodname = $xpath->query('//h1[@class="refname"]');
$refname = $xpath->query('//*[contains(@class, "description")]/p[@class="simpara"]/*[@class="methodname" or @class="function"]');
$name = trim(str_replace("\n", '', $methodname->item(0)->textContent));
$aliased_name = trim(str_replace("\n", '', $refname->item(0)->textContent));
$full_signature = "$name — Alias of $aliased_name";
return array(
'type' => 'alias',
'full_signature' => $full_signature,
'name' => $name,
'aliased_name' => $aliased_name,
);
}
function write_function_signatures_to_vim_hash($signatures, $outpath, $keyname, $enabled_extensions = null, $prettyprint = true) {
$fd = fopen($outpath, 'a');
if (!empty($enabled_extensions)) {
$enabled_extensions = array_flip($enabled_extensions);
}
foreach ($signatures as $extension_name => $functions) {
if (empty($functions)) {
continue;
}
if ($enabled_extensions && !isset($enabled_extensions[filenameize($extension_name)])) {
continue;
}
// weed out duplicates, (like nthmac) only keep the first occurance
$functions = array_index_by_col($functions, 'name', false);
if ($prettyprint) {
fwrite($fd, "let g:phpcomplete_builtin['".$keyname."']['".filenameize($extension_name)."'] = {\n");
} else {
fwrite($fd, "let g:phpcomplete_builtin['".$keyname."']['".filenameize($extension_name)."']={");
}
foreach ($functions as $function) {
if ($function['type'] == 'function') {
if ($prettyprint) {
fwrite($fd, "\\ '{$function['name']}(': '".format_method_signature($function)."',\n");
} else {
fwrite($fd, "'{$function['name']}(':'".format_method_signature($function)."',");
}
} else if ($function['type'] == 'alias') {
if ($prettyprint) {
fwrite($fd, "\\ '{$function['name']}(': '".vimstring_escape($function['full_signature'])."',\n");
} else {
fwrite($fd, "'{$function['name']}(':'".vimstring_escape($function['full_signature'])."',");
}
} else {
fwrite(STDERR, 'unknown signature type '.var_export($function, true));
exit;
}
}
if ($prettyprint) {
fwrite($fd, "\\ }\n");
} else {
fwrite($fd, "}\n");
}
}
fclose($fd);
}

View File

@ -0,0 +1,135 @@
<?php
function format_method_signature($signature) {
$optional_depth = 0;
$istr = '';
if (empty($signature['params'])) {
// "__construct"s have no return type, they dont need the " |" at the end
return 'void'.($signature['return_type'] ? ' | '.$signature['return_type'] : '');
}
foreach ($signature['params'] as $i => $param) {
if ($param['optional'] || isset($param['default']) || $optional_depth != 0) {
++$optional_depth;
if ($i != 0) {
$istr .= ' [, ';
} else {
$istr .= '[ ';
}
} elseif ($i != 0) {
$istr .= ', ';
}
$istr .= $param['type'];
$istr .= ' ';
$istr .= $param['name'];
if (isset($param['default'])) {
$istr .= ' = '.vimstring_escape($param['default']);
}
}
$istr .= str_repeat(']', $optional_depth);
if ($signature['return_type']) {
$istr .= ' | '.$signature['return_type'];
}
return trim($istr);
}
function get_extension_names($docs_dir) {
$re = array();
$doc = new DOMDocument('1.0', 'utf-8');
$doc->loadHTMLFile($docs_dir.'/extensions.membership.html');
$xpath = new DOMXPath($doc);
$links_nodes = $xpath->query('//ul[@class="itemizedlist"]//a[@class="xref"]');
foreach ($links_nodes as $link_node) {
$re[$link_node->getAttribute('href')] = $link_node->textContent;
}
$doc = new DOMDocument('1.0', 'utf-8');
@$doc->loadHTMLFile($docs_dir.'/funcref.html');
$xpath = new DOMXPath($doc);
$link_nodes = $xpath->query('//ul[@class="chunklist chunklist_set chunklist_children"]/li/a');
foreach ($link_nodes as $link_node) {
$re[$link_node->getAttribute('href')] = $link_node->textContent;
}
foreach (array('langref.html', 'appendices.html', 'features.html') as $file) {
$doc = new DOMDocument('1.0', 'utf-8');
$doc->loadHTMLFile($docs_dir.'/'.$file);
$xpath = new DOMXPath($doc);
$category_nodes = $xpath->query('//ul[@class="chunklist chunklist_book"]/li');
foreach ($category_nodes as $category_node) {
$category_name_node = $xpath->query('a', $category_node)->item(0);
$category_name = trim($category_name_node->textContent);
$re[$category_name_node->getAttribute('href')] = $category_name;
$link_nodes = $xpath->query('ul[@class="chunklist chunklist_book chunklist_children"]/li/a', $category_node);
if ($link_nodes->length > 0) {
foreach ($link_nodes as $link_node) {
// save sub-category file names under the category name
$re[$link_node->getAttribute('href')] = $category_name;
}
}
}
}
return $re;
}
function get_extension_name($file, $extensions) {
$doc_dir = dirname($file);
$current_file = basename($file);
$files_checked = array();
do {
if (isset($extensions[$current_file])) {
return $extensions[$current_file];
}
$doc = new DOMDocument;
$doc->loadHTMLFile($doc_dir.'/'.$current_file);
$xpath = new DOMXPath($doc);
$up_link = $xpath->query('//ul[@class="breadcrumbs-container"]/li[position()>=2 and position() <= (last() - 1)]/a');
if ($up_link->length == 0) {
fwrite(STDERR, "\nWARNING: Can't find up link in ".$current_file.' started ascending from '.$file);
return null;
}
$up_href = $up_link->item(0)->getAttribute('href');
if ($current_file == $up_href) {
fwrite(STDERR, "\nWARNING: up link traversal got stuck at ".$current_file." started ascending from ".$file);
return null;
}
$files_checked[] = $current_file;
$current_file = $up_href;
} while ($current_file != 'index.html');
fwrite(STDERR, "\nNOTICE: Can't find extension name for ".$file." files checked: ".join(", ", $files_checked));
return '_unknow';
}
function array_index_by_col($arr, $col, $overwrite_duplicate = true) {
$tmp = array();
foreach ($arr as $i) {
if (!isset($tmp[$i[$col]]) || $overwrite_duplicate) {
$tmp[$i[$col]] = $i;
}
}
return $tmp;
}
function vimstring_escape($str) {
return str_replace("'", "''", $str);
}
function filenameize($str) {
$clean = preg_replace('/[^a-zA-Z0-9\/_|+ -]/', '', $str);
$clean = strtolower(trim($clean, '_'));
$clean = preg_replace('/[\/_|+ -]+/', '_', $clean);
return $clean;
}

View File

@ -0,0 +1,67 @@
" Vim completion plugin
" Language: PHP
" Maintainer: Szabó Dávid ( complex857 AT gmail DOT com )
"
" OPTIONS:
" let g:phpcomplete_enhance_jump_to_definition = 1/0 [default 1]
" When enabled the <C-]> and <C-W><C-]> (see g:phpcomplete_mappings)
" will be mapped to phpcomplete#JumpToDefinition() which will try to
" make a more educated guess of the current symbol's location than simple
" tag search. If the symbol's location cannot be found the original
" <C-]> or <C-W><C-]> functionality will be invoked
"
" let g:phpcomplete_mappings = {..}
" Defines the mappings for the enhanced jump-to-definition.
" Keys:
" jump_to_def: Jumps to the definition in the current buffer
" jump_to_def_split: Jumps to the definition in a new split buffer
" jump_to_def_vsplit: Jumps to the definition in a new vertical split buffer
"
" You change any of them like this in your vimrc:
" let g:phpcomplete_mappings = {
" \ 'jump_to_def': ',g',
" \ }
"
" The keys you don't specify will be mapped to the defaults:
" let g:phpcomplete_mappings = {
" \ 'jump_to_def': '<C-]>',
" \ 'jump_to_def_split': '<C-W><C-]>',
" \ 'jump_to_def_vsplit': '<C-W><C-\>',
" \}
"
"
let s:save_cpo = &cpo
set cpo&vim
let g:phpcomplete_enhance_jump_to_definition = get(g:, 'phpcomplete_enhance_jump_to_definition', 1)
let g:phpcomplete_mappings = extend({
\ 'jump_to_def': '<C-]>',
\ 'jump_to_def_split': '<C-W><C-]>',
\ 'jump_to_def_vsplit': '<C-W><C-\>',
\ 'jump_to_def_tabnew': '<C-W><C-[>',
\}, get(g:, 'phpcomplete_mappings', {}))
if g:phpcomplete_enhance_jump_to_definition
if '' == mapcheck(g:phpcomplete_mappings['jump_to_def'])
silent! exe "nnoremap <silent> <unique> <buffer> ".g:phpcomplete_mappings['jump_to_def']." :<C-u>call phpcomplete#JumpToDefinition('normal')<CR>"
silent! exe "vnoremap <silent> <unique> <buffer> ".g:phpcomplete_mappings['jump_to_def']." :<C-u>call phpcomplete#JumpToDefinition('normal')<CR>"
endif
if '' == mapcheck(g:phpcomplete_mappings['jump_to_def_split'])
silent! exe "nnoremap <silent> <unique> <buffer> ".g:phpcomplete_mappings['jump_to_def_split']." :<C-u>call phpcomplete#JumpToDefinition('split')<CR>"
silent! exe "vnoremap <silent> <unique> <buffer> ".g:phpcomplete_mappings['jump_to_def_split']." :<C-u>call phpcomplete#JumpToDefinition('split')<CR>"
endif
if '' == mapcheck(g:phpcomplete_mappings['jump_to_def_vsplit'])
silent! exe "nnoremap <silent> <unique> <buffer> ".g:phpcomplete_mappings['jump_to_def_vsplit']." :<C-u>call phpcomplete#JumpToDefinition('vsplit')<CR>"
silent! exe "vnoremap <silent> <unique> <buffer> ".g:phpcomplete_mappings['jump_to_def_vsplit']." :<C-u>call phpcomplete#JumpToDefinition('vsplit')<CR>"
endif
if '' == mapcheck(g:phpcomplete_mappings['jump_to_def_tabnew'])
silent! exe "nnoremap <silent> <unique> <buffer> ".g:phpcomplete_mappings['jump_to_def_tabnew']." :<C-u>call phpcomplete#JumpToDefinition('tabnew')<CR>"
silent! exe "vnoremap <silent> <unique> <buffer> ".g:phpcomplete_mappings['jump_to_def_tabnew']." :<C-u>call phpcomplete#JumpToDefinition('tabnew')<CR>"
endif
endif
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: foldmethod=marker:noexpandtab:ts=4:sts=4:sw=4

View File

@ -0,0 +1,464 @@
Available function extensions:
math
strings
apache
apc
apcu
apd
arrays
php_options_info
classes_objects
urls
filesystem
bbcode
bc_math
bcompiler
gettext
blenc
variable_handling
mongo
bzip2
cairo
calendar
function_handling
chdb
directories
date_time
network
spl
classkit
com
commonmark
misc
crack
ctype
cubrid
curl
cyrus
ibm_db2
dba
dbase
db_
dbx
error_handling
zlib
direct_io
dom
eio
enchant
posix_regex
program_execution
libevent
exif
expect
mail
fam
fann
fastcgi_process_manager
firebird_interbase
frontbase
fdf
filepro
filter
fileinfo
output_control
fribidi
semaphore
ftp
gd
geoip
gmp
gnupg
gopher
intl
gupnp
hash
hyperwave_api
iconv
id3
informix
iis
imap
control_structures
inclued
ingres
inotify
soap
taint
json
judy
kadm5
ldap
libxml
lzf
mcve
mailparse
maxdb
multibyte_string
mcrypt
memcache
mhash
ming
vendor_specific_database_extensions
mqseries
msession
msql
mssql
mysql_original
mysqli
mysqlnd_memcache
mysqlnd_ms
mysqlnd_qc
mysqlnd_uh
ncurses
newt
nsapi
oauth
tidy
oci8
odbc
opcache
openal
openssl
parsekit
password_hashing
pcntl
pdf
postgresql
phpdbg
posix
pcre
ps
pspell
paradox
radius
csprng
rar
readline
recode
rpm_reader
rrd
runkit
seaslog
sessions
session_pgsql
streams
proctitle
shared_memory
simplexml
snmp
sockets
sodium
solr
sqlite
sqlsrv
ssdeep
ssh2
statistics
stomp
svn
swoole
sybase
tcp
tokenizer
trader
mnogosearch
ui
uopz
xml_parser
vpopmail
wddx
win32service
win32ps
wincache
xattr
xdiff
xhprof
xml_rpc
xmlwriter
yaml
yaz
yp_nis
zip
zookeeper
Available Class extensions:
oci8
apc
apcu
spl
predefined_exceptions
cairo
chdb
predefined_interfaces_and_classes
intl
com
commonmark
componere
pthreads
curl
date_time
directories
dom
data_structures
ev
event
fann
ffi
fileinfo
gearman
gender
gmagick
gmp
haru
hash
hrtime
imagemagick
json
judy
ktaglib
lapack
libxml
lua
luasandbox
memcache
memcached
mongo
vendor_specific_database_extensions
mysqli
mysqlnd_uh
oauth
parallel
parle
pdo
phar
phdfs
streams
pht
quickhash
rar
reflection
rrd
seaslog
sessions
simplexml
snmp
soap
solr
sphinx
spl_types
sqlite3
stomp
svm
ming
swoole
sync
tidy
tokyo_tyrant
ui
v8js
varnish
xlswriter
weakref
wkhtmltox
xmldiff
xmlreader
xsl
yaconf
yaf
yar
zip
0mq_messaging
zookeeper
Available Interface extensions:
predefined_interfaces_and_classes
pthreads
commonmark
spl
date_time
data_structures
json
mongo
vendor_specific_database_extensions
pht
reflection
sessions
Available Constant extensions:
common
apc
apcu
apd
arrays
bbcode
blenc
cairo
calendar
oci8
curl
date_time
ev
event
json
libxml
vendor_specific_database_extensions
mysqli
oauth
rar
spl
snmp
tidy
classkit
com
dbx
newt
context_options_and_parameters
cyrus
dbase
db_
direct_io
directories
dom
eio
enchant
exif
expect
fann
frontbase
fdf
command_line_usage
handling_file_uploads
fileinfo
filesystem
filter
fribidi
ftp
php_options_info
strings
cubrid
ibm_db2
error_handling
math
network
zlib
posix_regex
libevent
gmp
gnupg
gupnp
hash
urls
firebird_interbase
iconv
id3
intl
informix
gd
imap
ingres
inotify
kadm5
ldap
maxdb
multibyte_string
mcrypt
semaphore
msql
mssql
mysql_original
mysqlnd_ms
mysqlnd_qc
ncurses
output_control
odbc
openal
openssl
parsekit
password_hashing
pcntl
postgresql
posix
pcre
program_execution
pspell
paradox
radius
csprng
runkit
misc
sessions
variable_handling
sockets
sodium
sqlite
sqlsrv
ssh2
streams
svn
tokenizer
mnogosearch
uopz
win32service
xattr
xdiff
xhprof
xml_parser
yaml
gearman
geoip
hyperwave_api
iis
imagemagick
phpini_directives
mhash
types
luasandbox
mailparse
mcve
memcache
migrating_from_php_4_to_php_50x
migrating_from_php_50x_to_php_51x
migrating_from_php_51x_to_php_52x
migrating_from_php_52x_to_php_53x
migrating_from_php_53x_to_php_54x
migrating_from_php_54x_to_php_55x
migrating_from_php_55x_to_php_56x
migrating_from_php_56x_to_php_70x
migrating_from_php_70x_to_php_71x
migrating_from_php_71x_to_php_72x
migrating_from_php_72x_to_php_73x
ming
mongo
mysqlnd_memcache
mysqlnd_mux
mysqlnd_uh
mysqlnd
gopher
yp_nis
oggvorbis
pdo
phdfs
phpdbg
pthreads
readline
mysql_pdo
odbc_and_db2_pdo
reflection
list_of_reserved_words
rpm_reader
sam
seaslog
soap
solr
sphinx
sqlite3
swoole
list_of_parser_tokens
trader
php_type_comparison_tables
varnish
supported_protocols_and_wrappers
xsl
yaf
yar

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,57 @@
let g:phpcomplete_builtin['classes']['xmlwriter'] = {
\'xmlwriter': {
\ 'name': 'XMLWriter',
\ 'constants': {
\ },
\ 'properties': {
\ },
\ 'static_properties': {
\ },
\ 'methods': {
\ 'endAttribute': { 'signature': 'void | bool', 'return_type': 'bool'},
\ 'endCData': { 'signature': 'void | bool', 'return_type': 'bool'},
\ 'endComment': { 'signature': 'void | bool', 'return_type': 'bool'},
\ 'endDocument': { 'signature': 'void | bool', 'return_type': 'bool'},
\ 'endDTDAttlist': { 'signature': 'void | bool', 'return_type': 'bool'},
\ 'endDTDElement': { 'signature': 'void | bool', 'return_type': 'bool'},
\ 'endDTDEntity': { 'signature': 'void | bool', 'return_type': 'bool'},
\ 'endDTD': { 'signature': 'void | bool', 'return_type': 'bool'},
\ 'endElement': { 'signature': 'void | bool', 'return_type': 'bool'},
\ 'endPI': { 'signature': 'void | bool', 'return_type': 'bool'},
\ 'flush': { 'signature': '[bool $empty = true] | bool', 'return_type': 'bool'},
\ 'fullEndElement': { 'signature': 'void | bool', 'return_type': 'bool'},
\ 'openMemory': { 'signature': 'void | bool', 'return_type': 'bool'},
\ 'openURI': { 'signature': 'string $uri | bool', 'return_type': 'bool'},
\ 'outputMemory': { 'signature': '[bool $flush = true] | bool', 'return_type': 'bool'},
\ 'setIndentString': { 'signature': 'string $indentString | bool', 'return_type': 'bool'},
\ 'setIndent': { 'signature': 'bool $indent | bool', 'return_type': 'bool'},
\ 'startAttributeNS': { 'signature': 'string $prefix, string $name, string $uri | bool', 'return_type': 'bool'},
\ 'startAttribute': { 'signature': 'string $name | bool', 'return_type': 'bool'},
\ 'startCData': { 'signature': 'void | bool', 'return_type': 'bool'},
\ 'startComment': { 'signature': 'void | bool', 'return_type': 'bool'},
\ 'startDocument': { 'signature': '[string $version = 1.0 [, string $encoding = NULL [, string $standalone ]]] | bool', 'return_type': 'bool'},
\ 'startDTDAttlist': { 'signature': 'string $name | bool', 'return_type': 'bool'},
\ 'startDTDElement': { 'signature': 'string $qualifiedName | bool', 'return_type': 'bool'},
\ 'startDTDEntity': { 'signature': 'string $name, bool $isparam | bool', 'return_type': 'bool'},
\ 'startDTD': { 'signature': 'string $qualifiedName [, string $publicId [, string $systemId ]] | bool', 'return_type': 'bool'},
\ 'startElementNS': { 'signature': 'string $prefix, string $name, string $uri | bool', 'return_type': 'bool'},
\ 'startElement': { 'signature': 'string $name | bool', 'return_type': 'bool'},
\ 'startPI': { 'signature': 'string $target | bool', 'return_type': 'bool'},
\ 'text': { 'signature': 'string $content | bool', 'return_type': 'bool'},
\ 'writeAttributeNS': { 'signature': 'string $prefix, string $name, string $uri, string $content | bool', 'return_type': 'bool'},
\ 'writeAttribute': { 'signature': 'string $name, string $value | bool', 'return_type': 'bool'},
\ 'writeCData': { 'signature': 'string $content | bool', 'return_type': 'bool'},
\ 'writeComment': { 'signature': 'string $content | bool', 'return_type': 'bool'},
\ 'writeDTDAttlist': { 'signature': 'string $name, string $content | bool', 'return_type': 'bool'},
\ 'writeDTDElement': { 'signature': 'string $name, string $content | bool', 'return_type': 'bool'},
\ 'writeDTDEntity': { 'signature': 'string $name, string $content, bool $pe, string $pubid, string $sysid, string $ndataid | bool', 'return_type': 'bool'},
\ 'writeDTD': { 'signature': 'string $name [, string $publicId [, string $systemId [, string $subset ]]] | bool', 'return_type': 'bool'},
\ 'writeElementNS': { 'signature': 'string $prefix, string $name, string $uri [, string $content ] | bool', 'return_type': 'bool'},
\ 'writeElement': { 'signature': 'string $name [, string $content ] | bool', 'return_type': 'bool'},
\ 'writePI': { 'signature': 'string $target, string $content | bool', 'return_type': 'bool'},
\ 'writeRaw': { 'signature': 'string $content | bool', 'return_type': 'bool'},
\ },
\ 'static_methods': {
\ },
\},
\}

View File

@ -0,0 +1,29 @@
require 'formula'
class CtagsBetterPhp < Formula
homepage 'http://ctags.sourceforge.net/'
url 'https://github.com/shawncplus/phpcomplete.vim/raw/master/misc/ctags-5.8_better_php_parser.tar.gz'
sha1 '24167d881f6c5827b96564d64c14ec9ee1b2273c'
def install
system "./configure", "--prefix=#{prefix}",
"--enable-macro-patterns",
"--mandir=#{man}",
"--with-readlib"
system "make install"
end
def caveats
<<-EOS.undent
Under some circumstances, emacs and ctags can conflict. By default,
emacs provides an executable `ctags` that would conflict with the
executable of the same name that ctags provides. To prevent this,
Homebrew removes the emacs `ctags` and its manpage before linking.
However, if you install emacs with the `--keep-ctags` option, then
the `ctags` emacs provides will not be removed. In that case, you
won't be able to install ctags successfully. It will build but not
link.
EOS
end
end

View File

@ -0,0 +1,133 @@
let g:php_keywords = {
\ 'PHP_SELF':'',
\ 'argv':'',
\ 'argc':'',
\ 'GATEWAY_INTERFACE':'',
\ 'SERVER_ADDR':'',
\ 'SERVER_NAME':'',
\ 'SERVER_SOFTWARE':'',
\ 'SERVER_PROTOCOL':'',
\ 'REQUEST_METHOD':'',
\ 'REQUEST_TIME':'',
\ 'QUERY_STRING':'',
\ 'DOCUMENT_ROOT':'',
\ 'HTTP_ACCEPT':'',
\ 'HTTP_ACCEPT_CHARSET':'',
\ 'HTTP_ACCEPT_ENCODING':'',
\ 'HTTP_ACCEPT_LANGUAGE':'',
\ 'HTTP_CONNECTION':'',
\ 'HTTP_POST':'',
\ 'HTTP_REFERER':'',
\ 'HTTP_USER_AGENT':'',
\ 'HTTPS':'',
\ 'REMOTE_ADDR':'',
\ 'REMOTE_HOST':'',
\ 'REMOTE_PORT':'',
\ 'SCRIPT_FILENAME':'',
\ 'SERVER_ADMIN':'',
\ 'SERVER_PORT':'',
\ 'SERVER_SIGNATURE':'',
\ 'PATH_TRANSLATED':'',
\ 'SCRIPT_NAME':'',
\ 'REQUEST_URI':'',
\ 'PHP_AUTH_DIGEST':'',
\ 'PHP_AUTH_USER':'',
\ 'PHP_AUTH_PW':'',
\ 'AUTH_TYPE':'',
\ 'and':'',
\ 'or':'',
\ 'xor':'',
\ '__FILE__':'',
\ 'exception':'',
\ '__LINE__':'',
\ 'as':'',
\ 'break':'',
\ 'case':'',
\ 'class':'',
\ 'const':'',
\ 'continue':'',
\ 'declare':'',
\ 'default':'',
\ 'do':'',
\ 'echo':'',
\ 'else':'',
\ 'elseif':'',
\ 'enddeclare':'',
\ 'endfor':'',
\ 'endforeach':'',
\ 'endif':'',
\ 'endswitch':'',
\ 'endwhile':'',
\ 'extends':'',
\ 'for':'',
\ 'foreach':'',
\ 'function':'',
\ 'global':'',
\ 'if':'',
\ 'new':'',
\ 'static':'',
\ 'switch':'',
\ 'use':'',
\ 'var':'',
\ 'while':'',
\ 'final':'',
\ 'php_user_filter':'',
\ 'interface':'',
\ 'implements':'',
\ 'public':'',
\ 'private':'',
\ 'protected':'',
\ 'abstract':'',
\ 'clone':'',
\ 'try':'',
\ 'catch':'',
\ 'throw':'',
\ 'cfunction':'',
\ 'old_function':'',
\ 'this':'',
\ 'INI_USER': '',
\ 'INI_PERDIR': '',
\ 'INI_SYSTEM': '',
\ 'INI_ALL': '',
\ 'ABDAY_1': '',
\ 'ABDAY_2': '',
\ 'ABDAY_3': '',
\ 'ABDAY_4': '',
\ 'ABDAY_5': '',
\ 'ABDAY_6': '',
\ 'ABDAY_7': '',
\ 'DAY_1': '',
\ 'DAY_2': '',
\ 'DAY_3': '',
\ 'DAY_4': '',
\ 'DAY_5': '',
\ 'DAY_6': '',
\ 'DAY_7': '',
\ 'ABMON_1': '',
\ 'ABMON_2': '',
\ 'ABMON_3': '',
\ 'ABMON_4': '',
\ 'ABMON_5': '',
\ 'ABMON_6': '',
\ 'ABMON_7': '',
\ 'ABMON_8': '',
\ 'ABMON_9': '',
\ 'ABMON_10': '',
\ 'ABMON_11': '',
\ 'ABMON_12': '',
\ 'MON_1': '',
\ 'MON_2': '',
\ 'MON_3': '',
\ 'MON_4': '',
\ 'MON_5': '',
\ 'MON_6': '',
\ 'MON_7': '',
\ 'MON_8': '',
\ 'MON_9': '',
\ 'MON_10': '',
\ 'MON_11': '',
\ 'MON_12': '',
\ 'AM_STR': '',
\ 'D_T_FMT': '',
\ 'ALT_DIGITS': '',
\ }

View File

@ -0,0 +1,76 @@
" Vim syntax file
" Language: PHP - only with strings and comments for the autocomplete plugin
" Maintainer: Dávid Szabó ( complex857 AT gmail DOT com )
" URL: https://github.com/shawncplus/phpcomplete.vim
" Thanks: Paul Garvin <paul@paulgarvin.net>
" Whos php.vim project where I've got all the code from.
if exists("b:current_syntax")
finish
endif
syn match phpSpecialChar +\\"+ contained display
syn match phpSpecialChar "\\\$" contained display
syn match phpStrEsc "\\\\" contained display
syn match phpStrEsc "\\'" contained display
" Comment
syn region phpComment start="/\*" end="\*/" contained extend
syn match phpComment "#.\{-}\(?>\|$\)\@=" contained
syn match phpComment "//.\{-}\(?>\|$\)\@=" contained
syn region phpStringDouble matchgroup=phpStringDelimiter start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=phpSpecialChar,phpStrEsc contained extend keepend
syn region phpBacktick matchgroup=phpStringDelimiter start=+`+ skip=+\\\\\|\\"+ end=+`+ contains=phpSpecialChar,phpStrEsc contained extend keepend
syn region phpStringSingle matchgroup=phpStringDelimiter start=+'+ skip=+\\\\\|\\'+ end=+'+ contains=phpStrEsc contained keepend extend
" HereDoc
syn case match
syn region phpHereDoc matchgroup=Delimiter start="\(<<<\)\@<=\z(\I\i*\)$" end="^\z1\(;\=$\)\@=" contained contains=phpSpecialChar,phpStrEsc keepend extend
syn region phpHereDoc matchgroup=Delimiter start=+\(<<<\)\@<="\z(\I\i*\)"$+ end="^\z1\(;\=$\)\@=" contained contains=phpSpecialChar,phpStrEsc keepend extend
" including HTML,JavaScript,SQL even if not enabled via options
syn region phpHereDoc matchgroup=Delimiter start="\(<<<\)\@<=\z(\(\I\i*\)\=\(html\)\c\(\i*\)\)$" end="^\z1\(;\=$\)\@=" contained contains=phpSpecialChar,phpStrEsc keepend extend
syn region phpHereDoc matchgroup=Delimiter start="\(<<<\)\@<=\z(\(\I\i*\)\=\(sql\)\c\(\i*\)\)$" end="^\z1\(;\=$\)\@=" contained contains=phpSpecialChar,phpStrEsc keepend extend
syn region phpHereDoc matchgroup=Delimiter start="\(<<<\)\@<=\z(\(\I\i*\)\=\(javascript\)\c\(\i*\)\)$" end="^\z1\(;\=$\)\@=" contained contains=phpSpecialChar,phpStrEsc keepend extend
syn case ignore
" NowDoc
syn region phpNowDoc matchgroup=Delimiter start=+\(<<<\)\@<='\z(\I\i*\)'$+ end="^\z1\(;\=$\)\@=" contained keepend extend
" Clusters
syn cluster phpClConst contains=phpStringSingle,phpStringDouble,phpBacktick
syn cluster phpClInside contains=@phpClConst,phpComment,phpDocComment,phpHereDoc,phpNowDoc
syn region phpRegion matchgroup=Delimiter start="<?\(php\)\=" end="?>" contains=@phpClInside keepend
" Sync
if php_sync_method==-1
syn sync match phpRegionSync grouphere phpRegion "^\s*<?\(php\)\=\s*$"
syn sync match phpRegionSync grouphere NONE "^\s*?>\s*$"
syn sync match phpRegionSync grouphere NONE "^\s*%>\s*$"
syn sync match phpRegionSync grouphere phpRegion "function\s.*(.*\$"
elseif php_sync_method>0
exec "syn sync minlines=" . php_sync_method
else
exec "syn sync fromstart"
endif
" Define the default highlighting.
" For version 5.8 and later: only when an item doesn't have highlighting yet
if !exists("did_php_syn_inits")
hi def link phpComment Comment
hi def link phpDocComment Comment
hi def link phpCommentStar Comment
hi def link phpStringSingle String
hi def link phpStringDouble String
hi def link phpBacktick String
hi def link phpStringDelimiter String
hi def link phpHereDoc String
hi def link phpNowDoc String
hi def link phpSpecialChar String
endif
let b:current_syntax = "phpcompletetempbuffer"

View File

@ -0,0 +1,141 @@
fun! TestCase_returns_methods()
" setup
let g:php_builtin_classes = {
\'datetime': {
\ 'name': 'DateTime',
\ 'constants': {
\ },
\ 'properties': {
\ },
\ 'static_properties': {
\ },
\ 'methods': {
\ '__construct': { 'signature': '[ string $time = "now" [, DateTimeZone $timezone = NULL]]', 'return_type': ''},
\ 'add': { 'signature': 'DateInterval $interval | DateTime', 'return_type': 'DateTime'},
\ },
\ 'static_methods': {
\ },
\},
\}
let ret = phpcomplete#CompleteBuiltInClass('$d->', 'DateTime', 'add')
call VUAssertEquals(1, len(ret))
call VUAssertEquals([{
\ 'word': 'add(',
\ 'menu': 'DateInterval $interval | DateTime', 'info': 'DateInterval $interval | DateTime',
\ 'kind': 'f'}],
\ ret)
endfun
fun! TestCase_returns_properties()
" setup
let g:php_builtin_classes = {
\'domdocument': {
\ 'name': 'DOMDocument',
\ 'constants': {
\ },
\ 'properties': {
\ 'encoding': { 'initializer': '', 'type': 'string'},
\ },
\ 'static_properties': {
\ },
\ 'methods': {
\ },
\ 'static_methods': {
\ },
\},
\}
let ret = phpcomplete#CompleteBuiltInClass('$dom->', 'DOMDocument', 'enc')
call VUAssertEquals(1, len(ret))
call VUAssertEquals([{
\ 'word': 'encoding',
\ 'menu': 'string',
\ 'info': 'string',
\ 'kind': 'v'}],
\ ret)
endfun
fun! TestCase_returns_static_methods()
" setup
let g:php_builtin_classes = {
\'datetime': {
\ 'name': 'DateTime',
\ 'constants': {
\ },
\ 'properties': {
\ },
\ 'static_properties': {
\ },
\ 'methods': {
\ },
\ 'static_methods': {
\ 'createFromFormat': { 'signature': 'string $format, string $time [, DateTimeZone $timezone] | DateTime', 'return_type': 'DateTime'},
\ },
\},
\}
let ret = phpcomplete#CompleteBuiltInClass('DateTime::', 'DateTime', 'create')
call VUAssertEquals(1, len(ret))
call VUAssertEquals([{
\ 'word': 'createFromFormat(',
\ 'menu': 'string $format, string $time [, DateTimeZone $timezone] | DateTime',
\ 'info': 'string $format, string $time [, DateTimeZone $timezone] | DateTime',
\ 'kind': 'f'}],
\ ret)
endfun
fun! TestCase_returns_static_properties()
" setup
let g:php_builtin_classes = {
\'mongocursor': {
\ 'name': 'MongoCursor',
\ 'constants': {
\ },
\ 'properties': {
\ },
\ 'static_properties': {
\ '$timeout': { 'initializer': '20000', 'type': 'integer'},
\ },
\ 'methods': {
\ },
\ 'static_methods': {
\ },
\},
\}
let ret = phpcomplete#CompleteBuiltInClass('MongoCursor::', 'MongoCursor', '$tim')
call VUAssertEquals(1, len(ret))
call VUAssertEquals([{
\ 'word': '$timeout',
\ 'menu': 'integer',
\ 'info': 'integer',
\ 'kind': 'v'}],
\ ret)
endfun
fun! TestCase_returns_constants()
" setup
let g:php_builtin_classes = {
\ 'datetime': {
\ 'name': 'DateTime',
\ 'constants': {
\ 'ATOM': '"Y-m-d\TH:i:sP"',
\ },
\ 'properties': {
\ },
\ 'static_properties': {
\ },
\ 'methods': {
\ },
\ 'static_methods': {
\ },
\},
\}
let ret = phpcomplete#CompleteBuiltInClass('Datetime::', 'DateTime', 'ATO')
call VUAssertEquals(1, len(ret))
call VUAssertEquals([{
\ 'word': 'ATOM',
\ 'menu': '"Y-m-d\TH:i:sP"',
\ 'info': '"Y-m-d\TH:i:sP"',
\ 'kind': 'd'}],
\ ret)
endfun
" vim: foldmethod=marker:expandtab:ts=4:sts=4

View File

@ -0,0 +1,295 @@
fun! SetUp()
let g:phpcomplete_min_num_of_chars_for_namespace_completion = 1
" disable builtin information
let g:php_builtin_classnames = { }
" disable builtin information
let g:php_builtin_classes = { }
" disable builtin information
let g:php_builtin_interfaces = { }
" disable tag files
exe ':set tags='
endf
fun! TestCase_complete_classes_from_current_file()
call SetUp()
let path = expand('%:p:h')."/".'fixtures/CompleteClassName/foo.class.php'
below 1new
exe ":silent! edit ".path
let res = phpcomplete#CompleteClassName('', ['c', 'i'], '\', {})
call VUAssertEquals([
\ {'word': 'BarClass', 'kind': 'c'},
\ {'word': 'BarInterface', 'kind': 'i'},
\ {'word': 'FooClass', 'kind': 'c'}],
\ res)
silent! bw! %
endf
fun! TestCase_complete_classes_from_tags()
call SetUp()
" set tags to a fixture
let tags_path = expand('%:p:h').'/'.'fixtures/CompleteClassName/tags'
let old_style_tags_path = expand('%:p:h').'/'.'fixtures/CompleteClassName/old_style_tags'
exe ':set tags='.tags_path
" open an empty file so no 'local' class will be picked up
let path = expand('%:p:h')."/".'fixtures/CompleteClassName/empty.php'
below 1new
exe ":silent! edit ".path
let res = phpcomplete#CompleteClassName('LowerCase', ['c', 'i'], '\', {})
call VUAssertEquals([
\ {'word': 'lowercasetagclass', 'menu': 'fixtures/CompleteClassName/tagclass.php', 'info': 'fixtures/CompleteClassName/tagclass.php', 'kind': 'c'}],
\ res, "should match tag classes case insensitive")
let res = phpcomplete#CompleteClassName('T', ['c', 'i'], '\', {})
call VUAssertEquals([
\ {'word': 'TagClass', 'menu': 'fixtures/CompleteClassName/tagclass.php', 'info': 'fixtures/CompleteClassName/tagclass.php', 'kind': 'c'}],
\ res)
let res = phpcomplete#CompleteClassName('B', ['i'], '\', {})
call VUAssertEquals([
\ {'word': 'BarInterface', 'menu': 'fixtures/CompleteClassName/foo.class.php', 'info': 'fixtures/CompleteClassName/foo.class.php', 'kind': 'i'}],
\ res, "should find only interfaces")
let res = phpcomplete#CompleteClassName('B', ['c', 'i'], '\', {})
call VUAssertEquals([
\ {'word': 'BarClass', 'menu': 'fixtures/CompleteClassName/foo.class.php', 'info': 'fixtures/CompleteClassName/foo.class.php', 'kind': 'c'},
\ {'word': 'BarInterface', 'menu': 'fixtures/CompleteClassName/foo.class.php', 'info': 'fixtures/CompleteClassName/foo.class.php', 'kind': 'i'}],
\ res, "should find both classes and interfaces in tags")
" should work just the same with old ctags generated tag files
exe ':set tags='.old_style_tags_path
let res = phpcomplete#CompleteClassName('T', ['c', 'i'], '\', {})
call VUAssertEquals([
\ {'word': 'TagClass', 'menu': 'fixtures/CompleteClassName/tagclass.php', 'info': 'fixtures/CompleteClassName/tagclass.php', 'kind': 'c'}],
\ res)
let res = phpcomplete#CompleteClassName('B', ['i'], '\', {})
call VUAssertEquals([
\ {'word': 'BarInterface', 'menu': 'fixtures/CompleteClassName/foo.class.php', 'info': 'fixtures/CompleteClassName/foo.class.php', 'kind': 'i'}],
\ res, "should find only interfaces")
let res = phpcomplete#CompleteClassName('B', ['c', 'i'], '\', {})
call VUAssertEquals([
\ {'word': 'BarClass', 'menu': 'fixtures/CompleteClassName/foo.class.php', 'info': 'fixtures/CompleteClassName/foo.class.php', 'kind': 'c'},
\ {'word': 'BarInterface', 'menu': 'fixtures/CompleteClassName/foo.class.php', 'info': 'fixtures/CompleteClassName/foo.class.php', 'kind': 'i'}],
\ res, "should find both classes and interfaces in tags")
silent! bw! %
endf
fun! TestCase_complete_classes_from_built_in_classes()
call SetUp()
" open an empty file so no 'local' class will be picked up
let path = expand('%:p:h')."/".'fixtures/CompleteClassName/empty.php'
below 1new
exe ":silent! edit ".path
" set up example built-in list
let g:php_builtin_classnames = { 'DateTime':'' }
let g:php_builtin_classes = {
\'datetime': {
\ 'name': 'DateTime',
\ 'methods': {
\ },
\ },
\}
let res = phpcomplete#CompleteClassName('', ['c'], '\', {})
call VUAssertEquals([
\ {'word': 'DateTime', 'menu': '', 'kind': 'c'}],
\ res)
" user typed \ and hits <c-x><c-o> in a file starting with "namespace NS1;"
let res = phpcomplete#CompleteClassName('\', ['c'], 'NS1', {})
call VUAssertEquals([
\ {'word': '\DateTime', 'menu': '', 'kind': 'c'}],
\ res)
" set up example built-in list
let g:php_builtin_interfaces = {
\'traversable': {
\ 'name': 'Traversable'
\ },
\}
let res = phpcomplete#CompleteClassName('T', ['i'], '\', {})
call VUAssertEquals([
\ {'word': 'Traversable', 'menu': '', 'kind': 'i'}],
\ res)
" user typed \T and hits <c-x><c-o> in a file starting with "namespace NS1;"
let res = phpcomplete#CompleteClassName('\T', ['i'], 'NS1', {})
call VUAssertEquals([
\ {'word': '\Traversable', 'menu': '', 'kind': 'i'}],
\ res)
let g:php_builtin_interfaces = {
\'traversable': {
\ 'name': 'FindMeFoo'
\ },
\}
" the completion should give the value of the 'name' property regardless
" of the outer dictionary keys
let res = phpcomplete#CompleteClassName('tra', ['i'], '\', {})
call VUAssertEquals([
\ {'word': 'FindMeFoo', 'menu': '', 'kind': 'i'}],
\ res)
silent! bw! %
endf
fun! TestCase_adds_arguments_of_constructors_for_built_in_classes()
call SetUp()
" open an empty file so no 'local' class will be picked up
let path = expand('%:p:h')."/".'fixtures/CompleteClassName/empty.php'
below 1new
exe ":silent! edit ".path
" set up example built-in list
let g:php_builtin_classnames = { 'DateTime':'' }
let g:php_builtin_classes = {
\'datetime': {
\ 'name': 'DateTime',
\ 'methods': {
\ '__construct': { 'signature': '[ string $time = "now" [, DateTimeZone $timezone = NULL]]', 'return_type': ''},
\ },
\ },
\}
let res = phpcomplete#CompleteClassName('', ['c'], '\', {})
call VUAssertEquals([
\ {'word': 'DateTime', 'menu': '[ string $time = "now" [, DateTimeZone $timezone = NULL]]', 'kind': 'c'}],
\ res)
silent! bw! %
endf
fun! TestCase_filters_class_names_with_the_namespaces_typed_in_base()
call SetUp()
" set tags to a fixture
let tags_path = expand('%:p:h').'/'.'fixtures/CompleteClassName/tags'
let old_style_tags_path = expand('%:p:h').'/'.'fixtures/CompleteClassName/old_style_tags'
exe ':set tags='.tags_path
let res = phpcomplete#CompleteClassName('NS1\N', ['c'], '\', {})
call VUAssertEquals([
\ {'word': 'NS1\NameSpacedFoo', 'menu': 'fixtures/CompleteClassName/namespaced.foo.php', 'info': 'fixtures/CompleteClassName/namespaced.foo.php', 'kind': 'c'}],
\ res)
let res = phpcomplete#CompleteClassName('NS1\N', ['i'], '\', {})
call VUAssertEquals([
\ {'word': 'NS1\NameSpacedFooInterface', 'menu': 'fixtures/CompleteClassName/namespaced.foo.php', 'info': 'fixtures/CompleteClassName/namespaced.foo.php', 'kind': 'i'}],
\ res)
" with old style ctags, just complete every classame that matches the
" string after the last \
exe ':set tags='.old_style_tags_path
let res = phpcomplete#CompleteClassName('NS1\N', ['c'], '\', {})
call VUAssertEquals([
\ {'word': 'NS1\NameSpacedFoo', 'menu': 'fixtures/CompleteClassName/namespaced.foo.php', 'info': 'fixtures/CompleteClassName/namespaced.foo.php', 'kind': 'c'}],
\ res)
let res = phpcomplete#CompleteClassName('NS1\N', ['i'], '\', {})
call VUAssertEquals([
\ {'word': 'NS1\NameSpacedFooInterface', 'menu': 'fixtures/CompleteClassName/namespaced.foo.php', 'info': 'fixtures/CompleteClassName/namespaced.foo.php', 'kind': 'i'}],
\ res)
" test for when there are namespaces in the matched tags the non-namespaced
" matches are thrown out
exe ':set tags='.old_style_tags_path.','.tags_path
let res = phpcomplete#CompleteClassName('NS1\NameSpacedF', ['c'], '\', {})
call VUAssertEquals([
\ {'word': 'NS1\NameSpacedFoo', 'menu': 'fixtures/CompleteClassName/namespaced.foo.php', 'info': 'fixtures/CompleteClassName/namespaced.foo.php', 'kind': 'c'}],
\ res)
endf
fun! TestCase_filters_class_names_with_the_current_namespace_but_doesnt_add_the_current_namespace_to_the_completion_word()
call SetUp()
let tags_path = expand('%:p:h').'/'.'fixtures/CompleteClassName/tags'
let old_style_tags_path = expand('%:p:h').'/'.'fixtures/CompleteClassName/old_style_tags'
" set tags to a fixture
exe ':set tags='.tags_path
let res = phpcomplete#CompleteClassName('N', ['c'], 'NS1', {})
call VUAssertEquals([
\ {'word': 'NameSpacedFoo', 'menu': 'fixtures/CompleteClassName/namespaced.foo.php', 'info': 'fixtures/CompleteClassName/namespaced.foo.php', 'kind': 'c'}],
\ res)
let res = phpcomplete#CompleteClassName('N', ['i'], 'NS1', {})
call VUAssertEquals([
\ {'word': 'NameSpacedFooInterface', 'menu': 'fixtures/CompleteClassName/namespaced.foo.php', 'info': 'fixtures/CompleteClassName/namespaced.foo.php', 'kind': 'i'}],
\ res)
" old style tags
exe ':set tags='.old_style_tags_path
let res = phpcomplete#CompleteClassName('N', ['c'], 'NS1', {})
call VUAssertEquals([
\ {'word': 'NameSpacedFoo', 'menu': 'fixtures/CompleteClassName/namespaced.foo.php', 'info': 'fixtures/CompleteClassName/namespaced.foo.php', 'kind': 'c'}],
\ res)
let res = phpcomplete#CompleteClassName('N', ['i'], 'NS1', {})
call VUAssertEquals([
\ {'word': 'NameSpacedFooInterface', 'menu': 'fixtures/CompleteClassName/namespaced.foo.php', 'info': 'fixtures/CompleteClassName/namespaced.foo.php', 'kind': 'i'}],
\ res)
endf
fun! TestCase_completes_class_names_from_imported_names()
call SetUp()
let res = phpcomplete#CompleteClassName('A', ['c'], 'NS1', {'AO': {'name': 'ArrayObject', 'kind': 'c', 'builtin': 1,}})
call VUAssertEquals([
\ {'word': 'AO', 'menu': 'ArrayObject - builtin', 'kind': 'c'}],
\ res)
let res = phpcomplete#CompleteClassName('T', ['i'], 'NS1', {'Trav': {'name': 'Traversable', 'kind': 'i', 'builtin': 1,}})
call VUAssertEquals([
\ {'word': 'Trav', 'menu': 'Traversable - builtin', 'kind': 'i'}],
\ res)
endf
fun! TestCase_completes_class_names_from_imported_namespaces_via_tags()
call SetUp()
let tags_path = expand('%:p:h').'/'.'fixtures/common/namespaced_foo_tags'
let old_style_tags_path = expand('%:p:h').'/'.'fixtures/common/old_style_namespaced_foo_tags'
" set tags to a fixture
exe ':set tags='.tags_path
" comlete classes from imported namespace
let res = phpcomplete#CompleteClassName('SUBNS\F', ['c'], '\', {'SUBNS': {'name': 'NS1\SUBNS', 'kind': 'n', 'builtin': 0,}})
call VUAssertEquals([
\ {'word': 'SUBNS\FooSub', 'menu': 'fixtures/common/namespaced_foo.php', 'info': 'fixtures/common/namespaced_foo.php', 'kind': 'c'}],
\ res)
" comlete classes from imported and renamed namespace, leaving typed in part as-is
let res = phpcomplete#CompleteClassName('SUB\Fo', ['c'], '\', {'SUB': {'name': 'NS1\SUBNS', 'kind': 'n', 'builtin': 0,}})
call VUAssertEquals([
\ {'word': 'SUB\FooSub', 'menu': 'fixtures/common/namespaced_foo.php', 'info': 'fixtures/common/namespaced_foo.php', 'kind': 'c'}],
\ res)
" comlete classes from absolute namespace prefixes
let res = phpcomplete#CompleteClassName('\NS1\SUBNS\Fo', ['c'], 'NS1', {})
call VUAssertEquals([
\ {'word': '\NS1\SUBNS\FooSub', 'menu': 'fixtures/common/namespaced_foo.php', 'info': 'fixtures/common/namespaced_foo.php', 'kind': 'c'}],
\ res)
" set old tags to a fixture
exe ':set tags='.old_style_tags_path
" without namespaces in tags, every classname that matches word after the
" last \ will be returned
let res = phpcomplete#CompleteClassName('SUBNS\F', ['c'], '\', {'SUBNS': {'name': 'NS1\SUBNS', 'kind': 'n', 'builtin': 0,}})
call VUAssertEquals([
\ {'word': 'SUBNS\Foo', 'menu': 'fixtures/common/fixtures/common/namespaced_foo.php', 'info': 'fixtures/common/fixtures/common/namespaced_foo.php', 'kind': 'c'},
\ {'word': 'SUBNS\FooSub', 'menu': 'fixtures/common/fixtures/common/namespaced_foo.php', 'info': 'fixtures/common/fixtures/common/namespaced_foo.php', 'kind': 'c'},
\ {'word': 'SUBNS\FooSubSub', 'menu': 'fixtures/common/fixtures/common/namespaced_foo.php', 'info': 'fixtures/common/fixtures/common/namespaced_foo.php', 'kind': 'c'}],
\ res)
endf
" vim: foldmethod=marker:expandtab:ts=4:sts=4

View File

@ -0,0 +1,469 @@
fun! SetUp()
" disable built-in classes
let g:php_builtin_classnames = {}
" disable built-in interfaces
let g:php_builtin_interfacenames = {}
" disable built-in functions
let g:php_builtin_functions = {}
" disable built-in constants
let g:php_constants = {}
" disable php keywords
let g:php_keywords = {}
" disable tags
exe ':set tags='
" set related options to it's default
let g:phpcomplete_min_num_of_chars_for_namespace_completion = 1
endf
fun! TestCase_completes_functions_from_local_file() " {{{
call SetUp()
" load fixture with methods and functions in it
let path = expand('%:p:h').'/'.'fixtures/CompleteGeneral/functions.php'
below 1new
exe ":silent! edit ".path
let res = phpcomplete#CompleteGeneral('common_', '\', {})
call VUAssertEquals([
\ {'word': 'common_plain_old_function(' , 'info': 'common_plain_old_function()' , 'menu': ')', 'kind': 'f'},
\ {'word': 'common_plain_old_function_with_arguments(', 'info': "common_plain_old_function_with_arguments($a, $b='')" , 'menu': "$a, $b='')", 'kind': 'f'},
\ {'word': 'common_private_method(' , 'info': 'common_private_method($foo)' , 'menu': '$foo)', 'kind': 'f'},
\ {'word': 'common_private_static_method(' , 'info': 'common_private_static_method($foo)' , 'menu': '$foo)', 'kind': 'f'},
\ {'word': 'common_protected_method(' , 'info': 'common_protected_method($foo)' , 'menu': '$foo)', 'kind': 'f'},
\ {'word': 'common_protected_static_method(' , 'info': 'common_protected_static_method($foo)' , 'menu': '$foo)', 'kind': 'f'},
\ {'word': 'common_public_method(' , 'info': 'common_public_method($foo)' , 'menu': '$foo)', 'kind': 'f'},
\ {'word': 'common_public_static_method(' , 'info': 'common_public_static_method($foo)' , 'menu': '$foo)', 'kind': 'f'},
\ {'word': 'common_static_public_method(' , 'info': 'common_static_public_method($foo)' , 'menu': '$foo)', 'kind': 'f'}],
\ res)
silent! bw! %
endf " }}}
fun! TestCase_completes_functions_classes_constants_constants_from_tags() " {{{
call SetUp()
exe ':set tags='.expand('%:p:h').'/'.'fixtures/CompleteGeneral/tags'
let res = phpcomplete#CompleteGeneral('common', '\', {})
call VUAssertEquals([
\ {'word': 'COMMON_FOO', 'info': 'COMMON_FOO - fixtures/CompleteGeneral/foo.php', 'menu': ' - fixtures/CompleteGeneral/foo.php', 'kind': 'd'},
\ {'word': 'CommonFoo', 'info': 'CommonFoo - fixtures/CompleteGeneral/foo.php', 'menu': ' - fixtures/CompleteGeneral/foo.php', 'kind': 'c'},
\ {'word': 'CommonTrait', 'info': ' - fixtures/CompleteGeneral/foo.php', 'menu': ' - fixtures/CompleteGeneral/foo.php', 'kind': 't'},
\ {'word': 'common_plain_old_function(', 'info': 'common_plain_old_function() - fixtures/CompleteGeneral/foo.php', 'menu': ') - fixtures/CompleteGeneral/foo.php', 'kind': 'f'},
\ {'word': 'common_plain_old_function_with_arguments(', 'info': "common_plain_old_function_with_arguments($a, $b='') - fixtures/CompleteGeneral/foo.php", 'menu': "$a, $b='') - fixtures/CompleteGeneral/foo.php", 'kind': 'f'},
\ {'word': 'common_private_method(', 'info': 'common_private_method($foo) - fixtures/CompleteGeneral/foo.php', 'menu': '$foo) - fixtures/CompleteGeneral/foo.php', 'kind': 'f'},
\ {'word': 'common_private_static_method(', 'info': 'common_private_static_method($foo) - fixtures/CompleteGeneral/foo.php', 'menu': '$foo) - fixtures/CompleteGeneral/foo.php', 'kind': 'f'},
\ {'word': 'common_protected_method(', 'info': 'common_protected_method($foo) - fixtures/CompleteGeneral/foo.php', 'menu': '$foo) - fixtures/CompleteGeneral/foo.php', 'kind': 'f'},
\ {'word': 'common_protected_static_method(', 'info': 'common_protected_static_method($foo) - fixtures/CompleteGeneral/foo.php', 'menu': '$foo) - fixtures/CompleteGeneral/foo.php', 'kind': 'f'},
\ {'word': 'common_public_method(', 'info': 'common_public_method($foo) - fixtures/CompleteGeneral/foo.php', 'menu': '$foo) - fixtures/CompleteGeneral/foo.php', 'kind': 'f'},
\ {'word': 'common_public_static_method(', 'info': 'common_public_static_method($foo) - fixtures/CompleteGeneral/foo.php', 'menu': '$foo) - fixtures/CompleteGeneral/foo.php', 'kind': 'f'},
\ {'word': 'common_static_public_method(', 'info': 'common_static_public_method($foo) - fixtures/CompleteGeneral/foo.php', 'menu': '$foo) - fixtures/CompleteGeneral/foo.php', 'kind': 'f'}],
\ res)
endf " }}}
fun! TestCase_completes_function_signature_from_tags_if_field_available() " {{{
call SetUp()
exe ':set tags='.expand('%:p:h').'/'.'fixtures/CompleteGeneral/patched_tags'
let res = phpcomplete#CompleteGeneral('common_plain_old_function_with_', '\', {})
call VUAssertEquals([
\ {'word': 'common_plain_old_function_with_arguments(', 'info': "common_plain_old_function_with_arguments($a, $b = '') - fixtures/CompleteGeneral/functions.php", 'menu': "$a, $b = '') - fixtures/CompleteGeneral/functions.php", 'kind': 'f'}],
\ res)
endf " }}}
fun! TestCase_completes_constants_from_local_file() " {{{
call SetUp()
" load fixture with methods and functions in it
let path = expand('%:p:h').'/'.'fixtures/CompleteGeneral/constants.php'
below 1new
exe ":silent! edit ".path
let res = phpcomplete#CompleteGeneral('FIND', '\', {})
call VUAssertEquals([
\ {'word': 'FINDME_FOO', 'kind': 'd', 'menu': '', 'info': 'FINDME_FOO'}],
\ res)
silent! bw! %
endf " }}}
fun! TestCase_completes_builtin_functions() " {{{
call SetUp()
" the filter_* one should not be picked up
let g:php_builtin_functions = {
\ 'array_flip(': 'array $trans | array',
\ 'array_product(': 'array $array | number',
\ 'filter_var(': 'mixed $variable [, int $filter = FILTER_DEFAULT [, mixed $options]] | mixed',
\ }
let res = phpcomplete#CompleteGeneral('array_', '\', {})
call VUAssertEquals([
\ {'word': 'array_flip(', 'info': 'array_flip(array $trans | array', 'menu': 'array $trans | array', 'kind': 'f'},
\ {'word': 'array_product(', 'info': 'array_product(array $array | number', 'menu': 'array $array | number', 'kind': 'f'}],
\ res)
endf " }}}
fun! TestCase_completes_builtin_constants() " {{{
call SetUp()
" the FILE_* ones should not be picked up
let g:php_constants = {
\ 'FILE_TEXT': '',
\ 'FILE_USE_INCLUDE_PATH': '',
\ 'FILTER_CALLBACK': '',
\ 'FILTER_DEFAULT': '',
\ }
let res = phpcomplete#CompleteGeneral('FILTER_', '\', {})
call VUAssertEquals([
\ {'word': 'FILTER_CALLBACK', 'kind': 'd', 'menu': ' - builtin', 'info': 'FILTER_CALLBACK - builtin'},
\ {'word': 'FILTER_DEFAULT', 'kind': 'd', 'menu': ' - builtin', 'info': 'FILTER_DEFAULT - builtin'}],
\ res)
endf " }}}
fun! TestCase_completes_builtin_keywords() " {{{
call SetUp()
let g:php_keywords = {
\ 'argv':'',
\ 'argc':'',
\ 'and':'',
\ }
let res = phpcomplete#CompleteGeneral('a', '\', {})
call VUAssertEquals([
\ {'word': 'and'},
\ {'word': 'argc'},
\ {'word': 'argv'}],
\ res)
endf " }}}
fun! TestCase_completes_builtin_class_names() " {{{
call SetUp()
" PDO should not be picked up
let g:php_builtin_classnames = {
\ 'datetime':'',
\ 'pdo':'',
\ }
let g:php_builtin_classes = {
\ 'datetime':{
\ 'name': 'DateTime',
\ },
\ 'pdo':{
\ 'name': 'PDO',
\ }
\ }
let res = phpcomplete#CompleteGeneral('date', '\', {})
call VUAssertEquals([
\ {'word': 'DateTime', 'kind': 'c', 'menu': ' - builtin', 'info': 'DateTime - builtin'}],
\ res)
endf " }}}
fun! TestCase_completes_builtin_interface_names() " {{{
call SetUp()
" PDO should not be picked up
let g:php_builtin_interfacenames = {
\ 'traversable':'',
\ }
let g:php_builtin_interfaces = {
\ 'traversable':{
\ 'name': 'Traversable',
\ }
\ }
let res = phpcomplete#CompleteGeneral('Tr', '\', {})
call VUAssertEquals([
\ {'word': 'Traversable', 'kind': 'i', 'menu': ' - builtin', 'info': 'Traversable - builtin'}],
\ res)
endf " }}}
fun! TestCase_completes_builtin_functions_when_in_namespace() " {{{
call SetUp()
" the filter_* one should not be picked up
let g:php_builtin_functions = {
\ 'array_flip(': 'array $trans | array',
\ 'array_product(': 'array $array | number',
\ 'filter_var(': 'mixed $variable [, int $filter = FILTER_DEFAULT [, mixed $options]] | mixed',
\ }
" should find completions when base prefixed with \
let res = phpcomplete#CompleteGeneral('\array_', 'SomeNameSpace', {})
call VUAssertEquals([
\ {'word': '\array_flip(', 'info': '\array_flip(array $trans | array', 'menu': 'array $trans | array', 'kind': 'f'},
\ {'word': '\array_product(', 'info': '\array_product(array $array | number', 'menu': 'array $array | number', 'kind': 'f'}],
\ res)
" should find completions even without \ in the beginning of base
let res = phpcomplete#CompleteGeneral('array_', 'SomeNameSpace', {})
call VUAssertEquals([
\ {'word': 'array_flip(', 'info': 'array_flip(array $trans | array', 'menu': 'array $trans | array', 'kind': 'f'},
\ {'word': 'array_product(', 'info': 'array_product(array $array | number', 'menu': 'array $array | number', 'kind': 'f'}],
\ res)
endf " }}}
fun! TestCase_completes_builtin_constants_when_in_namespace() " {{{
call SetUp()
" the FILE_* ones should not be picked up
let g:php_constants = {
\ 'FILE_TEXT': '',
\ 'FILE_USE_INCLUDE_PATH': '',
\ 'FILTER_CALLBACK': '',
\ 'FILTER_DEFAULT': '',
\ }
" should find completions when base prefixed with \
let res = phpcomplete#CompleteGeneral('\FILTER_', 'SomeNameSpace', {})
call VUAssertEquals([
\ {'word': '\FILTER_CALLBACK', 'kind': 'd', 'info': '\FILTER_CALLBACK - builtin', 'menu': ' - builtin'},
\ {'word': '\FILTER_DEFAULT', 'kind': 'd', 'info': '\FILTER_DEFAULT - builtin', 'menu': ' - builtin'}],
\ res)
" should find completions even without \ in the beginning of base
let res = phpcomplete#CompleteGeneral('FILTER_', 'SomeNameSpace', {})
call VUAssertEquals([
\ {'word': 'FILTER_CALLBACK', 'kind': 'd', 'info': 'FILTER_CALLBACK - builtin', 'menu': ' - builtin'},
\ {'word': 'FILTER_DEFAULT', 'kind': 'd', 'info': 'FILTER_DEFAULT - builtin', 'menu': ' - builtin'}],
\ res)
endf " }}}
fun! TestCase_doesnt_complete_keywords_when_theres_a_leading_slash() " {{{
call SetUp()
let g:php_keywords = {
\ 'argv':'',
\ 'argc':'',
\ 'and':'',
\ }
let res = phpcomplete#CompleteGeneral('\a', '\', {})
call VUAssertEquals([], res)
endf " }}}
fun! TestCase_completes_builtin_class_names_when_in_namespace_and_base_starts_with_slash() " {{{
call SetUp()
" PDO should not be picked up
let g:php_builtin_classnames = {
\ 'datetime':'',
\ 'pdo':'',
\ }
let g:php_builtin_classes = {
\ 'datetime':{
\ 'name': 'DateTime',
\ },
\ 'pdo':{
\ 'name': 'PDO',
\ }
\ }
let res = phpcomplete#CompleteGeneral('\date', 'SomeNameSpace', {})
call VUAssertEquals([
\ {'word': '\DateTime', 'kind': 'c', 'info': '\DateTime - builtin', 'menu': ' - builtin'}],
\ res)
endf " }}}
fun! TestCase_completes_namespace_names_from_tags() " {{{
call SetUp()
exe ':set tags='.expand('%:p:h').'/'.'fixtures/CompleteGeneral/namespaced_tags'
let res = phpcomplete#CompleteGeneral('NS', '\', {})
call VUAssertEquals([
\ {'word': 'NS1\', 'menu': 'NS1 - fixtures/CompleteGeneral/namespaced_foo.php', 'info': 'NS1 - fixtures/CompleteGeneral/namespaced_foo.php', 'kind': 'n'},
\ {'word': 'NS1\SUBNS\', 'menu': 'NS1\SUBNS - fixtures/CompleteGeneral/namespaced_foo.php', 'info': 'NS1\SUBNS - fixtures/CompleteGeneral/namespaced_foo.php', 'kind': 'n'},
\ {'word': 'NS1\SUBNS\SUBSUB\', 'menu': 'NS1\SUBNS\SUBSUB - fixtures/CompleteGeneral/namespaced_foo.php', 'info': 'NS1\SUBNS\SUBSUB - fixtures/CompleteGeneral/namespaced_foo.php', 'kind': 'n'}],
\ res)
let res = phpcomplete#CompleteGeneral('\NS', 'SomeNameSpace', {})
call VUAssertEquals([
\ {'word': '\NS1\', 'kind': 'n', 'menu': 'NS1 - fixtures/CompleteGeneral/namespaced_foo.php', 'info': 'NS1 - fixtures/CompleteGeneral/namespaced_foo.php'},
\ {'word': '\NS1\SUBNS\', 'kind': 'n', 'menu': 'NS1\SUBNS - fixtures/CompleteGeneral/namespaced_foo.php', 'info': 'NS1\SUBNS - fixtures/CompleteGeneral/namespaced_foo.php'},
\ {'word': '\NS1\SUBNS\SUBSUB\', 'kind': 'n', 'menu': 'NS1\SUBNS\SUBSUB - fixtures/CompleteGeneral/namespaced_foo.php', 'info': 'NS1\SUBNS\SUBSUB - fixtures/CompleteGeneral/namespaced_foo.php'}],
\ res)
" leaves leading slash if you have typed that in
let res = phpcomplete#CompleteGeneral('\NS', '\', {})
call VUAssertEquals([
\ {'word': '\NS1\', 'menu': 'NS1 - fixtures/CompleteGeneral/namespaced_foo.php', 'info': 'NS1 - fixtures/CompleteGeneral/namespaced_foo.php', 'kind': 'n'},
\ {'word': '\NS1\SUBNS\', 'menu': 'NS1\SUBNS - fixtures/CompleteGeneral/namespaced_foo.php', 'info': 'NS1\SUBNS - fixtures/CompleteGeneral/namespaced_foo.php', 'kind': 'n'},
\ {'word': '\NS1\SUBNS\SUBSUB\', 'menu': 'NS1\SUBNS\SUBSUB - fixtures/CompleteGeneral/namespaced_foo.php', 'info': 'NS1\SUBNS\SUBSUB - fixtures/CompleteGeneral/namespaced_foo.php', 'kind': 'n'}],
\ res)
" completes namespaces relative to the current namespace
let res = phpcomplete#CompleteGeneral('SUB', 'NS1', {})
call VUAssertEquals([
\ {'word': 'SUBNS\', 'kind': 'n', 'menu': 'NS1\SUBNS - fixtures/CompleteGeneral/namespaced_foo.php', 'info': 'NS1\SUBNS - fixtures/CompleteGeneral/namespaced_foo.php'},
\ {'word': 'SUBNS\SUBSUB\', 'kind': 'n', 'menu': 'NS1\SUBNS\SUBSUB - fixtures/CompleteGeneral/namespaced_foo.php', 'info': 'NS1\SUBNS\SUBSUB - fixtures/CompleteGeneral/namespaced_foo.php'}],
\ res)
endf " }}}
fun! TestCase_completes_class_names_from_tags_matching_namespaces() " {{{
call SetUp()
exe ':set tags='.expand('%:p:h').'/'.'fixtures/CompleteGeneral/namespaced_tags'
" this is where class name part must have at least the configured amount
" of letters to start matching
let g:phpcomplete_min_num_of_chars_for_namespace_completion = 1
let res = phpcomplete#CompleteGeneral('F', 'NS1', {})
call VUAssertEquals([{'word': 'Foo', 'kind': 'c', 'menu': ' - fixtures/CompleteGeneral/namespaced_foo.php', 'info': 'Foo - fixtures/CompleteGeneral/namespaced_foo.php'}], res)
" leaves typed in namespace even when its the same we are in
let res = phpcomplete#CompleteGeneral('\NS1\F', 'NS1', {})
call VUAssertEquals([{'word': '\NS1\Foo', 'kind': 'c', 'menu': ' - fixtures/CompleteGeneral/namespaced_foo.php', 'info': '\NS1\Foo - fixtures/CompleteGeneral/namespaced_foo.php'}], res)
let res = phpcomplete#CompleteGeneral('\NS1\SUBNS\F', 'NS1', {})
call VUAssertEquals([{'word': '\NS1\SUBNS\FooSub', 'kind': 'c', 'menu': ' - fixtures/CompleteGeneral/namespaced_foo.php', 'info': '\NS1\SUBNS\FooSub - fixtures/CompleteGeneral/namespaced_foo.php'}], res)
" completes classnames from subnamespaces
let res = phpcomplete#CompleteGeneral('SUBNS\F', 'NS1', {})
call VUAssertEquals([{'word': 'SUBNS\FooSub', 'kind': 'c', 'menu': ' - fixtures/CompleteGeneral/namespaced_foo.php', 'info': 'SUBNS\FooSub - fixtures/CompleteGeneral/namespaced_foo.php'}], res)
" stable ctags branch with no actual namespace information
exe ':set tags='.expand('%:p:h').'/'.'fixtures/CompleteGeneral/old_style_namespaced_tags'
" class names should be completed regardless of the namespaces,
" simply matching the word after the last \ segment
let res = phpcomplete#CompleteGeneral('\NS1\F', 'NS1', {})
call VUAssertEquals([
\ {'word': 'Foo', 'menu': ' - fixtures/CompleteGeneral/fixtures/CompleteGeneral/namespaced_foo.php', 'info': 'Foo - fixtures/CompleteGeneral/fixtures/CompleteGeneral/namespaced_foo.php', 'kind': 'c'},
\ {'word': 'FooSub', 'menu': ' - fixtures/CompleteGeneral/fixtures/CompleteGeneral/namespaced_foo.php', 'info': 'FooSub - fixtures/CompleteGeneral/fixtures/CompleteGeneral/namespaced_foo.php', 'kind': 'c'},
\ {'word': 'FooSubSub', 'menu': ' - fixtures/CompleteGeneral/fixtures/CompleteGeneral/namespaced_foo.php', 'info': 'FooSubSub - fixtures/CompleteGeneral/fixtures/CompleteGeneral/namespaced_foo.php', 'kind': 'c'}],
\ res)
endf " }}}
fun! TestCase_completes_top_level_functions_from_tags_in_matching_namespaces() " {{{
call SetUp()
exe ':set tags='.expand('%:p:h').'/'.'fixtures/CompleteGeneral/namespaced_tags'
" this is where function name part must have at least the configured amount
" of letters to start matching
let g:phpcomplete_min_num_of_chars_for_namespace_completion = 1
let res = phpcomplete#CompleteGeneral('b', 'NS1', {})
call VUAssertEquals([
\ {'word': 'bar(', 'info': 'bar() - fixtures/CompleteGeneral/namespaced_foo.php', 'menu': ') - fixtures/CompleteGeneral/namespaced_foo.php', 'kind': 'f'}],
\ res)
" leaves leading slash in
let res = phpcomplete#CompleteGeneral('\NS1\b', 'NS1', {})
call VUAssertEquals([
\ {'word': '\NS1\bar(', 'info': '\NS1\bar() - fixtures/CompleteGeneral/namespaced_foo.php', 'menu': ') - fixtures/CompleteGeneral/namespaced_foo.php', 'kind': 'f'}],
\ res)
" returns functions from subnamespace
let res = phpcomplete#CompleteGeneral('SUBNS\b', 'NS1', {})
call VUAssertEquals([
\ {'word': 'SUBNS\barsub(', 'info': 'SUBNS\barsub() - fixtures/CompleteGeneral/namespaced_foo.php', 'menu': ') - fixtures/CompleteGeneral/namespaced_foo.php', 'kind': 'f'}],
\ res)
" stable ctags branch with no actual namespace information
exe ':set tags='.expand('%:p:h').'/'.'fixtures/CompleteGeneral/old_style_namespaced_tags'
" functions should be completed regardless of the namespaces,
" simply matching the word after the last \ segment
let res = phpcomplete#CompleteGeneral('\NS1\ba', 'NS1', {})
call VUAssertEquals([
\ {'word': 'bar(', 'info': 'bar() - fixtures/CompleteGeneral/fixtures/CompleteGeneral/namespaced_foo.php', 'menu': ') - fixtures/CompleteGeneral/fixtures/CompleteGeneral/namespaced_foo.php', 'kind': 'f'},
\ {'word': 'barsub(', 'info': 'barsub() - fixtures/CompleteGeneral/fixtures/CompleteGeneral/namespaced_foo.php', 'menu': ') - fixtures/CompleteGeneral/fixtures/CompleteGeneral/namespaced_foo.php', 'kind': 'f'},
\ {'word': 'barsubsub(', 'info': 'barsubsub() - fixtures/CompleteGeneral/fixtures/CompleteGeneral/namespaced_foo.php', 'menu': ') - fixtures/CompleteGeneral/fixtures/CompleteGeneral/namespaced_foo.php', 'kind': 'f'}],
\ res)
endf " }}}
fun! TestCase_completes_constants_from_tags_in_matching_namespaces() " {{{
call SetUp()
exe ':set tags='.expand('%:p:h').'/'.'fixtures/CompleteGeneral/namespaced_tags'
let res = phpcomplete#CompleteGeneral('Z', 'NS1', {})
call VUAssertEquals([
\ {'word': 'ZAP', 'menu': ' - fixtures/CompleteGeneral/namespaced_foo.php', 'info': 'ZAP - fixtures/CompleteGeneral/namespaced_foo.php', 'kind': 'd'}],
\ res)
" leaves leading slash in
let res = phpcomplete#CompleteGeneral('\NS1\Z', 'NS1', {})
call VUAssertEquals([
\ {'word': '\NS1\ZAP', 'menu': ' - fixtures/CompleteGeneral/namespaced_foo.php', 'info': '\NS1\ZAP - fixtures/CompleteGeneral/namespaced_foo.php', 'kind': 'd'}],
\ res)
" returns constants from subnamespace
let res = phpcomplete#CompleteGeneral('SUBNS\Z', 'NS1', {})
call VUAssertEquals([
\ {'word': 'SUBNS\ZAPSUB', 'menu': ' - fixtures/CompleteGeneral/namespaced_foo.php', 'info': 'SUBNS\ZAPSUB - fixtures/CompleteGeneral/namespaced_foo.php', 'kind': 'd'}],
\ res)
" stable ctags branch with no actual namespace information
exe ':set tags='.expand('%:p:h').'/'.'fixtures/CompleteGeneral/old_style_namespaced_tags'
" constants should be completed regardless of the namespaces,
" simply matching the word after the last \ segment
" leaves leading slash in
let res = phpcomplete#CompleteGeneral('\NS1\Z', 'NS1', {})
call VUAssertEquals([
\ {'word': 'ZAP', 'menu': ' - fixtures/CompleteGeneral/fixtures/CompleteGeneral/namespaced_constants.php', 'info': 'ZAP - fixtures/CompleteGeneral/fixtures/CompleteGeneral/namespaced_constants.php', 'kind': 'd'},
\ {'word': 'ZAPSUB', 'menu': ' - fixtures/CompleteGeneral/fixtures/CompleteGeneral/namespaced_constants.php', 'info': 'ZAPSUB - fixtures/CompleteGeneral/fixtures/CompleteGeneral/namespaced_constants.php', 'kind': 'd'},
\ {'word': 'ZAPSUBSUB', 'menu': ' - fixtures/CompleteGeneral/fixtures/CompleteGeneral/namespaced_constants.php', 'info': 'ZAPSUBSUB - fixtures/CompleteGeneral/fixtures/CompleteGeneral/namespaced_constants.php', 'kind': 'd'}],
\ res)
endf " }}}
fun! TestCase_returns_completions_from_imported_names() " {{{
call SetUp()
let res = phpcomplete#CompleteGeneral('A', '', {'AO': {'name': 'ArrayObject', 'kind': 'c', 'builtin': 1,}})
call VUAssertEquals([
\ {'word': 'AO', 'menu': ' ArrayObject - builtin', 'info': 'AO ArrayObject - builtin', 'kind': 'c'}],
\ res)
let res = phpcomplete#CompleteGeneral('NS', '', {'NS1': {'name': 'NS1', 'kind': 'n', 'builtin': 0, 'filename': 'some_file.php'}})
call VUAssertEquals([
\ {'word': 'NS1\', 'menu': ' NS1 - some_file.php', 'info': ' NS1 - some_file.php', 'kind': 'n'}],
\ res)
endf " }}}
fun! TestCase_returns_tags_from_imported_namespaces() " {{{
call SetUp()
exe ':set tags='.expand('%:p:h').'/'.'fixtures/common/namespaced_foo_tags'
" class in imported namespace without renaming
let res = phpcomplete#CompleteGeneral('SUBNS\F', '\', {'SUBNS': {'name': 'NS1\SUBNS', 'kind': 'n', 'builtin': 0, 'filename': 'fixtures/common/namespaced_foo.php'}})
call VUAssertEquals([
\ {'word': 'SUBNS\FooSub', 'menu': ' - fixtures/common/namespaced_foo.php', 'info': 'SUBNS\FooSub - fixtures/common/namespaced_foo.php', 'kind': 'c'}],
\ res)
" class in imported namespace when the import is renamed
let res = phpcomplete#CompleteGeneral('SUB\F', '\', {'SUB': {'name': 'NS1\SUBNS', 'kind': 'n', 'builtin': 0, 'filename': 'fixtures/common/namespaced_foo.php'}})
call VUAssertEquals([
\ {'word': 'SUB\FooSub', 'menu': ' - fixtures/common/namespaced_foo.php', 'info': 'SUB\FooSub - fixtures/common/namespaced_foo.php', 'kind': 'c'}],
\ res)
" class in sub-namespace of the imported namespace when the import is renamed
let res = phpcomplete#CompleteGeneral('SUB\SUBSUB\F', '\', {'SUB': {'name': 'NS1\SUBNS', 'kind': 'n', 'builtin': 0, 'filename': 'fixtures/common/namespaced_foo.php'}})
call VUAssertEquals([
\ {'word': 'SUB\SUBSUB\FooSubSub', 'menu': ' - fixtures/common/namespaced_foo.php', 'info': 'SUB\SUBSUB\FooSubSub - fixtures/common/namespaced_foo.php', 'kind': 'c'}],
\ res)
" imported namespace name
let res = phpcomplete#CompleteGeneral('SUB', '\', {'SUBNS': {'name': 'NS1\SUBNS', 'kind': 'n', 'builtin': 0, 'filename': 'fixtures/common/namespaced_foo.php'}})
call VUAssertEquals([
\ {'word': 'SUBNS\', 'menu': ' NS1\SUBNS - fixtures/common/namespaced_foo.php', 'info': ' NS1\SUBNS - fixtures/common/namespaced_foo.php', 'kind': 'n'}],
\ res)
" imported and renamed namespace name
let res = phpcomplete#CompleteGeneral('SU', '\', {'SUB': {'name': 'NS1\SUBNS', 'kind': 'n', 'builtin': 0, 'filename': 'fixtures/common/namespaced_foo.php'}})
call VUAssertEquals([
\ {'word': 'SUB\', 'menu': ' NS1\SUBNS - fixtures/common/namespaced_foo.php', 'info': ' NS1\SUBNS - fixtures/common/namespaced_foo.php', 'kind': 'n'}],
\ res)
" sub namespace of imported and renamed namespace name
let res = phpcomplete#CompleteGeneral('SUB\SUB', '\', {'SUB': {'name': 'NS1\SUBNS', 'kind': 'n', 'builtin': 0, 'filename': 'fixtures/common/namespaced_foo.php'}})
call VUAssertEquals([
\ {'word': 'SUB\SUBSUB\', 'menu': 'NS1\SUBNS\SUBSUB - fixtures/common/namespaced_foo.php', 'info': 'NS1\SUBNS\SUBSUB - fixtures/common/namespaced_foo.php', 'kind': 'n'}],
\ res)
endf " }}}
" vim: foldmethod=marker:expandtab:ts=4:sts=4

View File

@ -0,0 +1,27 @@
fun! TestCase_split_height_doesnt_change_when_completing()
" set up
set noequalalways
let winno = winnr()
" open a second split, get back to the first one
below 1new
let winno2 = winnr()
silent! exec winno.'wincmd w'
" measure height
let before_height = winheight(0)
" trigger plugin
let ret = phpcomplete#CompletePHP(0, 2)
" take a second measurement
let after_height = winheight(0)
call VUAssertEquals(before_height, after_height, 'split heights should not change')
" clean up
silent! exec winno2.'wincmd w'
silent! bw! %
set equalalways
endfun
" vim: foldmethod=marker:expandtab:ts=4:sts=4

View File

@ -0,0 +1,130 @@
fun! SetUp()
let g:phpcomplete_complete_for_unknown_classes = 1
" disable built-in functions
let g:php_builtin_object_functions = {}
" disable tags
exe ':set tags='
endf
fun! TestCase_returns_class_properties_from_current_file()
call SetUp()
" load fixture with variables in it
let path = expand('%:p:h')."/".'fixtures/CompleteUnknownClass/foo_properties.class.php'
below 1new
exe ":silent! edit ".path
let res = phpcomplete#CompleteUnknownClass("prop", "$a->")
call VUAssertEquals([
\ {'word': 'property1', 'info': ' ', 'kind': 'v'},
\ {'word': 'property2', 'info': ' ', 'kind': 'v'}],
\ res)
silent! bw! %
endf
fun! TestCase_returns_functions_from_current_file()
call SetUp()
" load fixture with methods and functions in it
let path = expand('%:p:h')."/".'fixtures/CompleteUnknownClass/foo_methods.class.php'
below 1new
exe ":silent! edit ".path
let res = phpcomplete#CompleteUnknownClass("met", "$a->")
" TODO: At this moment, the code finds private and protected methods, it should not do that
" TODO: At this moment, the code doesn't take filter for staticness of results
call VUAssertEquals([
\ {'word': 'method1(', 'info': 'method1($foo)', 'menu': '$foo)', 'kind': 'f'},
\ {'word': 'method2(', 'info': 'method2($foo)', 'menu': '$foo)', 'kind': 'f'},
\ {'word': 'method3(', 'info': 'method3($foo)', 'menu': '$foo)', 'kind': 'f'},
\ {'word': 'method4(', 'info': 'method4($foo)', 'menu': '$foo)', 'kind': 'f'},
\ {'word': 'method5(', 'info': 'method5($foo)', 'menu': '$foo)', 'kind': 'f'},
\ {'word': 'method6(', 'info': 'method6($foo)', 'menu': '$foo)', 'kind': 'f'}],
\ res)
silent! bw! %
endf
fun! TestCase_completes_function_signature_from_tags_if_field_available()
call SetUp()
" disable tags
exe 'set tags='.expand('%:p:h')."/".'fixtures/CompleteUnknownClass/patched_tags'
" load an empty fixture so no local functions / variables show up
let path = expand('%:p:h')."/".'fixtures/CompleteUnknownClass/empty.php'
below 1new
exe ":silent! edit ".path
let res = phpcomplete#CompleteUnknownClass("method_with_", "$a->")
" TODO: At this moment, the code finds functions that are not in a class
" (so they are no methods)
" TODO: At this moment, the code doesn't take filter for staticness
call VUAssertEquals([
\ {'word': 'method_with_arguments(', 'info': "method_with_arguments($bar = 42, $foo = '') - fixtures/CompleteUnknownClass/irrelevant.class.php", 'menu': "$bar = 42, $foo = '') - fixtures/CompleteUnknownClass/irrelevant.class.php", 'kind': 'f'}],
\ res)
silent! bw! %
endf
fun! TestCase_returns_functions_from_tags()
call SetUp()
" disable tags
exe 'set tags='.expand('%:p:h')."/".'fixtures/CompleteUnknownClass/tags'
" load an empty fixture so no local functions / variables show up
let path = expand('%:p:h')."/".'fixtures/CompleteUnknownClass/empty.php'
below 1new
exe ":silent! edit ".path
let res = phpcomplete#CompleteUnknownClass("fun", "$a->")
" TODO: At this moment, the code finds functions that are not in a class
" (so they are no methods)
" TODO: At this moment, the code doesn't take filter for staticness
call VUAssertEquals([
\ {'word': 'function1(', 'info': 'function1($baz = ''foo'') - fixtures/CompleteUnknownClass/irrelevant.php', 'menu': '$baz = ''foo'') - fixtures/CompleteUnknownClass/irrelevant.php', 'kind': 'f'},
\ {'word': 'function2(', 'info': 'function2($baz = ''foo'') - fixtures/CompleteUnknownClass/irrelevant.php', 'menu': '$baz = ''foo'') - fixtures/CompleteUnknownClass/irrelevant.php', 'kind': 'f'},
\ {'word': 'function3(', 'info': 'function3() - fixtures/CompleteUnknownClass/irrelevant.php', 'menu': ') - fixtures/CompleteUnknownClass/irrelevant.php', 'kind': 'f'},
\ {'word': 'function4(', 'info': 'function4() - fixtures/CompleteUnknownClass/irrelevant.php', 'menu': ') - fixtures/CompleteUnknownClass/irrelevant.php', 'kind': 'f'}],
\ res)
silent! bw! %
endf
fun! TestCase_returns_built_in_object_functions()
call SetUp()
" load an empty fixture so no local functions / variables show up
let path = expand('%:p:h')."/".'fixtures/CompleteUnknownClass/empty.php'
below 1new
exe ":silent! edit ".path
" disable built-in functions
let g:php_builtin_object_functions = {
\ 'DateTime::add(': 'DateInterval $interval | DateTime',
\ 'DateTime::setDate(': 'int $year, int $month, int $day | DateTime',
\ }
let res = phpcomplete#CompleteUnknownClass("set", "$d->")
" TODO: At this moment, the code doesn't take filter for staticness
call VUAssertEquals([{
\ 'word': 'setDate(',
\ 'info': 'DateTime::setDate(int $year, int $month, int $day | DateTime',
\ 'menu': 'int $year, int $month, int $day | DateTime',
\ 'kind': 'f'}],
\ res)
silent! bw! %
endf
fun! TestCase_returns_empty_list_when_unknown_class_completion_disabled()
call SetUp()
let g:phpcomplete_complete_for_unknown_classes = 0
let res = phpcomplete#CompleteUnknownClass("setDat", "$d->")
call VUAssertEquals([], res)
endf
" vim: foldmethod=marker:expandtab:ts=4:sts=4

View File

@ -0,0 +1,123 @@
fun! SetUp()
" normalize g:phpcomplete_min_num_of_chars_for_namespace_completion option
let g:phpcomplete_min_num_of_chars_for_namespace_completion = 2
" disable built-in classes
let g:php_builtin_classnames = {}
" disable built-in interfaces
let g:php_builtin_interfaces = {}
" disable built-in interfaces
let g:php_builtin_interfacenames = {}
" disable tags
exe ':set tags='
endf
fun! TestCase_completes_builtin_classes()
call SetUp()
let g:php_builtin_classnames = {
\ 'arrayaccess': '',
\ 'arrayobject': '',
\ }
let g:php_builtin_classes = {
\ 'arrayaccess':{
\ 'name': 'ArrayAccess',
\ },
\ 'arrayobject':{
\ 'name': 'ArrayObject',
\ },
\ }
" returns every builtin class when nothing typed in
let res = phpcomplete#CompleteUse('')
call VUAssertEquals([
\{'word': 'ArrayAccess', 'kind': 'c'},
\{'word': 'ArrayObject', 'kind': 'c'}],
\res)
" returns every builtin class when only a \ typed in
let res = phpcomplete#CompleteUse('\')
call VUAssertEquals([
\{'word': 'ArrayAccess', 'kind': 'c'},
\{'word': 'ArrayObject', 'kind': 'c'}],
\res)
" filters to the typed in string
let res = phpcomplete#CompleteUse('ArrayO')
call VUAssertEquals([
\{'word': 'ArrayObject', 'kind': 'c'}]
\, res)
" removes the leading \ when its in the base, php manual doesn't recommend
" to type out those since imports are always absolute
let res = phpcomplete#CompleteUse('\ArrayO')
call VUAssertEquals([
\{'word': 'ArrayObject', 'kind': 'c'}]
\, res)
endf
fun! TestCase_completes_namespaces_from_tags()
call SetUp()
exe ':set tags='.expand('%:p:h').'/'.'fixtures/CompleteUse/tags'
let res = phpcomplete#CompleteUse('Ass')
call VUAssertEquals([
\ {'word': 'Assetic', 'menu': 'fixtures/CompleteUse/foo.php', 'info': 'fixtures/CompleteUse/foo.php', 'kind': 'n'},
\ {'word': 'Assetic\Asset', 'menu': 'fixtures/CompleteUse/foo.php', 'info': 'fixtures/CompleteUse/foo.php', 'kind': 'n'},
\ {'word': 'Assetic\Asset\Iterator', 'menu': 'fixtures/CompleteUse/foo.oho', 'info': 'fixtures/CompleteUse/foo.oho', 'kind': 'n'},
\ {'word': 'Assetic\Cache', 'menu': 'fixtures/CompleteUse/foo.php', 'info': 'fixtures/CompleteUse/foo.php', 'kind': 'n'}],
\ res)
" removes the leading \ when its in the base, php manual doesn't recommend
" to type out those since imports are always absolute
let res = phpcomplete#CompleteUse('\Ass')
call VUAssertEquals([
\ {'word': 'Assetic', 'menu': 'fixtures/CompleteUse/foo.php', 'info': 'fixtures/CompleteUse/foo.php', 'kind': 'n'},
\ {'word': 'Assetic\Asset', 'menu': 'fixtures/CompleteUse/foo.php', 'info': 'fixtures/CompleteUse/foo.php', 'kind': 'n'},
\ {'word': 'Assetic\Asset\Iterator', 'menu': 'fixtures/CompleteUse/foo.oho', 'info': 'fixtures/CompleteUse/foo.oho', 'kind': 'n'},
\ {'word': 'Assetic\Cache', 'menu': 'fixtures/CompleteUse/foo.php', 'info': 'fixtures/CompleteUse/foo.php', 'kind': 'n'}],
\ res)
" Should return traits too (tags with kind "t")
let res = phpcomplete#CompleteUse('Some')
call VUAssertEquals([
\ {'word': 'SomeTrait', 'menu': 'fixtures/CompleteUse/foo.php', 'info': 'fixtures/CompleteUse/foo.php', 'kind': 't'}],
\ res)
endf
fun! TestCase_completes_namespaces_and_classes_from_tags_when_a_leading_namespace_is_already_typed_in()
call SetUp()
exe ':set tags='.expand('%:p:h').'/'.'fixtures/CompleteUse/tags'
let res = phpcomplete#CompleteUse('Assetic\Asset\Ba')
call VUAssertEquals([
\ {'word': 'Assetic\Asset\BaseAsset', 'menu': 'fixtures/CompleteUse/foo.php', 'info': 'fixtures/CompleteUse/foo.php', 'kind': 'c'}],
\ res)
" should complete tags matching the word after the last \ when no
" namespaces found in tags file
exe ':set tags='.expand('%:p:h').'/'.'fixtures/CompleteUse/old_style_tags'
let res = phpcomplete#CompleteUse('Assetic\Asset\Ba')
call VUAssertEquals([
\ {'word': 'Assetic\Asset\BaseAsset', 'menu': 'fixtures/CompleteUse/foo.php', 'info': 'fixtures/CompleteUse/foo.php', 'kind': 'c'}],
\ res)
endf
fun! TestCase_honors_the_min_num_of_chars_for_namespace_completion_setting_for_namespaces()
call SetUp()
exe ':set tags='.expand('%:p:h').'/'.'fixtures/CompleteUse/tags'
let g:phpcomplete_min_num_of_chars_for_namespace_completion = 99
let res = phpcomplete#CompleteUse('Assetic\')
call VUAssertEquals([], res)
endf
fun! TestCase_honors_the_min_num_of_chars_for_namespace_completion_setting_for_classnames()
call SetUp()
exe ':set tags='.expand('%:p:h').'/'.'fixtures/CompleteUse/tags'
let g:phpcomplete_min_num_of_chars_for_namespace_completion = 99
let res = phpcomplete#CompleteUse('Assetic\Asset\Ba')
call VUAssertEquals([], res)
endf
" vim: foldmethod=marker:expandtab:ts=4:sts=4

View File

@ -0,0 +1,149 @@
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, 'private')
call VUAssertEquals([
\{'word': 'A_CONST', 'info': 'A_CONST', 'menu': '', 'kind': 'd'},
\{'word': 'final_private_method(', 'info': 'final_private_method($foo = null)', 'menu': '$foo = null)', 'kind': 'f'},
\{'word': 'naked_public_method(', 'info': 'naked_public_method()', 'menu': ')', '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': 'naked_public_method(', 'info': 'naked_public_method()', '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, 'private')
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, 'private')
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, 'private')
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': 'final_static_public_method(', 'info': 'final_static_public_method()', 'menu': ')', 'kind': 'f'},
\ {'word': 'naked_public_method(', 'info': 'naked_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_from_docblock', 'info': "Description:\n Foo\n \n @property DateTime $commented_from_docblock\n", 'menu': '', 'kind': 'v'},
\ {'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
fun! TestCase_returns_static_properties_with_only_a_dollarsign_base()
call SetUp()
let ret = phpcomplete#CompleteUserClass('self::', '$', g:fixture_class_content, 'private')
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'}],
\ ret)
endfun
fun! TestCase_gets_functions_from_implemented_interfaces()
call SetUp()
let fixture_content = readfile(expand('%:p:h').'/'.'fixtures/CompleteUserClass/user_interface_implemented.php')[4:7]
let ret = phpcomplete#CompleteUserClass('$f->', '', fixture_content, 'public')
call VUAssertEquals([
\ {'word': 'bar(', 'info': 'bar($baz = 42)', 'menu': '$baz = 42)', 'kind': 'f'}],
\ ret)
endf
" vim: foldmethod=marker:expandtab:ts=4:sts=4

View File

@ -0,0 +1,75 @@
fun! SetUp()
" disable tag files
exe ':set tags='
" disable builtin variables
let g:php_builtin_vars = {}
let g:phpcomplete_search_tags_for_variables = 0
endf
fun! TestCase_complete_variables_from_current_file()
call SetUp()
let path = expand('%:p:h')."/".'fixtures/CompleteVariable/local_variables.php'
below 1new
exe ":silent! edit ".path
let res = phpcomplete#CompleteVariable('$find')
" -> added for the variable detected as an object
call VUAssertEquals([
\ {'word': '$find_me', 'kind': 'v'},
\ {'word': '$find_me2', 'kind': 'v'},
\ {'word': '$find_me3', 'kind': 'v'},
\ {'word': '$find_me4', 'kind': 'v'}
\],
\ res)
silent! bw! %
endf
fun! TestCase_complete_variables_built_in_global_variable()
call SetUp()
" disable local variables from current file
let path = expand('%:p:h')."/".'fixtures/CompleteVariable/empty.php'
below 1new
exe ":silent! edit ".path
" fill with test data '$this' is in the list to test that filtering
" actually happens to the '$_' base
let g:php_builtin_vars = {
\ '$_GET':'',
\ '$_POST':'',
\ '$this':'',
\ }
let res = phpcomplete#CompleteVariable('$_')
call VUAssertEquals([
\ {'word': '$_GET', 'kind': 'v'},
\ {'word': '$_POST', 'kind': 'v'}],
\ res)
silent! bw! %
endf
fun! TestCase_complete_variables_from_tags()
call SetUp()
" enable variable search in tags
let g:phpcomplete_search_tags_for_variables = 1
" set tags to a fixture
exe ':set tags='.expand('%:p:h').'/'.'fixtures/CompleteVariable/tags'
" disable local variables from current file
let path = expand('%:p:h')."/".'fixtures/CompleteVariable/empty.php'
below 1new
exe ":silent! edit ".path
let res = phpcomplete#CompleteVariable('$find_')
call VUAssertEquals([
\ {'word': '$find_instance_in_tags', 'info': '$find_instance_in_tags class foo', 'menu': 'foo', 'kind': 'v'},
\ {'word': '$find_variable_in_tags', 'kind': 'v'}],
\ res)
silent! bw! %
endf
" vim: foldmethod=marker:expandtab:ts=4:sts=4

View File

@ -0,0 +1,62 @@
fun! SetUp()
exe ':set tags='
endf
fun! TestCase_removes_leading_slash()
call SetUp()
let [classname, namespace] = phpcomplete#ExpandClassName('\ArrayObject', '\', {})
call VUAssertEquals('ArrayObject', classname)
let [classname, namespace] = phpcomplete#ExpandClassName('ArrayObject', '\Mahou', {})
call VUAssertEquals('ArrayObject', classname)
call VUAssertEquals('Mahou', namespace)
endf
fun! TestCase_appends_relative_namespace_parts_from_classname_to_current_namespace()
call SetUp()
let [classname, namespace] = phpcomplete#ExpandClassName('Baz\Foo', 'Bor\Bar', {})
call VUAssertEquals('Foo', classname)
call VUAssertEquals('Bor\Bar\Baz', namespace)
endf
fun! TestCase_extracts_namespace_from_classname_when_its_prefixed_with_absolute_namespace()
call SetUp()
let [classname, namespace] = phpcomplete#ExpandClassName('\Bar\Baz\Foo', 'Mahou', {})
call VUAssertEquals('Foo', classname)
call VUAssertEquals('Bar\Baz', namespace)
endf
fun! TestCase_matches_classname_from_imported_names()
call SetUp()
" imported builtin
let [classname, namespace] = phpcomplete#ExpandClassName('AO', 'Mahou', {'AO': {'name': 'ArrayObject', 'kind': 'c', 'builtin': 1,}})
call VUAssertEquals(['ArrayObject', ''], [classname, namespace])
" imported user class
let [classname, namespace] = phpcomplete#ExpandClassName('Foo', 'Mahou', {'Foo': {'name': 'Foo', 'kind': 'c', 'builtin': 0, 'namespace': 'NS1'}})
call VUAssertEquals(['Foo', 'NS1'], [classname, namespace])
" imported user interface
let [classname, namespace] = phpcomplete#ExpandClassName('FooInterface', 'Mahou', {'FooInterface': {'name': 'FooInterface', 'kind': 'i', 'builtin': 0, 'namespace': 'NS1'}})
call VUAssertEquals(['FooInterface', 'NS1'], [classname, namespace])
" imported user trait
let [classname, namespace] = phpcomplete#ExpandClassName('FooTrait', 'Mahou', {'FooTrait': {'name': 'FooTrait', 'kind': 't', 'builtin': 0, 'namespace': 'NS2'}})
call VUAssertEquals(['FooTrait', 'NS2'], [classname, namespace])
endf
fun! TestCase_matches_namespace_from_imported_names()
" class in imported namespace
let [classname, namespace] = phpcomplete#ExpandClassName('SUBNS\FooSub', 'Mahou', {'SUBNS': {'name': 'NS1\SUBNS', 'kind': 'n', 'builtin': 0,}})
call VUAssertEquals(['FooSub', 'NS1\SUBNS'], [classname, namespace])
" class in imported and renamed namespace
let [classname, namespace] = phpcomplete#ExpandClassName('SUB\FooSub', 'Mahou', {'SUB': {'name': 'NS1\SUBNS', 'kind': 'n', 'builtin': 0,}})
call VUAssertEquals(['FooSub', 'NS1\SUBNS'], [classname, namespace])
endf
" vim: foldmethod=marker:expandtab:ts=4:sts=4

View File

@ -0,0 +1,140 @@
fun! SetUp()
" disable built-in classes
let g:php_builtin_classnames = {}
" disable built-in classes
let g:php_builtin_classes = {}
" disable built-in interfaces
let g:php_builtin_interfacenames = {}
" disable built-in interfaces
let g:php_builtin_interfaces = {}
" disable built-in functions
let g:php_builtin_functions = {}
" disable built-in constants
let g:php_constants = {}
" disable php keywords
let g:php_keywords = {}
" disable tags
exe ':set tags='
" set related options to it's default
let g:phpcomplete_min_num_of_chars_for_namespace_completion = 1
endf
fun! TestCase_can_generates_empty_class() " {{{
call SetUp()
" load fixture with methods and functions in it
let g:php_builtin_classnames['fictionalbuiltinclass'] = ''
let g:php_builtin_classes['fictionalbuiltinclass'] = {
\ 'name': 'FictionalBuiltinClass',
\ 'constants': {
\ },
\ 'properties': {
\ },
\ 'static_properties': {
\ },
\ 'methods': {
\ },
\ 'static_methods': {
\ },
\}
let res = phpcomplete#GenerateBuiltinClassStub('class', g:php_builtin_classes['fictionalbuiltinclass'])
call VUAssertEquals({
\ 'file': 'VIMPHP_BUILTINOBJECT',
\ 'mtime': 0,
\ 'namespace': '',
\ 'class': 'FictionalBuiltinClass',
\ 'imports': {},
\ 'content': "class FictionalBuiltinClass {\n}",
\}, res)
endf " }}}
fun! TestCase_can_generates_empty_interface() " {{{
call SetUp()
" load fixture with methods and functions in it
let g:php_builtin_interfacenames['fictionalbuiltininterface'] = ''
let g:php_builtin_interfaces['fictionalbuiltininterface'] = {
\ 'name': 'FictionalBuiltinInterface',
\ 'methods': {
\ },
\}
let res = phpcomplete#GenerateBuiltinClassStub('interface', g:php_builtin_interfaces['fictionalbuiltininterface'])
call VUAssertEquals({
\ 'file': 'VIMPHP_BUILTINOBJECT',
\ 'mtime': 0,
\ 'namespace': '',
\ 'interface': 'FictionalBuiltinInterface',
\ 'imports': {},
\ 'content': "interface FictionalBuiltinInterface {\n}",
\}, res)
endf " }}}
fun! TestCase_can_generates_class_from_class_info() " {{{
call SetUp()
" load fixture with methods and functions in it
let g:php_builtin_classnames['fictionalbuiltinclass'] = ''
let g:php_builtin_classes['fictionalbuiltinclass'] = {
\ 'name': 'FictionalBuiltinClass',
\ 'constants': {
\ 'IS_PUBLIC': '256',
\ },
\ 'properties': {
\ 'name': { 'initializer': '2', 'type': 'Foo'},
\ },
\ 'static_properties': {
\ '$_app': { 'initializer': '3', 'type': 'Foo2'},
\ },
\ 'methods': {
\ '__construct': { 'signature': 'string $name', 'return_type': 'Foo'},
\ 'getName': { 'signature': 'object $object | Closure', 'return_type': 'Closure'},
\ },
\ 'static_methods': {
\ 'export': { 'signature': 'mixed $class, string $name [, bool $return] | string', 'return_type': 'string'},
\ },
\}
let path = expand('%:p:h').'/'.'fixtures/GenerateBuiltinClassStub/fictionalbuiltinclass.txt'
let good_answer = join(readfile(path), "\n")
let res = phpcomplete#GenerateBuiltinClassStub('class', g:php_builtin_classes['fictionalbuiltinclass'])
call VUAssertEquals({
\ 'file': 'VIMPHP_BUILTINOBJECT',
\ 'mtime': 0,
\ 'namespace': '',
\ 'class': 'FictionalBuiltinClass',
\ 'imports': {},
\ 'content': good_answer,
\}, res)
endf " }}}
fun! TestCase_can_generates_class_from_class_info() " {{{
call SetUp()
" load fixture with methods and functions in it
let g:php_builtin_interfacenames['arrayaccess'] = ''
let g:php_builtin_interfaces['arrayaccess'] = {
\ 'name': 'ArrayAccess',
\ 'methods': {
\ 'offsetExists': { 'signature': 'mixed $offset | boolean', 'return_type': 'boolean'},
\ 'offsetGet': { 'signature': 'mixed $offset | mixed', 'return_type': 'mixed'},
\ 'offsetSet': { 'signature': 'mixed $offset, mixed $value | void', 'return_type': 'void'},
\ 'offsetUnset': { 'signature': 'mixed $offset | void', 'return_type': 'void'},
\ },
\}
let path = expand('%:p:h').'/'.'fixtures/GenerateBuiltinClassStub/arrayaccess.txt'
let good_answer = join(readfile(path), "\n")
let res = phpcomplete#GenerateBuiltinClassStub('interface', g:php_builtin_interfaces['arrayaccess'])
call VUAssertEquals({
\ 'file': 'VIMPHP_BUILTINOBJECT',
\ 'mtime': 0,
\ 'namespace': '',
\ 'interface': 'ArrayAccess',
\ 'imports': {},
\ 'content': good_answer,
\}, res)
endf " }}}
" vim: foldmethod=marker:expandtab:ts=4:sts=4

View File

@ -0,0 +1,239 @@
fun! SetUp()
exe 'set tags='.expand('%:p:h')."/".'fixtures/GetClassContents/tags'
let g:php_builtin_classes = {}
let g:php_builtin_classnames = {}
let g:php_builtin_interfacenames = {}
let g:php_builtin_interfaces = {}
endf
fun! TestCase_reads_in_the_class_from_the_list_of_lines()
call SetUp()
let location = expand('%:p:h')."/".'fixtures/GetClassContents/foo.class.php'
let contents = phpcomplete#GetClassContents(location, 'FooClass')
let expected = join(readfile(location)[1:], "\n")
call VUAssertEquals(expected, contents)
let location = expand('%:p:h')."/".'fixtures/GetClassContents/foo_whitespace.class.php'
let contents = phpcomplete#GetClassContents(location, 'FooClass')
let expected = join(readfile(location)[4:9], "\n")
call VUAssertEquals(expected, contents)
let location = expand('%:p:h')."/".'fixtures/GetClassContents/foo.interface.php'
let contents = phpcomplete#GetClassContents(location, 'FooInterface')
let expected = join(readfile(location)[1:], "\n")
call VUAssertEquals(expected, contents)
endf
fun! TestCase_only_reads_in_the_class_content()
call SetUp()
let location = expand('%:p:h')."/".'fixtures/GetClassContents/foo_with_extra_content.class.php'
let contents = phpcomplete#GetClassContents(location, 'FooClass')
let expected = join(readfile(location)[5:8], "\n")
call VUAssertEquals(expected, contents)
endf
fun! TestCase_reads_in_the_extended_class_content()
call SetUp()
" tags used to find the extended classes
exe 'set tags='.expand('%:p:h')."/".'fixtures/GetClassContents/tags'
let location = expand('%:p:h')."/".'fixtures/GetClassContents/extends/foo_extends_bar.class.php'
let extends_location = expand('%:p:h')."/".'fixtures/GetClassContents/extends/bar.class.php'
let contents = phpcomplete#GetClassContents(location, 'FooClass')
let expected = readfile(location)[2]."\n".readfile(extends_location)[2]
call VULog(expected)
call VUAssertEquals(expected, contents)
endf
fun! TestCase_reads_in_the_extended_classes_recursive()
call SetUp()
" tags used to find the extended classes
exe 'set tags='.expand('%:p:h')."/".'fixtures/GetClassContents/tags'
let location = expand('%:p:h')."/".'fixtures/GetClassContents/extends_extends/foo2_extends_bar2.class.php'
let extends_location = expand('%:p:h')."/".'fixtures/GetClassContents/extends_extends/bar2_extends_baz.class.php'
let extends_extends_location = expand('%:p:h')."/".'fixtures/GetClassContents/extends_extends/baz.class.php'
let expected = readfile(location)[2]."\n"
let expected .= readfile(extends_location)[2]."\n"
let expected .= readfile(extends_extends_location)[2]
call VULog(expected)
let contents = phpcomplete#GetClassContents(location, 'FooClass2')
call VUAssertEquals(expected, contents)
endf
fun! TestCase_reads_in_the_extended_classes_recursive_with_namespaces()
call SetUp()
" tags used to find the extended classes
exe 'set tags='.expand('%:p:h')."/".'fixtures/GetClassContents/tags'
let location = expand('%:p:h')."/".'fixtures/GetClassContents/ns1_foo2.php'
let extends_location = expand('%:p:h')."/".'fixtures/GetClassContents/ns2_foo.php'
let expected = readfile(location)[3]."\n"
let expected .= readfile(extends_location)[3]
call VULog(expected)
let contents = phpcomplete#GetClassContents(location, 'NamespacedFoo2')
call VUAssertEquals(expected, contents)
endf
fun! TestCase_reads_in_the_extended_classes_with_imports()
call SetUp()
" tags used to find the extended classes
exe 'set tags='.expand('%:p:h')."/".'fixtures/GetClassContents/import/tags'
let g:php_builtin_classes = {}
let location = expand('%:p:h')."/".'fixtures/GetClassContents/import/ns1_foo2.php'
let extends_location = expand('%:p:h')."/".'fixtures/GetClassContents/import/ns2_foo.php'
let expected = readfile(location)[4]."\n"
let expected .= readfile(extends_location)[3]
call VULog(expected)
let contents = phpcomplete#GetClassContents(location, 'NamespacedFoo2')
call VUAssertEquals(expected, contents)
endf
fun! TestCase_handles_matching_class_name_extends_with_different_namespaces()
call SetUp()
" tags used to find the extended classes
exe 'set tags='.expand('%:p:h')."/".'fixtures/GetClassContents/same_classname/tags'
let location = expand('%:p:h')."/".'fixtures/GetClassContents/same_classname/foo.class.php'
let extends_location = expand('%:p:h')."/".'fixtures/GetClassContents/same_classname/ns1_foo.class.php'
let class_contents = readfile(location)[2:10]
let expected = join(class_contents, "\n")."\n"
let expected .= readfile(extends_location)[4]
below 1new
exe ":silent! edit ".location
exe ':7'
let structure = phpcomplete#GetClassContentsStructure(location, class_contents, 'Foo')
call VUAssertEquals(expected, structure[0].content."\n".structure[1].content)
silent! bw! %
endf
" fails with the dist version
fun! TestCase_returns_contents_of_a_class_regardless_of_comments_or_strings()
let path1 = expand('%:p:h')."/".'fixtures/GetClassContents/foo2.class.php'
let expected1 = join(readfile(path1)[2:12], "\n")
let contents1 = readfile(path1)
below 1new
exe ":silent! edit ".path1
let structure = phpcomplete#GetClassContentsStructure(path1, contents1, 'Foo2')
call VUAssertEquals(expected1, structure[0].content)
silent! bw! %
endf
fun! TestCase_returns_contents_of_used_traits_too()
call SetUp()
exe 'set tags='.expand('%:p:h')."/".'fixtures/GetClassContents/tags'
let path1 = expand('%:p:h')."/".'fixtures/GetClassContents/foo3.class.php'
let path2 = expand('%:p:h')."/".'fixtures/GetClassContents/foo.trait.php'
let expected = join(readfile(path1)[2:7], "\n")."\n".join(readfile(path2)[2:4], "\n")
below 1new
exe ":silent! edit ".path1
let contents = phpcomplete#GetClassContents(path1, 'Foo3')
call VUAssertEquals(expected, contents)
silent! bw! %
endf
fun! TestCase_returns_class_content_from_inside_the_same_file()
call SetUp()
let location = expand('%:p:h')."/".'fixtures/GetClassContents/same_file_class.php'
let class_contents = readfile(location)[4:6]
let expected = join(class_contents, "\n")."\n"
let expected .= readfile(location)[2]
let expected2 = join(readfile(location)[8:10], "\n")
below 1new
exe ":silent! edit ".location
" Even if there's no tags or other help to locate the extended class, the
" plugin should try to find it in the same file that the extending class
" located
exe ':8'
let structure = phpcomplete#GetClassContentsStructure(location, readfile(location), 'SomeTraitedClass')
call VUAssertEquals(expected, structure[0].content."\n".structure[1].content)
" The function should just skip any non-locatable extended class
exe ':12'
let structure = phpcomplete#GetClassContentsStructure(location, readfile(location), 'ExtendsNonExistsing')
call VUAssertEquals(expected2, structure[0].content)
silent! bw! %
endf
fun! TestCase_returns_contents_of_implemented_interfaces()
call SetUp()
exe 'set tags='.expand('%:p:h')."/".'fixtures/GetClassContents/interface_tags'
let path1 = expand('%:p:h')."/".'fixtures/GetClassContents/interfaces.php'
let path2 = expand('%:p:h')."/".'fixtures/GetClassContents/implements.php'
let expected = join(readfile(path2)[2:3], "\n")."\n".join(readfile(path1)[2:3], "\n")
let expected2 = join(readfile(path2)[5:6], "\n")."\n".join(readfile(path1)[2:3], "\n")."\n".join(readfile(path1)[5:6], "\n")
below 1new
exe ":silent! edit ".path2
let contents = phpcomplete#GetClassContents(path2, 'X')
call VUAssertEquals(expected, contents)
let contents2 = phpcomplete#GetClassContents(path2, 'Y')
call VUAssertEquals(expected2, contents2)
silent! bw! %
endf
fun! TestCase_returns_the_contents_of_extended_interfaces()
call SetUp()
exe 'set tags='
let path = expand('%:p:h')."/".'fixtures/GetClassContents/interfaces.php'
below 1new
exe ":silent! edit ".path
let contents = phpcomplete#GetClassContentsStructure(path, readfile(path), 'FooFoo2')
call VUAssertEquals('FooFoo2', contents[0].class)
call VUAssertEquals('Foo', contents[1].class)
call VUAssertEquals('Foo2', contents[2].class)
silent! bw! %
endf
fun! TestCase_returns_the_contents_of_extended_interfaces()
call SetUp()
exe 'set tags='
let path = expand('%:p:h')."/".'fixtures/GetClassContents/docblocked_foo.php'
let expected = join(readfile(path)[2:], "\n")
below 1new
exe ":silent! edit ".path
let contents = phpcomplete#GetClassContentsStructure(path, readfile(path), 'DocBlockedFoo')
call VUAssertEquals(expected, contents[0].content, "Should read class contents with it's docblock")
silent! bw! %
endf
" vim: foldmethod=marker:expandtab:ts=4:sts=4

View File

@ -0,0 +1,80 @@
fun! SetUp()
" disable builtin information
let g:php_builtin_classnames = {}
let g:php_builtin_classes = {}
let g:php_builtin_interfaces = {}
let g:php_builtin_interfacenames = {}
" disable tag files
exe ':set tags='
endf
fun! TestCase_return_VIMPHP_BUILTINOBJECT_when_classname_in_builtin_classes()
call SetUp()
let g:php_builtin_classnames = {'datetime': ''}
let g:php_builtin_classes = {
\'datetime':{}
\}
let res = phpcomplete#GetClassLocation('DateTime', '')
call VUAssertEquals('VIMPHP_BUILTINOBJECT', res)
let res = phpcomplete#GetClassLocation('DateTime', '\')
call VUAssertEquals('VIMPHP_BUILTINOBJECT', res)
endf
fun! TestCase_return_current_file_path_when_classname_found_in_previous_lines_of_current_buffer()
call SetUp()
let path = expand('%:p:h').'/'.'fixtures/GetClassLocation/foo.class.php'
below 1new
exe ":silent! edit ".path
exe ':6'
let res = phpcomplete#GetClassLocation('Foo', '')
call VUAssertEquals(path, res)
exe ':14'
let res = phpcomplete#GetClassLocation('Foo2', '')
call VUAssertEquals(path, res)
exe ':21'
let res = phpcomplete#GetClassLocation('Foo3', '')
call VUAssertEquals(path, res)
silent! bw! %
endf
fun! TestCase_return_class_location_from_tags()
call SetUp()
let tags_path = expand('%:p:h').'/'.'fixtures/GetClassLocation/tags'
let old_style_tags_path = expand('%:p:h').'/'.'fixtures/GetClassLocation/old_style_tags'
let path = expand('%:p:h').'/'.'fixtures/GetClassLocation/empty.php'
exe ':set tags='.tags_path
below 1new
exe ":silent! edit ".path
exe ':3'
let res = phpcomplete#GetClassLocation('Foo', '')
call VUAssertEquals('fixtures/GetClassLocation/foo.class.php', res)
let res = phpcomplete#GetClassLocation('FooInterface', '')
call VUAssertEquals('fixtures/GetClassLocation/foo.class.php', res)
let res = phpcomplete#GetClassLocation('FooTrait', '')
call VUAssertEquals('fixtures/GetClassLocation/foo.class.php', res)
" when there are no namespaces to match for the classes from the tags file
" should return the first class's location where the name matches
exe ':set tags='.old_style_tags_path
let res = phpcomplete#GetClassLocation('Foo', '')
call VUAssertEquals('fixtures/GetClassLocation/foo.class.php', res)
let res = phpcomplete#GetClassLocation('FooInterface', '')
call VUAssertEquals('fixtures/GetClassLocation/foo.class.php', res)
silent! bw! %
endf
" vim: foldmethod=marker:expandtab:ts=4:sts=4

View File

@ -0,0 +1,923 @@
fun! SetUp()
let g:php_builtin_classes = {}
let g:php_builtin_classnames = {}
let g:php_builtin_interfacenames = {}
let g:php_builtin_interfaces = {}
let g:php_builtin_functions = {}
endf
fun! TestCase_extract_class_from_the_same_file_when_line_referes_to_this()
call SetUp()
let path = expand('%:p:h')."/"."fixtures/GetClassName/foo.class.php"
below 1new
exe ":silent! edit ".path
exe ':6'
let classname = phpcomplete#GetClassName(6, '$this->', '\', {})
call VUAssertEquals('FooClass', classname)
let classname = phpcomplete#GetClassName(6, '$this->', 'Foo', {})
call VUAssertEquals('Foo\FooClass', classname)
exe ':7'
let classname = phpcomplete#GetClassName(7, 'self::', '\', {})
call VUAssertEquals('FooClass', classname)
silent! bw! %
" detection should work with extra whitespace
" around keywords or uppercase keywords
let path = expand('%:p:h')."/"."fixtures/GetClassName/foo_with_whitespace.class.php"
below 1new
exe ":silent! edit ".path
exe ':10'
let classname = phpcomplete#GetClassName(10, '$this->', '\', {})
call VUAssertEquals('FooClass', classname)
exe ':11'
let classname = phpcomplete#GetClassName(11, 'self::', '\', {})
call VUAssertEquals('FooClass', classname)
silent! bw! %
endf
fun! TestCase_returns_empty_when_sees_curlyclose_on_line_start()
call SetUp()
let path = expand('%:p:h')."/"."fixtures/GetClassName/foo_outside.class.php"
below 1new
exe ":silent! edit ".path
exe ':6'
let classname = phpcomplete#GetClassName(6, '$this->', '\', {})
call VUAssertEquals('', classname)
exe ':7'
let classname = phpcomplete#GetClassName(7, 'self::', '\', {})
call VUAssertEquals('', classname)
silent! bw! %
endf
fun! TestCase_finds_abstract_classes()
call SetUp()
let path = expand('%:p:h')."/"."fixtures/GetClassName/foo_abstract.class.php"
below 1new
exe ":silent! edit ".path
exe ':6'
let classname = phpcomplete#GetClassName(6, '$this->', '\', {})
call VUAssertEquals('FooAbstract', classname)
exe ':7'
let classname = phpcomplete#GetClassName(7, 'self::', '\', {})
call VUAssertEquals('FooAbstract', classname)
silent! bw! %
" detection should work with extra whitespace
" around keywords or uppercase keywords
let path = expand('%:p:h')."/"."fixtures/GetClassName/foo_abstract_with_whitespace.class.php"
below 1new
exe ":silent! edit ".path
exe ':10'
let classname = phpcomplete#GetClassName(10, '$this->', '\', {})
call VUAssertEquals('FooAbstract', classname)
exe ':12'
let classname = phpcomplete#GetClassName(12, 'self::', '\', {})
call VUAssertEquals('FooAbstract', classname)
silent! bw! %
endf
fun! TestCase_finds_new_keyword_instantiations_in_parentheses_from_php5_4()
call SetUp()
let classname = phpcomplete#GetClassName(1, '$a = (new FooClass)->', '\', {})
call VUAssertEquals('FooClass', classname)
let classname = phpcomplete#GetClassName(1, '$a = (new \Foo\FooClass)->', 'Bar', {})
call VUAssertEquals('Foo\FooClass', classname)
let classname = phpcomplete#GetClassName(1, '$a = (new FooClass)->', 'Bar', {})
call VUAssertEquals('Bar\FooClass', classname)
endf
fun! TestCase_finds_variables_marked_with_AT_VAR_comments()
call SetUp()
let path = expand('%:p:h')."/"."fixtures/GetClassName/var_comment_mark.php"
below 1new
exe ":silent! edit ".path
exe ':3'
let classname = phpcomplete#GetClassName(3, '$bar->', '\', {})
call VUAssertEquals('FooClass', classname)
exe ':6'
let classname = phpcomplete#GetClassName(6, '$bar2->', '\', {})
call VUAssertEquals('FooClass', classname)
let classname = phpcomplete#GetClassName(6, '$bar2->', 'Bar', {})
call VUAssertEquals('Bar\FooClass', classname)
exe ':9'
let classname = phpcomplete#GetClassName(9, '$bar3->', '\', {'Renamed': {'name': 'OriginalFoo', 'kind': 'c', 'builtin':0,}})
call VUAssertEquals('OriginalFoo', classname)
exe ':13'
let classname = phpcomplete#GetClassName(13, '$foo_conflicting_sources->', '\', {})
call VUAssertEquals('Foo', classname, 'when multiple sources available for the class name, explicit marker takes precedence')
exe ':19'
let classname = phpcomplete#GetClassName(19, '$foo2->', '\', {})
call VUAssertEquals('Foo2', classname)
exe ':25'
let classname = phpcomplete#GetClassName(25, '$foo3->', '\', {})
call VUAssertEquals('Foo3', classname)
exe ':28'
let classname = phpcomplete#GetClassName(28, '$foo2->', '\', {})
call VUAssertEquals('Foo2', classname)
exe ':32'
let classname = phpcomplete#GetClassName(32, '$baz->', '\', {})
call VUAssertEquals('FooClass2', classname)
exe ':35'
let classname = phpcomplete#GetClassName(35, '$baz2->', '\', {})
call VUAssertEquals('FooClass2', classname)
exe ':38'
let classname = phpcomplete#GetClassName(38, '$baz3->', 'Bar', {})
call VUAssertEquals('Bar\FooClass2', classname)
silent! bw! %
endf
fun! TestCase_finds_classes_from_variable_equals_new_class_lines()
call SetUp()
let path = expand('%:p:h')."/"."fixtures/GetClassName/foo_equals_new_foo.php"
below 1new
exe ":silent! edit ".path
exe ':4'
let classname = phpcomplete#GetClassName(4, '$foo->', '\', {})
call VUAssertEquals('FooClass', classname)
exe ':4'
let classname = phpcomplete#GetClassName(4, '$foo->', 'Bar', {})
call VUAssertEquals('Bar\FooClass', classname)
exe ':8'
let classname = phpcomplete#GetClassName(8, '$foo2->', '\', {'RenamedFoo': {'name': 'OriginalFoo', 'kind': 'c', 'builtin':0,}})
call VUAssertEquals('OriginalFoo', classname)
exe ':12'
let classname = phpcomplete#GetClassName(12, '$foo3->', 'NS1', {})
call VUAssertEquals('NS2\Foo', classname)
silent! bw! %
endf
fun! TestCase_finds_common_singleton_getInstance_calls()
call SetUp()
let path = expand('%:p:h')."/"."fixtures/GetClassName/singleton_getinstance.php"
below 1new
exe ":silent! edit ".path
exe ':4'
let classname = phpcomplete#GetClassName(4, '$foo->', '\', {})
call VUAssertEquals('FooClass', classname)
exe ':4'
let classname = phpcomplete#GetClassName(4, '$foo->', 'Bar', {})
call VUAssertEquals('Bar\FooClass', classname)
exe ':8'
let classname = phpcomplete#GetClassName(8, '$foo2->', '\', {'RenamedFoo': {'name': 'OriginalFoo', 'kind': 'c', 'builtin':0,}})
call VUAssertEquals('OriginalFoo', classname)
exe ':10'
let classname = phpcomplete#GetClassName(12, '$foo3->', 'NS1', {})
call VUAssertEquals('NS2\Foo', classname)
silent! bw! %
endf
fun! TestCase_returns_return_type_of_built_in_objects_static_methods()
call SetUp()
let path = expand('%:p:h')."/"."fixtures/GetClassName/builtin_static_return_type.php"
below 1new
exe ":silent! edit ".path
exe ':4'
call phpcomplete#LoadData()
let classname = phpcomplete#GetClassName(4, '$d->', '\', {})
call VUAssertEquals('DateTime', classname)
" built in class return values should not be affected by current namespace
exe ':4'
call phpcomplete#LoadData()
let classname = phpcomplete#GetClassName(4, '$d->', 'Bar', {})
call VUAssertEquals('DateTime', classname)
exe ':7'
call phpcomplete#LoadData()
let classname = phpcomplete#GetClassName(7, '$d->', '\', {'DT': {'name': 'DateTime', 'kind': 'c', 'builtin':1,}})
call VUAssertEquals('DateTime', classname)
silent! bw! %
endf
fun! TestCase_returns_class_from_static_method_call()
call SetUp()
let classname = phpcomplete#GetClassName(1, 'FooClass::', '\', {})
call VUAssertEquals('FooClass', classname)
let classname = phpcomplete#GetClassName(1, 'FooClass::', 'Bar', {})
call VUAssertEquals('Bar\FooClass', classname)
let classname = phpcomplete#GetClassName(1, 'RenamedFoo::', '\', {'RenamedFoo': {'name': 'OriginalFoo', 'kind': 'c', 'builtin':0,}})
call VUAssertEquals('OriginalFoo', classname)
endf
fun! TestCase_returns_class_from_tags_with_tag_of_v_kind_and_a_new_equals_class_cmd()
call SetUp()
" see TAGS file in the tests/fixtures/GetClassName directory
exe 'set tags='.expand('%:p:h')."/".'fixtures/GetClassName/TAGS'
" enable variable search in tags
let g:phpcomplete_search_tags_for_variables = 1
let path = expand('%:p:h')."/"."fixtures/GetClassName/foo_only_from_tags.php"
below 1new
exe ":silent! edit ".path
exe ':3'
let classname = phpcomplete#GetClassName(3, '$foo_only_in_tags->', '\', {})
call VUAssertEquals('FooClass', classname)
exe ':4'
let classname = phpcomplete#GetClassName(4, '$namespaced_foo_only_in_tags->', '\', {})
call VUAssertEquals('Test\FooClass', classname)
" TODO
" exe ':6'
" let classname = phpcomplete#GetClassName('$foo_only_in_tags::')
" call VUAssertEquals('FooClass', classname)
silent! bw! %
endf
fun! TestCase_extract_typehint_from_function_calls()
call SetUp()
call phpcomplete#LoadData()
let path = expand('%:p:h')."/"."fixtures/GetClassName/typehinted_functions.php"
below 1new
exe ":silent! edit ".path
exe ':4'
let classname = phpcomplete#GetClassName(4, '$bar->', '\', {})
call VUAssertEquals('FooClass1', classname)
" typehinds are affected by current namespace as everyting else
let classname = phpcomplete#GetClassName(4, '$bar->', 'Bar', {})
call VUAssertEquals('Bar\FooClass1', classname)
exe ':8'
let classname = phpcomplete#GetClassName(8, '$bar->', '\', {})
call VUAssertEquals('FooClass2', classname)
exe ':12'
let classname = phpcomplete#GetClassName(12, '$bar->', '\', {})
call VUAssertEquals('FooClass3', classname)
exe ':16'
let classname = phpcomplete#GetClassName(16, '$bar->', '\', {})
call VUAssertEquals('FooClass4', classname)
exe ':20'
let classname = phpcomplete#GetClassName(20, '$bar->', '\', {})
call VUAssertEquals('FooClass5', classname)
exe ':24'
let classname = phpcomplete#GetClassName(24, '$bar->', '\', {})
call VUAssertEquals('FooClass6', classname)
exe ':28'
let classname = phpcomplete#GetClassName(28, '$bar->', '\', {})
call VUAssertEquals('FooClass7', classname)
exe ':33'
let classname = phpcomplete#GetClassName(33, '$bar->', '\', {})
call VUAssertEquals('FooClass8', classname)
exe ':40'
let classname = phpcomplete#GetClassName(40, '$bar->', '\', {})
call VUAssertEquals('FooClass9', classname, 'expect $baz to use type-hinting from class method')
exe ':45'
let classname = phpcomplete#GetClassName(45, '$baz->', '\', {})
call VUAssertEquals('FooClass10', classname, 'expect $baz to use type-hinting from class method')
exe ':50'
let classname = phpcomplete#GetClassName(50, '$bar->', '\', {'RenamedFoo': {'name': 'OriginalFoo', 'kind': 'c', 'builtin':0,}})
call VUAssertEquals('OriginalFoo', classname)
exe ':58'
let classname = phpcomplete#GetClassName(58, '$multi->', '\', {})
call VUAssertEquals('DateTime', classname)
silent! bw! %
endf
fun! TestCase_extract_parameter_type_from_docblock()
call SetUp()
let path = expand('%:p:h')."/"."fixtures/GetClassName/function_docblock.php"
below 1new
exe ":silent! edit ".path
exe ':11'
let classname = phpcomplete#GetClassName(11, '$bar1->', '\', {})
call VUAssertEquals('BarClass1', classname)
exe ':11'
let classname = phpcomplete#GetClassName(11, '$bar1->', 'Bar', {})
call VUAssertEquals('Bar\BarClass1', classname)
exe ':27'
let classname = phpcomplete#GetClassName(27, '$bar2->', '\', {})
call VUAssertEquals('BarClass2', classname)
exe ':39'
let classname = phpcomplete#GetClassName(39, '$bar3->', '\', {})
call VUAssertEquals('BarClass3', classname)
exe ':54'
let classname = phpcomplete#GetClassName(54, '$docblocked->', '\', {})
call VUAssertEquals('DateTime', classname)
silent! bw! %
endf
fun! TestCase_returns_static_function_calls_return_type()
call SetUp()
exe 'set tags='.expand('%:p:h')."/".'fixtures/GetClassName/static_docblock_return_tags'
let path = expand('%:p:h').'/'.'fixtures/GetClassName/static_docblock_return.php'
below 1new
exe ":silent! edit ".path
exe ':15'
let classname = phpcomplete#GetClassName(15, '$u->', '\', {})
call VUAssertEquals('User', classname)
silent! bw! %
endf
fun! TestCase_returns_static_function_calls_retun_type_with_namespaces()
call SetUp()
let imports = {'P': {'name': 'Page', 'namespace': 'Foo', 'kind': 'c', 'builtin': 0}, 'RenamedFoo': {'name': 'Foo', 'kind': 'n', 'builtin': 0}}
exe 'set tags='.expand('%:p:h').'/'.'fixtures/GetClassName/static_docblock_return_tags'
let path = expand('%:p:h').'/'.'fixtures/GetClassName/static_docblock_namespaced.php'
below 1new
exe ":silent! edit ".path
exe ':32'
let classname = phpcomplete#GetClassName(32, '$p->', 'Foo', imports)
call VUAssertEquals('Foo\Page', classname)
exe ':35'
let classname = phpcomplete#GetClassName(35, '$p->', 'Foo', imports)
call VUAssertEquals('Foo\Page', classname)
exe ':38'
let classname = phpcomplete#GetClassName(38, '$p->', 'Foo', imports)
call VUAssertEquals('Foo\Page', classname)
exe ':41'
let classname = phpcomplete#GetClassName(41, '$p->', 'Foo', imports)
call VUAssertEquals('Foo\Page', classname)
exe ':44'
let classname = phpcomplete#GetClassName(44, '$p->', 'Foo', imports)
call VUAssertEquals('Foo\Page', classname)
exe ':47'
let classname = phpcomplete#GetClassName(47, '$p->', 'Foo', imports)
call VUAssertEquals('Foo\Page', classname)
exe ':50'
let classname = phpcomplete#GetClassName(50, '$p->', 'Foo', imports)
call VUAssertEquals('Foo\Page', classname)
silent! bw! %
endf
fun! TestCase_returns_static_function_calls_retun_type_with_namespaces_from_the_global_scope()
call SetUp()
let imports = {'Page': {'name': 'Page', 'namespace': 'Foo', 'kind': 'c', 'builtin': 0}}
exe 'set tags='.expand('%:p:h').'/'.'fixtures/GetClassName/static_docblock_namespaced_tags'
let path = expand('%:p:h').'/'.'fixtures/GetClassName/static_docblock_namespaced_imported.php'
below 1new
exe ":silent! edit ".path
exe ':5'
let classname = phpcomplete#GetClassName(5, '$p->', '', imports)
call VUAssertEquals('Foo\Page', classname)
silent! bw! %
endf
fun! TestCase_resolves_call_chains_return_type_with_this()
call SetUp()
let path = expand('%:p:h')."/"."fixtures/GetClassName/foo_method_chains.php"
below 1new
exe ":silent! edit ".path
exe ':89'
let classname = phpcomplete#GetClassName(89, '$this->', 'FooNS', {})
call VUAssertEquals('FooNS\Foo', classname)
exe ':85'
let classname = phpcomplete#GetClassName(85, '$this->getSomething()->', 'FooNS', {})
call VUAssertEquals('FooNS\SomethingNS\Something', classname)
exe ':53'
let classname = phpcomplete#GetClassName(53, '$this->getSomething()->', 'FooNS\SubNameSpace', {})
call VUAssertEquals('FooNS\SomethingNS\Something', classname)
silent! bw! %
endf
fun! TestCase_resolves_call_chains_return_type_with_tags()
call SetUp()
exe 'set tags='.expand('%:p:h')."/".'fixtures/GetClassName/tags_inheritance'
let path = expand('%:p:h')."/"."fixtures/GetClassName/foo_inheritance_level1.php"
below 1new
exe ":silent! edit ".path
exe ':13'
let classname = phpcomplete#GetClassName(13, '$this->', 'NS1\SubNS2', {})
call VUAssertEquals('NS1\SubNS2\Level1', classname)
exe ':14'
let classname = phpcomplete#GetClassName(14, '$this->getLevel31Instance()->', 'NS1\SubNS2', {})
call VUAssertEquals('NS31\SubNS\Level31', classname)
exe ':15'
let classname = phpcomplete#GetClassName(15, '$this->getAnother31Instance()->', 'NS1\SubNS2', {})
call VUAssertEquals('NS31\SubNS\Level31', classname)
silent! bw! %
endf
fun! TestCase_resolves_call_chains_return_type_with_php5_4_new()
call SetUp()
let path = expand('%:p:h')."/"."fixtures/GetClassName/foo_new_oneline_chain.php"
below 1new
exe ":silent! edit ".path
exe ':18'
let classname = phpcomplete#GetClassName(18, '(new Foo)->return_bar()->', '\', {})
call VUAssertEquals('Bar', classname)
silent! bw! %
endf
fun! TestCase_resolves_call_chains_return_type_with_when_chain_head_class_detectable()
call SetUp()
let path = expand('%:p:h')."/"."fixtures/GetClassName/call_chains.php"
below 1new
exe ":silent! edit ".path
exe ':68'
let classname = phpcomplete#GetClassName(68, '$foo->return_bar()->return_foo()->return_bar()->', '\', {})
call VUAssertEquals('Bar', classname)
exe ':71'
let classname = phpcomplete#GetClassName(71, '$foo->return_bar()->return_foo()->return_bar()->', '\', {})
call VUAssertEquals('Bar', classname)
exe ':74'
let classname = phpcomplete#GetClassName(74, '$foo->return_bar()->return_foo()->return_bar()->', '\', {})
call VUAssertEquals('Bar', classname)
exe ':77'
let classname = phpcomplete#GetClassName(77, '$foo->bar->', '\', {})
call VUAssertEquals('Bar', classname)
exe ':78'
let classname = phpcomplete#GetClassName(78, '$foo->bar->', '\', {})
call VUAssertEquals('Bar', classname)
exe ':79'
let classname = phpcomplete#GetClassName(79, '$foo->bar->', '\', {})
call VUAssertEquals('Bar', classname)
exe ':80'
let classname = phpcomplete#GetClassName(80, '$foo->bar->foo->', '\', {})
call VUAssertEquals('Foo', classname)
exe ':132'
let classname = phpcomplete#GetClassName(132, '$foo3->return_self()->return_()->', '\', {})
call VUAssertEquals('Foo', classname)
exe ':145'
let classname = phpcomplete#GetClassName(145, '$commentedFoo->docBlockProperty->', '\', {})
call VUAssertEquals('DateTime', classname)
silent! bw! %
endf
fun! TestCase_resolves_call_chains_return_type_with_when_chain_head_class_detectable_with_builtin_types()
call phpcomplete#LoadData()
let path = expand('%:p:h')."/"."fixtures/GetClassName/call_chains.php"
below 1new
exe ":silent! edit ".path
exe ':87'
let classname = phpcomplete#GetClassName(87, '$doc->createAttribute()->ownerElement->', '\', {})
call VUAssertEquals('DOMElement', classname)
exe ':90'
let classname = phpcomplete#GetClassName(90, '$d->add()->getTimezone()->', '\', {})
call VUAssertEquals('DateTimeZone', classname)
exe ':94'
let classname = phpcomplete#GetClassName(94, '$tz->', '\', {})
call VUAssertEquals('DateTimeZone', classname)
exe ':98'
let classname = phpcomplete#GetClassName(98, '$foobar->', '\', {})
call VUAssertEquals('Foo', classname)
" set up place of the opening <?php, this would be set up from the main
" completion function for the current completion
exe 'let b:phpbegin = [0, 0]'
exe ':105'
let classname = phpcomplete#GetClassName(105, '$bar2->', '\', {})
call VUAssertEquals('Bar', classname)
exe ':109'
let classname = phpcomplete#GetClassName(109, '$bar3->return_foo()->', '\', {})
call VUAssertEquals('Foo', classname)
silent! bw! %
endf
fun! TestCase_handles_array_completion()
call phpcomplete#LoadData()
let path = expand('%:p:h')."/"."fixtures/GetClassName/arrays.php"
below 1new
exe ":silent! edit ".path
exe 'let b:phpbegin = [0, 0]'
exe ':12'
let classname = phpcomplete#GetClassName(12, '$a[42]->', '\', {})
call VUAssertEquals('Foo', classname)
exe ':24'
let classname2 = phpcomplete#GetClassName(24, '$foo[0]->', '\', {})
call VUAssertEquals('Foo', classname2)
exe ':28'
let classname3 = phpcomplete#GetClassName(28, '$foo2->fooarray[42]->', '\', {})
call VUAssertEquals('Foo', classname3)
exe ':33'
let classname4 = phpcomplete#GetClassName(33, '$foo4[42]->', '\', {})
call VUAssertEquals('Foo', classname4)
exe ':38'
let classname5 = phpcomplete#GetClassName(38, '$f->', '\', {})
call VUAssertEquals('Foo', classname5)
exe ':43'
let classname6 = phpcomplete#GetClassName(43, '$f->', '\', {})
call VUAssertEquals('Foo', classname6)
exe ':48'
let classname7 = phpcomplete#GetClassName(48, '$f->', '\', {})
call VUAssertEquals('Foo', classname7)
exe ':53'
let classname7 = phpcomplete#GetClassName(53, '$f->', '\', {})
call VUAssertEquals('Foo', classname7)
silent! bw! %
endf
fun! TestCase_handles_parent_keyword()
let path = expand('%:p:h')."/"."fixtures/GetClassName/parent.php"
below 1new
exe ":silent! edit ".path
exe 'let b:phpbegin = [0, 0]'
exe ':6'
let classname = phpcomplete#GetClassName(6, 'parent::', '\', {})
call VUAssertEquals('FooBase', classname)
silent! bw! %
endf
fun! TestCase_catch_clause()
let path = expand('%:p:h')."/"."fixtures/GetClassName/catch.php"
below 1new
exe ":silent! edit ".path
exe 'let b:phpbegin = [0, 0]'
exe ':5'
let classname = phpcomplete#GetClassName(5, '$e->', '\', {})
call VUAssertEquals('Exception', classname)
exe ':11'
let classname = phpcomplete#GetClassName(11, '$e->', '\', {})
call VUAssertEquals('NS\Exception', classname)
silent! bw! %
endf
fun! TestCase_builtin_function_return_type()
let g:php_builtin_functions = {
\ 'simplexml_load_string(': 'string $data [, string $class_name = "SimpleXMLElement" [, int $options = 0 [, string $ns = "" [, bool $is_prefix = false]]]] | SimpleXMLElement',
\}
let path = expand('%:p:h')."/"."fixtures/GetClassName/builtin_function.php"
below 1new
exe ":silent! edit ".path
exe 'let b:phpbegin = [0, 0]'
exe ':5'
let classname = phpcomplete#GetClassName(5, '$xml->', 'Foo', {})
call VUAssertEquals('SimpleXMLElement', classname)
silent! bw! %
endf
fun! TestCase_function_return_type()
let g:php_builtin_functions = {}
let path = expand('%:p:h')."/"."fixtures/GetClassName/function_return_type.php"
let tags_path = expand('%:p:h')."/".'fixtures/GetClassName/function_return_type_tags'
let old_style_tags_path = expand('%:p:h')."/".'fixtures/GetClassName/old_style_function_return_type_tags'
exe 'set tags='.tags_path
below 1new
exe ":silent! edit ".path
exe 'let b:phpbegin = [0, 0]'
exe ':29'
let classname = phpcomplete#GetClassName(29, '$foo->', 'Foo', {})
call VUAssertEquals('Foo\FooClass', classname)
exe ':32'
let classname = phpcomplete#GetClassName(32, '$foo2->', 'Foo', {'F': {'cmd': '/^class FooClass {$/', 'static': 0, 'name': 'FooClass', 'namespace': 'Foo', 'kind': 'c', 'builtin': 0, 'filename': 'fixtures/GetClassName/function_return_type.php'}})
call VUAssertEquals('Foo\FooClass', classname)
exe ':35'
let classname = phpcomplete#GetClassName(35, '$foo3->', 'Foo', {'F': {'cmd': '/^class FooClass {$/', 'static': 0, 'name': 'FooClass', 'namespace': 'Foo', 'kind': 'c', 'builtin': 0, 'filename': 'fixtures/GetClassName/function_return_type.php'}})
call VUAssertEquals('Foo\FooClass', classname)
" the same should work with old style tags too, namespaces are extracted
" from the source
exe 'set tags='.old_style_tags_path
exe ':29'
let classname = phpcomplete#GetClassName(29, '$foo->', 'Foo', {})
call VUAssertEquals('Foo\FooClass', classname)
exe ':32'
let classname = phpcomplete#GetClassName(32, '$foo2->', 'Foo', {'F': {'cmd': '/^class FooClass {$/', 'static': 0, 'name': 'FooClass', 'kind': 'c', 'builtin': 0, 'filename': 'fixtures/GetClassName/function_return_type.php'}})
call VUAssertEquals('Foo\FooClass', classname)
silent! bw! %
endf
fun! TestCase_function_invocation_return_type()
let g:php_builtin_functions = {
\ 'simplexml_load_string(': 'string $data [, string $class_name = "SimpleXMLElement" [, int $options = 0 [, string $ns = "" [, bool $is_prefix = false]]]] | SimpleXMLElement',
\}
let path = expand('%:p:h')."/"."fixtures/GetClassName/function_return_type.php"
let tags_path = expand('%:p:h')."/".'fixtures/GetClassName/function_return_type_tags'
let old_style_tags_path = expand('%:p:h')."/".'fixtures/GetClassName/old_style_function_return_type_tags'
below 1new
exe ":silent! edit ".path
exe 'let b:phpbegin = [0, 0]'
" built-in function with class return type
exe ':38'
let classname = phpcomplete#GetClassName(38, 'simplexml_load_string()->', 'Foo', {})
call VUAssertEquals('SimpleXMLElement', classname)
exe ':41'
let classname = phpcomplete#GetClassName(41, 'make_a_foo()->', 'Foo', {})
call VUAssertEquals('Foo\FooClass', classname)
" renamed imports need tags to locate the renamed class
exe 'set tags='.tags_path
exe ':44'
let classname = phpcomplete#GetClassName(44, 'make_a_renamed_foo()->', 'Foo', {})
call VUAssertEquals('Foo\FooClass', classname)
" renamed imports need tags to locate the renamed class
exe 'set tags='.tags_path
exe ':47'
let classname = phpcomplete#GetClassName(47, 'no_ns_make_a_foo()->', 'Foo', {})
call VUAssertEquals('Foo\FooClass', classname)
" same import should work with old style tags too (namespace is ignored)
exe 'set tags='.tags_path
exe ':44'
let classname = phpcomplete#GetClassName(44, 'make_a_renamed_foo()->', 'Foo', {})
call VUAssertEquals('Foo\FooClass', classname)
silent! bw! %
endf
fun! TestCase_resolves_self_this_static_in_return_docblock()
call SetUp()
let path = expand('%:p:h')."/"."fixtures/GetClassName/self_return_type.php"
below 1new
exe ":silent! edit ".path
exe 'let b:phpbegin = [0, 0]'
exe ':32'
let classname = phpcomplete#GetClassName(32, '$b2->return_self()->', '', {})
call VUAssertEquals('Baz2', classname)
exe ':33'
let classname = phpcomplete#GetClassName(33, '$b2->return_this()->', '', {})
call VUAssertEquals('Baz2', classname)
exe ':34'
let classname = phpcomplete#GetClassName(34, '$b2->return_static()->', '', {})
call VUAssertEquals('Baz2', classname)
silent! bw! %
endf
fun! TestCase_resolves_self_this_static_in_return_docblock_in_array_situation()
call SetUp()
let path = expand('%:p:h')."/"."fixtures/GetClassName/self_return_type_array.php"
below 1new
exe ":silent! edit ".path
exe 'let b:phpbegin = [0, 0]'
exe ':38'
let classname = phpcomplete#GetClassName(38, '$self->', '', {})
call VUAssertEquals('Baz3', classname)
exe ':42'
let classname = phpcomplete#GetClassName(42, '$that->', '', {})
call VUAssertEquals('Baz3', classname)
exe ':46'
let classname = phpcomplete#GetClassName(46, '$static->', '', {})
call VUAssertEquals('Baz3', classname)
silent! bw! %
endf
" fails with the dist version
fun! TestCase_resolves_classnames_with_multiple_methods_recursively()
call SetUp()
let path = expand('%:p:h')."/"."fixtures/GetClassName/multi_hoops.php"
below 1new
exe ":silent! edit ".path
exe 'let b:phpbegin = [0, 0]'
exe ':16'
let classname = phpcomplete#GetClassName(16, '$result->', '', {})
call VUAssertEquals('Model', classname)
silent! bw! %
endf
fun! TestCase_resolves_classnames_with_multiple_methods_recursively_even_with_extra_whitespace()
call SetUp()
let path = expand('%:p:h')."/"."fixtures/GetClassName/multi_hoops_extra_whitespace.php"
below 1new
exe ":silent! edit ".path
exe 'let b:phpbegin = [0, 0]'
exe ':18'
let classname = phpcomplete#GetClassName(18, '$result->', '', {})
call VUAssertEquals('Model', classname)
silent! bw! %
endf
fun! TestCase_resolves_classnames_from_cloned_variables()
call SetUp()
let path = expand('%:p:h')."/"."fixtures/GetClassName/clone.php"
below 1new
exe ":silent! edit ".path
exe 'let b:phpbegin = [0, 0]'
exe ':5'
let classname = phpcomplete#GetClassName(5, '$d->', '', {})
call VUAssertEquals('DateTime', classname)
silent! bw! %
endf
fun! TestCase_should_not_loop_forever_around_stuff_having_the_word_class_class_in_them()
call SetUp()
let path = expand('%:p:h')."/"."fixtures/GetClassName/stuff_with_the_word_class_in_them.php"
below 1new
exe ":silent! edit ".path
exe 'let b:phpbegin = [0, 0]'
exe ':8'
let classname = phpcomplete#GetClassName(8, '$this->', '', {})
call VUAssertEquals('will', classname) " the result in itself is wrong, the plugin picks up the class word inside of a string
exe ':13'
let classname = phpcomplete#GetClassName(12, 'self::', '', {})
call VUAssertEquals('will', classname) " the result in itself is wrong, the plugin picks up the class word inside of a string
exe ':16'
let classname = phpcomplete#GetClassName(15, 'parent::', '', {})
call VUAssertEquals('DateTime', classname)
silent! bw! %
endf
fun! TestCase_resolves_inside_a_function_body()
call SetUp()
let path = expand('%:p:h')."/"."fixtures/GetClassName/completion_in_function_insides.php"
below 1new
exe ":silent! edit ".path
exe 'let b:phpbegin = [0, 0]'
exe ':11'
let classname = phpcomplete#GetClassName(11, '$d->', '', {})
call VUAssertEquals('DateTime', classname) " the result in itself is wrong, the plugin picks up the class word inside of a string
exe ':20'
let classname = phpcomplete#GetClassName(20, '$d->', '', {})
call VUAssertEquals('DateTime', classname) " the result in itself is wrong, the plugin picks up the class word inside of a string
exe ':25'
let classname = phpcomplete#GetClassName(25, '$d->', '', {})
call VUAssertEquals('DateTime', classname) " the result in itself is wrong, the plugin picks up the class word inside of a string
silent! bw! %
endf
fun! TestCase_resolves_return_type_hints()
call SetUp()
let path = expand('%:p:h')."/"."fixtures/GetClassName/return_typehinted_functions.php"
below 1new
exe ":silent! edit ".path
exe 'let b:phpbegin = [0, 0]'
exe ':24'
let classname = phpcomplete#GetClassName(24, '$f->', '', {})
call VUAssertEquals('FooReturnBars', classname)
exe ':26'
let classname = phpcomplete#GetClassName(26, '$f->returnBar()->', '', {})
call VUAssertEquals('Bar', classname)
exe ':28'
let classname = phpcomplete#GetClassName(28, '$f->returnBar2()->', '', {})
call VUAssertEquals('Bar2', classname)
silent! bw! %
endf
" vim: foldmethod=marker:expandtab:ts=4:sts=4

View File

@ -0,0 +1,33 @@
fun! TestCase_returns_zero_when_no_function_found_above()
let path = expand('%:p:h')."/".'fixtures/GetCurrentFunctionBoundaries/test.php'
below 1new
exe ":silent! edit ".path
exe ':3'
let res = phpcomplete#GetCurrentFunctionBoundaries()
call VUAssertEquals(0, res, "should return zero for top level code")
exe ':10'
let res2 = phpcomplete#GetCurrentFunctionBoundaries()
call VUAssertEquals(0, res2, "should return zero for top level code even if there's a function above it")
exe ':7'
let res3 = phpcomplete#GetCurrentFunctionBoundaries()
call VUAssertEquals([[5, 1], [8, 1]], res3)
exe ':17'
let res4 = phpcomplete#GetCurrentFunctionBoundaries()
call VUAssertEquals([[14, 2], [18, 2]], res4)
exe ':32'
let res6 = phpcomplete#GetCurrentFunctionBoundaries()
call VUAssertEquals([[31, 1], [33, 0]], res6)
" fails with the dist version
exe ':28'
let res5 = phpcomplete#GetCurrentFunctionBoundaries()
call VUAssertEquals([[21, 1], [29, 1]], res5)
silent! bw! %
endf

View File

@ -0,0 +1,151 @@
fun! TestCase_returns_instuction_string()
let path = expand('%:p:h')."/".'fixtures/GetCurrentInstruction/instructions.php'
below 1new
exe ":silent! edit ".path
call cursor(3, 8)
let res = phpcomplete#GetCurrentInstruction(3, 8, [1, 1])
call VUAssertEquals('use Foo1', res, 'should read in the first line as-is')
call cursor(7, 7)
let res = phpcomplete#GetCurrentInstruction(7, 7, [1, 1])
call VUAssertEquals('use Foo2, Bar', res, 'should return the previous line if the instruction spans multiple line')
call cursor(12, 7)
let res = phpcomplete#GetCurrentInstruction(12, 7, [1, 1])
call VUAssertEquals('use Foo3, Baz', res, 'should skip content of a comment inside an instruction')
call cursor(17, 7)
let res = phpcomplete#GetCurrentInstruction(17, 7, [1, 1])
call VUAssertEquals('new Foo', res, 'should simply ignore empty lines')
call cursor(23, 3)
let res = phpcomplete#GetCurrentInstruction(23, 3, [1, 1])
call VUAssertEquals(
\ '$foo()->bar( array('';''))->',
\ res,
\ 'semicolons in comments or string should be ignored')
call cursor(37, 6)
let res = phpcomplete#GetCurrentInstruction(37, 6, [1, 1])
call VUAssertEquals(
\ '$some_long_variable->love()->me()->love()->me()->say()->that()->you()->love',
\ res)
call cursor(42, 20)
let res = phpcomplete#GetCurrentInstruction(42, 20, [1, 1])
call VUAssertEquals(
\ '$this->foo->',
\ res)
call cursor(48, 6)
let res = phpcomplete#GetCurrentInstruction(48, 6, [1, 1])
call VUAssertEquals(
\ '$foo->',
\ res)
call cursor(53, 36)
let res = phpcomplete#GetCurrentInstruction(53, 36, [1, 1])
call VUAssertEquals(
\ '$date->',
\ res)
call cursor(55, 38)
let res = phpcomplete#GetCurrentInstruction(55, 38, [1, 1])
call VUAssertEquals(
\ '$date->',
\ res)
call cursor(57, 40)
let res = phpcomplete#GetCurrentInstruction(57, 40, [1, 1])
call VUAssertEquals(
\ '$date->',
\ res)
call cursor(59, 35)
let res = phpcomplete#GetCurrentInstruction(59, 35, [1, 1])
call VUAssertEquals(
\ '$date->',
\ res)
call cursor(64, 28)
let res = phpcomplete#GetCurrentInstruction(64, 28, [1, 1])
call VUAssertEquals(
\ '$bar2->',
\ res)
call cursor(65, 46)
let res = phpcomplete#GetCurrentInstruction(65, 46, [1, 1])
call VUAssertEquals(
\ '(new foo)->',
\ res)
call cursor(68, 8)
let res = phpcomplete#GetCurrentInstruction(68, 8, [1, 1])
call VUAssertEquals(
\ '$foo->',
\ res)
call cursor(70, 8)
let res = phpcomplete#GetCurrentInstruction(70, 8, [1, 1])
call VUAssertEquals(
\ '$foo->',
\ res)
call cursor(72, 14)
let res = phpcomplete#GetCurrentInstruction(72, 14, [1, 1])
call VUAssertEquals(
\ '$foo->',
\ res)
call cursor(74, 14)
let res = phpcomplete#GetCurrentInstruction(74, 14, [1, 1])
call VUAssertEquals(
\ '$foo->',
\ res)
call cursor(76, 28)
let res = phpcomplete#GetCurrentInstruction(76, 28, [1, 1])
call VUAssertEquals(
\ '$baz->',
\ res)
call cursor(78, 14)
let res = phpcomplete#GetCurrentInstruction(78, 14, [1, 1])
call VUAssertEquals(
\ '$foo->',
\ res)
call cursor(80, 15)
let res = phpcomplete#GetCurrentInstruction(80, 15, [1, 1])
call VUAssertEquals(
\ '$foo->',
\ res)
call cursor(82, 16)
let res = phpcomplete#GetCurrentInstruction(82, 16, [1, 1])
call VUAssertEquals(
\ '$foo->',
\ res)
call cursor(84, 13)
let res = phpcomplete#GetCurrentInstruction(84, 13, [1, 1])
call VUAssertEquals(
\ '$foo[$bar]->',
\ res)
call cursor(86, 12)
let res = phpcomplete#GetCurrentInstruction(86, 12, [1, 1])
call VUAssertEquals(
\ '$bar->',
\ res)
call cursor(88, 31)
let res = phpcomplete#GetCurrentInstruction(88, 31, [1, 1])
call VUAssertEquals(
\ 'DateTime::createFromFormat()->',
\ res)
call cursor(91, 13)
let res = phpcomplete#GetCurrentInstruction(91, 13, [1, 1])
call VUAssertEquals(
\ '$foo->',
\ res)
call cursor(93, 14)
let res = phpcomplete#GetCurrentInstruction(93, 14, [1, 1])
call VUAssertEquals(
\ '$foo->',
\ res)
call cursor(96, 48)
let res = phpcomplete#GetCurrentInstruction(96, 48, [1, 1])
call VUAssertEquals(
\ 'class Foo extends Bar implements ArrayAccess, It',
\ res)
silent! bw! %
endf
" vim: foldmethod=marker:expandtab:ts=4:sts=4

View File

@ -0,0 +1,107 @@
fun! SetUp()
exe ':set tags='
endf
fun! TestCase_returns_slash_when_no_namespace_found()
call SetUp()
let [namespace, imports] = phpcomplete#GetCurrentNameSpace([])
call VUAssertEquals('\', namespace)
endf
fun! TestCase_returns_namespace_from_file_lines()
call SetUp()
let file_lines = readfile(expand('%:p:h').'/'.'fixtures/GetCurrentNameSpace/single_namespace.php')
let [namespace, imports] = phpcomplete#GetCurrentNameSpace(file_lines)
call VUAssertEquals('Mahou', namespace)
let file_lines = readfile(expand('%:p:h').'/'.'fixtures/GetCurrentNameSpace/single_namespace2.php')
let [namespace, imports] = phpcomplete#GetCurrentNameSpace(file_lines)
call VUAssertEquals('Mahou', namespace)
endf
fun! TestCase_returns_closest_namespace_from_the_current_line()
call SetUp()
let file_lines = readfile(expand('%:p:h').'/'.'fixtures/GetCurrentNameSpace/multiple_namespace.php')
let [namespace, imports] = phpcomplete#GetCurrentNameSpace(file_lines)
call VUAssertEquals('FindMe', namespace)
endf
fun! TestCase_returns_imported_namespaces_and_classes_with_their_info_from_tags()
call SetUp()
exe 'set tags='.expand('%:p:h')."/".'fixtures/common/namespaced_foo_tags'
let file_lines = readfile(expand('%:p:h').'/'.'fixtures/GetCurrentNameSpace/imports.php')
call phpcomplete#LoadData()
let [namespace, imports] = phpcomplete#GetCurrentNameSpace(file_lines)
call VUAssertEquals({
\ 'Foo': {'cmd': '/^class Foo {$/', 'static': 0, 'name': 'Foo', 'namespace': 'NS1', 'kind': 'c', 'builtin': 0, 'filename': 'fixtures/common/namespaced_foo.php'},
\ 'ArrayAccess': {'name': 'ArrayAccess', 'kind': 'i', 'builtin': 1},
\ 'AO': {'name': 'ArrayObject', 'kind': 'c', 'builtin': 1},
\ 'DateTimeZone': {'name': 'DateTimeZone', 'kind': 'c', 'builtin': 1},
\ 'LE': {'name': 'LogicException', 'kind': 'c', 'builtin': 1},
\ 'DateTime': {'name': 'DateTime', 'kind': 'c', 'builtin': 1},
\ 'SUBNS': {'cmd': '/^namespace NS1\\SUBNS;$/', 'static': 0, 'name': 'NS1\SUBNS', 'kind': 'n', 'builtin': 0, 'filename': 'fixtures/common/namespaced_foo.php'},
\ 'EE': {'name': 'ErrorException', 'kind': 'c', 'builtin': 1},
\ 'E': {'name': 'Exception', 'kind': 'c', 'builtin': 1}},
\ imports)
" with old style tags, matching tags with no namespace matches will be returned
" matching is done regardeless of the namespace we are actually looking
" for however the desired namespace will be added to the tag
" namespace import just not recognized with the kind 'n' and filename
exe 'set tags='.expand('%:p:h')."/".'fixtures/common/old_style_namespaced_foo_tags'
let [namespace, imports] = phpcomplete#GetCurrentNameSpace(file_lines)
call VUAssertEquals({
\ 'Foo': {'cmd': '/^class Foo {$/', 'static': 0, 'name': 'Foo', 'namespace': 'NS1', 'kind': 'c', 'builtin': 0, 'filename': 'fixtures/common/fixtures/common/namespaced_foo.php'},
\ 'ArrayAccess': {'name': 'ArrayAccess', 'kind': 'i', 'builtin': 1},
\ 'AO': {'name': 'ArrayObject', 'kind': 'c', 'builtin': 1},
\ 'DateTimeZone': {'name': 'DateTimeZone', 'kind': 'c', 'builtin': 1},
\ 'LE': {'name': 'LogicException', 'kind': 'c', 'builtin': 1},
\ 'DateTime': {'name': 'DateTime', 'kind': 'c', 'builtin': 1},
\ 'SUBNS': {'name': 'SUBNS', 'namespace': 'NS1', 'kind': '', 'builtin': 0},
\ 'EE': {'name': 'ErrorException', 'kind': 'c', 'builtin': 1},
\ 'E': {'name': 'Exception', 'kind': 'c', 'builtin': 1}},
\ imports)
endf
fun! TestCase_does_not_pick_up_trait_uses_inside_classes()
call SetUp()
let file_lines = readfile(expand('%:p:h').'/'.'fixtures/GetCurrentNameSpace/traits.php')
call phpcomplete#LoadData()
let [namespace, imports] = phpcomplete#GetCurrentNameSpace(file_lines)
call VUAssertEquals('NS1', namespace)
call VUAssertEquals({
\ 'DateTime': {'name': 'DateTime', 'kind': 'c', 'builtin': 1},
\}, imports)
endf
fun! TestCase_should_pick_up_imports_regardeless_the_upperlower_case_of_keywords()
call SetUp()
call phpcomplete#LoadData()
let file_lines = readfile(expand('%:p:h').'/'.'fixtures/GetCurrentNameSpace/single_namespace_uppercase.php')
let [namespace, imports] = phpcomplete#GetCurrentNameSpace(file_lines)
call VUAssertEquals('Mahou', namespace)
call VUAssertEquals({
\ 'DT': {'name': 'DateTime', 'kind': 'c', 'builtin': 1}},
\ imports)
endf
fun! TestCase_should_find_imports_when_called_with_non_balanced_braces()
call SetUp()
let file_lines = readfile(expand('%:p:h').'/'.'fixtures/GetCurrentNameSpace/code_blocks.php')[0:7]
call phpcomplete#LoadData()
let [namespace, imports] = phpcomplete#GetCurrentNameSpace(file_lines)
call VUAssertEquals({
\ 'SomeChildNS': {'name': 'SomeChildNS', 'namespace': 'SomeParentNS', 'kind': '', 'builtin': 0}
\}, imports)
endf
" vim: foldmethod=marker:expandtab:ts=4:sts=4

View File

@ -0,0 +1,94 @@
fun! SetUp()
" normalize g:phpcomplete_min_num_of_chars_for_namespace_completion option
let g:phpcomplete_min_num_of_chars_for_namespace_completion = 2
" disable built-in classes
let g:php_builtin_classnames = {}
" disable built-in interfaces
let g:php_builtin_interfaces = {}
" disable built-in interfaces
let g:php_builtin_interfacenames = {}
" disable tags
exe ':set tags='
endf
fun! TestCase_returns_empty_strings_when_outside_php_block()
call SetUp()
let path = expand('%:p:h')."/".'fixtures/GetCurrentSymbolWithContext/foo.php'
below 1new
exe ":silent! edit ".path
call cursor(26, 1)
let res = phpcomplete#GetCurrentSymbolWithContext()
call VUAssertEquals(['', '', '', ''], res)
silent! bw! %
endf
fun! TestCase_returns_current_symbol_under_cursor()
call SetUp()
let path = expand('%:p:h')."/".'fixtures/GetCurrentSymbolWithContext/foo.php'
below 1new
exe ":silent! edit ".path
call cursor(18, 5)
let res = phpcomplete#GetCurrentSymbolWithContext()
call VUAssertEquals(['get_foo', '', '', {}], res)
call cursor(18, 13)
let res = phpcomplete#GetCurrentSymbolWithContext()
call VUAssertEquals(['baz', 'get_foo()->', '', {}], res)
call cursor(20, 1)
let res = phpcomplete#GetCurrentSymbolWithContext()
call VUAssertEquals(['Foo', '', '', {}], res)
call cursor(20, 8)
let res = phpcomplete#GetCurrentSymbolWithContext()
call VUAssertEquals(['baz', 'Foo::', '', {}], res)
call cursor(23, 29)
let res = phpcomplete#GetCurrentSymbolWithContext()
call VUAssertEquals(['returnFoo2', '$f2->returnBaz2()->', '', {}], res)
silent! bw! %
endf
fun! TestCase_returns_current_symbol_with_the_current_namespace_and_imports()
call SetUp()
exe ':set tags='.expand('%:p:h').'/'.'fixtures/GetCurrentSymbolWithContext/namespaced_tags'
let path = expand('%:p:h')."/".'fixtures/GetCurrentSymbolWithContext/namespaced_foo.php'
below 1new
exe ":silent! edit ".path
call cursor(21, 5)
let res = phpcomplete#GetCurrentSymbolWithContext()
call VUAssertEquals(['get_foo', '', 'NS1', {'RenamedFoo2': {'cmd': '/^class Foo2 {$/', 'static': 0, 'name': 'Foo2', 'namespace': 'NS2', 'kind': 'c', 'builtin': 0, 'filename': 'fixtures/GetCurrentSymbolWithContext/namespaced_foo2.php'}}], res)
call cursor(21, 13)
let res = phpcomplete#GetCurrentSymbolWithContext()
call VUAssertEquals(['baz', 'get_foo()->', 'NS1', {'RenamedFoo2': {'cmd': '/^class Foo2 {$/', 'static': 0, 'name': 'Foo2', 'namespace': 'NS2', 'kind': 'c', 'builtin': 0, 'filename': 'fixtures/GetCurrentSymbolWithContext/namespaced_foo2.php'}}], res)
call cursor(23, 18)
let res = phpcomplete#GetCurrentSymbolWithContext()
call VUAssertEquals(['Foo2', 'new \NS2\', 'NS2', {'RenamedFoo2': {'cmd': '/^class Foo2 {$/', 'static': 0, 'name': 'Foo2', 'namespace': 'NS2', 'kind': 'c', 'builtin': 0, 'filename': 'fixtures/GetCurrentSymbolWithContext/namespaced_foo2.php'}}], res)
call cursor(27, 18)
let res = phpcomplete#GetCurrentSymbolWithContext()
call VUAssertEquals(['Foo2', 'new', 'NS2', {'RenamedFoo2': {'cmd': '/^class Foo2 {$/', 'static': 0, 'name': 'Foo2', 'namespace': 'NS2', 'kind': 'c', 'builtin': 0, 'filename': 'fixtures/GetCurrentSymbolWithContext/namespaced_foo2.php'}}], res)
call cursor(3, 10)
let res = phpcomplete#GetCurrentSymbolWithContext()
call VUAssertEquals(['Foo2', 'use NS2\', 'NS2', {'RenamedFoo2': {'cmd': '/^class Foo2 {$/', 'static': 0, 'name': 'Foo2', 'namespace': 'NS2', 'kind': 'c', 'builtin': 0, 'filename': 'fixtures/GetCurrentSymbolWithContext/namespaced_foo2.php'}}], res)
call cursor(3, 20)
let res = phpcomplete#GetCurrentSymbolWithContext()
call VUAssertEquals(['Foo2', 'use NS2\Foo2 as', 'NS2', {'RenamedFoo2': {'cmd': '/^class Foo2 {$/', 'static': 0, 'name': 'Foo2', 'namespace': 'NS2', 'kind': 'c', 'builtin': 0, 'filename': 'fixtures/GetCurrentSymbolWithContext/namespaced_foo2.php'}}], res)
silent! bw! %
endf
" vim: foldmethod=marker:expandtab:ts=4:sts=4

View File

@ -0,0 +1,53 @@
fun! SetUp()
let g:fixture_class_content = readfile(expand('%:p:h').'/'.'fixtures/DocBlock/foo.class.php')[2:]
let g:phpcomplete_relax_static_constraint = 0
endf
fun! TestCase_returns_empty_string_when_no_comment_block_found()
call SetUp()
let ret = phpcomplete#GetDocBlock(g:fixture_class_content, 'function\<not_commented\>')
call VUAssertEquals('', ret)
let ret = phpcomplete#GetDocBlock(g:fixture_class_content, ' public $nocomment;')
call VUAssertEquals('', ret)
endf
fun! TestCase_returns_the_comment_block_without_last_and_first_line_and_without_leading_stars()
call SetUp()
let ret = phpcomplete#GetDocBlock(g:fixture_class_content, 'function\s*\<minimally_commented\>')
call VUAssertEquals(
\ "minimally_commented",
\ ret)
let ret = phpcomplete#GetDocBlock(g:fixture_class_content, ' public $foo;')
call VUAssertEquals(
\ "@var Foo",
\ ret)
let ret = phpcomplete#GetDocBlock(g:fixture_class_content, ' public $bar;')
call VUAssertEquals(
\ "@type Bar",
\ ret)
endf
fun! TestCase_recognizes_a_oneline_comment_block_for_properties()
call SetUp()
let ret = phpcomplete#GetDocBlock(g:fixture_class_content, ' public $onliner;')
call VUAssertEquals(
\ "@var Bar",
\ ret)
endf
fun! TestCase_retuns_docblock_for_the_class_itself()
call SetUp()
let ret = phpcomplete#GetDocBlock(g:fixture_class_content, 'class Foo')
call VUAssertEquals(
\ "Foo\n\n@property DateTime $baz",
\ ret)
endf
" vim: foldmethod=marker:expandtab:ts=4:sts=4

View File

@ -0,0 +1,62 @@
fun! SetUp()
" disable builtin information
let g:php_builtin_functions = {}
" disable tag files
exe ':set tags='
endf
fun! TestCase_return_VIMPHP_BUILTINFUNCTION_when_function_name_is_builtin()
call SetUp()
let g:php_builtin_functions = {
\ 'array_map(': 'callable $callback, array $array1 [, array $...] | array',
\ }
let res = phpcomplete#GetFunctionLocation('array_map', '')
call VUAssertEquals('VIMPHP_BUILTINFUNCTION', res)
let res = phpcomplete#GetFunctionLocation('array_map', '\')
call VUAssertEquals('VIMPHP_BUILTINFUNCTION', res)
let res = phpcomplete#GetFunctionLocation('array_map', 'FooNS')
call VUAssertEquals('VIMPHP_BUILTINFUNCTION', res)
endf
fun! TestCase_return_current_file_path_when_function_declaration_is_found_in_the_file()
call SetUp()
let path = expand('%:p:h').'/'.'fixtures/GetFunctionLocation/foo.function.php'
below 1new
exe ":silent! edit ".path
let res = phpcomplete#GetFunctionLocation('foo', '')
call VUAssertEquals(path, res)
" function names are case in-sensitive
let res = phpcomplete#GetFunctionLocation('foo2', '')
call VUAssertEquals(path, res)
silent! bw! %
endf
fun! TestCase_return_function_location_from_tags()
call SetUp()
let tags_path = expand('%:p:h').'/'.'fixtures/GetFunctionLocation/tags'
let path = expand('%:p:h').'/'.'fixtures/GetFunctionLocation/empty.php'
exe ':set tags='.tags_path
below 1new
exe ":silent! edit ".path
exe ':3'
let res = phpcomplete#GetFunctionLocation('foo', '')
call VUAssertEquals('fixtures/GetFunctionLocation/foo.function.php', res)
let res = phpcomplete#GetFunctionLocation('foo2', '')
call VUAssertEquals('fixtures/GetFunctionLocation/foo.function.php', res)
silent! bw! %
endf
" vim: foldmethod=marker:expandtab:ts=4:sts=4

View File

@ -0,0 +1,20 @@
fun! SetUp()
" disable builtin information
let g:php_builtin_functions = {}
" disable tag files
exe ':set tags='
let g:fixture_file_content = readfile(expand('%:p:h').'/'.'fixtures/GetFunctionReturnTypeHint/functions.php')[2:]
endf
fun! TestCase_return_current_file_path_when_function_declaration_is_found_in_the_file()
call SetUp()
let ret = phpcomplete#GetFunctionReturnTypeHint(g:fixture_file_content, 'function\s*\<returnFoo\>')
call VUAssertEquals('Foo', ret)
let ret = phpcomplete#GetFunctionReturnTypeHint(g:fixture_file_content, 'function\s*\<returnBar\>')
call VUAssertEquals('Bar', ret)
let ret = phpcomplete#GetFunctionReturnTypeHint(g:fixture_file_content, 'function\s*\<returnBar2\>')
call VUAssertEquals('Bar2', ret)
endf

View File

@ -0,0 +1,27 @@
fun! TestCase_returns_the_line_splited_on_arrows_and_double_colons()
let res = phpcomplete#GetMethodStack('$this->foo()->bar()')
call VUAssertEquals(['$this', 'foo()', 'bar()'], res)
let res = phpcomplete#GetMethodStack('Foo::bar()->baz')
call VUAssertEquals(['Foo', 'bar()', 'baz'], res)
endf
fun! TestCase_ignores_arrows_and_double_colons_inside_paretns()
let res = phpcomplete#GetMethodStack('Foo::bar($foobar->foo())->baz')
call VUAssertEquals(['Foo', 'bar($foobar->foo())', 'baz'], res)
endf
fun! TestCase_ignores_arrows_and_double_colons_and_parents_inside_strings()
let res = phpcomplete#GetMethodStack('Foo::bar($foobar->foo(" ) -> :: '' \" \\"))->baz')
call VUAssertEquals(['Foo', 'bar($foobar->foo(" ) -> :: '' \" \\"))', 'baz'], res)
endf
fun! TestCase_have_no_empty_element_on_the_end_if_the_context_ended_with_an_arrow_or_double_colon()
let res = phpcomplete#GetMethodStack('Foo::bar()->')
call VUAssertEquals(['Foo', 'bar()'], res)
let res = phpcomplete#GetMethodStack('Foo::bar::')
call VUAssertEquals(['Foo', 'bar'], res)
endf
" vim: foldmethod=marker:expandtab:ts=4:sts=4

View File

@ -0,0 +1,25 @@
fun! TestCase_returns_input_if_no_pipe_detected()
let ret = phpcomplete#GetTypeFromDocBlockParam('FooClass')
call VUAssertEquals('FooClass', ret)
endfun
fun! TestCase_returns_first_non_primitive_type()
let ret = phpcomplete#GetTypeFromDocBlockParam('bool|FooClass')
call VUAssertEquals('FooClass', ret)
let ret = phpcomplete#GetTypeFromDocBlockParam('FooClass|bool')
call VUAssertEquals('FooClass', ret)
let ret = phpcomplete#GetTypeFromDocBlockParam('bool|string|BarClass|FooClass')
call VUAssertEquals('BarClass', ret)
let ret = phpcomplete#GetTypeFromDocBlockParam('string[]|BazClass')
call VUAssertEquals('BazClass', ret)
endfun
fun! TestCase_returns_the_first_type_if_only_primitives_found()
let ret = phpcomplete#GetTypeFromDocBlockParam('string|bool')
call VUAssertEquals('string', ret)
endfun
" vim: foldmethod=marker:expandtab:ts=4:sts=4

View File

@ -0,0 +1,24 @@
fun! SetUp()
endf
fun! TestCase_creates_various_global_hashes()
call phpcomplete#LoadData()
call VUAssertTrue(exists('g:php_builtin_classes'))
call VUAssertTrue(exists('g:php_builtin_classnames'))
call VUAssertTrue(exists('g:php_builtin_interfaces'))
call VUAssertTrue(exists('g:php_builtin_interfacenames'))
call VUAssertTrue(exists('g:php_builtin_functions'))
call VUAssertTrue(exists('g:php_builtin_vars'))
endf
fun! TestCase_php_built_classnames_and_builtin_classes_are_indexed_lowercase()
call phpcomplete#LoadData()
call VUAssertTrue(has_key(g:php_builtin_classes, 'datetime'))
call VUAssertTrue(has_key(g:php_builtin_classnames, 'datetime'))
call VUAssertTrue(has_key(g:php_builtin_interfaces, 'traversable'))
call VUAssertTrue(has_key(g:php_builtin_interfacenames, 'traversable'))
endf
" vim: foldmethod=marker:expandtab:ts=4:sts=4

View File

@ -0,0 +1,104 @@
fun! SetUp()
" normalize g:phpcomplete_min_num_of_chars_for_namespace_completion option
let g:phpcomplete_min_num_of_chars_for_namespace_completion = 2
" disable built-in classes
let g:php_builtin_classnames = {}
let g:php_builtin_classes = {}
" disable built-in interfaces
let g:php_builtin_interfaces = {}
let g:php_builtin_interfacenames = {}
" disable built-in functions
let g:php_builtin_functions = {}
" disable tags
exe ':set tags='
endf
fun! TestCase_returns_empty_strings_when_symbol_not_found()
call SetUp()
let res = phpcomplete#LocateSymbol('no_such_thing', '', '', {})
call VUAssertEquals(['', '', ''], res)
endf
fun! TestCase_returns_symbol_locations()
call SetUp()
let path = expand('%:p:h')."/".'fixtures/GetCurrentSymbolWithContext/foo.php'
below 1new
exe ":silent! edit ".path
call cursor(18, 2)
let res = phpcomplete#LocateSymbol('get_foo', '', '', {})
call VUAssertEquals([path, 15, 10], res)
call cursor(18, 13)
let res = phpcomplete#LocateSymbol('baz', 'get_foo()->', '', {})
call VUAssertEquals([path, 4, 18], res)
call cursor(20, 3)
let res = phpcomplete#LocateSymbol('Foo', '', '', {})
call VUAssertEquals([path, 2, 7], res)
call cursor(20, 7)
let res = phpcomplete#LocateSymbol('baz', 'Foo::', '', {})
call VUAssertEquals([path, 4, 18], res)
silent! bw! %
endf
fun! TestCase_returns_symbol_locations_with_namespaces()
call SetUp()
exe ':set tags='.expand('%:p:h').'/'.'fixtures/GetCurrentSymbolWithContext/namespaced_tags'
let foo2_path = expand('%:p:h')."/".'fixtures/GetCurrentSymbolWithContext/namespaced_foo2.php'
let path = expand('%:p:h')."/".'fixtures/GetCurrentSymbolWithContext/namespaced_foo.php'
below 1new
exe ":silent! edit ".path
call cursor(24, 25)
let res = phpcomplete#LocateSymbol('returnFoo2', '$f2->returnBaz2()->', 'NS1', {})
call VUAssertEquals([foo2_path, 22, 18], res)
call cursor(28, 10)
let res = phpcomplete#LocateSymbol('returnBaz2', '$f2->', 'NS1', {})
call VUAssertEquals([foo2_path, 11, 18], res)
silent! bw! %
endf
fun! TestCase_returns_location_for_inherited_methods()
call SetUp()
exe ':set tags='.expand('%:p:h').'/'.'fixtures/GetCurrentSymbolWithContext/inherited_tags'
let base_path = expand('%:p:h')."/".'fixtures/GetCurrentSymbolWithContext/base_foo.php'
let path = expand('%:p:h')."/".'fixtures/GetCurrentSymbolWithContext/child_foo.php'
below 1new
exe ":silent! edit ".path
call cursor(7, 10)
let res = phpcomplete#LocateSymbol('inherited', '$f->', '', {})
call VUAssertEquals([base_path, 5, 18], res)
silent! bw! %
endf
fun! TestCase_returns_locations_for_reference_returning_functions()
call SetUp()
let path = expand('%:p:h')."/".'fixtures/GetCurrentSymbolWithContext/foo_references.php'
below 1new
exe ":silent! edit ".path
call cursor(16, 5)
let res = phpcomplete#LocateSymbol('return_foo_ref', '', '', {})
call VUAssertEquals([path, 13, 11], res)
call cursor(16, 32)
let res = phpcomplete#LocateSymbol('return_foo_ref_method', 'return_foo_ref()->', '', {})
call VUAssertEquals([path, 4, 19], res)
silent! bw! %
endf
" vim: foldmethod=marker:expandtab:ts=4:sts=4

View File

@ -0,0 +1,85 @@
fun! SetUp()
endf
fun! TestCase_collects_lines_up_until_the_first_param_var_or_return_as_description_whitespace_trimmed_down_from_the_ends()
call SetUp()
let ret = phpcomplete#ParseDocBlock(
\ "short description\n".
\ "\n".
\ "long description line\n".
\ "long description line2\n".
\ "@return Foo some foo\n".
\ "not included in description\n")
call VUAssertEquals("".
\ "short description\n".
\ "\n".
\ "long description line\n".
\ "long description line2",
\ ret.description)
endf
fun! TestCase_extracts_return_type_and_description()
call SetUp()
let ret = phpcomplete#ParseDocBlock("@return Foo some foo\n")
call VUAssertEquals("Foo", ret.return.type)
call VUAssertEquals("some foo", ret.return.description)
" description is empty string when not specified
let ret = phpcomplete#ParseDocBlock("@return Foo\n")
call VUAssertEquals("Foo", ret.return.type)
call VUAssertEquals("", ret.return.description)
endf
fun! TestCase_extracts_parameters_with_types_and_descriptions()
call SetUp()
let ret = phpcomplete#ParseDocBlock("".
\ "@param mixed $foo\n".
\ "@param Foo $bar some description\n")
call VUAssertEquals("mixed", ret.params[0].type)
call VUAssertEquals("$foo", ret.params[0].name)
call VUAssertEquals("", ret.params[0].description)
call VUAssertEquals("Foo", ret.params[1].type)
call VUAssertEquals("$bar", ret.params[1].name)
call VUAssertEquals("some description", ret.params[1].description)
endf
fun! TestCase_extracts_throws_and_exception_lines_with_type_and_description()
call SetUp()
let ret = phpcomplete#ParseDocBlock("".
\ "@exception Foo on full moons\n".
\ "@throws Foo\n")
call VUAssertEquals("Foo", ret.throws[0].type)
call VUAssertEquals("on full moons", ret.throws[0].description)
call VUAssertEquals("Foo", ret.throws[1].type)
call VUAssertEquals("", ret.throws[1].description)
endf
fun! TestCase_extracts_var_lines_with_type_and_description()
call SetUp()
let ret = phpcomplete#ParseDocBlock("@var Foo some description\n")
call VUAssertEquals("Foo", ret.var.type)
call VUAssertEquals("some description", ret.var.description)
let ret = phpcomplete#ParseDocBlock("@var Foo\n")
call VUAssertEquals("Foo", ret.var.type)
call VUAssertEquals("", ret.var.description)
endf
fun! TestCase_extracts_AT_properties_from_docblock_of_a_class()
call SetUp()
let ret = phpcomplete#ParseDocBlock("Foo\n\n@property DateTime $baz Some comments here")
call VUAssertEquals([{'description': '$baz Some comments here', 'line': '@property DateTime $baz Some comments here', 'type': 'DateTime'}], ret.properties)
endf
" vim: foldmethod=marker:expandtab:ts=4:sts=4

View File

@ -0,0 +1,9 @@
## Running the tests
You can run the test suite with the `./runtests.sh` script.
Tests are using the [vimunit plugin](https://github.com/dsummersl/vimunit) if you don't have
it next to your phpcomplete.vim the script will try to get it with git. Running all the tests
you simply enter the tests/ directory and start the script:
cd ~/.vim/bundle/phpcomplete.vim/tests
./runtests.sh

View File

@ -0,0 +1,3 @@
<?php

View File

@ -0,0 +1,10 @@
<?php
class FooClass {
}
class BarClass {
}
interface BarInterface {
}

View File

@ -0,0 +1,8 @@
<?php
namespace NS1;
class NameSpacedFoo {
}
interface NameSpacedFooInterface {
}

View File

@ -0,0 +1,15 @@
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/
!_TAG_PROGRAM_NAME Exuberant Ctags //
!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/
!_TAG_PROGRAM_VERSION 5.8 //
BarClass foo.class.php /^class BarClass {$/;" c
BarInterface foo.class.php /^interface BarInterface {$/;" i
FooClass foo.class.php /^class FooClass {$/;" c
NameSpacedFoo namespaced.foo.php /^class NameSpacedFoo {$/;" c
NameSpacedFooInterface namespaced.foo.php /^interface NameSpacedFooInterface {$/;" i
SubNameSpaced subnamespace.php /^class SubNameSpaced {$/;" c
SubNameSpacedInterface subnamespace.php /^interface SubNameSpacedInterface {$/;" i
TagClass tagclass.php /^class TagClass {$/;" c
lowercasetagclass tagclass.php /^class lowercasetagclass {$/;" c

View File

@ -0,0 +1,8 @@
<?php
namespace NS1\SubNS;
class SubNameSpaced {
}
interface SubNameSpacedInterface {
}

View File

@ -0,0 +1,7 @@
<?php
class TagClass {
}
class lowercasetagclass {
}

View File

@ -0,0 +1,4 @@
<?php
define('FINDME_FOO', 42);
define('DONT_FIND_ME', 6 * 7);

View File

@ -0,0 +1,16 @@
<?php
class CommonFoo {
public function common_public_method($foo) { }
private function common_private_method($foo) { }
protected function common_protected_method($foo) { }
public static function common_public_static_method($foo) { }
static public function common_static_public_method($foo) { }
private static function common_private_static_method($foo) { }
protected static function common_protected_static_method($foo) { }
}
trait CommonTrait {}
function common_plain_old_function(){}
function common_plain_old_function_with_arguments($a, $b=''){}

View File

@ -0,0 +1,10 @@
<?php
namespace NS1;
define('ZAP', 42);
namespace NS1\SUBNS;
define('ZAPSUB', 6 * 7);
namespace NS1\SUBNS\SUBSUBNS;
define('ZAPSUBSUB', 2 * 3 * 7);

View File

@ -0,0 +1,22 @@
<?php
namespace NS1;
class Foo {
}
const ZAP = '';
function bar(){}
namespace NS1\SUBNS;
class FooSub {
}
function barsub(){}
const ZAPSUB = '';
namespace NS1\SUBNS\SUBSUB;
class FooSubSub {
}
function barsubsub(){}
const ZAPSUBSUB = '';

View File

@ -0,0 +1,18 @@
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/
!_TAG_PROGRAM_NAME Exuberant Ctags //
!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/
!_TAG_PROGRAM_VERSION Development //
Foo namespaced_foo.php /^class Foo {$/;" c namespace:NS1
FooSub namespaced_foo.php /^class FooSub {$/;" c namespace:NS1\SUBNS
FooSubSub namespaced_foo.php /^class FooSubSub {$/;" c namespace:NS1\SUBNS\SUBSUB
NS1 namespaced_foo.php /^namespace NS1;$/;" n
NS1\SUBNS namespaced_foo.php /^namespace NS1\\SUBNS;$/;" n
NS1\SUBNS\SUBSUB namespaced_foo.php /^namespace NS1\\SUBNS\\SUBSUB;$/;" n
ZAP namespaced_foo.php /^const ZAP = '';$/;" d namespace:NS1
ZAPSUB namespaced_foo.php /^const ZAPSUB = '';$/;" d namespace:NS1\SUBNS
ZAPSUBSUB namespaced_foo.php /^const ZAPSUBSUB = '';$/;" d namespace:NS1\SUBNS\SUBSUB
bar namespaced_foo.php /^function bar(){}$/;" f namespace:NS1 signature:()
barsub namespaced_foo.php /^function barsub(){}$/;" f namespace:NS1\SUBNS signature:()
barsubsub namespaced_foo.php /^function barsubsub(){}$/;" f namespace:NS1\SUBNS\SUBSUB signature:()

View File

@ -0,0 +1,15 @@
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/
!_TAG_PROGRAM_NAME Exuberant Ctags //
!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/
!_TAG_PROGRAM_VERSION 5.8 //
Foo fixtures/CompleteGeneral/namespaced_foo.php /^class Foo {$/;" c
FooSub fixtures/CompleteGeneral/namespaced_foo.php /^class FooSub {$/;" c
FooSubSub fixtures/CompleteGeneral/namespaced_foo.php /^class FooSubSub {$/;" c
ZAP fixtures/CompleteGeneral/namespaced_constants.php /^define('ZAP', 42);$/;" d
ZAPSUB fixtures/CompleteGeneral/namespaced_constants.php /^define('ZAPSUB', 6 * 7);$/;" d
ZAPSUBSUB fixtures/CompleteGeneral/namespaced_constants.php /^define('ZAPSUBSUB', 2 * 3 * 7);$/;" d
bar fixtures/CompleteGeneral/namespaced_foo.php /^function bar(){}$/;" f
barsub fixtures/CompleteGeneral/namespaced_foo.php /^function barsub(){}$/;" f
barsubsub fixtures/CompleteGeneral/namespaced_foo.php /^function barsubsub(){}$/;" f

View File

@ -0,0 +1,7 @@
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/
!_TAG_PROGRAM_NAME Exuberant Ctags //
!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/
!_TAG_PROGRAM_VERSION Development //
common_plain_old_function_with_arguments functions.php /^function common_plain_old_function_with_arguments($/;" f signature:($a, $b = '')

View File

@ -0,0 +1,3 @@
<?php

View File

@ -0,0 +1,22 @@
<?php
class FooMethodsClass {
function method1($foo) {
}
public function method2($foo) {
}
public static function method3($foo) {
}
static public function method4($foo) {
}
private function method5($foo) {
}
protected function method6($foo) {
}
}

View File

@ -0,0 +1,8 @@
<?php
class FooPropertiesClass {
var $property1 = 'foo';
public $property2 = 'bar';
public static $static_property = 'bar';
}

View File

@ -0,0 +1,7 @@
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/
!_TAG_PROGRAM_NAME Exuberant Ctags //
!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/
!_TAG_PROGRAM_VERSION Development //
method_with_arguments irrelevant.class.php /^ protected function method_with_arguments( {$/;" f class:FooMethodsClass access:protected signature:($bar = 42, $foo = '')

View File

@ -0,0 +1,7 @@
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/
!_TAG_PROGRAM_NAME Exuberant Ctags //
!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/
!_TAG_PROGRAM_VERSION 5.8 //
BaseAsset foo.php /^abstract class BaseAsset implements AssetInterface$/;" c

View File

@ -0,0 +1,20 @@
<?php
/**
* Foo
*
* @property DateTime $commented_from_docblock
*/
class Foo {
/**
* @var Foo
*/
public $commented_property;
/**
* @return string description of return
*/
public function commented_method($foo, $bar, $baz = '') {
}
}

View File

@ -0,0 +1,73 @@
<?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()
{
}
function naked_public_method(){
}
}

View File

@ -0,0 +1,9 @@
<?php
class Foo implements FooAble {
}
interface FooAble {
public function bar($baz = 42);
}

View File

@ -0,0 +1,3 @@
<?php

View File

@ -0,0 +1,7 @@
<?php
$find_me = "var";
$find_me2 = time();
$find_me3 = new DateTime;
$find_me4 = new BarClass;
$dont_find_me = 42;

View File

@ -0,0 +1,61 @@
<?php
/**
* Foo
*
* @property DateTime $baz
*/
class Foo {
/**
* FOO constant description
*/
const FOO_CONST = 42;
/**
* @var Foo
*/
public $foo;
/**
* @type Bar
*/
public $bar;
/**
* description, here i come
*
* @var string
*/
var $foo2 = '';
public $nocomment;
public static $nocomment2;
/**
* Short description
*
* @param mixed $foo
* @param mixed $bar bar
* @param string $baz baz some description of this baz
* @return string description of return
* @throws Foo
* @exception Foo some description
* @throws Foo
*/
public function commentedfoo($foo, $bar, $baz = '') {
}
public function not_commented() {
}
/**
* minimally_commented
*/
public function minimally_commented() {
}
/** @var Bar */
public $onliner;
}

View File

@ -0,0 +1,30 @@
interface ArrayAccess {
/**
* offsetSet
*
* @return void
*/
public function offsetSet(mixed $offset, mixed $value | void){
}
/**
* offsetUnset
*
* @return void
*/
public function offsetUnset(mixed $offset | void){
}
/**
* offsetExists
*
* @return boolean
*/
public function offsetExists(mixed $offset | boolean){
}
/**
* offsetGet
*
* @return mixed
*/
public function offsetGet(mixed $offset | mixed){
}
}

View File

@ -0,0 +1,21 @@
class FictionalBuiltinClass {
const IS_PUBLIC = 256;
// @var $name Foo
public $name;
// @var $_app Foo2
public static $_app = 3;
/**
* getName
*
* @return Closure
*/
public function getName(object $object | Closure){
}
/**
* export
*
* @return string
*/
public static function export(mixed $class, string $name [, bool $return] | string){
}
}

View File

@ -0,0 +1,10 @@
<?php
/**
* DocBlockedFoo
*
* @property DateTime $docBlockFoo
*/
class DocBlockedFoo {
}

View File

@ -0,0 +1,3 @@
<?php
class BarClass { }

View File

@ -0,0 +1,3 @@
<?php
class FooClass extends BarClass { }

View File

@ -0,0 +1,3 @@
<?php
class BarClass2 extends BazClass { }

View File

@ -0,0 +1,3 @@
<?php
class BazClass { }

View File

@ -0,0 +1,3 @@
<?php
class FooClass2 extends BarClass2 { }

View File

@ -0,0 +1,5 @@
<?php
class FooClass {
public function bar( $baz = 'foo') {
}
}

View File

@ -0,0 +1,4 @@
<?php
interface FooInterface {
const SOME_CONTENT = 'bar';
}

View File

@ -0,0 +1,5 @@
<?php
trait FooTrait {
public $prop = 'baz';
}

View File

@ -0,0 +1,13 @@
<?php
class Foo2 {
public function bar() {
// }
/*
}
*/
$a = '}';
$b = "}";
return $a;
}
}

View File

@ -0,0 +1,8 @@
<?php
class Foo3 {
use FooTrait;
public function bar() {
}
}

View File

@ -0,0 +1,4 @@
<?php
$foo_only_in_tags->
$foo_only_in_tags::

View File

@ -0,0 +1,11 @@
<?php
class FooClassNotThisOne {
}
class FooClass
{
public function bar( $baz = 'foo')
{
}
}

View File

@ -0,0 +1,13 @@
<?php
function foo() {
// code
}
class FooClass {
public function bar( $baz = 'foo') {
}
}
function bar() {
// code
}

View File

@ -0,0 +1,8 @@
<?php
class X implements Foo {
}
class Y implements Foo, Foo2 {
}

View File

@ -0,0 +1,5 @@
<?php
namespace NS1;
use NS2\NamespacedFoo as NamespacedFoo;
class NamespacedFoo2 extends NamespacedFoo {}

View File

@ -0,0 +1,4 @@
<?php
namespace NS2;
class NamespacedFoo {}

View File

@ -0,0 +1,10 @@
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/
!_TAG_PROGRAM_NAME Exuberant Ctags //
!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/
!_TAG_PROGRAM_VERSION Development //
Foo interfaces.php /^interface Foo {$/;" i
Foo2 interfaces.php /^interface Foo2 {$/;" i
X implements.php /^class X implements Foo {$/;" c inherits:Foo
Y implements.php /^class Y implements Foo, Foo2 {$/;" c inherits:Foo,Foo2

View File

@ -0,0 +1,10 @@
<?php
interface Foo {
}
interface Foo2 {
}
interface FooFoo2 extends Foo, Foo2 {
}

View File

@ -0,0 +1,4 @@
<?php
namespace NS1;
class NamespacedFoo2 extends \NS2\NamespacedFoo {}

View File

@ -0,0 +1,4 @@
<?php
namespace NS2;
class NamespacedFoo {}

View File

@ -0,0 +1,10 @@
<?php
class Foo extends \NS1\Foo {
public function bar()
{
$this->
}
}

View File

@ -0,0 +1,5 @@
<?php
namespace NS1;
class Foo { }

View File

@ -0,0 +1,12 @@
<?php
trait FooTrait { }
class SomeTraitedClass {
use FooTrait;
}
class ExtendsNonExistsing extends NoSuchClass {
}

View File

@ -0,0 +1,3 @@
<?php

View File

@ -0,0 +1,23 @@
<?php
class Foo {
public function bar() {
// search from here
}
}
// leading whitespace intentional
final class Foo2 {
function bar2() {
// search from here
}
}
// no whitespace before {
class Foo3{
function bar2() {
// search from here
}
}

View File

@ -0,0 +1,9 @@
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/
!_TAG_PROGRAM_NAME Exuberant Ctags //
!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/
!_TAG_PROGRAM_VERSION 5.8 //
Foo foo.class.php /^class Foo {$/;" c
FooInterface foo.class.php /^interface Foo {$/;" i
bar foo.class.php /^ public function bar() {$/;" f

View File

@ -0,0 +1,54 @@
<?php
class Foo {
/**
* findme
*
* @param Foo[] $a a
*
* @return Foo[]
*/
public function findme($a) {
$a[42]->
}
/**
* fooarray
*
* @var Foo[]
*/
public $fooarray;
}
// @var $foo Foo[]
$foo[0]->
;
$foo2 = new Foo;
$foo2->fooarray[42]->
;
$foo3 = new Foo;
$foo4 = $foo2->fooarray[42]->findme();
$foo4[42]->
;
// @var $foo5 Foo[]
foreach ($foo5 as $f) {
$f->
}
// @var $foo6 Foo[]
foreach ($foo6 as $i => $f) {
$f->
}
// @var $foo7 Foo[]
foreach ($foo7[0]->fooarray as $i => $f) {
$f->
}
// @var $foo7 Foo[]
foreach ($foo7[0]->fooarray[42]->findme() as $i => $f) {
$f->
}

Some files were not shown because too many files have changed in this diff Show More