1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-01-24 06:30:03 +08:00
SpaceVim/bundle/phpcomplete.vim-vim7/bin/generator/classes.php

412 lines
16 KiB
PHP
Vendored

<?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);
}