Skip to content

Commit e9bc2b9

Browse files
committed
\LastDragon_ru\LaraASP\Documentator\Editor\Editor::getText() replace by \LastDragon_ru\LaraASP\Documentator\Editor\Editor::extract().
1 parent 528f6d4 commit e9bc2b9

File tree

11 files changed

+453
-63
lines changed

11 files changed

+453
-63
lines changed

packages/documentator/src/Editor/Editor.php

+12-23
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace LastDragon_ru\LaraASP\Documentator\Editor;
44

5+
use LastDragon_ru\LaraASP\Documentator\Editor\Mutators\Extractor;
56
use LastDragon_ru\LaraASP\Documentator\Utils\Text;
67
use Override;
78
use Stringable;
@@ -25,7 +26,8 @@
2526
/**
2627
* @var list<string>
2728
*/
28-
protected array $lines;
29+
protected array $lines;
30+
protected Extractor $extractor;
2931

3032
/**
3133
* @param list<string>|string $content
@@ -35,7 +37,8 @@ final public function __construct(
3537
protected int $startLine = 0,
3638
protected string $endOfLine = "\n",
3739
) {
38-
$this->lines = is_string($content) ? Text::getLines($content) : $content;
40+
$this->lines = is_string($content) ? Text::getLines($content) : $content;
41+
$this->extractor = new Extractor();
3942
}
4043

4144
#[Override]
@@ -44,29 +47,15 @@ public function __toString(): string {
4447
}
4548

4649
/**
47-
* @param iterable<array-key, Coordinate> $location
50+
* @param iterable<mixed, iterable<mixed, Coordinate>> $locations
51+
*
52+
* @return new<static>
4853
*/
49-
public function getText(iterable $location): ?string {
50-
// Select
51-
$selected = null;
52-
53-
foreach ($location as $coordinate) {
54-
$number = $coordinate->line - $this->startLine;
54+
public function extract(iterable $locations): static {
55+
$extracted = ($this->extractor)($this->lines, $locations, $this->startLine);
56+
$editor = new static($extracted, $this->startLine, $this->endOfLine);
5557

56-
if (isset($this->lines[$number])) {
57-
$selected[] = mb_substr($this->lines[$number], $coordinate->offset, $coordinate->length);
58-
} else {
59-
$selected = null;
60-
break;
61-
}
62-
}
63-
64-
if ($selected === null) {
65-
return null;
66-
}
67-
68-
// Return
69-
return implode($this->endOfLine, $selected);
58+
return $editor;
7059
}
7160

7261
/**

packages/documentator/src/Editor/EditorTest.php

+42-33
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,48 @@ public function getLines(): array {
8484
self::assertSame($expected, $actual->getLines());
8585
}
8686

87+
public function testExtract(): void {
88+
$startLine = 2;
89+
$locations = [
90+
new Location(0 + $startLine, 0 + $startLine, 2, 5),
91+
new Location(0 + $startLine, 0 + $startLine, 14, 5),
92+
new Location(0 + $startLine, 0 + $startLine, 26, 5),
93+
new Location(1 + $startLine, 2 + $startLine, 17, null),
94+
new Location(1 + $startLine, 2 + $startLine, 17, null), // same line -> should be ignored
95+
new Location(4 + $startLine, 4 + $startLine, 2, 7),
96+
new Location(4 + $startLine, 4 + $startLine, 9, 7),
97+
new Location(4 + $startLine, 4 + $startLine, 16, 5),
98+
new Location(5 + $startLine, 5 + $startLine, 16, 5), // no line -> should be ignored
99+
];
100+
$lines = [
101+
'11111 11111 11111 11111 11111 11111',
102+
'22222 22222 22222 22222 22222 22222',
103+
'33333 33333 33333 33333 33333 33333',
104+
'44444 44444 44444 44444 44444 44444',
105+
'55555 55555 55555 55555 55555 55555',
106+
];
107+
$expected = [
108+
'111 1 111 1 111 1',
109+
' 22222 22222 22222',
110+
'33333 33333 33333 33333 33333 33333',
111+
'555 55555 55555 555',
112+
];
113+
$editor = new readonly class($lines, $startLine) extends Editor {
114+
/**
115+
* @return list<string>
116+
*/
117+
public function getLines(): array {
118+
return $this->lines;
119+
}
120+
};
121+
122+
$actual = $editor->extract($locations);
123+
124+
self::assertNotSame($editor, $actual);
125+
self::assertEquals($lines, $editor->getLines());
126+
self::assertSame($expected, $actual->getLines());
127+
}
128+
87129
public function testPrepare(): void {
88130
$editor = new readonly class(['L1', 'L2']) extends Editor {
89131
/**
@@ -177,37 +219,4 @@ public function expand(array $changes): array {
177219

178220
self::assertEquals($expected, $editor->expand($changes));
179221
}
180-
181-
public function testGetText(): void {
182-
$editor = new Editor(
183-
[
184-
0 => 'a b c d',
185-
1 => 'e f g h',
186-
2 => 'i j k l',
187-
3 => 'm n o p',
188-
4 => '',
189-
5 => 'q r s t',
190-
6 => 'u v w x',
191-
],
192-
1,
193-
);
194-
195-
self::assertNull($editor->getText(new Location(25, 25, 0)));
196-
self::assertSame('f g', $editor->getText(new Location(2, 2, 2, 3)));
197-
self::assertSame(
198-
<<<'TEXT'
199-
k l
200-
m n o p
201-
202-
q r s
203-
TEXT,
204-
$editor->getText(new Location(3, 6, 4, 5)),
205-
);
206-
self::assertSame(
207-
<<<'TEXT'
208-
f g
209-
TEXT,
210-
$editor->getText([new Coordinate(2, 2, 3)]),
211-
);
212-
}
213222
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace LastDragon_ru\LaraASP\Documentator\Editor\Mutators;
4+
5+
use LastDragon_ru\LaraASP\Documentator\Editor\Coordinate;
6+
7+
use const PHP_INT_MAX;
8+
9+
readonly class Base {
10+
public function __construct() {
11+
// empty
12+
}
13+
14+
protected function compare(Coordinate $a, Coordinate $b): int {
15+
$result = $a->line <=> $b->line;
16+
$result = $result === 0
17+
? $a->offset <=> $b->offset
18+
: $result;
19+
$result = $result === 0
20+
? ($a->length ?? PHP_INT_MAX) <=> ($b->length ?? PHP_INT_MAX)
21+
: $result;
22+
23+
return $result;
24+
}
25+
26+
/**
27+
* @phpstan-assert-if-true int $key
28+
*
29+
* @param array<int, array<int, Coordinate>> $coordinates
30+
*/
31+
protected function isOverlapped(array $coordinates, Coordinate $coordinate, ?int &$key = null): bool {
32+
$key = null;
33+
34+
foreach ($coordinates[$coordinate->line] ?? [] as $k => $c) {
35+
$aStart = $c->offset;
36+
$aEnd = $aStart + ($c->length ?? PHP_INT_MAX) - 1;
37+
$bStart = $coordinate->offset;
38+
$bEnd = $bStart + ($coordinate->length ?? PHP_INT_MAX) - 1;
39+
40+
if (!($bEnd < $aStart || $bStart > $aEnd)) {
41+
$key = $k;
42+
break;
43+
}
44+
}
45+
46+
return $key !== null;
47+
}
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace LastDragon_ru\LaraASP\Documentator\Editor\Mutators;
4+
5+
use LastDragon_ru\LaraASP\Documentator\Editor\Coordinate;
6+
use LastDragon_ru\LaraASP\Documentator\Testing\Package\TestCase;
7+
use Override;
8+
use PHPUnit\Framework\Attributes\CoversClass;
9+
use PHPUnit\Framework\Attributes\DataProvider;
10+
11+
/**
12+
* @internal
13+
*/
14+
#[CoversClass(Extractor::class)]
15+
final class BaseTest extends TestCase {
16+
// <editor-fold desc="Tests">
17+
// =========================================================================
18+
public function testCompare(): void {
19+
$base = new readonly class() extends Base {
20+
#[Override]
21+
public function compare(Coordinate $a, Coordinate $b): int {
22+
return parent::compare($a, $b);
23+
}
24+
};
25+
26+
self::assertSame(-1, $base->compare(new Coordinate(1, 0, 1), new Coordinate(2, 0, 1)));
27+
self::assertSame(1, $base->compare(new Coordinate(2, 0, 1), new Coordinate(1, 0, 1)));
28+
self::assertSame(0, $base->compare(new Coordinate(1, 0, 1), new Coordinate(1, 0, 1)));
29+
self::assertSame(1, $base->compare(new Coordinate(1, 10, 1), new Coordinate(1, 0, 1)));
30+
self::assertSame(-1, $base->compare(new Coordinate(1, 0, 1), new Coordinate(1, 0, 2)));
31+
}
32+
33+
/**
34+
* @param array{bool, ?int} $expected
35+
* @param array<int, array<int, Coordinate>> $lines
36+
*/
37+
#[DataProvider('dataProviderIsOverlapped')]
38+
public function testIsOverlapped(array $expected, array $lines, Coordinate $coordinate): void {
39+
$base = new readonly class() extends Base {
40+
/**
41+
* @inheritDoc
42+
*/
43+
#[Override]
44+
public function isOverlapped(
45+
array $coordinates,
46+
Coordinate $coordinate,
47+
?int &$key = null,
48+
): bool {
49+
return parent::isOverlapped(
50+
$coordinates,
51+
$coordinate,
52+
$key,
53+
);
54+
}
55+
};
56+
57+
self::assertSame($expected[0], $base->isOverlapped($lines, $coordinate, $key));
58+
self::assertSame($expected[1], $key);
59+
}
60+
// </editor-fold>
61+
62+
// <editor-fold desc="DataProviders">
63+
// =========================================================================
64+
/**
65+
* @return array<string, array{array{bool, ?int}, array<int, array<int, Coordinate>>, Coordinate}>
66+
*/
67+
public static function dataProviderIsOverlapped(): array {
68+
return [
69+
'nope' => [
70+
[false, null],
71+
[
72+
10 => [
73+
new Coordinate(10, 10, null),
74+
],
75+
],
76+
new Coordinate(11, 10, null),
77+
],
78+
'nope (same line)' => [
79+
[false, null],
80+
[
81+
10 => [
82+
new Coordinate(10, 10, 10),
83+
],
84+
],
85+
new Coordinate(10, 20, 10),
86+
],
87+
'overlapped' => [
88+
[true, 0],
89+
[
90+
10 => [
91+
new Coordinate(10, 10, null),
92+
],
93+
],
94+
new Coordinate(10, 15, 10),
95+
],
96+
'overlapped (reverse)' => [
97+
[true, 0],
98+
[
99+
10 => [
100+
new Coordinate(10, 15, 10),
101+
],
102+
],
103+
new Coordinate(10, 10, null),
104+
],
105+
'overlapped (one character)' => [
106+
[true, 1],
107+
[
108+
10 => [
109+
new Coordinate(10, 0, 5),
110+
new Coordinate(10, 10, 10),
111+
],
112+
],
113+
new Coordinate(10, 19, 10),
114+
],
115+
];
116+
}
117+
//</editor-fold>
118+
}

0 commit comments

Comments
 (0)