Skip to content

Commit

Permalink
Merge pull request #34 from kellegous/source-info
Browse files Browse the repository at this point in the history
Add optional filename and line number information to patterns
  • Loading branch information
timoschinkel authored Oct 2, 2024
2 parents 5b9f93e + 16b5b09 commit 3ce6451
Show file tree
Hide file tree
Showing 5 changed files with 215 additions and 30 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [2.3.0] - 2024-09-24
### Changed
- Add optional source and line number information to patterns - [#34](https://github.com/timoschinkel/codeowners/pull/34)

## [2.2.2] - 2024-07-10
### Changed
- Update deprecated string interpolation usage - [#33](https://github.com/timoschinkel/codeowners/pull/33) by kchung
Expand Down
18 changes: 10 additions & 8 deletions src/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,30 +15,32 @@ final class Parser implements ParserInterface
*/
public function parseFile(string $file): array
{
return $this->parseIterable($this->getFileIterable($file));
return $this->parseIterable($this->getFileIterable($file), $file);
}

/**
* @param string $lines
* @param ?string $filename
* @return Pattern[]
* @throws UnableToParseException
*/
public function parseString(string $lines): array
public function parseString(string $lines, ?string $filename = null): array
{
return $this->parseIterable(explode(PHP_EOL, $lines));
return $this->parseIterable(explode(PHP_EOL, $lines), $filename);
}

/**
* @param iterable<string> $lines
* @param ?string $filename
* @return Pattern[]
*/
private function parseIterable(iterable $lines): array
private function parseIterable(iterable $lines, ?string $filename = null): array
{
$patterns = [];

foreach ($lines as $line) {
foreach ($lines as $index => $line) {
$line = trim($line);
$pattern = $this->parseLine($line);
$pattern = $this->parseLine($line, new SourceInfo($filename, $index + 1));

if ($pattern instanceof Pattern) {
$patterns[] = $pattern;
Expand All @@ -48,7 +50,7 @@ private function parseIterable(iterable $lines): array
return $patterns;
}

private function parseLine(string $line): ?Pattern
private function parseLine(string $line, SourceInfo $sourceInfo): ?Pattern
{
$line = trim($line);

Expand All @@ -64,7 +66,7 @@ private function parseLine(string $line): ?Pattern

if (preg_match('/^(?P<file_pattern>[^\s]+)\s+(?P<owners>[^#]+)/si', $line, $matches) !== 0) {
$owners = preg_split('/\s+/', trim($matches['owners']));
return new Pattern($matches['file_pattern'], $owners);
return new Pattern($matches['file_pattern'], $owners, $sourceInfo);
}

return null;
Expand Down
10 changes: 9 additions & 1 deletion src/Pattern.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,13 @@ final class Pattern
/** @var string[] */
private $owners;

public function __construct(string $pattern, array $owners)
private ?SourceInfo $sourceInfo;

public function __construct(string $pattern, array $owners, ?SourceInfo $sourceInfo = null)
{
$this->pattern = $pattern;
$this->owners = $owners;
$this->sourceInfo = $sourceInfo;
}

public function getPattern(): string
Expand All @@ -27,4 +30,9 @@ public function getOwners(): array
{
return $this->owners;
}

public function getSourceInfo(): ?SourceInfo
{
return $this->sourceInfo;
}
}
28 changes: 28 additions & 0 deletions src/SourceInfo.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace CodeOwners;

final class SourceInfo
{
private ?string $filename;

private int $line;

public function __construct(
?string $filename,
int $line
) {
$this->filename = $filename;
$this->line = $line;
}

public function getFilename(): ?string
{
return $this->filename;
}

public function getLine(): int
{
return $this->line;
}
}
185 changes: 164 additions & 21 deletions tests/ParserTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use CodeOwners\Exception\UnableToParseException;
use CodeOwners\Parser;
use CodeOwners\Pattern;
use CodeOwners\SourceInfo;
use CodeOwners\Tests\Fixtures\FileOperations;
use PHPUnit\Framework\TestCase;

Expand Down Expand Up @@ -41,19 +42,60 @@ public function testParsingNonOpenableFileThrowsException()

public function testParsingResultsInPatterns()
{
$patterns = (new Parser())->parseFile(__DIR__ . '/Fixtures/CODEOWNERS.example');
$filename = __DIR__ . '/Fixtures/CODEOWNERS.example';
$patterns = (new Parser())->parseFile($filename);

$this->assertEquals([
new Pattern('*', ['@global-owner1', '@global-owner2']),
new Pattern('*.js', ['@js-owner']),
new Pattern('*.go', ['docs@example.com']),
new Pattern('/build/logs/', ['@doctocat']),
new Pattern('docs/*', ['docs@example.com']),
new Pattern('apps/', ['@octocat']),
new Pattern('/docs/', ['@doctocat']),
new Pattern('**/foo', ['@doctocat']),
new Pattern('abc/**', ['@doctocat']),
new Pattern('a/**/b', ['@doctocat']),
new Pattern(
'*',
['@global-owner1', '@global-owner2'],
new SourceInfo($filename, 10)
),
new Pattern(
'*.js',
['@js-owner'],
new SourceInfo($filename, 16)
),
new Pattern(
'*.go',
['docs@example.com'],
new SourceInfo($filename, 21)
),
new Pattern(
'/build/logs/',
['@doctocat'],
new SourceInfo($filename, 26)
),
new Pattern(
'docs/*',
['docs@example.com'],
new SourceInfo($filename, 31)
),
new Pattern(
'apps/',
['@octocat'],
new SourceInfo($filename, 35)
),
new Pattern(
'/docs/',
['@doctocat'],
new SourceInfo($filename, 39)
),
new Pattern(
'**/foo',
['@doctocat'],
new SourceInfo($filename, 45)
),
new Pattern(
'abc/**',
['@doctocat'],
new SourceInfo($filename, 50)
),
new Pattern(
'a/**/b',
['@doctocat'],
new SourceInfo($filename, 55)
),
], $patterns);
}

Expand All @@ -62,16 +104,117 @@ public function testParsingStringResultsInPatterns()
$patterns = (new Parser())->parseString(file_get_contents(__DIR__ . '/Fixtures/CODEOWNERS.example'));

$this->assertEquals([
new Pattern('*', ['@global-owner1', '@global-owner2']),
new Pattern('*.js', ['@js-owner']),
new Pattern('*.go', ['docs@example.com']),
new Pattern('/build/logs/', ['@doctocat']),
new Pattern('docs/*', ['docs@example.com']),
new Pattern('apps/', ['@octocat']),
new Pattern('/docs/', ['@doctocat']),
new Pattern('**/foo', ['@doctocat']),
new Pattern('abc/**', ['@doctocat']),
new Pattern('a/**/b', ['@doctocat']),
new Pattern(
'*',
['@global-owner1', '@global-owner2'],
new SourceInfo('', 10)
),
new Pattern(
'*.js',
['@js-owner'],
new SourceInfo('', 16)
),
new Pattern(
'*.go',
['docs@example.com'],
new SourceInfo('', 21)
),
new Pattern(
'/build/logs/',
['@doctocat'],
new SourceInfo('', 26)
),
new Pattern(
'docs/*',
['docs@example.com'],
new SourceInfo(null, 31)
),
new Pattern(
'apps/',
['@octocat'],
new SourceInfo(null, 35)
),
new Pattern(
'/docs/',
['@doctocat'],
new SourceInfo(null, 39)
),
new Pattern(
'**/foo',
['@doctocat'],
new SourceInfo(null, 45)
),
new Pattern(
'abc/**',
['@doctocat'],
new SourceInfo(null, 50)
),
new Pattern(
'a/**/b',
['@doctocat'],
new SourceInfo(null, 55)
),
], $patterns);
}

public function testParsingStringWithOptionalFilename()
{
$patterns = (new Parser())->parseString(
file_get_contents(__DIR__ . '/Fixtures/CODEOWNERS.example'),
'anonymous'
);

$this->assertEquals([
new Pattern(
'*',
['@global-owner1', '@global-owner2'],
new SourceInfo('anonymous', 10)
),
new Pattern(
'*.js',
['@js-owner'],
new SourceInfo('anonymous', 16)
),
new Pattern(
'*.go',
['docs@example.com'],
new SourceInfo('anonymous', 21)
),
new Pattern(
'/build/logs/',
['@doctocat'],
new SourceInfo('anonymous', 26)
),
new Pattern(
'docs/*',
['docs@example.com'],
new SourceInfo('anonymous', 31)
),
new Pattern(
'apps/',
['@octocat'],
new SourceInfo('anonymous', 35)
),
new Pattern(
'/docs/',
['@doctocat'],
new SourceInfo('anonymous', 39)
),
new Pattern(
'**/foo',
['@doctocat'],
new SourceInfo('anonymous', 45)
),
new Pattern(
'abc/**',
['@doctocat'],
new SourceInfo('anonymous', 50)
),
new Pattern(
'a/**/b',
['@doctocat'],
new SourceInfo('anonymous', 55)
),
], $patterns);
}
}

0 comments on commit 3ce6451

Please sign in to comment.