Skip to content

Commit

Permalink
Output analysed files count & elapsed time (#32)
Browse files Browse the repository at this point in the history
  • Loading branch information
janedbal authored Oct 9, 2023
1 parent 838c03e commit 322993a
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 14 deletions.
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Check duplicate types:
vendor/bin/detect-collisions dir1 dir2 dir3 # relative to cwd
```

Example output:
Example error output:
```
Foo\NamespacedClass2 is defined 2 times:
> /tests/sample-collisions/file2.php
Expand All @@ -27,6 +27,16 @@ GlobalInterface1 is defined 2 times:
> /tests/sample-collisions/file2.php
```

Example success output:
```
OK (no name collision found)
* analysed files: 9867
* excluded files: 0
* elapsed time: 1.057 s
```

- Note the performance: **10 000 files takes few seconds**!

## Configuration:
If file named `collision-detector.json` is present within current working directory, its contents are taken as configuration options. Possible config options:
```json5
Expand Down
12 changes: 10 additions & 2 deletions bin/detect-collisions
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,12 @@ try {
}

$detector = new CollisionDetector($config);
$collisions = $detector->getCollidingTypes();

$startTime = microtime(true);
$result = $detector->getCollidingTypes();
$elapsedTime = microtime(true) - $startTime;

$collisions = $result->getCollisions();
} catch (FileParsingException | InvalidConfigException $e) {
$exit($e->getMessage());
}
Expand All @@ -82,7 +87,10 @@ foreach ($collisions as $name => $fileLines) {
}

if ($collisions === []) {
echo "OK: no name collision found". PHP_EOL;
echo "OK (no name collision found)". PHP_EOL;
echo " * analysed files: " . $result->getAnalysedFilesCount() . PHP_EOL;
echo " * excluded files: " . $result->getExcludedFilesCount() . PHP_EOL;
echo " * elapsed time: " . round($elapsedTime, 3) . ' s' . PHP_EOL;
}

echo PHP_EOL;
Expand Down
15 changes: 12 additions & 3 deletions src/CollisionDetector.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,21 +60,23 @@ public function __construct(DetectionConfig $config)
}

/**
* @return array<string, list<FileLine>>
* @throws FileParsingException
*/
public function getCollidingTypes(): array
public function getCollidingTypes(): DetectionResult
{
$groups = [
self::TYPE_GROUP_CLASS,
self::TYPE_GROUP_FUNCTION,
self::TYPE_GROUP_CONSTANT,
];
$types = [];
$filesAnalysed = 0;
$filesExcluded = 0;

foreach ($this->config->getScanPaths() as $scanPath) {
foreach ($this->listPhpFilesIn($scanPath) as $filePath) {
if ($this->isExcluded($filePath)) {
$filesExcluded++;
continue;
}

Expand All @@ -86,11 +88,14 @@ public function getCollidingTypes(): array
}
} catch (FileParsingException $e) {
if ($this->config->shouldIgnoreParseFailures()) {
$filesExcluded++;
continue;
}

throw $e;
}

$filesAnalysed++;
}
}

Expand All @@ -117,7 +122,11 @@ public function getCollidingTypes(): array
}
}

return $collidingTypes;
return new DetectionResult(
$filesAnalysed,
$filesExcluded,
$collidingTypes
);
}

private function stripCwdFromPath(string $path): string
Expand Down
51 changes: 51 additions & 0 deletions src/DetectionResult.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php declare(strict_types = 1);

namespace ShipMonk\NameCollision;

