@@ -79,25 +79,15 @@ private function updateDocCommentOfClass(Class_ $classNode): void
7979 $ allowedTypes = (new \ReflectionClass ($ class ))->getDefaultProperties ()['allowedTypes ' ] ?? [];
8080 $ phpDocInfo = $ this ->phpDocInfoFactory ->createEmpty ($ classNode );
8181
82- $ this ->definedFor ($ class )
82+ collect (Utils::definedFor ($ class ))
83+ ->filter (static fn (string $ option ): bool => !str ($ option )->is (['*@* ' ]))
84+ ->sort ()
8385 ->each (fn (string $ option ) => $ phpDocInfo ->addPhpDocTagNode (
8486 $ this ->createPhpDocTagNodeOfMethod ($ option , $ allowedTypes )
8587 ))
8688 ->whenNotEmpty (fn () => $ this ->docBlockUpdater ->updateRefactoredNodeWithPhpDocInfo ($ classNode ));
8789 }
8890
89- /**
90- * @param class-string<\Guanguans\Notify\Foundation\Message> $class
91- *
92- * @throws \ReflectionException
93- */
94- private function definedFor (string $ class ): Collection
95- {
96- return collect (Utils::definedFor ($ class ))
97- ->filter (static fn (string $ option ): bool => !str ($ option )->is (['*@* ' ]))
98- ->sort ();
99- }
100-
10191 /**
10292 * @see \Symfony\Component\OptionsResolver\OptionsResolver::VALIDATION_FUNCTIONS
10393 *
@@ -129,22 +119,99 @@ private function createPhpDocTagNodeOfMethod(string $option, array $allowedTypes
129119 return new PhpDocTagNode ('@method ' , new GenericTagValueNode ("self $ camelCasedOption( $ parameter) " ));
130120 }
131121
122+ /**
123+ * @throws \ReflectionException
124+ */
132125 private function updateAllowedTypesProperty (Class_ $ classNode ): void
133126 {
134- collect ($ classNode ->getMethods ())
127+ // $defined = Utils::definedFor($this->getName($classNode));
128+ $ allowedTypes = collect ($ classNode ->getMethods ())
135129 ->filter (
136130 fn (ClassMethod $ classMethodNode ): bool => 1 === \count ($ classMethodNode ->params )
137131 && str_starts_with ($ this ->getName ($ classMethodNode ), 'add ' )
138132 )
139133 ->mapWithKeys (function (ClassMethod $ classMethodNode ): array {
140- $ option = str ($ this ->getName ($ classMethodNode ))->after ('add ' )->snake ()->plural ()->toString ();
134+ // $rawOption = str($this->getName($classMethodNode))->after('add');
135+ // $caster = collect([
136+ // static fn (string $name): string => $name,
137+ // static fn (string $name): string => Str::snake($name),
138+ // Str::camel(...),
139+ // Str::pascal(...),
140+ // Str::kebab(...),
141+ // ])
142+ // ->flatMap(static fn (\Closure $caster): array => [
143+ // $caster,
144+ // static fn (string $name): string => $caster(\Illuminate\Support\Str::plural($name)),
145+ // ])
146+ // ->firstOrFail(fn (\Closure $caster) => $rawOption->pipe($caster)->is($defined));
147+ // $option = $rawOption->pipe($caster)->toString();
148+ $ option = $ this ->valueResolver ->getValue ($ classMethodNode ->stmts [0 ]->expr ->var ->var ->dim );
141149
142- return [$ option => $ classMethodNode ->params [0 ]->type ->toString ()];
143- })
144- ->dump ();
150+ return [$ option => $ this ->getName ($ classMethodNode ->params [0 ]->type ).'[] ' ];
151+ });
152+
153+ if ($ allowedTypes ->isEmpty ()) {
154+ return ;
155+ }
156+
157+ $ allowedTypesPropertyNode = collect ($ classNode ->stmts )->first (
158+ fn (Stmt $ stmtNode ): bool => $ stmtNode instanceof Property && $ this ->isName ($ stmtNode , 'allowedTypes ' )
159+ );
160+
161+ if (
162+ !$ allowedTypesPropertyNode instanceof Property
163+ || !($ defaultNode = $ allowedTypesPropertyNode ->props [0 ]->default ) instanceof Array_
164+ ) {
165+ array_splice ($ classNode ->stmts , 1 , 0 , [
166+ (new PropertyBuilder ('allowedTypes ' ))
167+ ->makeProtected ()
168+ ->setDocComment ('/** @var array<string, list<string>|string> */ ' )
169+ ->setType ('array ' )
170+ ->setDefault ($ allowedTypes ->all ())
171+ ->getNode (),
172+ ]);
173+
174+ return ;
175+ }
176+
177+ $ value = $ this ->valueResolver ->getValue ($ defaultNode );
178+ $ allowedTypes ->diffAssoc ($ value )->each (
179+ function (string $ allowedType , string $ option ) use ($ defaultNode ): void {
180+ $ arrayItemNode = collect ($ defaultNode ->items )->first (
181+ fn (ArrayItem $ arrayItemNode ) => (string ) $ this ->valueResolver ->getValue ($ arrayItemNode ->key ) === $ option ,
182+ );
183+
184+ if ($ arrayItemNode ) {
185+ $ arrayItemNode ->value ->value = $ allowedType ;
186+
187+ return ;
188+ }
189+
190+ $ defaultNode ->items [] = new ArrayItem (new String_ ($ allowedType ), new String_ ($ option ));
191+ }
192+ );
193+
194+ // $newValue = [...$value, ...$allowedTypes->all()];
195+ //
196+ // if ($value !== $newValue) {
197+ // $allowedTypesPropertyNode->props[0]->default = $this->nodeFactory->createArray($newValue);
198+ // }
199+
200+ // collect($defaultNode->items)
201+ // ->each(function (ArrayItem $arrayItemNode): void {
202+ // $key = (string) $this->valueResolver->getValue($arrayItemNode->key);
203+ //
204+ // if (!isset($allowedTypes[$key])) {
205+ // return;
206+ // }
207+ //
208+ // $arrayItemNode->value->value = $allowedTypes[$key];
209+ // });
145210 }
146211
147212 /**
213+ * @throws \ReflectionException
214+ *
148215 * @noinspection PhpPossiblePolymorphicInvocationInspection
149216 */
150217 private function updateMethodsOfListTypeOption (Class_ $ classNode ): void
@@ -175,6 +242,7 @@ private function updateMethodsOfListTypeOption(Class_ $classNode): void
175242 if (!$ optionsPropertyNode instanceof Property) {
176243 $ classNode ->stmts [] = (new PropertyBuilder ('options ' ))
177244 ->makeProtected ()
245+ ->setDocComment ('/** @var array<string, mixed> */ ' )
178246 ->setType ('array ' )
179247 ->setDefault ($ allowedTypes ->map (static fn (): array => [])->all ())
180248 ->getNode ();
@@ -218,16 +286,26 @@ class Message
218286 /**
219287 * @api
220288 */
221- final public function add%s(%s $%s): self
289+ %spublic function add%s(%s $%s): self
222290 {
223291 $this->options['%s'][] = $%s;
224292
225293 return $this;
226294 }
227295 }
228296 PHP,
297+ (new \ReflectionClass ($ this ->getName ($ classNode )))->isAbstract () ? 'final ' : ' ' ,
229298 str ($ option )->singular ()->studly (),
230299 str ($ allowedType )->beforeLast ('[] ' ),
300+ // match ($type = str($allowedType)->beforeLast('[]')) {
301+ // 'array' => <<<'DOCBLOCK'
302+ // /**
303+ // * @param array<array-key, mixed> $array
304+ // */
305+ // DOCBLOCK
306+ // ,
307+ // default => $type,
308+ // },
231309 $ camelSingularOption = str ($ option )->singular ()->camel (),
232310 $ option ,
233311 $ camelSingularOption ,
0 commit comments