files[$fileName])) { return; } $this->files[$fileName] = $fileName; $reflection = new FileReflector($fileName, true); $reflection->process(); foreach($reflection->getClasses() as $class) { $class = new ClassDoc($class); $class->sourceFile = $fileName; $this->addClass($class); } foreach($reflection->getInterfaces() as $interface) { $interface = new InterfaceDoc($interface); $interface->sourceFile = $fileName; $this->addInterface($interface); } foreach($reflection->getTraits() as $trait) { $trait = new TraitDoc($trait); $trait->sourceFile = $fileName; $this->addTrait($trait); } } /** * @param ClassDoc $class * @throws \yii\base\Exception when class is already part of this context */ public function addClass($class) { if (isset($this->classes[$class->name])) { throw new Exception('Duplicate class definition: ' . $class->name . ' in file ' . $class->sourceFile . '.'); } $this->classes[$class->name] = $class; } /** * @param InterfaceDoc $interface * @throws \yii\base\Exception when interface is already part of this context */ public function addInterface($interface) { if (isset($this->interfaces[$interface->name])) { throw new Exception('Duplicate interface definition: ' . $interface->name . ' in file ' . $interface->sourceFile); } $this->interfaces[$interface->name] = $interface; } /** * @param TraitDoc $trait * @throws \yii\base\Exception when trait is already part of this context */ public function addTrait($trait) { if (isset($this->traits[$trait->name])) { throw new Exception('Duplicate trait definition: ' . $trait->name . ' in file ' . $trait->sourceFile); } $this->traits[$trait->name] = $trait; } public function updateReferences() { // update all subclass references foreach($this->classes as $class) { $className = $class->name; while (isset($this->classes[$class->parentClass])) { $class = $this->classes[$class->parentClass]; $class->subclasses[] = $className; } } // update interfaces of subclasses foreach($this->classes as $class) { // TODO do the same for events, constants, methods, properties $this->updateSubclassInferfacesTraits($class); } // update implementedBy and usedBy for interfaces and traits foreach($this->classes as $class) { foreach($class->interfaces as $interface) { if (isset($this->interfaces[$interface])) { $this->interfaces[$interface]->implementedBy[] = $class->name; } } foreach($class->traits as $trait) { if (isset($this->traits[$trait])) { $this->traits[$trait]->usedBy[] = $class->name; } } } } /** * Add implemented interfaces and used traits to subclasses * @param ClassDoc $class */ protected function updateSubclassInferfacesTraits($class) { foreach($class->subclasses as $subclass) { $subclass = $this->classes[$subclass]; $subclass->interfaces = array_unique(array_merge($subclass->interfaces, $class->interfaces)); $subclass->traits = array_unique(array_merge($subclass->traits, $class->traits)); $this->updateSubclassInferfacesTraits($subclass); } } }