1111use PhpParser \Node \Scalar \String_ ;
1212use PhpParser \Node \Stmt ;
1313use PhpParser \NodeVisitorAbstract ;
14+ use PhpStaticAnalysis \Attributes \DefineType ;
1415use PhpStaticAnalysis \Attributes \Deprecated ;
1516use PhpStaticAnalysis \Attributes \Immutable ;
17+ use PhpStaticAnalysis \Attributes \ImportType ;
1618use PhpStaticAnalysis \Attributes \Impure ;
1719use PhpStaticAnalysis \Attributes \Internal ;
1820use PhpStaticAnalysis \Attributes \IsReadOnly ;
@@ -50,6 +52,7 @@ class AttributeNodeVisitor extends NodeVisitorAbstract
5052 private const ARGS_TWO_WITH_TYPE = 'two with type ' ;
5153 private const ARGS_MANY_IN_USE = "many in use " ;
5254 private const ARGS_MANY_WITH_NAME = "many with name " ;
55+ private const ARGS_MANY_IN_TYPE = "many in type " ;
5356 private const ARGS_MANY_WITHOUT_NAME = "many without name " ;
5457 private const ARGS_MANY_WITHOUT_NAME_AND_PREFIX = "many without name and prexif " ;
5558
@@ -65,8 +68,10 @@ class AttributeNodeVisitor extends NodeVisitorAbstract
6568
6669 private const ALLOWED_ATTRIBUTES_PER_NODE_TYPE = [
6770 Stmt \Class_::class => [
71+ DefineType::class,
6872 Deprecated::class,
6973 Immutable::class,
74+ ImportType::class,
7075 Internal::class,
7176 Method::class,
7277 Mixin::class,
@@ -79,6 +84,7 @@ class AttributeNodeVisitor extends NodeVisitorAbstract
7984 TemplateExtends::class,
8085 TemplateImplements::class,
8186 TemplateUse::class,
87+ Type::class,
8288 ],
8389 Stmt \ClassConst::class => [
8490 Deprecated::class,
@@ -111,8 +117,10 @@ class AttributeNodeVisitor extends NodeVisitorAbstract
111117 Type::class,
112118 ],
113119 Stmt \Interface_::class => [
120+ DefineType::class,
114121 Deprecated::class,
115122 Immutable::class,
123+ ImportType::class,
116124 Internal::class,
117125 Method::class,
118126 Mixin::class,
@@ -122,6 +130,7 @@ class AttributeNodeVisitor extends NodeVisitorAbstract
122130 Template::class,
123131 TemplateContravariant::class,
124132 TemplateCovariant::class,
133+ Type::class,
125134 ],
126135 Stmt \Property::class => [
127136 Deprecated::class,
@@ -131,8 +140,10 @@ class AttributeNodeVisitor extends NodeVisitorAbstract
131140 Type::class,
132141 ],
133142 Stmt \Trait_::class => [
143+ DefineType::class,
134144 Deprecated::class,
135145 Immutable::class,
146+ ImportType::class,
136147 Internal::class,
137148 Method::class,
138149 Mixin::class,
@@ -144,12 +155,15 @@ class AttributeNodeVisitor extends NodeVisitorAbstract
144155 Template::class,
145156 TemplateContravariant::class,
146157 TemplateCovariant::class,
158+ Type::class,
147159 ],
148160 ];
149161
150162 private const SHORT_NAME_TO_FQN = [
163+ 'DefineType ' => DefineType::class,
151164 'Deprecated ' => Deprecated::class,
152165 'Immutable ' => Immutable::class,
166+ 'ImportType ' => ImportType::class,
153167 'Impure ' => Impure::class,
154168 'Internal ' => Internal::class,
155169 'IsReadOnly ' => IsReadOnly::class,
@@ -176,12 +190,18 @@ class AttributeNodeVisitor extends NodeVisitorAbstract
176190 ];
177191
178192 private const ANNOTATION_PER_ATTRIBUTE = [
193+ DefineType::class => [
194+ 'all ' => 'type ' ,
195+ ],
179196 Deprecated::class => [
180197 'all ' => 'deprecated ' ,
181198 ],
182199 Immutable::class => [
183200 'all ' => 'immutable ' ,
184201 ],
202+ ImportType::class => [
203+ 'all ' => 'import-type ' ,
204+ ],
185205 Impure::class => [
186206 'all ' => 'impure ' ,
187207 ],
@@ -250,6 +270,7 @@ class AttributeNodeVisitor extends NodeVisitorAbstract
250270 'all ' => 'throws ' ,
251271 ],
252272 Type::class => [
273+ Stmt \Class_::class => 'type ' ,
253274 Stmt \ClassConst::class => 'var ' ,
254275 Stmt \ClassMethod::class => 'return ' ,
255276 Stmt \Function_::class => 'return ' ,
@@ -258,12 +279,18 @@ class AttributeNodeVisitor extends NodeVisitorAbstract
258279 ];
259280
260281 private const ARGUMENTS_PER_ATTRIBUTE = [
282+ DefineType::class => [
283+ 'all ' => self ::ARGS_MANY_IN_TYPE ,
284+ ],
261285 Deprecated::class => [
262286 'all ' => self ::ARGS_NONE ,
263287 ],
264288 Immutable::class => [
265289 'all ' => self ::ARGS_NONE_WITH_PREFIX ,
266290 ],
291+ ImportType::class => [
292+ 'all ' => self ::ARGS_MANY_IN_TYPE ,
293+ ],
267294 Impure::class => [
268295 'all ' => self ::ARGS_NONE_WITH_PREFIX ,
269296 ],
@@ -447,6 +474,12 @@ public function enterNode(Node $node)
447474 }
448475 }
449476 break ;
477+ case self ::ARGS_MANY_IN_TYPE :
478+ foreach ($ args as $ arg ) {
479+ $ tagsToAdd [] = $ this ->createTag ($ nodeType , $ attributeName , $ arg , prefixWithName: true , prefix: $ this ->toolType );
480+ $ tagCreated = true ;
481+ }
482+ break ;
450483 }
451484 if ($ tagCreated ) {
452485 $ this ->updatePositions ($ attribute );
@@ -474,7 +507,8 @@ private function createTag(
474507 Arg $ of = null ,
475508 bool $ useName = false ,
476509 string $ nameToUse = null ,
477- string $ prefix = null
510+ string $ prefix = null ,
511+ bool $ prefixWithName = false
478512 ): string {
479513 if (array_key_exists ($ nodeType , self ::ANNOTATION_PER_ATTRIBUTE [$ attributeName ])) {
480514 $ tagName = self ::ANNOTATION_PER_ATTRIBUTE [$ attributeName ][$ nodeType ];
@@ -502,6 +536,15 @@ private function createTag(
502536 $ type = '\\' . $ type ;
503537 }
504538 }
539+ if ($ prefixWithName ) {
540+ $ alias = $ argument ->name ;
541+ if ($ alias instanceof Node \Identifier) {
542+ if ($ attributeName === ImportType::class) {
543+ $ type = 'from ' . $ type ;
544+ }
545+ $ type = $ alias ->toString () . ' ' . $ type ;
546+ }
547+ }
505548 if ($ type !== '' ) {
506549 $ tag .= ' ' . $ type ;
507550 }
0 commit comments