class DetectionResult
{

/**
* @var int
*/
private $analysedFilesCount;

/**
* @var int
*/
private $excludedFilesCount;

/**
* @var array<string, list<FileLine>>
*/
private $collisions;

/**
* @param array<string, list<FileLine>> $collisions
*/
public function __construct(int $analysedFilesCount, int $excludedFilesCount, array $collisions)
{
$this->analysedFilesCount = $analysedFilesCount;
$this->excludedFilesCount = $excludedFilesCount;
$this->collisions = $collisions;
}

public function getAnalysedFilesCount(): int
{
return $this->analysedFilesCount;
}

public function getExcludedFilesCount(): int
{
return $this->excludedFilesCount;
}

/**
* @return array<string, list<FileLine>>
*/
public function getCollisions(): array
{
return $this->collisions;
}

}
43 changes: 35 additions & 8 deletions tests/CollisionDetectorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ public function testBinScript(): void
{
$expectedNoDirectoryRegex = '~^ERROR: No directories provided, use e.g. `detect-collisions src tests` or setup scanPaths in~';
$expectedInvalidDirectoryRegex = '~^ERROR: Provided directory to scan ".*?nonsense" is not directory nor a file~';
$expectedSuccessWithConfigRegex = '~^Using config .*?' . PHP_EOL . PHP_EOL . 'OK: no name collision found~';
$expectedSuccessRegex = '~^OK: no name collision found~';
$expectedSuccessWithConfigRegex = '~^Using config .*?' . PHP_EOL . PHP_EOL . 'OK \(no name collision found\)~';
$expectedSuccessRegex = '~^OK \(no name collision found\)~';

$space = ' '; // bypass editorconfig checker
$expectedClasses = <<<EOF
Expand Down Expand Up @@ -85,7 +85,13 @@ public function testParseError(): void
* @param array<string, list<string>> $expectedResults
* @dataProvider provideCases
*/
public function testCollisionDetection(array $paths, array $excludedPaths, array $expectedResults): void
public function testCollisionDetection(
array $paths,
array $excludedPaths,
int $expectedAnalysedFiles,
int $expectedExcludedFiles,
array $expectedResults
): void
{
$detector = new CollisionDetector(
new DetectionConfig(
Expand All @@ -95,12 +101,11 @@ public function testCollisionDetection(array $paths, array $excludedPaths, array
__DIR__
)
);
$collidingClasses = $detector->getCollidingTypes();
$result = $detector->getCollidingTypes();

self::assertEquals(
$expectedResults,
$collidingClasses
);
self::assertSame($expectedAnalysedFiles, $result->getAnalysedFilesCount());
self::assertSame($expectedExcludedFiles, $result->getExcludedFilesCount());
self::assertEquals($expectedResults, $result->getCollisions());
}

private function runCommand(string $command, int $expectedExitCode): string
Expand Down Expand Up @@ -143,18 +148,24 @@ public function provideCases(): iterable
yield 'allowed duplicates' => [
'paths' => [__DIR__ . '/data/allowed-duplicates'],
'excludedPaths' => [],
'expectedAnalysedFiles' => 1,
'expectedExcludedFiles' => 0,
'expectedResults' => [],
];

yield 'use statements' => [
'paths' => [__DIR__ . '/data/use-statement'], // basically tests that isWithinUseStatement is working properly
'excludedPaths' => [],
'expectedAnalysedFiles' => 3,
'expectedExcludedFiles' => 0,
'expectedResults' => [],
];

yield 'simple cases' => [
'paths' => [__DIR__ . '/data/basic-cases/simple.php'],
'excludedPaths' => [],
'expectedAnalysedFiles' => 1,
'expectedExcludedFiles' => 0,
'expectedResults' => [
'DuplicateClass' => [
new FileLine('/data/basic-cases/simple.php', 3),
Expand All @@ -174,6 +185,8 @@ public function provideCases(): iterable
yield 'html case' => [
'paths' => [__DIR__ . '/data/basic-cases/html.php'],
'excludedPaths' => [],
'expectedAnalysedFiles' => 1,
'expectedExcludedFiles' => 0,
'expectedResults' => [
'Bar' => [
new FileLine('/data/basic-cases/html.php', 3),
Expand All @@ -185,6 +198,8 @@ public function provideCases(): iterable
yield 'fatal error' => [
'paths' => [__DIR__ . '/data/fatal-error/code.php'],
'excludedPaths' => [],
'expectedAnalysedFiles' => 1,
'expectedExcludedFiles' => 0,
'expectedResults' => [
'Exists' => [
new FileLine('/data/fatal-error/code.php', 6),
Expand All @@ -196,6 +211,8 @@ public function provideCases(): iterable
yield 'groups' => [
'paths' => [__DIR__ . '/data/basic-cases/groups.php'],
'excludedPaths' => [],
'expectedAnalysedFiles' => 1,
'expectedExcludedFiles' => 0,
'expectedResults' => [
'Go' => [
new FileLine('/data/basic-cases/groups.php', 3),
Expand All @@ -209,6 +226,8 @@ public function provideCases(): iterable
yield 'groups with enum' => [
'paths' => [__DIR__ . '/data/basic-cases/groups-with-enum.php'],
'excludedPaths' => [],
'expectedAnalysedFiles' => 1,
'expectedExcludedFiles' => 0,
'expectedResults' => [
'Go' => [
new FileLine('/data/basic-cases/groups-with-enum.php', 3),
Expand All @@ -223,6 +242,8 @@ public function provideCases(): iterable
yield 'multi namespace' => [
'paths' => [__DIR__ . '/data/basic-cases/multiple-namespaces.php'],
'excludedPaths' => [],
'expectedAnalysedFiles' => 1,
'expectedExcludedFiles' => 0,
'expectedResults' => [
'Foo\X' => [
new FileLine('/data/basic-cases/multiple-namespaces.php', 5),
Expand All @@ -234,6 +255,8 @@ public function provideCases(): iterable
yield 'multi namespace braced' => [
'paths' => [__DIR__ . '/data/basic-cases/multiple-namespaces-braced.php'],
'excludedPaths' => [],
'expectedAnalysedFiles' => 1,
'expectedExcludedFiles' => 0,
'expectedResults' => [
'Foo\X' => [
new FileLine('/data/basic-cases/multiple-namespaces-braced.php', 4),
Expand All @@ -245,6 +268,8 @@ public function provideCases(): iterable
yield 'more files' => [
'paths' => [__DIR__ . '/data/multiple-files'],
'excludedPaths' => [],
'expectedAnalysedFiles' => 5,
'expectedExcludedFiles' => 0,
'expectedResults' => [
'Foo\NamespacedClass' => [
new FileLine('/data/multiple-files/colliding1.php', 11),
Expand Down Expand Up @@ -276,6 +301,8 @@ public function provideCases(): iterable
yield 'more files with exclude' => [
'paths' => [__DIR__ . '/data/multiple-files'],
'excludedPaths' => [__DIR__ . '/data/multiple-files/colliding3.php'],
'expectedAnalysedFiles' => 4,
'expectedExcludedFiles' => 1,
'expectedResults' => [
'GlobalClass' => [
new FileLine('/data/multiple-files/colliding1.php', 4),
Expand Down

0 comments on commit 322993a

Please sign in to comment.