diff --git a/features/fix_class_names.feature b/features/fix_class_names.feature index 54bb326..863ce18 100644 --- a/features/fix_class_names.feature +++ b/features/fix_class_names.feature @@ -75,6 +75,13 @@ Feature: Fix Class Names | dir | src/ | Then the PHP File "src/Foo.php" should be refactored: """ + --- a/vfs://project/src/Foo.php + +++ b/vfs://project/src/Foo.php + @@ -1,2 +1,2 @@ + codeAnalysis = $codeAnalysis; $this->editor = $editor; $this->nameScanner = $nameScanner; } + public function refactor(Directory $directory) { $phpFiles = $directory->findAllPhpFilesRecursivly(); - $renames = new Set(); - $occurances = array(); - $noImportedUsages = new NoImportedUsagesFilter(); + $this->renames = new Set(); foreach ($phpFiles as $phpFile) { - $classes = $this->codeAnalysis->findClasses($phpFile); + $this->checkIfRenameIsRequired($phpFile); + } - $occurances = array_merge( - $noImportedUsages->filter($this->nameScanner->findNames($phpFile)), - $occurances - ); + $occurances = $this->findOccurances($phpFiles); - if (count($classes) !== 1) { - continue; - } + foreach ($occurances as $occurance) { + $this->performRename($occurance); + } - $class = $classes[0]; - $currentClassName = $class->declarationName(); - $expectedClassName = $phpFile->extractPsr0ClassName(); + $this->editor->save(); + } - $buffer = $this->editor->openBuffer($phpFile); // This is weird to be required here - if ($expectedClassName->shortName() !== $currentClassName->shortName()) { - $renames->add(new PhpNameChange($currentClassName, $expectedClassName)); - } + private function checkIfRenameIsRequired(File $phpFile) + { + $classes = $this->codeAnalysis->findClasses($phpFile); + + // Why skip for multiple classes in a file? + if (count($classes) !== 1) { + return; + } - if (!$expectedClassName->namespaceName()->equals($currentClassName->namespaceName())) { - $renames->add(new PhpNameChange($currentClassName->fullyQualified(), $expectedClassName->fullyQualified())); + $class = $classes[0]; - $buffer->replaceString( - $class->namespaceDeclarationLine(), - $currentClassName->namespaceName()->fullyQualifiedName(), - $expectedClassName->namespaceName()->fullyQualifiedName() - ); - } + $currentClassName = $class->declarationName(); + $expectedClassName = $phpFile->extractPsr0ClassName(); + + if ($this->shortNameHasChanged($expectedClassName, $currentClassName)) { + // Queue a rename to happen in the next loop + $this->renames->add(new PhpNameChange($currentClassName, $expectedClassName)); } - $occurances = array_filter($occurances, function ($occurance) { - return $occurance->name()->type() !== PhpName::TYPE_NAMESPACE; - }); + if ($this->namespaceHasChanged($expectedClassName, $currentClassName)) { + $this->renames->add(new PhpNameChange($currentClassName->fullyQualified(), $expectedClassName->fullyQualified())); + } + } - foreach ($occurances as $occurance) { - $name = $occurance->name(); - - foreach ($renames as $rename) { - if ($rename->affects($name)) { - $buffer = $this->editor->openBuffer($occurance->file()); - $buffer->replaceString($occurance->declarationLine(), $name->relativeName(), $rename->change($name)->relativeName()); - continue 2; - } + /** + * @return boolean + */ + private function shortNameHasChanged(PhpName $expectedClassName, PhpName $currentClassName) + { + return $expectedClassName->shortName() !== $currentClassName->shortName(); + } + + /** + * @return boolean + */ + private function namespaceHasChanged(PhpName $expectedClassName, PhpName $currentClassName) + { + return !$expectedClassName->namespaceName()->equals($currentClassName->namespaceName()); + } + + private function performRename(PhpNameOccurance $occurance) + { + $name = $occurance->name(); + + foreach ($this->renames as $rename) { + if (!$rename->affects($name)) { + continue; } + + $buffer = $this->editor->openBuffer($occurance->file()); + + $buffer->replaceString( + $occurance->declarationLine(), + $name->relativeName(), + $rename->change($name)->relativeName() + ); + + // Why is a contnue required? Surely 2 renames can't apply + // to the same occurance? + break; } + } - $this->editor->save(); + /** + * @param File[] $phpFiles + * + * @return PhpNameOccurance[] + */ + private function findOccurances($phpFiles) + { + $occurances = array(); + + $noImportedUsages = new NoImportedUsagesFilter(); + + foreach ($phpFiles as $phpFile) { + $occurances = array_merge( + $noImportedUsages->filter($this->nameScanner->findNames($phpFile)), + $occurances + ); + } + + return $occurances; } } -