Skip to content

Commit 570fa30

Browse files
committed
refactor: centralised source range construction
1 parent 120578a commit 570fa30

9 files changed

Lines changed: 62 additions & 20 deletions

src/Sniff/AbstractSniff.php

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,17 +69,15 @@ protected function elementNameRanges(File $file, int $beginOffset, int $untilOff
6969
$elementNameLength = strlen($elementName);
7070

7171
return [
72-
new SourceRange(
73-
$file->lineAtOffset($openingNameOffset)->number,
72+
SourceRange::fromFile(
73+
$file,
7474
$openingNameOffset,
7575
$openingNameOffset + $elementNameLength,
76-
$elementName,
7776
),
78-
new SourceRange(
79-
$file->lineAtOffset($closingNameOffset)->number,
77+
SourceRange::fromFile(
78+
$file,
8079
$closingNameOffset,
8180
$closingNameOffset + $elementNameLength,
82-
$elementName,
8381
),
8482
];
8583
}

src/Sniff/AttributeOrderSniff.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717
*/
1818
final class AttributeOrderSniff extends AbstractSniff implements Fixable
1919
{
20-
private const string REPORTING_MESSAGE = 'Element <%s>: xml:id should appear before xmlns attributes.';
2120
private const string OPENING_TAG_PATTERN = '/<([a-zA-Z0-9:_-]+)\b([^<>]*?)>/';
2221
private const string ATTRIBUTE_NAME_PATTERN = '/([a-zA-Z0-9:_-]+)\s*=/';
22+
private const string REPORTING_MESSAGE = 'Element <%s>: xml:id should appear before xmlns attributes.';
2323

2424
public static function getCode(): string
2525
{
@@ -65,11 +65,10 @@ public function process(\DOMDocument $document, File $file): array
6565
$tagName,
6666
$attrString,
6767
$file->path,
68-
new SourceRange(
69-
$file->lineAtOffset($beginOffset)->number,
68+
SourceRange::fromFile(
69+
$file,
7070
$beginOffset,
7171
$beginOffset + strlen($fullMatch),
72-
$fullMatch,
7372
),
7473
$violations,
7574
);

src/Sniff/MixedIndentationSniff.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ public static function fixerClassName(): string
2323
return MixedIndentationFixer::class;
2424
}
2525

26-
/** @throws \InvalidArgumentException if a generated source range is inconsistent */
26+
/**
27+
* @throws \InvalidArgumentException if a generated source range is inconsistent
28+
* @throws \OutOfBoundsException if a generated source range lies outside the source
29+
*/
2730
public function process(\DOMDocument $document, File $file): array
2831
{
2932
$violations = [];
@@ -42,11 +45,10 @@ public function process(\DOMDocument $document, File $file): array
4245
$file->path,
4346
self::REPORTING_MESSAGE,
4447
[
45-
new SourceRange(
46-
$line->number,
48+
SourceRange::fromFile(
49+
$file,
4750
$line->beginOffset,
4851
$line->beginOffset + strlen($indentation),
49-
$indentation,
5052
),
5153
],
5254
);

src/Sniff/TrailingWhitespaceSniff.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ public static function fixerClassName(): string
2323
return TrailingWhitespaceFixer::class;
2424
}
2525

26-
/** @throws \InvalidArgumentException if a generated source range is inconsistent */
26+
/**
27+
* @throws \InvalidArgumentException if a generated source range is inconsistent
28+
* @throws \OutOfBoundsException if a generated source range lies outside the source
29+
*/
2730
public function process(\DOMDocument $document, File $file): array
2831
{
2932
$violations = [];
@@ -39,7 +42,7 @@ public function process(\DOMDocument $document, File $file): array
3942
$violations[] = $this->createViolation(
4043
$file->path,
4144
self::REPORTING_MESSAGE,
42-
[new SourceRange($line->number, $beginOffset, $beginOffset + strlen($whitespace), $whitespace)],
45+
[SourceRange::fromFile($file, $beginOffset, $beginOffset + strlen($whitespace))],
4346
);
4447
}
4548

src/Sniff/WhitespaceSniff.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,12 @@ public static function fixerClassName(): string
3232
/**
3333
* @throws \InvalidArgumentException if a generated source range is inconsistent
3434
* @throws \LogicException if source content cannot be split into lines
35+
* @throws \OutOfBoundsException if a generated source range lies outside the source
3536
*/
3637
public function process(\DOMDocument $document, File $file): array
3738
{
3839
$violations = [];
3940
$offset = 0;
40-
$line = 1;
4141

4242
$lines = preg_split(self::LINE_ENDING_PATTERN, $file->content, -1, PREG_SPLIT_DELIM_CAPTURE);
4343
if ($lines === false) {
@@ -59,12 +59,11 @@ public function process(\DOMDocument $document, File $file): array
5959
$violations[] = $this->createViolation(
6060
$file->path,
6161
$message,
62-
[new SourceRange($line, $offset, $offset + $lineContentLength, $lineContent)],
62+
[SourceRange::fromFile($file, $offset, $offset + $lineContentLength)],
6363
);
6464
}
6565

6666
$offset += $lineContentLength + strlen($lineEnding);
67-
$line++;
6867
}
6968

7069
return $violations;

src/Violation/SourceRange.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,24 @@
44

55
namespace DocbookCS\Violation;
66

7+
use DocbookCS\Source\File;
8+
79
final readonly class SourceRange
810
{
11+
/**
12+
* @throws \InvalidArgumentException if the source range is inconsistent
13+
* @throws \OutOfBoundsException if the begin offset lies outside the source
14+
*/
15+
public static function fromFile(File $file, int $beginOffset, int $untilOffset): self
16+
{
17+
return new self(
18+
line: $file->lineAtOffset($beginOffset)->number,
19+
beginOffset: $beginOffset,
20+
untilOffset: $untilOffset,
21+
content: substr($file->content, $beginOffset, $untilOffset - $beginOffset),
22+
);
23+
}
24+
925
/** @throws \InvalidArgumentException if the source range is inconsistent */
1026
public function __construct(
1127
public int $line,

tests/Unit/Fix/WhitespaceFixerTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use DocbookCS\Runner\RunMode;
1313
use DocbookCS\Sniff\WhitespaceSniff;
1414
use DocbookCS\Source\File;
15+
use DocbookCS\Source\Line;
1516
use DocbookCS\Violation\SourceRange;
1617
use DocbookCS\Violation\Violation;
1718
use PHPUnit\Framework\Attributes\CoversClass;
@@ -30,6 +31,7 @@
3031
//
3132
UsesClass(File::class),
3233
UsesClass(FixPlan::class),
34+
UsesClass(Line::class),
3335
UsesClass(SourceRange::class),
3436
]
3537
final class WhitespaceFixerTest extends TestCase

tests/Unit/Sniff/WhitespaceSniffTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use DocbookCS\Sniff\WhitespaceSniff;
88
use DocbookCS\Source\File;
9+
use DocbookCS\Source\Line;
910
use DocbookCS\Violation\SourceRange;
1011
use DocbookCS\Violation\Violation;
1112
use PHPUnit\Framework\Attributes\CoversClass;
@@ -18,6 +19,7 @@
1819
CoversClass(WhitespaceSniff::class),
1920
//
2021
UsesClass(File::class),
22+
UsesClass(Line::class),
2123
UsesClass(SourceRange::class),
2224
]
2325
final class WhitespaceSniffTest extends TestCase

tests/Unit/Violation/AffectedRangesTest.php

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,41 @@
44

55
namespace DocbookCS\Tests\Unit\Violation;
66

7-
use DocbookCS\Violation\SourceRange;
7+
use DocbookCS\Source\File;
8+
use DocbookCS\Source\Line;
89
use DocbookCS\Violation\Severity;
10+
use DocbookCS\Violation\SourceRange;
911
use DocbookCS\Violation\Violation;
1012
use PHPUnit\Framework\Attributes\CoversClass;
1113
use PHPUnit\Framework\Attributes\DataProvider;
1214
use PHPUnit\Framework\Attributes\Test;
15+
use PHPUnit\Framework\Attributes\UsesClass;
1316
use PHPUnit\Framework\TestCase;
1417

1518
#[
1619
CoversClass(SourceRange::class),
1720
CoversClass(Violation::class),
21+
//
22+
UsesClass(File::class),
23+
UsesClass(Line::class),
1824
]
1925
final class AffectedRangesTest extends TestCase
2026
{
27+
#[Test]
28+
public function itCreatesSourceRangesFromFileOffsets(): void
29+
{
30+
$range = SourceRange::fromFile(
31+
new File('file.xml', "first\nsecond\n"),
32+
6,
33+
12,
34+
);
35+
36+
self::assertSame(2, $range->line);
37+
self::assertSame(6, $range->beginOffset);
38+
self::assertSame(12, $range->untilOffset);
39+
self::assertSame('second', $range->content);
40+
}
41+
2142
#[Test]
2243
public function itRejectsViolationsWithoutAffectedRanges(): void
2344
{

0 commit comments

Comments
 (0)