| 1 | <?php |
|---|
| 2 | |
|---|
| 3 | require_once('DojoFunctionBody.php'); |
|---|
| 4 | require_once('DojoBlock.php'); |
|---|
| 5 | |
|---|
| 6 | class DojoFunctionDeclare extends DojoBlock |
|---|
| 7 | { |
|---|
| 8 | private $object = 'DojoFunctionDeclare'; |
|---|
| 9 | |
|---|
| 10 | private $parameters; |
|---|
| 11 | private $function_name; |
|---|
| 12 | private $body; |
|---|
| 13 | |
|---|
| 14 | private $anonymous = false; |
|---|
| 15 | private $prototype = ''; |
|---|
| 16 | private $constructor = false; |
|---|
| 17 | private $aliases = ''; |
|---|
| 18 | |
|---|
| 19 | public function __construct($package, $line_number = false, $position = false) |
|---|
| 20 | { |
|---|
| 21 | parent::__construct($package, $line_number, $position); |
|---|
| 22 | $this->parameters = new DojoParameters($package); |
|---|
| 23 | $this->body = new DojoFunctionBody($package); |
|---|
| 24 | } |
|---|
| 25 | |
|---|
| 26 | public function getFunctionName() |
|---|
| 27 | { |
|---|
| 28 | return $this->function_name; |
|---|
| 29 | } |
|---|
| 30 | |
|---|
| 31 | public function getAliases() |
|---|
| 32 | { |
|---|
| 33 | return $this->aliases; |
|---|
| 34 | } |
|---|
| 35 | |
|---|
| 36 | public function setFunctionName($function_name) |
|---|
| 37 | { |
|---|
| 38 | $this->function_name = $function_name; |
|---|
| 39 | } |
|---|
| 40 | |
|---|
| 41 | public function setPrototype($function_name) |
|---|
| 42 | { |
|---|
| 43 | $this->prototype = $function_name; |
|---|
| 44 | } |
|---|
| 45 | |
|---|
| 46 | public function getPrototype() |
|---|
| 47 | { |
|---|
| 48 | return $this->prototype; |
|---|
| 49 | } |
|---|
| 50 | |
|---|
| 51 | public function setInstance($function_name) |
|---|
| 52 | { |
|---|
| 53 | $this->instance = $function_name; |
|---|
| 54 | } |
|---|
| 55 | |
|---|
| 56 | public function getInstance() |
|---|
| 57 | { |
|---|
| 58 | return $this->instance; |
|---|
| 59 | } |
|---|
| 60 | |
|---|
| 61 | public function setConstructor($constructor) |
|---|
| 62 | { |
|---|
| 63 | $this->constructor = $constructor; |
|---|
| 64 | } |
|---|
| 65 | |
|---|
| 66 | public function isConstructor() |
|---|
| 67 | { |
|---|
| 68 | return $this->constructor; |
|---|
| 69 | } |
|---|
| 70 | |
|---|
| 71 | public function isAnonymous() |
|---|
| 72 | { |
|---|
| 73 | return $this->anonymous; |
|---|
| 74 | } |
|---|
| 75 | |
|---|
| 76 | public function isThis() |
|---|
| 77 | { |
|---|
| 78 | return ($this->prototype || $this->instance); |
|---|
| 79 | } |
|---|
| 80 | |
|---|
| 81 | public function getThis() |
|---|
| 82 | { |
|---|
| 83 | return ($this->prototype) ? $this->prototype : $this->instance; |
|---|
| 84 | } |
|---|
| 85 | |
|---|
| 86 | public function getInstanceVariableNames() |
|---|
| 87 | { |
|---|
| 88 | return array_unique($this->body->getInstanceVariableNames()); |
|---|
| 89 | } |
|---|
| 90 | |
|---|
| 91 | public function getReturnComments() |
|---|
| 92 | { |
|---|
| 93 | return array_unique($this->body->getReturnComments()); |
|---|
| 94 | } |
|---|
| 95 | |
|---|
| 96 | public function getThisInheritanceCalls() |
|---|
| 97 | { |
|---|
| 98 | return array_unique($this->body->getThisInheritanceCalls()); |
|---|
| 99 | } |
|---|
| 100 | |
|---|
| 101 | public function removeCodeFrom($lines){ |
|---|
| 102 | for ($i = $this->start[0]; $i <= $this->end[0]; $i++) { |
|---|
| 103 | $line = $lines[$i]; |
|---|
| 104 | if ($i == $this->start[0]) { |
|---|
| 105 | $lines[$i] = Text::blankOutAt($line, $this->start[1]); |
|---|
| 106 | } |
|---|
| 107 | elseif ($i == $this->end[0]) { |
|---|
| 108 | $lines[$i] = Text::blankOutAt($line, 0, $this->end[1]); |
|---|
| 109 | } |
|---|
| 110 | else { |
|---|
| 111 | $lines[$i] = Text::blankOut($line, $line); |
|---|
| 112 | } |
|---|
| 113 | } |
|---|
| 114 | return $lines; |
|---|
| 115 | } |
|---|
| 116 | |
|---|
| 117 | public function build(){ |
|---|
| 118 | if (!$this->start) { |
|---|
| 119 | die("DojoFunctionDeclare->build() used before setting a start position"); |
|---|
| 120 | } |
|---|
| 121 | if ($this->end) { |
|---|
| 122 | return $this->end; |
|---|
| 123 | } |
|---|
| 124 | |
|---|
| 125 | $lines = Text::chop($this->package->getCode(), $this->start[0], $this->start[1]); |
|---|
| 126 | $line = trim($lines[$this->start[0]]); |
|---|
| 127 | if (strpos($line, 'function') === 0) { |
|---|
| 128 | $line = substr($line, 8); |
|---|
| 129 | preg_match('%[^\s]%', $line, $match); |
|---|
| 130 | if ($match[0] != '(') { |
|---|
| 131 | $this->function_name = trim(substr($line, 0, strpos($line, '('))); |
|---|
| 132 | } |
|---|
| 133 | } |
|---|
| 134 | else { |
|---|
| 135 | $name = trim(substr($line, 0, strpos($line, '='))); |
|---|
| 136 | $extra = substr($line, strpos($line, '=') + 1); |
|---|
| 137 | if (preg_match('%^\s+new\s+%', $name, $match) || preg_match('%^\s*new\s+%', $extra, $match)) { |
|---|
| 138 | $this->anonymous = true; |
|---|
| 139 | $name = str_replace($match[0], '', $name); |
|---|
| 140 | } |
|---|
| 141 | if (($pos = strpos($name, '.prototype.')) !== false) { |
|---|
| 142 | $this->prototype = substr($name, 0, $pos); |
|---|
| 143 | $name = str_replace('.prototype', '', $name); |
|---|
| 144 | } |
|---|
| 145 | if (($pos = strpos($name, 'this.')) === 0) { |
|---|
| 146 | $this->instance = $this->getFunctionName(); |
|---|
| 147 | $name = $this->getFunctionName() . "." . preg_replace('%^this\.%', '', $name); |
|---|
| 148 | } |
|---|
| 149 | |
|---|
| 150 | $full_lines = Text::chop($this->package->getCode(), $this->start[0], 0); |
|---|
| 151 | $full_line = substr($full_lines[$this->start[0]], 0, $this->start[1]); |
|---|
| 152 | if (preg_match('%(?:[a-zA-Z0-9._$]+\s*=\s*)+$%', $full_line, $matches)) { |
|---|
| 153 | $aliases = preg_split('%\s*=\s*%', $matches[0]); |
|---|
| 154 | foreach ($aliases as $alias) { |
|---|
| 155 | $alias = trim($alias); |
|---|
| 156 | if ($alias) { |
|---|
| 157 | if (strpos($alias, 'this.') === 0) { |
|---|
| 158 | print $this->getFunctionName; |
|---|
| 159 | $alias = $this->getFunctionName() . "." . preg_replace('%^this\.%', '', $alias); |
|---|
| 160 | } |
|---|
| 161 | $this->aliases[] = $alias; |
|---|
| 162 | } |
|---|
| 163 | } |
|---|
| 164 | } |
|---|
| 165 | |
|---|
| 166 | $this->function_name = $name; |
|---|
| 167 | } |
|---|
| 168 | |
|---|
| 169 | $this->parameters->setStart($this->start[0], strpos($lines[$this->start[0]], '(')); |
|---|
| 170 | $end = $this->parameters->build(); |
|---|
| 171 | |
|---|
| 172 | $lines = Text::chop($this->package->getCode(), $end[0], $end[1]); |
|---|
| 173 | foreach ($lines as $line_number => $line) { |
|---|
| 174 | if (($pos = strpos($line, '{')) !== false) { |
|---|
| 175 | $this->body->setStart($line_number, $pos); |
|---|
| 176 | return $this->end = $this->body->build(); |
|---|
| 177 | } |
|---|
| 178 | } |
|---|
| 179 | } |
|---|
| 180 | |
|---|
| 181 | public function getParameter($pos) |
|---|
| 182 | { |
|---|
| 183 | return $this->parameters->getParameter($pos); |
|---|
| 184 | } |
|---|
| 185 | |
|---|
| 186 | public function getParameters() |
|---|
| 187 | { |
|---|
| 188 | return $this->parameters->getParameters(); |
|---|
| 189 | } |
|---|
| 190 | |
|---|
| 191 | public function addBlockCommentKey($key) |
|---|
| 192 | { |
|---|
| 193 | $this->body->addBlockCommentKey($key); |
|---|
| 194 | } |
|---|
| 195 | |
|---|
| 196 | public function getBlockCommentKeys() |
|---|
| 197 | { |
|---|
| 198 | return $this->body->getBlockCommentKeys(); |
|---|
| 199 | } |
|---|
| 200 | |
|---|
| 201 | public function getBlockComment($key) |
|---|
| 202 | { |
|---|
| 203 | return $this->body->getBlockComment($key); |
|---|
| 204 | } |
|---|
| 205 | |
|---|
| 206 | public function getSource() |
|---|
| 207 | { |
|---|
| 208 | return $this->body->getSource(); |
|---|
| 209 | } |
|---|
| 210 | |
|---|
| 211 | public function getInstanceFunctions($function_name) |
|---|
| 212 | { |
|---|
| 213 | return $this->body->getInstanceFunctions($function_name); |
|---|
| 214 | } |
|---|
| 215 | |
|---|
| 216 | public function rollOut(&$output) { |
|---|
| 217 | $masquerading_as_function = $function_name = $this->getFunctionName(); |
|---|
| 218 | if ($this->isThis()) { |
|---|
| 219 | $masquerading_as_function = $this->getThis(); |
|---|
| 220 | } |
|---|
| 221 | |
|---|
| 222 | $package_name = $this->package->getPackageName(); |
|---|
| 223 | |
|---|
| 224 | if ($aliases = $this->getAliases()) { |
|---|
| 225 | foreach ($aliases as $alias) { |
|---|
| 226 | $output[$package_name]['meta']['functions'][$alias]['meta']['is'] = $function_name; |
|---|
| 227 | } |
|---|
| 228 | } |
|---|
| 229 | if ($this->isAnonymous()) { |
|---|
| 230 | $output[$package_name]['meta']['functions'][$function_name]['meta']['initialized'] = true; |
|---|
| 231 | } |
|---|
| 232 | $output[$package_name]['meta']['functions'][$function_name]['meta']['summary'] = ''; |
|---|
| 233 | |
|---|
| 234 | $parameters = $this->getParameters(); |
|---|
| 235 | foreach ($parameters as $parameter) { |
|---|
| 236 | if ($parameter->isA(DojoVariable)) { |
|---|
| 237 | $output[$package_name]['meta']['functions'][$function_name]['meta']['parameters'][$parameter->getVariable()]['type'] = $parameter->getType(); |
|---|
| 238 | $this->addBlockCommentKey($parameter->getVariable()); |
|---|
| 239 | } |
|---|
| 240 | } |
|---|
| 241 | |
|---|
| 242 | $this->addBlockCommentKey('summary'); |
|---|
| 243 | $this->addBlockCommentKey('description'); |
|---|
| 244 | $this->addBlockCommentKey('returns'); |
|---|
| 245 | |
|---|
| 246 | $output[$package_name]['meta']['functions'][$function_name]['meta']['src'] = $this->getSource(); |
|---|
| 247 | |
|---|
| 248 | $all_variables = array(); |
|---|
| 249 | $instance_variables = $this->getInstanceVariableNames(); |
|---|
| 250 | foreach ($instance_variables as $instance_variable) { |
|---|
| 251 | $this->addBlockCommentKey($instance_variable); |
|---|
| 252 | $all_variables[] = $instance_variable; |
|---|
| 253 | if (isset($output[$package_name]['meta']['functions'][$masquerading_as_function]['meta']['instance_variables'])) { |
|---|
| 254 | if (!in_array($instance_variable, $output[$package_name]['meta']['functions'][$masquerading_as_function]['meta']['instance_variables'])) { |
|---|
| 255 | $output[$package_name]['meta']['functions'][$masquerading_as_function]['meta']['instance_variables'][] = $instance_variable; |
|---|
| 256 | } |
|---|
| 257 | } |
|---|
| 258 | else { |
|---|
| 259 | $output[$package_name]['meta']['functions'][$masquerading_as_function]['meta']['instance_variables'][] = $instance_variable; |
|---|
| 260 | } |
|---|
| 261 | } |
|---|
| 262 | |
|---|
| 263 | $instance_functions = $this->getInstanceFunctions($function_name); |
|---|
| 264 | foreach ($instance_functions as $instance_function) { |
|---|
| 265 | $instance_function->rollOut($output); |
|---|
| 266 | $output[$package_name]['meta']['functions'][$instance_function->getFunctionName()]['meta']['instance'] = $function_name; |
|---|
| 267 | } |
|---|
| 268 | |
|---|
| 269 | $comment_keys = $this->getBlockCommentKeys(); |
|---|
| 270 | foreach ($comment_keys as $key) { |
|---|
| 271 | if ($key == 'summary') { |
|---|
| 272 | $output[$package_name]['meta']['functions'][$function_name]['meta']['summary'] = $this->getBlockComment($key); |
|---|
| 273 | } |
|---|
| 274 | elseif ($key == 'description') { |
|---|
| 275 | $output[$package_name]['meta']['functions'][$function_name]['meta']['description'] = $this->getBlockComment($key); |
|---|
| 276 | } |
|---|
| 277 | elseif ($key == 'returns') { |
|---|
| 278 | $output[$package_name]['meta']['functions'][$function_name]['extra']['returns'] = $this->getBlockComment($key); |
|---|
| 279 | } |
|---|
| 280 | elseif (in_array($key, $all_variables) && $comment = $this->getBlockComment($key)) { |
|---|
| 281 | list($type, $comment) = explode(' ', $comment, 2); |
|---|
| 282 | $type = preg_replace('%(^[^a-zA-Z0-9._$]|[^a-zA-Z0-9._$?]$)%', '', $type); |
|---|
| 283 | $output[$package_name]['meta']['functions'][$function_name]['extra']['variables'][$key]['type'] = $type; |
|---|
| 284 | $output[$package_name]['meta']['functions'][$function_name]['extra']['variables'][$key]['summary'] = $comment; |
|---|
| 285 | } |
|---|
| 286 | elseif (!empty($output[$package_name]['meta']['functions'][$function_name]['meta']['parameters']) && array_key_exists($key, $output[$package_name]['meta']['functions'][$function_name]['meta']['parameters']) && $comment = $this->getBlockComment($key)) { |
|---|
| 287 | list($type, $comment) = explode(' ', $comment, 2); |
|---|
| 288 | $type = preg_replace('%(^[^a-zA-Z0-9._$]|[^a-zA-Z0-9._$?]$)%', '', $type); |
|---|
| 289 | $output[$package_name]['meta']['functions'][$function_name]['extra']['parameters'][$key]['type'] = $type; |
|---|
| 290 | $output[$package_name]['meta']['functions'][$function_name]['extra']['parameters'][$key]['summary'] = $comment; |
|---|
| 291 | } |
|---|
| 292 | } |
|---|
| 293 | |
|---|
| 294 | $returns = $this->getReturnComments(); |
|---|
| 295 | if (count($returns) == 1) { |
|---|
| 296 | $output[$package_name]['meta']['functions'][$function_name]['meta']['returns'] = $returns[0]; |
|---|
| 297 | } |
|---|
| 298 | elseif ($returns) { |
|---|
| 299 | $output[$package_name]['meta']['functions'][$function_name]['meta']['returns'] = 'mixed'; |
|---|
| 300 | } |
|---|
| 301 | |
|---|
| 302 | if ($calls = $this->getThisInheritanceCalls()) { |
|---|
| 303 | $output[$package_name]['meta']['functions'][$function_name]['meta']['call_chain'] = $calls; |
|---|
| 304 | } |
|---|
| 305 | |
|---|
| 306 | if ($this->getPrototype()) { |
|---|
| 307 | $output[$package_name]['meta']['functions'][$function_name]['meta']['prototype'] = $this->getPrototype(); |
|---|
| 308 | } |
|---|
| 309 | if ($this->getInstance()) { |
|---|
| 310 | $output[$package_name]['meta']['functions'][$function_name]['meta']['instance'] = $this->getInstance(); |
|---|
| 311 | } |
|---|
| 312 | } |
|---|
| 313 | } |
|---|
| 314 | |
|---|
| 315 | ?> |
|---|