Skip to content

Commit b5803e6

Browse files
committed
Merge createNameScopeMap and createPhpDocNodeMap
1 parent 0bf4e1e commit b5803e6

File tree

1 file changed

+27
-221
lines changed

1 file changed

+27
-221
lines changed

src/Type/FileTypeMapper.php

Lines changed: 27 additions & 221 deletions
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,7 @@ private function getNameScopeMap(string $fileName): array
218218
*/
219219
private function createResolvedPhpDocMap(string $fileName): array
220220
{
221-
$phpDocNodeMap = $this->createPhpDocNodeMap($fileName, null, $fileName, [], $fileName);
222-
$nameScopeMap = $this->createNameScopeMap($fileName, null, null, [], $fileName, $phpDocNodeMap);
221+
[/*$phpDocNodeMap*/, $nameScopeMap] = $this->createPhpDocNodeMap($fileName, null, null, [], $fileName);
223222
$resolvedNameScopeMap = [];
224223

225224
try {
@@ -240,211 +239,13 @@ private function createResolvedPhpDocMap(string $fileName): array
240239

241240
/**
242241
* @param array<string, string> $traitMethodAliases
243-
* @return array<string, PhpDocNode>
242+
* @return array{array<string, PhpDocNode>, (callable(): NameScope)[]}
244243
*/
245244
private function createPhpDocNodeMap(string $fileName, ?string $lookForTrait, ?string $traitUseClass, array $traitMethodAliases, string $originalClassFileName): array
246245
{
247246
/** @var array<string, PhpDocNode> $phpDocNodeMap */
248247
$phpDocNodeMap = [];
249248

250-
/** @var string[] $classStack */
251-
$classStack = [];
252-
if ($lookForTrait !== null && $traitUseClass !== null) {
253-
$classStack[] = $traitUseClass;
254-
}
255-
$namespace = null;
256-
257-
$traitFound = false;
258-
259-
/** @var array<string|null> $functionStack */
260-
$functionStack = [];
261-
$this->processNodes(
262-
$this->phpParser->parseFile($fileName),
263-
function (Node $node) use ($fileName, $lookForTrait, &$traitFound, $traitMethodAliases, $originalClassFileName, &$phpDocNodeMap, &$classStack, &$namespace, &$functionStack): ?int {
264-
if ($node instanceof Node\Stmt\ClassLike) {
265-
if ($traitFound && $fileName === $originalClassFileName) {
266-
return self::SKIP_NODE;
267-
}
268-
269-
if ($lookForTrait !== null && !$traitFound) {
270-
if (!$node instanceof Node\Stmt\Trait_) {
271-
return self::SKIP_NODE;
272-
}
273-
if ((string) $node->namespacedName !== $lookForTrait) {
274-
return self::SKIP_NODE;
275-
}
276-
277-
$traitFound = true;
278-
$functionStack[] = null;
279-
} else {
280-
if ($node->name === null) {
281-
if (!$node instanceof Node\Stmt\Class_) {
282-
throw new ShouldNotHappenException();
283-
}
284-
285-
$className = $this->anonymousClassNameHelper->getAnonymousClassName($node, $fileName);
286-
} elseif ($node instanceof Node\Stmt\Class_ && $node->isAnonymous()) {
287-
$className = $node->name->name;
288-
} else {
289-
if ($traitFound) {
290-
return self::SKIP_NODE;
291-
}
292-
$className = ltrim(sprintf('%s\\%s', $namespace, $node->name->name), '\\');
293-
}
294-
$classStack[] = $className;
295-
$functionStack[] = null;
296-
}
297-
} elseif ($node instanceof Node\Stmt\ClassMethod) {
298-
if (array_key_exists($node->name->name, $traitMethodAliases)) {
299-
$functionStack[] = $traitMethodAliases[$node->name->name];
300-
} else {
301-
$functionStack[] = $node->name->name;
302-
}
303-
} elseif ($node instanceof Node\Stmt\Function_) {
304-
$functionStack[] = ltrim(sprintf('%s\\%s', $namespace, $node->name->name), '\\');
305-
} elseif ($node instanceof Node\PropertyHook) {
306-
$propertyName = $node->getAttribute('propertyName');
307-
if ($propertyName !== null) {
308-
$functionStack[] = sprintf('$%s::%s', $propertyName, $node->name->toString());
309-
}
310-
}
311-
312-
$className = array_last($classStack) ?? null;
313-
$functionName = array_last($functionStack) ?? null;
314-
315-
if ($node instanceof Node\Stmt\ClassLike || $node instanceof Node\Stmt\ClassMethod || $node instanceof Node\Stmt\Function_) {
316-
$docComment = GetLastDocComment::forNode($node);
317-
if ($docComment !== null) {
318-
$nameScopeKey = $this->getNameScopeKey($originalClassFileName, $className, $lookForTrait, $functionName);
319-
$phpDocNodeMap[$nameScopeKey] = $this->phpDocStringResolver->resolve($docComment);
320-
}
321-
322-
return null;
323-
} elseif ($node instanceof Node\PropertyHook) {
324-
$propertyName = $node->getAttribute('propertyName');
325-
if ($propertyName !== null) {
326-
$docComment = GetLastDocComment::forNode($node);
327-
if ($docComment !== null) {
328-
$nameScopeKey = $this->getNameScopeKey($originalClassFileName, $className, $lookForTrait, $functionName);
329-
$phpDocNodeMap[$nameScopeKey] = $this->phpDocStringResolver->resolve($docComment);
330-
}
331-
}
332-
333-
return null;
334-
}
335-
336-
if ($node instanceof Node\Stmt\Namespace_) {
337-
$namespace = $node->name !== null ? (string) $node->name : null;
338-
} elseif ($node instanceof Node\Stmt\TraitUse) {
339-
$traitMethodAliases = [];
340-
foreach ($node->adaptations as $traitUseAdaptation) {
341-
if (!$traitUseAdaptation instanceof Node\Stmt\TraitUseAdaptation\Alias) {
342-
continue;
343-
}
344-
345-
if ($traitUseAdaptation->newName === null) {
346-
continue;
347-
}
348-
349-
$methodName = $traitUseAdaptation->method->toString();
350-
$newTraitName = $traitUseAdaptation->newName->toString();
351-
352-
if ($traitUseAdaptation->trait === null) {
353-
foreach ($node->traits as $traitName) {
354-
$traitMethodAliases[$traitName->toString()][$methodName] = $newTraitName;
355-
}
356-
continue;
357-
}
358-
359-
$traitMethodAliases[$traitUseAdaptation->trait->toString()][$methodName] = $newTraitName;
360-
}
361-
362-
foreach ($node->traits as $traitName) {
363-
/** @var class-string $traitName */
364-
$traitName = (string) $traitName;
365-
$reflectionProvider = $this->reflectionProviderProvider->getReflectionProvider();
366-
if (!$reflectionProvider->hasClass($traitName)) {
367-
continue;
368-
}
369-
370-
$traitReflection = $reflectionProvider->getClass($traitName);
371-
if (!$traitReflection->isTrait()) {
372-
continue;
373-
}
374-
if ($traitReflection->getFileName() === null) {
375-
continue;
376-
}
377-
if (!is_file($traitReflection->getFileName())) {
378-
continue;
379-
}
380-
381-
$className = array_last($classStack) ?? null;
382-
if ($className === null) {
383-
throw new ShouldNotHappenException();
384-
}
385-
386-
$phpDocNodeMap = array_merge($phpDocNodeMap, $this->createPhpDocNodeMap(
387-
$traitReflection->getFileName(),
388-
$traitName,
389-
$className,
390-
$traitMethodAliases[$traitName] ?? [],
391-
$originalClassFileName,
392-
));
393-
}
394-
}
395-
396-
return null;
397-
},
398-
static function (Node $node) use (&$namespace, &$functionStack, &$classStack): void {
399-
if ($node instanceof Node\Stmt\ClassLike) {
400-
if (count($classStack) === 0) {
401-
throw new ShouldNotHappenException();
402-
}
403-
array_pop($classStack);
404-
405-
if (count($functionStack) === 0) {
406-
throw new ShouldNotHappenException();
407-
}
408-
409-
array_pop($functionStack);
410-
} elseif ($node instanceof Node\Stmt\Namespace_) {
411-
$namespace = null;
412-
} elseif ($node instanceof Node\Stmt\ClassMethod || $node instanceof Node\Stmt\Function_) {
413-
if (count($functionStack) === 0) {
414-
throw new ShouldNotHappenException();
415-
}
416-
417-
array_pop($functionStack);
418-
} elseif ($node instanceof Node\PropertyHook) {
419-
$propertyName = $node->getAttribute('propertyName');
420-
if ($propertyName !== null) {
421-
if (count($functionStack) === 0) {
422-
throw new ShouldNotHappenException();
423-
}
424-
425-
array_pop($functionStack);
426-
}
427-
}
428-
},
429-
);
430-
431-
return $phpDocNodeMap;
432-
}
433-
434-
/**
435-
* @param array<string, string> $traitMethodAliases
436-
* @param array<string, PhpDocNode> $phpDocNodeMap
437-
* @return (callable(): NameScope)[]
438-
*/
439-
private function createNameScopeMap(
440-
string $fileName,
441-
?string $lookForTrait,
442-
?string $traitUseClass,
443-
array $traitMethodAliases,
444-
string $originalClassFileName,
445-
array $phpDocNodeMap,
446-
): array
447-
{
448249
/** @var (callable(): NameScope)[] $nameScopeMap */
449250
$nameScopeMap = [];
450251

@@ -470,7 +271,7 @@ private function createNameScopeMap(
470271
$constUses = [];
471272
$this->processNodes(
472273
$this->phpParser->parseFile($fileName),
473-
function (Node $node) use ($fileName, $lookForTrait, $phpDocNodeMap, &$traitFound, $traitMethodAliases, $originalClassFileName, &$nameScopeMap, &$classStack, &$typeAliasStack, &$namespace, &$functionStack, &$uses, &$typeMapStack, &$constUses): ?int {
274+
function (Node $node) use ($fileName, $lookForTrait, &$traitFound, $traitMethodAliases, $originalClassFileName, &$phpDocNodeMap, &$nameScopeMap, &$typeMapStack, &$typeAliasStack, &$classStack, &$namespace, &$functionStack, &$uses, &$constUses): ?int {
474275
if ($node instanceof Node\Stmt\ClassLike) {
475276
if ($traitFound && $fileName === $originalClassFileName) {
476277
return self::SKIP_NODE;
@@ -485,12 +286,6 @@ function (Node $node) use ($fileName, $lookForTrait, $phpDocNodeMap, &$traitFoun
485286
}
486287

487288
$traitFound = true;
488-
$traitNameScopeKey = $this->getNameScopeKey($originalClassFileName, $classStack[count($classStack) - 1] ?? null, $lookForTrait, null);
489-
if (array_key_exists($traitNameScopeKey, $phpDocNodeMap)) {
490-
$typeAliasStack[] = $this->getTypeAliasesMap($phpDocNodeMap[$traitNameScopeKey]);
491-
} else {
492-
$typeAliasStack[] = [];
493-
}
494289
$functionStack[] = null;
495290
} else {
496291
if ($node->name === null) {
@@ -508,12 +303,6 @@ function (Node $node) use ($fileName, $lookForTrait, $phpDocNodeMap, &$traitFoun
508303
$className = ltrim(sprintf('%s\\%s', $namespace, $node->name->name), '\\');
509304
}
510305
$classStack[] = $className;
511-
$classNameScopeKey = $this->getNameScopeKey($originalClassFileName, $className, $lookForTrait, null);
512-
if (array_key_exists($classNameScopeKey, $phpDocNodeMap)) {
513-
$typeAliasStack[] = $this->getTypeAliasesMap($phpDocNodeMap[$classNameScopeKey]);
514-
} else {
515-
$typeAliasStack[] = [];
516-
}
517306
$functionStack[] = null;
518307
}
519308
} elseif ($node instanceof Node\Stmt\ClassMethod) {
@@ -536,9 +325,13 @@ function (Node $node) use ($fileName, $lookForTrait, $phpDocNodeMap, &$traitFoun
536325
$nameScopeKey = $this->getNameScopeKey($originalClassFileName, $className, $lookForTrait, $functionName);
537326

538327
if ($node instanceof Node\Stmt\ClassLike || $node instanceof Node\Stmt\ClassMethod || $node instanceof Node\Stmt\Function_) {
539-
// property hook skipped on purpose, it does not support @template
540-
if (array_key_exists($nameScopeKey, $phpDocNodeMap)) {
541-
$phpDocNode = $phpDocNodeMap[$nameScopeKey];
328+
$docComment = GetLastDocComment::forNode($node);
329+
if ($docComment !== null) {
330+
$phpDocNode = $this->phpDocStringResolver->resolve($docComment);
331+
$phpDocNodeMap[$nameScopeKey] = $phpDocNode;
332+
if ($node instanceof Node\Stmt\ClassLike) {
333+
$typeAliasStack[] = $this->getTypeAliasesMap($phpDocNode);
334+
}
542335
$typeMapStack[] = function () use ($namespace, $uses, $className, $lookForTrait, $functionName, $phpDocNode, $typeMapStack, $typeAliasStack, $constUses): TemplateTypeMap {
543336
$typeMapCb = array_last($typeMapStack) ?? null;
544337
$currentTypeMap = $typeMapCb !== null ? $typeMapCb() : null;
@@ -559,12 +352,24 @@ function (Node $node) use ($fileName, $lookForTrait, $phpDocNodeMap, &$traitFoun
559352
$templateTypeMap->getTypes(),
560353
));
561354
};
355+
} elseif ($node instanceof Node\Stmt\ClassLike) {
356+
$typeAliasStack[] = [];
562357
}
563358
}
564359

565360
$typeMapCb = array_last($typeMapStack) ?? null;
566361
$typeAliasesMap = array_last($typeAliasStack) ?? [];
567362

363+
if ($node instanceof Node\PropertyHook) {
364+
$propertyName = $node->getAttribute('propertyName');
365+
if ($propertyName !== null) {
366+
$docComment = GetLastDocComment::forNode($node);
367+
if ($docComment !== null) {
368+
$phpDocNodeMap[$nameScopeKey] = $this->phpDocStringResolver->resolve($docComment);
369+
}
370+
}
371+
}
372+
568373
if (
569374
(
570375
$node instanceof Node\PropertyHook
@@ -594,8 +399,9 @@ function (Node $node) use ($fileName, $lookForTrait, $phpDocNodeMap, &$traitFoun
594399
}
595400

596401
if ($node instanceof Node\Stmt\ClassLike || $node instanceof Node\Stmt\ClassMethod || $node instanceof Node\Stmt\Function_) {
402+
$docComment = GetLastDocComment::forNode($node);
597403
// property hook skipped on purpose, it does not support @template
598-
if (array_key_exists($nameScopeKey, $phpDocNodeMap)) {
404+
if ($docComment !== null) {
599405
return self::POP_TYPE_MAP_STACK;
600406
}
601407

@@ -676,14 +482,14 @@ function (Node $node) use ($fileName, $lookForTrait, $phpDocNodeMap, &$traitFoun
676482
throw new ShouldNotHappenException();
677483
}
678484

679-
$traitPhpDocMap = $this->createNameScopeMap(
485+
[$tmpPhpDocNodeMap, $traitPhpDocMap] = $this->createPhpDocNodeMap(
680486
$traitReflection->getFileName(),
681487
$traitName,
682488
$className,
683489
$traitMethodAliases[$traitName] ?? [],
684490
$originalClassFileName,
685-
$phpDocNodeMap,
686491
);
492+
$phpDocNodeMap = array_merge($phpDocNodeMap, $tmpPhpDocNodeMap);
687493
$finalTraitPhpDocMap = [];
688494
foreach ($traitPhpDocMap as $nameScopeTraitKey => $callback) {
689495
$finalTraitPhpDocMap[$nameScopeTraitKey] = function () use ($callback, $traitReflection, $fileName, $className, $lookForTrait, $useDocComment): NameScope {
@@ -787,7 +593,7 @@ static function (Node $node, $callbackResult) use (&$namespace, &$functionStack,
787593
throw new ShouldNotHappenException();
788594
}
789595

790-
return $nameScopeMap;
596+
return [$phpDocNodeMap, $nameScopeMap];
791597
}
792598

793599
/**

0 commit comments

Comments
 (0)