Mercurial > hg > isophonics-drupal-site
comparison vendor/psy/psysh/src/Psy/Formatter/SignatureFormatter.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children | 7a779792577d |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4c8ae668cc8c |
---|---|
1 <?php | |
2 | |
3 /* | |
4 * This file is part of Psy Shell. | |
5 * | |
6 * (c) 2012-2017 Justin Hileman | |
7 * | |
8 * For the full copyright and license information, please view the LICENSE | |
9 * file that was distributed with this source code. | |
10 */ | |
11 | |
12 namespace Psy\Formatter; | |
13 | |
14 use Psy\Reflection\ReflectionConstant; | |
15 use Psy\Reflection\ReflectionLanguageConstruct; | |
16 use Psy\Util\Json; | |
17 use Symfony\Component\Console\Formatter\OutputFormatter; | |
18 | |
19 /** | |
20 * An abstract representation of a function, class or property signature. | |
21 */ | |
22 class SignatureFormatter implements Formatter | |
23 { | |
24 /** | |
25 * Format a signature for the given reflector. | |
26 * | |
27 * Defers to subclasses to do the actual formatting. | |
28 * | |
29 * @param \Reflector $reflector | |
30 * | |
31 * @return string Formatted signature | |
32 */ | |
33 public static function format(\Reflector $reflector) | |
34 { | |
35 switch (true) { | |
36 case $reflector instanceof \ReflectionFunction: | |
37 case $reflector instanceof ReflectionLanguageConstruct: | |
38 return self::formatFunction($reflector); | |
39 | |
40 // this case also covers \ReflectionObject: | |
41 case $reflector instanceof \ReflectionClass: | |
42 return self::formatClass($reflector); | |
43 | |
44 case $reflector instanceof ReflectionConstant: | |
45 return self::formatConstant($reflector); | |
46 | |
47 case $reflector instanceof \ReflectionMethod: | |
48 return self::formatMethod($reflector); | |
49 | |
50 case $reflector instanceof \ReflectionProperty: | |
51 return self::formatProperty($reflector); | |
52 | |
53 default: | |
54 throw new \InvalidArgumentException('Unexpected Reflector class: ' . get_class($reflector)); | |
55 } | |
56 } | |
57 | |
58 /** | |
59 * Print the signature name. | |
60 * | |
61 * @param \Reflector $reflector | |
62 * | |
63 * @return string Formatted name | |
64 */ | |
65 public static function formatName(\Reflector $reflector) | |
66 { | |
67 return $reflector->getName(); | |
68 } | |
69 | |
70 /** | |
71 * Print the method, property or class modifiers. | |
72 * | |
73 * Technically this should be a trait. Can't wait for 5.4 :) | |
74 * | |
75 * @param \Reflector $reflector | |
76 * | |
77 * @return string Formatted modifiers | |
78 */ | |
79 private static function formatModifiers(\Reflector $reflector) | |
80 { | |
81 return implode(' ', array_map(function ($modifier) { | |
82 return sprintf('<keyword>%s</keyword>', $modifier); | |
83 }, \Reflection::getModifierNames($reflector->getModifiers()))); | |
84 } | |
85 | |
86 /** | |
87 * Format a class signature. | |
88 * | |
89 * @param \ReflectionClass $reflector | |
90 * | |
91 * @return string Formatted signature | |
92 */ | |
93 private static function formatClass(\ReflectionClass $reflector) | |
94 { | |
95 $chunks = array(); | |
96 | |
97 if ($modifiers = self::formatModifiers($reflector)) { | |
98 $chunks[] = $modifiers; | |
99 } | |
100 | |
101 if (version_compare(PHP_VERSION, '5.4', '>=') && $reflector->isTrait()) { | |
102 $chunks[] = 'trait'; | |
103 } else { | |
104 $chunks[] = $reflector->isInterface() ? 'interface' : 'class'; | |
105 } | |
106 | |
107 $chunks[] = sprintf('<class>%s</class>', self::formatName($reflector)); | |
108 | |
109 if ($parent = $reflector->getParentClass()) { | |
110 $chunks[] = 'extends'; | |
111 $chunks[] = sprintf('<class>%s</class>', $parent->getName()); | |
112 } | |
113 | |
114 $interfaces = $reflector->getInterfaceNames(); | |
115 if (!empty($interfaces)) { | |
116 sort($interfaces); | |
117 | |
118 $chunks[] = 'implements'; | |
119 $chunks[] = implode(', ', array_map(function ($name) { | |
120 return sprintf('<class>%s</class>', $name); | |
121 }, $interfaces)); | |
122 } | |
123 | |
124 return implode(' ', $chunks); | |
125 } | |
126 | |
127 /** | |
128 * Format a constant signature. | |
129 * | |
130 * @param ReflectionConstant $reflector | |
131 * | |
132 * @return string Formatted signature | |
133 */ | |
134 private static function formatConstant(ReflectionConstant $reflector) | |
135 { | |
136 $value = $reflector->getValue(); | |
137 $style = self::getTypeStyle($value); | |
138 | |
139 return sprintf( | |
140 '<keyword>const</keyword> <const>%s</const> = <%s>%s</%s>', | |
141 self::formatName($reflector), | |
142 $style, | |
143 OutputFormatter::escape(Json::encode($value)), | |
144 $style | |
145 ); | |
146 } | |
147 | |
148 /** | |
149 * Helper for getting output style for a given value's type. | |
150 * | |
151 * @param mixed $value | |
152 * | |
153 * @return string | |
154 */ | |
155 private static function getTypeStyle($value) | |
156 { | |
157 if (is_int($value) || is_float($value)) { | |
158 return 'number'; | |
159 } elseif (is_string($value)) { | |
160 return 'string'; | |
161 } elseif (is_bool($value) || is_null($value)) { | |
162 return 'bool'; | |
163 } else { | |
164 return 'strong'; | |
165 } | |
166 } | |
167 | |
168 /** | |
169 * Format a property signature. | |
170 * | |
171 * @param \ReflectionProperty $reflector | |
172 * | |
173 * @return string Formatted signature | |
174 */ | |
175 private static function formatProperty(\ReflectionProperty $reflector) | |
176 { | |
177 return sprintf( | |
178 '%s <strong>$%s</strong>', | |
179 self::formatModifiers($reflector), | |
180 $reflector->getName() | |
181 ); | |
182 } | |
183 | |
184 /** | |
185 * Format a function signature. | |
186 * | |
187 * @param \ReflectionFunction $reflector | |
188 * | |
189 * @return string Formatted signature | |
190 */ | |
191 private static function formatFunction(\ReflectionFunctionAbstract $reflector) | |
192 { | |
193 return sprintf( | |
194 '<keyword>function</keyword> %s<function>%s</function>(%s)', | |
195 $reflector->returnsReference() ? '&' : '', | |
196 self::formatName($reflector), | |
197 implode(', ', self::formatFunctionParams($reflector)) | |
198 ); | |
199 } | |
200 | |
201 /** | |
202 * Format a method signature. | |
203 * | |
204 * @param \ReflectionMethod $reflector | |
205 * | |
206 * @return string Formatted signature | |
207 */ | |
208 private static function formatMethod(\ReflectionMethod $reflector) | |
209 { | |
210 return sprintf( | |
211 '%s %s', | |
212 self::formatModifiers($reflector), | |
213 self::formatFunction($reflector) | |
214 ); | |
215 } | |
216 | |
217 /** | |
218 * Print the function params. | |
219 * | |
220 * @param \ReflectionFunctionAbstract $reflector | |
221 * | |
222 * @return string | |
223 */ | |
224 private static function formatFunctionParams(\ReflectionFunctionAbstract $reflector) | |
225 { | |
226 $params = array(); | |
227 foreach ($reflector->getParameters() as $param) { | |
228 $hint = ''; | |
229 try { | |
230 if ($param->isArray()) { | |
231 $hint = '<keyword>array</keyword> '; | |
232 } elseif ($class = $param->getClass()) { | |
233 $hint = sprintf('<class>%s</class> ', $class->getName()); | |
234 } | |
235 } catch (\Exception $e) { | |
236 // sometimes we just don't know... | |
237 // bad class names, or autoloaded classes that haven't been loaded yet, or whathaveyou. | |
238 // come to think of it, the only time I've seen this is with the intl extension. | |
239 | |
240 // Hax: we'll try to extract it :P | |
241 $chunks = explode('$' . $param->getName(), (string) $param); | |
242 $chunks = explode(' ', trim($chunks[0])); | |
243 $guess = end($chunks); | |
244 | |
245 $hint = sprintf('<urgent>%s</urgent> ', $guess); | |
246 } | |
247 | |
248 if ($param->isOptional()) { | |
249 if (!$param->isDefaultValueAvailable()) { | |
250 $value = 'unknown'; | |
251 $typeStyle = 'urgent'; | |
252 } else { | |
253 $value = $param->getDefaultValue(); | |
254 $typeStyle = self::getTypeStyle($value); | |
255 $value = is_array($value) ? 'array()' : is_null($value) ? 'null' : var_export($value, true); | |
256 } | |
257 $default = sprintf(' = <%s>%s</%s>', $typeStyle, OutputFormatter::escape($value), $typeStyle); | |
258 } else { | |
259 $default = ''; | |
260 } | |
261 | |
262 $params[] = sprintf( | |
263 '%s%s<strong>$%s</strong>%s', | |
264 $param->isPassedByReference() ? '&' : '', | |
265 $hint, | |
266 $param->getName(), | |
267 $default | |
268 ); | |
269 } | |
270 | |
271 return $params; | |
272 } | |
273 } |