@@ -21,49 +21,66 @@ public function __construct(\SimpleXMLElement $parameter, ?PhpStanFunction $phpS
21
21
}
22
22
23
23
/**
24
- * Returns the type as declared in the doc.
25
- * @return string
24
+ * Tries to identify the typehint from the doc-block parameter
26
25
*/
27
- public function getType (): string
26
+ public function getSignatureType (): string
28
27
{
29
- $ type = $ this ->parameter ->type ->__toString ();
30
- $ strType = Type::toRootNamespace ($ type );
31
- if ($ strType !== 'mixed ' && $ strType !== 'resource ' && $ this ->phpStanFunction !== null ) {
32
- $ phpStanParameter = $ this ->phpStanFunction ->getParameter ($ this ->getParameter ());
33
- if ($ phpStanParameter ) {
34
- // Let's make the parameter nullable if it is by reference and is used only for writing.
35
- if ($ phpStanParameter ->isWriteOnly ()) {
36
- $ strType = '? ' .$ strType ;
37
- }
38
- }
28
+ $ coreType = $ this ->getDocBlockType ();
29
+ //list all types in the doc-block
30
+ $ types = explode ('| ' , $ coreType );
31
+ //no typehint exists for thoses cases
32
+ if (in_array ('resource ' , $ types ) || in_array ('mixed ' , $ types )) {
33
+ return '' ;
34
+ }
35
+ //remove 'null' from the list to identify if the signature type should be nullable
36
+ $ nullablePosition = array_search ('null ' , $ types );
37
+ if ($ nullablePosition !== false ) {
38
+ array_splice ($ types , $ nullablePosition , 1 );
39
+ }
40
+ if (count ($ types ) === 0 ) {
41
+ throw new \RuntimeException ('Error when trying to extract parameter type ' );
42
+ }
43
+ //if there is still several types, no typehint
44
+ if (count ($ types ) > 1 ) {
45
+ return '' ;
46
+ }
47
+
48
+ $ finalType = $ types [0 ];
49
+ //strip callable type of its possible parenthesis and return (ex: callable(): void)
50
+ if (\strpos ($ finalType , 'callable( ' ) > -1 ) {
51
+ $ finalType = 'callable ' ;
52
+ } elseif (strpos ($ finalType , '[] ' ) !== false ) {
53
+ $ finalType = 'iterable ' ; //generics cannot be typehinted and have to be turned into iterable
39
54
}
40
- return $ strType ;
55
+ return ( $ nullablePosition !== false ? ' ? ' : '' ). $ finalType ;
41
56
}
42
57
43
58
/**
44
- * Returns the type as declared in the doc.
45
- * @return string
59
+ * Try to fetch the complete type used in the doc_block, first from phpstan, then from the regular documentation
46
60
*/
47
- public function getBestType (): string
61
+ public function getDocBlockType (): string
48
62
{
49
- // Get the type from PhpStan database first, then from the php doc.
50
63
if ($ this ->phpStanFunction !== null ) {
51
64
$ phpStanParameter = $ this ->phpStanFunction ->getParameter ($ this ->getParameter ());
52
65
if ($ phpStanParameter ) {
53
66
try {
54
- return $ phpStanParameter ->getType ();
67
+ $ type = $ phpStanParameter ->getType ();
68
+ // Let's make the parameter nullable if it is by reference and is used only for writing.
69
+ if ($ phpStanParameter ->isWriteOnly () && $ type !== 'resource ' && $ type !== 'mixed ' ) {
70
+ $ type = $ type .'|null ' ;
71
+ }
72
+ return $ type ;
55
73
} catch (EmptyTypeException $ e ) {
56
- // If the type is empty in PHPStan, let's fallback to documentation.
57
- return $ this -> getType ();
74
+ // If the type is empty in PHPStan, we fallback to documentation.
75
+ // @ignoreException
58
76
}
59
77
}
60
78
}
61
- return $ this ->getType ();
79
+
80
+ $ type = $ this ->parameter ->type ->__toString ();
81
+ return Type::toRootNamespace ($ type );
62
82
}
63
83
64
- /*
65
- * @return string
66
- */
67
84
public function getParameter (): string
68
85
{
69
86
if ($ this ->isVariadic ()) {
@@ -157,9 +174,4 @@ private function getInnerXml(\SimpleXMLElement $SimpleXMLElement): string
157
174
$ inner_xml = trim ($ inner_xml );
158
175
return $ inner_xml ;
159
176
}
160
-
161
- public function isTypeable (): bool
162
- {
163
- return $ this ->getType () !== 'mixed ' && $ this ->getType () !== 'resource ' && \count (\explode ("| " , $ this ->getType ())) < 2 ;
164
- }
165
177
}
0 commit comments