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

Commit 1086616

Browse files
committed
Merge pull request #41 from tomphp/fix/extract-method-from-block
Extract method works properly with code indented more than one level
2 parents 7fc6349 + 103632a commit 1086616

File tree

8 files changed

+164
-7
lines changed

8 files changed

+164
-7
lines changed

features/extract_method.feature

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,3 +265,43 @@ Feature: Extract Method
265265
}
266266
}
267267
"""
268+
269+
Scenario: Extract method from inside a block
270+
Given a PHP File named "src/ExtractMethodFromBlock.php" with:
271+
"""
272+
<?php
273+
class ExtractMethodFromBlock
274+
{
275+
public function operation()
276+
{
277+
for ($i=0; $i<5; $i++) {
278+
echo "Hello World";
279+
}
280+
}
281+
}
282+
"""
283+
When I use refactoring "extract-method" with:
284+
| arg | value |
285+
| file | src/ExtractMethodFromBlock.php |
286+
| range | 7-7 |
287+
| newmethod | hello |
288+
Then the PHP File "src/ExtractMethodFromBlock.php" should be refactored:
289+
"""
290+
--- a/vfs://project/src/ExtractMethodFromBlock.php
291+
+++ b/vfs://project/src/ExtractMethodFromBlock.php
292+
@@ -4,7 +4,12 @@
293+
public function operation()
294+
{
295+
for ($i=0; $i<5; $i++) {
296+
- echo "Hello World";
297+
+ $this->hello();
298+
}
299+
}
300+
+
301+
+ private function hello()
302+
+ {
303+
+ echo "Hello World";
304+
+ }
305+
}
306+
307+
"""

src/main/QafooLabs/Refactoring/Adapters/PatchBuilder/PatchBuffer.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
* to kontakt@beberlei.de so I can send you a copy immediately.
1212
*/
1313

14-
1514
namespace QafooLabs\Refactoring\Adapters\PatchBuilder;
1615

1716
use QafooLabs\Refactoring\Domain\Model\EditorBuffer;
@@ -30,6 +29,11 @@ public function __construct(PatchBuilder $builder)
3029
$this->builder = $builder;
3130
}
3231

32+
public function getLines(LineRange $range)
33+
{
34+
return $this->builder->getOriginalLines($range->getStart(), $range->getEnd());
35+
}
36+
3337
public function replace(LineRange $range, array $newLines)
3438
{
3539
$this->builder->replaceLines($range->getStart(), $range->getEnd(), $newLines);

src/main/QafooLabs/Refactoring/Adapters/PatchBuilder/PatchBuilder.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,15 @@ public function __construct($contents, $path = null)
5050
$this->path = $path;
5151
}
5252

53+
public function getOriginalLines($start, $end)
54+
{
55+
return array_slice(
56+
$this->buffer->getOriginalContents(),
57+
$start - 1,
58+
$end - $start + 1
59+
);
60+
}
61+
5362
/**
5463
* Change Token in given line from old to new.
5564
*
@@ -75,7 +84,6 @@ public function changeToken($originalLine, $oldToken, $newToken)
7584
);
7685
}
7786

78-
7987
/**
8088
* Append new lines to an original line of the file.
8189
*

src/main/QafooLabs/Refactoring/Domain/Model/EditingAction/ReplaceWithMethodCall.php

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
use QafooLabs\Refactoring\Domain\Model\EditorBuffer;
77
use QafooLabs\Refactoring\Domain\Model\MethodSignature;
88
use QafooLabs\Refactoring\Domain\Model\LineRange;
9+
use QafooLabs\Refactoring\Domain\Model\LineCollection;
10+
use QafooLabs\Refactoring\Domain\Model\IndentationDetector;
911

1012
class ReplaceWithMethodCall implements EditingAction
1113
{
@@ -27,12 +29,23 @@ public function __construct(LineRange $range, MethodSignature $newMethod)
2729

2830
public function performEdit(EditorBuffer $buffer)
2931
{
30-
$buffer->replace($this->range, array($this->getIndent() . $this->getMethodCall()));
32+
$extractedCode = $buffer->getLines($this->range);
33+
34+
$buffer->replace($this->range, array($this->getIndent($extractedCode) . $this->getMethodCall()));
3135
}
3236

33-
private function getIndent()
37+
/**
38+
* @param string[] $lines
39+
*
40+
* @return string
41+
*/
42+
private function getIndent(array $lines)
3443
{
35-
return ' ';
44+
$detector = new IndentationDetector(
45+
LineCollection::createFromArray($lines)
46+
);
47+
48+
return str_repeat(' ', $detector->getFirstLineIndentation());
3649
}
3750

3851
private function getMethodCall()

src/main/QafooLabs/Refactoring/Domain/Model/EditorBuffer.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,15 @@
1919
*/
2020
interface EditorBuffer
2121
{
22+
/**
23+
* Return the given range of lines from the buffer.
24+
*
25+
* @param LineRange $range
26+
*
27+
* @return string[]
28+
*/
29+
public function getLines(LineRange $range);
30+
2231
/**
2332
* Replace LineRange with new lines.
2433
*

src/test/QafooLabs/Refactoring/Adapters/PatchBuilder/PatchBuilderTest.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,4 +200,12 @@ public function testReplaceLines()
200200
DIFF;
201201
$this->assertEquals($expected, $this->builder->generateUnifiedDiff());
202202
}
203+
204+
public function testGetOriginalLines()
205+
{
206+
$this->assertEquals(
207+
array('line4', 'line5', 'line6'),
208+
$this->builder->getOriginalLines(4, 6)
209+
);
210+
}
203211
}

src/test/QafooLabs/Refactoring/Domain/Model/EditingAction/ReplaceWithMethodCallTest.php

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ public function testBufferReplacesAtGivenRange()
3939
->method('replace')
4040
->with($this->equalTo($range), $this->anything());
4141

42+
$this->setCodeBeingReplaced();
43+
4244
$action->performEdit($this->buffer);
4345
}
4446

@@ -49,6 +51,8 @@ public function testMethodCallIsCorrectForSimpleMethod()
4951
new MethodSignature('testMethod')
5052
);
5153

54+
$this->setCodeBeingReplaced();
55+
5256
$this->assertGeneratedMethodCallMatches('$this->testMethod();', $action);
5357
}
5458

@@ -59,6 +63,8 @@ public function testMethodCallUsesGivenMethodName()
5963
new MethodSignature('realMethod')
6064
);
6165

66+
$this->setCodeBeingReplaced();
67+
6268
$this->assertGeneratedMethodCallMatches('$this->realMethod();', $action);
6369
}
6470

@@ -69,6 +75,8 @@ public function testStaticMethodCall()
6975
new MethodSignature('testMethod', MethodSignature::IS_STATIC)
7076
);
7177

78+
$this->setCodeBeingReplaced();
79+
7280
$this->assertGeneratedMethodCallMatches('self::testMethod();', $action);
7381
}
7482

@@ -79,6 +87,8 @@ public function testMethodCallWithSingleReturnVariable()
7987
new MethodSignature('testMethod', 0, array(), array('result'))
8088
);
8189

90+
$this->setCodeBeingReplaced();
91+
8292
$this->assertGeneratedMethodCallMatches('$result = $this->testMethod();', $action);
8393
}
8494

@@ -89,6 +99,8 @@ public function testMethodCallWithMultipleReturnVariables()
8999
new MethodSignature('testMethod', 0, array(), array('result1', 'result2'))
90100
);
91101

102+
$this->setCodeBeingReplaced();
103+
92104
$this->assertGeneratedMethodCallMatches(
93105
'list($result1, $result2) = $this->testMethod();',
94106
$action
@@ -102,15 +114,67 @@ public function testMethodCallWithArguments()
102114
new MethodSignature('testMethod', 0, array('arg1', 'arg2'))
103115
);
104116

117+
$this->setCodeBeingReplaced();
118+
105119
$this->assertGeneratedMethodCallMatches(
106120
'$this->testMethod($arg1, $arg2);',
107121
$action
108122
);
109123
}
110124

111-
private function assertGeneratedMethodCallMatches($expected, $action)
125+
public function testExtractedRangeIsReadFromTheBuffer()
126+
{
127+
$range = LineRange::fromLines(1, 2);
128+
129+
$this->buffer
130+
->expects($this->once())
131+
->method('getLines')
132+
->with($this->equalTo($range))
133+
->will($this->returnValue(array()));
134+
135+
$action = new ReplaceWithMethodCall(
136+
$range,
137+
new MethodSignature('testMethod')
138+
);
139+
140+
$action->performEdit($this->buffer);
141+
}
142+
143+
public function testExtractRangeIndentsMethodCallForFirstLineWithExtraIndent()
144+
{
145+
$lines = array(
146+
' echo "Something";',
147+
);
148+
149+
$this->buffer
150+
->expects($this->once())
151+
->method('getLines')
152+
->will($this->returnValue($lines));
153+
154+
$action = new ReplaceWithMethodCall(
155+
LineRange::fromLines(1, 2),
156+
new MethodSignature('testMethod')
157+
);
158+
159+
$this->assertGeneratedMethodCallMatches(
160+
'$this->testMethod();',
161+
$action,
162+
12
163+
);
164+
}
165+
166+
private function setCodeBeingReplaced(
167+
array $lines = array(' echo "Replace me";')
168+
) {
169+
$this->buffer
170+
->expects($this->any())
171+
->method('getLines')
172+
->will($this->returnValue($lines));
173+
}
174+
175+
private function assertGeneratedMethodCallMatches($expected, $action, $indentSize = 8)
112176
{
113-
$expected = ' ' . $expected;
177+
$expected = str_repeat(' ', $indentSize) . $expected;
114178

115179
$this->buffer
116180
->expects($this->once())

src/test/QafooLabs/Refactoring/Domain/Model/EditingSessionTest.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,15 @@
11
<?php
2+
/**
3+
* Qafoo PHP Refactoring Browser
4+
*
5+
* LICENSE
6+
*
7+
* This source file is subject to the MIT license that is bundled
8+
* with this package in the file LICENSE.txt.
9+
* If you did not receive a copy of the license and are unable to
10+
* obtain it through the world-wide-web, please send an email
11+
* to kontakt@beberlei.de so I can send you a copy immediately.
12+
*/
213

314
namespace QafooLabs\Refactoring\Domain\Model;
415

0 commit comments

Comments
 (0)