Skip to content
This repository was archived by the owner on Jul 12, 2020. It is now read-only.

Start breaking EditingSession down into EditingActions #48

Merged
merged 1 commit into from
Jan 9, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,56 +13,50 @@
use QafooLabs\Refactoring\Domain\Services\VariableScanner;
use QafooLabs\Refactoring\Domain\Services\CodeAnalysis;
use QafooLabs\Refactoring\Domain\Services\Editor;
use QafooLabs\Refactoring\Domain\Model\EditingAction\AddProperty;
use QafooLabs\Refactoring\Domain\Model\EditingAction\LocalVariableToInstance;

class ConvertLocalToInstanceVariable
class ConvertLocalToInstanceVariable extends SingleFileRefactoring
{
/**
* @var \QafooLabs\Refactoring\Domain\Services\VariableScanner
* @var Variable
*/
private $variableScanner;
private $convertVariable;

/**
* @var \QafooLabs\Refactoring\Domain\Services\CodeAnalysis
* @param int $line
*/
private $codeAnalysis;
public function refactor(File $file, $line, Variable $convertVariable)
{
$this->file = $file;
$this->line = $line;
$this->convertVariable = $convertVariable;

/**
* @var \QafooLabs\Refactoring\Domain\Services\Editor
*/
private $editor;
$this->assertIsInsideMethod();

public function __construct(VariableScanner $variableScanner, CodeAnalysis $codeAnalysis, Editor $editor)
{
$this->variableScanner = $variableScanner;
$this->codeAnalysis = $codeAnalysis;
$this->editor = $editor;
$this->startEditingSession();
$this->addProperty();
$this->convertVariablesToInstanceVariables();
$this->completeEditingSession();
}

public function refactor(File $file, $line, Variable $convertVariable)
private function addProperty()
{
if ( ! $this->codeAnalysis->isInsideMethod($file, LineRange::fromSingleLine($line))) {
throw RefactoringException::rangeIsNotInsideMethod(LineRange::fromSingleLine($line));
}
$line = $this->codeAnalysis->getLineOfLastPropertyDefinedInScope($this->file, $this->line);

$instanceVariable = $convertVariable->convertToInstance();
$lastPropertyLine = $this->codeAnalysis->getLineOfLastPropertyDefinedInScope($file, $line);

$selectedMethodLineRange = $this->codeAnalysis->findMethodRange($file, LineRange::fromSingleLine($line));
$definedVariables = $this->variableScanner->scanForVariables(
$file, $selectedMethodLineRange
$this->session->addEdit(
new AddProperty($line, $this->convertVariable->getName())
);
}

if ( ! $definedVariables->contains($convertVariable)) {
throw RefactoringException::variableNotInRange($convertVariable, $selectedMethodLineRange);
}

$buffer = $this->editor->openBuffer($file);
private function convertVariablesToInstanceVariables()
{
$definedVariables = $this->getDefinedVariables();

$session = new EditingSession($buffer);
$session->addProperty($lastPropertyLine, $convertVariable->getName());
$session->replaceString($definedVariables, $convertVariable, $instanceVariable);
if ( ! $definedVariables->contains($this->convertVariable)) {
throw RefactoringException::variableNotInRange($this->convertVariable, $selectedMethodLineRange);
}

$this->editor->save();
$this->session->addEdit(new LocalVariableToInstance($definedVariables, $this->convertVariable));
}
}

85 changes: 58 additions & 27 deletions src/main/QafooLabs/Refactoring/Application/ExtractMethod.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,60 +11,91 @@
use QafooLabs\Refactoring\Domain\Services\VariableScanner;
use QafooLabs\Refactoring\Domain\Services\CodeAnalysis;
use QafooLabs\Refactoring\Domain\Services\Editor;
use QafooLabs\Refactoring\Domain\Model\LineCollection;
use QafooLabs\Refactoring\Domain\Model\EditingAction\AddMethod;
use QafooLabs\Refactoring\Domain\Model\EditingAction\ReplaceWithMethodCall;

/**
* Extract Method Refactoring
*/
class ExtractMethod
class ExtractMethod extends SingleFileRefactoring
{
/**
* @var \QafooLabs\Refactoring\Domain\Services\VariableScanner
* @var LineRange
*/
private $variableScanner;
private $extractRange;

/**
* @var \QafooLabs\Refactoring\Domain\Services\CodeAnalysis
* @var MethodSignature
*/
private $codeAnalysis;
private $newMethod;

/**
* @var \QafooLabs\Refactoring\Domain\Services\Editor
* @param string $newMethodName
*/
private $editor;

public function __construct(VariableScanner $variableScanner, CodeAnalysis $codeAnalysis, Editor $editor)
public function refactor(File $file, LineRange $extractRange, $newMethodName)
{
$this->variableScanner = $variableScanner;
$this->codeAnalysis = $codeAnalysis;
$this->editor = $editor;
$this->file = $file;
$this->extractRange = $extractRange;

$this->assertIsInsideMethod();

$this->createNewMethodSignature($newMethodName);

$this->startEditingSession();
$this->replaceCodeWithMethodCall();
$this->addNewMethod();
$this->completeEditingSession();
}

public function refactor(File $file, LineRange $extractRange, $newMethodName)
protected function assertIsInsideMethod()
{
if ( ! $this->codeAnalysis->isInsideMethod($file, $extractRange)) {
throw RefactoringException::rangeIsNotInsideMethod($extractRange);
if ( ! $this->codeAnalysis->isInsideMethod($this->file, $this->extractRange)) {
throw RefactoringException::rangeIsNotInsideMethod($this->extractRange);
}
}

$isStatic = $this->codeAnalysis->isMethodStatic($file, $extractRange);
$methodRange = $this->codeAnalysis->findMethodRange($file, $extractRange);
$selectedCode = $extractRange->sliceCode($file->getCode());

$extractVariables = $this->variableScanner->scanForVariables($file, $extractRange);
$methodVariables = $this->variableScanner->scanForVariables($file, $methodRange);
private function createNewMethodSignature($newMethodName)
{
$extractVariables = $this->variableScanner->scanForVariables($this->file, $this->extractRange);
$methodVariables = $this->variableScanner->scanForVariables($this->file, $this->findMethodRange());

$buffer = $this->editor->openBuffer($file);
$isStatic = $this->codeAnalysis->isMethodStatic($this->file, $this->extractRange);

$newMethod = new MethodSignature(
$this->newMethod = new MethodSignature(
$newMethodName,
$isStatic ? MethodSignature::IS_STATIC : 0,
$methodVariables->variablesFromSelectionUsedBefore($extractVariables),
$methodVariables->variablesFromSelectionUsedAfter($extractVariables)
);
}

$session = new EditingSession($buffer);
$session->replaceRangeWithMethodCall($extractRange, $newMethod);
$session->addMethod($methodRange->getEnd(), $newMethod, $selectedCode);
private function addNewMethod()
{
$this->session->addEdit(new AddMethod(
$this->findMethodRange()->getEnd(),
$this->newMethod,
$this->getSelectedCode()
));
}

private function replaceCodeWithMethodCall()
{
$this->session->addEdit(new ReplaceWithMethodCall(
$this->extractRange,
$this->newMethod
));
}

$this->editor->save();
private function findMethodRange()
{
return $this->codeAnalysis->findMethodRange($this->file, $this->extractRange);
}

private function getSelectedCode()
{
return LineCollection::createFromArray(
$this->extractRange->sliceCode($this->file->getCode())
);
}
}
65 changes: 30 additions & 35 deletions src/main/QafooLabs/Refactoring/Application/RenameLocalVariable.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,63 +12,58 @@
use QafooLabs\Refactoring\Domain\Services\VariableScanner;
use QafooLabs\Refactoring\Domain\Services\CodeAnalysis;
use QafooLabs\Refactoring\Domain\Services\Editor;
use QafooLabs\Refactoring\Domain\Model\EditingAction\RenameVariable;

/**
* Rename Local Variable Refactoring
*/
class RenameLocalVariable
class RenameLocalVariable extends SingleFileRefactoring
{
/**
* @var \QafooLabs\Refactoring\Domain\Services\VariableScanner
* @var Variable
*/
private $variableScanner;
private $oldName;

/**
* @var \QafooLabs\Refactoring\Domain\Services\CodeAnalysis
* @var Variable
*/
private $codeAnalysis;
private $newName;

/**
* @var \QafooLabs\Refactoring\Domain\Services\Editor
* @param int $line
*/
private $editor;

public function __construct(VariableScanner $variableScanner, CodeAnalysis $codeAnalysis, Editor $editor)
{
$this->variableScanner = $variableScanner;
$this->codeAnalysis = $codeAnalysis;
$this->editor = $editor;
}

public function refactor(File $file, $line, Variable $oldName, Variable $newName)
{
if ( ! $this->codeAnalysis->isInsideMethod($file, LineRange::fromSingleLine($line))) {
throw RefactoringException::rangeIsNotInsideMethod(LineRange::fromSingleLine($line));
}
$this->file = $file;
$this->line = $line;
$this->newName = $newName;
$this->oldName = $oldName;

if ( ! $oldName->isLocal()) {
throw RefactoringException::variableNotLocal($oldName);
}
$this->assertIsInsideMethod();

if ( ! $newName->isLocal()) {
throw RefactoringException::variableNotLocal($newName);
}
$this->assertVariableIsLocal($this->oldName);
$this->assertVariableIsLocal($this->newName);

$selectedMethodLineRange = $this->codeAnalysis->findMethodRange($file, LineRange::fromSingleLine($line));
$definedVariables = $this->variableScanner->scanForVariables(
$file, $selectedMethodLineRange
);
$this->startEditingSession();
$this->renameLocalVariable();
$this->completeEditingSession();
}

if ( ! $definedVariables->contains($oldName)) {
throw RefactoringException::variableNotInRange($oldName, $selectedMethodLineRange);
private function assertVariableIsLocal(Variable $variable)
{
if ( ! $variable->isLocal()) {
throw RefactoringException::variableNotLocal($variable);
}
}

$buffer = $this->editor->openBuffer($file);
private function renameLocalVariable()
{
$definedVariables = $this->getDefinedVariables();

$session = new EditingSession($buffer);
$session->replaceString($definedVariables, $oldName, $newName);
if ( ! $definedVariables->contains($this->oldName)) {
throw RefactoringException::variableNotInRange($this->oldName, $selectedMethodLineRange);
}

$this->editor->save();
$this->session->addEdit(new RenameVariable($definedVariables, $this->oldName, $this->newName));
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?php

namespace QafooLabs\Refactoring\Application;

use QafooLabs\Refactoring\Domain\Services\VariableScanner;
use QafooLabs\Refactoring\Domain\Services\CodeAnalysis;
use QafooLabs\Refactoring\Domain\Services\Editor;
use QafooLabs\Refactoring\Domain\Model\EditingSession;
use QafooLabs\Refactoring\Domain\Model\File;
use QafooLabs\Refactoring\Domain\Model\LineRange;

abstract class SingleFileRefactoring
{
/**
* @var VariableScanner
*/
protected $variableScanner;

/**
* @var CodeAnalysis
*/
protected $codeAnalysis;

/**
* @var Editor
*/
protected $editor;

/**
* @var EditingSession
*/
protected $session;

/**
* @var File
*/
protected $file;

/**
* @var int
*/
protected $line;

public function __construct(
VariableScanner $variableScanner,
CodeAnalysis $codeAnalysis,
Editor $editor
) {
$this->variableScanner = $variableScanner;
$this->codeAnalysis = $codeAnalysis;
$this->editor = $editor;
}

protected function assertIsInsideMethod()
{
if ( ! $this->codeAnalysis->isInsideMethod($this->file, LineRange::fromSingleLine($this->line))) {
throw RefactoringException::rangeIsNotInsideMethod(LineRange::fromSingleLine($this->line));
}
}

protected function startEditingSession()
{
$buffer = $this->editor->openBuffer($this->file);

$this->session = new EditingSession($buffer);
}

protected function completeEditingSession()
{
$this->session->performEdits();

$this->editor->save();
}

protected function getDefinedVariables()
{
$selectedMethodLineRange = $this->codeAnalysis->findMethodRange($this->file, LineRange::fromSingleLine($this->line));

$definedVariables = $this->variableScanner->scanForVariables(
$this->file, $selectedMethodLineRange
);

return $definedVariables;
}
}
8 changes: 8 additions & 0 deletions src/main/QafooLabs/Refactoring/Domain/Model/EditingAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace QafooLabs\Refactoring\Domain\Model;

interface EditingAction
{
public function performEdit(EditorBuffer $buffer);
}
Loading