These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * phpDocumentor |
||
4 | * |
||
5 | * PHP Version 5.3 |
||
6 | * |
||
7 | * @copyright 2010-2014 Mike van Riel / Naenius (http://www.naenius.com) |
||
8 | * @license http://www.opensource.org/licenses/mit-license.php MIT |
||
9 | * @link http://phpdoc.org |
||
10 | */ |
||
11 | |||
12 | namespace phpDocumentor\Compiler\Pass; |
||
13 | |||
14 | use phpDocumentor\Compiler\CompilerPassInterface; |
||
15 | use phpDocumentor\Descriptor\Collection; |
||
16 | use phpDocumentor\Descriptor\DescriptorAbstract; |
||
17 | use phpDocumentor\Descriptor\NamespaceDescriptor; |
||
18 | use phpDocumentor\Descriptor\ProjectDescriptor; |
||
19 | use phpDocumentor\Reflection\Fqsen; |
||
20 | |||
21 | /** |
||
22 | * Rebuilds the namespace tree from the elements found in files. |
||
23 | * |
||
24 | * On every compiler pass is the namespace tree rebuild to aid in the process |
||
25 | * of incremental updates. The Files Collection in the Project Descriptor is the |
||
26 | * only location where aliases to elements may be serialized. |
||
27 | * |
||
28 | * If the namespace tree were to be persisted then both locations needed to be |
||
29 | * invalidated if a file were to change. |
||
30 | */ |
||
31 | class NamespaceTreeBuilder implements CompilerPassInterface |
||
32 | { |
||
33 | const COMPILER_PRIORITY = 9000; |
||
34 | |||
35 | /** |
||
36 | * {@inheritDoc} |
||
37 | */ |
||
38 | 1 | public function getDescription() |
|
39 | { |
||
40 | 1 | return 'Build "namespaces" index and add namespaces to "elements"'; |
|
41 | } |
||
42 | |||
43 | /** |
||
44 | * {@inheritDoc} |
||
45 | */ |
||
46 | 6 | public function execute(ProjectDescriptor $project) |
|
47 | { |
||
48 | 6 | $project->getIndexes()->get('elements', new Collection())->set('~\\', $project->getNamespace()); |
|
49 | 6 | $project->getIndexes()->get('namespaces', new Collection())->set('\\', $project->getNamespace()); |
|
50 | |||
51 | 6 | foreach ($project->getFiles() as $file) { |
|
52 | 6 | $this->addElementsOfTypeToNamespace($project, $file->getConstants()->getAll(), 'constants'); |
|
53 | 6 | $this->addElementsOfTypeToNamespace($project, $file->getFunctions()->getAll(), 'functions'); |
|
54 | 6 | $this->addElementsOfTypeToNamespace($project, $file->getClasses()->getAll(), 'classes'); |
|
55 | 6 | $this->addElementsOfTypeToNamespace($project, $file->getInterfaces()->getAll(), 'interfaces'); |
|
56 | 6 | $this->addElementsOfTypeToNamespace($project, $file->getTraits()->getAll(), 'traits'); |
|
57 | } |
||
58 | |||
59 | /** @var NamespaceDescriptor $namespace */ |
||
60 | 6 | foreach ($project->getIndexes()->get('namespaces')->getAll() as $namespace) { |
|
61 | 6 | if ($namespace->getNamespace() !== '') { |
|
62 | 6 | $this->addToParentNamespace($project, $namespace); |
|
63 | |||
0 ignored issues
–
show
Coding Style
introduced
by
Loading history...
|
|||
64 | } |
||
65 | } |
||
66 | 6 | } |
|
67 | |||
68 | /** |
||
69 | * Adds the given elements of a specific type to their respective Namespace Descriptors. |
||
70 | * |
||
71 | * This method will assign the given elements to the namespace as registered in the namespace field of that |
||
72 | * element. If a namespace does not exist yet it will automatically be created. |
||
73 | * |
||
74 | * @param ProjectDescriptor $project |
||
75 | * @param DescriptorAbstract[] $elements Series of elements to add to their respective namespace. |
||
76 | * @param string $type Declares which field of the namespace will be populated with the given |
||
77 | * series of elements. This name will be transformed to a getter which must exist. Out of performance |
||
78 | * considerations will no effort be done to verify whether the provided type is valid. |
||
79 | * |
||
80 | * @return void |
||
81 | */ |
||
82 | 6 | protected function addElementsOfTypeToNamespace(ProjectDescriptor $project, array $elements, $type) |
|
83 | { |
||
84 | /** @var DescriptorAbstract $element */ |
||
85 | 6 | foreach ($elements as $element) { |
|
86 | 6 | $namespaceName = (string)$element->getNamespace(); |
|
87 | //TODO: find out why this can happen. Some bug in the assembler? |
||
88 | 6 | if ($namespaceName === '') { |
|
89 | $namespaceName = '\\'; |
||
90 | } |
||
91 | |||
92 | 6 | $namespace = $project->getIndexes()->get('namespaces', new Collection())->get($namespaceName); |
|
93 | |||
94 | 6 | if ($namespace === null) { |
|
95 | 6 | $namespace = new NamespaceDescriptor(); |
|
96 | 6 | $fqsen = new Fqsen($namespaceName); |
|
97 | 6 | $namespace->setName($fqsen->getName()); |
|
98 | 6 | $namespace->setFullyQualifiedStructuralElementName($fqsen); |
|
99 | 6 | $namespaceName = substr((string)$fqsen, 0, -strlen($fqsen->getName())-1); |
|
100 | 6 | $namespace->setNamespace($namespaceName); |
|
101 | 6 | $project->getIndexes()->get('namespaces')->set((string)$namespace->getFullyQualifiedStructuralElementName(), $namespace); |
|
102 | 6 | $this->addToParentNamespace($project, $namespace); |
|
103 | } |
||
104 | |||
105 | // replace textual representation with an object representation |
||
106 | 6 | $element->setNamespace($namespace); |
|
107 | |||
108 | // add element to namespace |
||
109 | 6 | $getter = 'get' . ucfirst($type); |
|
110 | |||
111 | /** @var Collection $collection */ |
||
112 | 6 | $collection = $namespace->$getter(); |
|
113 | 6 | $collection->add($element); |
|
114 | |||
0 ignored issues
–
show
|
|||
115 | } |
||
116 | 6 | } |
|
117 | |||
118 | /** |
||
119 | * @param ProjectDescriptor $project |
||
120 | * @param $namespace |
||
121 | */ |
||
122 | 6 | private function addToParentNamespace(ProjectDescriptor $project, NamespaceDescriptor $namespace) |
|
123 | { |
||
124 | /** @var NamespaceDescriptor $parent */ |
||
125 | 6 | $parent = $project->getIndexes()->get('namespaces')->get($namespace->getNamespace()); |
|
126 | 6 | $project->getIndexes()->get('elements')->set( |
|
127 | 6 | '~' . (string)$namespace->getFullyQualifiedStructuralElementName(), |
|
128 | 6 | $namespace |
|
129 | ); |
||
130 | |||
131 | try { |
||
132 | 6 | if ($parent === null) { |
|
133 | 6 | $parent = new NamespaceDescriptor(); |
|
134 | 6 | $fqsen = new Fqsen($namespace->getNamespace()); |
|
135 | 6 | $parent->setFullyQualifiedStructuralElementName($fqsen); |
|
136 | 6 | $parent->setName($fqsen->getName()); |
|
137 | 6 | $namespaceName = substr((string)$fqsen, 0, -strlen($parent->getName())-1); |
|
138 | 6 | $parent->setNamespace($namespaceName === '' ? '\\' : $namespaceName); |
|
139 | 6 | $project->getIndexes()->get('namespaces')->set((string)$parent->getFullyQualifiedStructuralElementName(), $parent); |
|
140 | 6 | $this->addToParentNamespace($project, $parent); |
|
141 | } |
||
142 | |||
143 | 6 | $namespace->setParent($parent); |
|
144 | 6 | $parent->getChildren()->set($namespace->getName(), $namespace); |
|
145 | 6 | } catch (\InvalidArgumentException $e) { |
|
146 | //bit hacky but it works for now. |
||
147 | //$project->getNamespace()->getChildren()->add($namespace); |
||
148 | } |
||
149 | 6 | } |
|
150 | } |
||
151 |