-
-
Notifications
You must be signed in to change notification settings - Fork 117
/
ClassDeclarationIndexer.php
103 lines (86 loc) · 3.48 KB
/
ClassDeclarationIndexer.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
<?php
namespace Phpactor\Indexer\Adapter\Tolerant\Indexer;
use Microsoft\PhpParser\MissingToken;
use Microsoft\PhpParser\Node;
use Microsoft\PhpParser\Node\Attribute;
use Microsoft\PhpParser\Node\Statement\ClassDeclaration;
use Phpactor\Indexer\Model\Exception\CannotIndexNode;
use Phpactor\Indexer\Model\Index;
use Phpactor\Indexer\Model\Name\FullyQualifiedName;
use Phpactor\Indexer\Model\Record\ClassRecord;
use Phpactor\TextDocument\TextDocument;
class ClassDeclarationIndexer extends AbstractClassLikeIndexer
{
public function canIndex(Node $node): bool
{
return $node instanceof ClassDeclaration;
}
public function index(Index $index, TextDocument $document, Node $node): void
{
assert($node instanceof ClassDeclaration);
if ($node->name instanceof MissingToken) {
throw new CannotIndexNode(sprintf(
'Class name is missing (maybe a reserved word) in: %s',
$document->uri()?->__toString() ?? '?',
));
}
$record = $this->getClassLikeRecord(ClassRecord::TYPE_CLASS, $node, $index, $document);
$this->removeImplementations($index, $record);
$record->clearImplemented();
$this->indexClassInterfaces($index, $record, $node);
$this->indexBaseClass($index, $record, $node);
$this->indexAttributes($record, $node);
$index->write($record);
}
public function indexAttributes(ClassRecord $record, ClassDeclaration $node): void
{
$attributes = $node->attributes ?? [];
if (count($attributes) === 0) {
return;
}
foreach ($attributes as $attributeGroup) {
foreach ($attributeGroup->attributes->children as $attribute) {
if (!$attribute instanceof Attribute) {
continue;
}
/** @phpstan-ignore-next-line */
if ((string) $attribute->name?->getResolvedName() === \Attribute::class) {
$record->addFlag(ClassRecord::FLAG_ATTRIBUTE);
return;
}
}
}
}
private function indexClassInterfaces(Index $index, ClassRecord $classRecord, ClassDeclaration $node): void
{
// @phpstan-ignore-next-line because ClassInterfaceClause _can_ (and has been) be NULL
if (null === $interfaceClause = $node->classInterfaceClause) {
return;
}
if (null == $interfaceList = $interfaceClause->interfaceNameList) {
return;
}
$this->indexInterfaceList($interfaceList, $classRecord, $index);
}
private function indexBaseClass(Index $index, ClassRecord $record, ClassDeclaration $node): void
{
// @phpstan-ignore-next-line because classBaseClause _can_ be NULL
if (null === $baseClause = $node->classBaseClause) {
return;
}
// @phpstan-ignore-next-line because classBaseClause _can_ be NULL
if (null === $baseClass = $baseClause->baseClass) {
return;
}
/** @phpstan-ignore-next-line */
if ($baseClass instanceof MissingToken) {
return;
}
$name = $baseClass->getResolvedName();
$record->addImplements(FullyQualifiedName::fromString((string)$name));
$baseClassRecord = $index->get(ClassRecord::fromName($name));
assert($baseClassRecord instanceof ClassRecord);
$baseClassRecord->addImplementation($record->fqn());
$index->write($baseClassRecord);
}
}