Skip to content

Commit 6d168dc

Browse files
committed
chore: dto refactor and workflows
1 parent e46cd1a commit 6d168dc

13 files changed

+282
-52
lines changed

.github/workflows/checks.yml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
name: Formats
2+
3+
on: ['push', 'pull_request']
4+
5+
jobs:
6+
ci:
7+
runs-on: ${{ matrix.os }}
8+
9+
strategy:
10+
fail-fast: true
11+
matrix:
12+
os: [ubuntu-latest]
13+
php: [8.3]
14+
dependency-version: [prefer-lowest, prefer-stable]
15+
16+
name: Formats P${{ matrix.php }} - ${{ matrix.os }} - ${{ matrix.dependency-version }}
17+
18+
steps:
19+
20+
- name: Checkout
21+
uses: actions/checkout@v3
22+
23+
- name: Setup PHP
24+
uses: shivammathur/setup-php@v2
25+
with:
26+
php-version: ${{ matrix.php }}
27+
extensions: dom, mbstring, zip
28+
coverage: pcov
29+
30+
- name: Get Composer cache directory
31+
id: composer-cache
32+
shell: bash
33+
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
34+
35+
- name: Cache dependencies
36+
uses: actions/cache@v3
37+
with:
38+
path: ${{ steps.composer-cache.outputs.dir }}
39+
key: dependencies-php-${{ matrix.php }}-os-${{ matrix.os }}-version-${{ matrix.dependency-version }}-composer-${{ hashFiles('composer.json') }}
40+
restore-keys: dependencies-php-${{ matrix.php }}-os-${{ matrix.os }}-version-${{ matrix.dependency-version }}-composer-
41+
42+
- name: Install Composer dependencies
43+
run: composer update --${{ matrix.dependency-version }} --no-interaction --prefer-dist
44+
45+
- name: Coding Style Checks
46+
run: composer test:lint
47+
48+
- name: Type Checks
49+
run: composer test:types

.github/workflows/tests.yml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
name: Tests
2+
3+
on: ['push', 'pull_request']
4+
5+
jobs:
6+
ci:
7+
runs-on: ${{ matrix.os }}
8+
strategy:
9+
fail-fast: true
10+
matrix:
11+
os: [ubuntu-latest, macos-latest]
12+
php: ['8.3']
13+
dependency-version: [prefer-stable]
14+
15+
name: Tests P${{ matrix.php }} - ${{ matrix.os }} - ${{ matrix.dependency-version }}
16+
17+
steps:
18+
19+
- name: Checkout
20+
uses: actions/checkout@v3
21+
22+
- name: Setup PHP
23+
uses: shivammathur/setup-php@v2
24+
with:
25+
php-version: ${{ matrix.php }}
26+
extensions: dom, mbstring, zip
27+
coverage: none
28+
29+
- name: Get Composer cache directory
30+
id: composer-cache
31+
shell: bash
32+
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
33+
34+
- name: Cache dependencies
35+
uses: actions/cache@v3
36+
with:
37+
path: ${{ steps.composer-cache.outputs.dir }}
38+
key: dependencies-php-${{ matrix.php }}-os-${{ matrix.os }}-version-${{ matrix.dependency-version }}-composer-${{ hashFiles('composer.json') }}
39+
restore-keys: dependencies-php-${{ matrix.php }}-os-${{ matrix.os }}-version-${{ matrix.dependency-version }}-composer-
40+
41+
- name: Install Composer dependencies
42+
run: composer update --${{ matrix.dependency-version }} --no-interaction --prefer-dist
43+
44+
- name: Integration Tests
45+
run: php ./vendor/bin/pest

codemap.txt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
File: CodemapClassDto.php
2+
Class: Kauffinger\Codemap\Dto\CodemapClassDto
3+
public function __construct(): mixed
4+
public property $methods
5+
public property $properties
6+
7+
File: CodemapPropertyDto.php
8+
Class: Kauffinger\Codemap\Dto\CodemapPropertyDto
9+
public function __construct(): mixed
10+
11+
File: CodemapMethodDto.php
12+
Class: Kauffinger\Codemap\Dto\CodemapMethodDto
13+
public function __construct(): mixed
14+
15+
File: CodemapFileDto.php
16+
Class: Kauffinger\Codemap\Dto\CodemapFileDto
17+
public function __construct(): mixed
18+
public property $classes
19+
20+
File: TextCodemapFormatter.php
21+
Class: Kauffinger\Codemap\TextCodemapFormatter
22+
public function format(): string
23+
24+
File: CodemapCommand.php
25+
Class: Kauffinger\Codemap\CodemapCommand
26+
public function __invoke(): int
27+
28+
File: CodemapGenerator.php
29+
Class: Kauffinger\Codemap\CodemapGenerator
30+
public function generate(): array
31+
private function processFile(): array
32+
Class:
33+
public function enterNode(): mixed
34+
public property $classes
35+

phpstan.neon.dist

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
parameters:
2+
level: max
3+
paths:
4+
- src
5+
6+
reportUnmatchedIgnoredErrors: true

src/CodemapCommand.php

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ final class CodemapCommand
99
/**
1010
* Invokes the codemap command.
1111
*
12-
* @param array $args The command-line arguments (if any).
12+
* @param string[] $args The command-line arguments (if any).
1313
* @return int Exit code.
1414
*/
1515
public function __invoke(array $args): int
@@ -26,6 +26,7 @@ public function __invoke(array $args): int
2626
$outputFile = __DIR__.'/../codemap.txt';
2727

2828
$generator = new CodemapGenerator;
29+
/** @var array<string, Dto\CodemapFileDto> $allResults */
2930
$allResults = [];
3031

3132
foreach ($pathsToScan as $path) {
@@ -35,13 +36,17 @@ public function __invoke(array $args): int
3536
continue;
3637
}
3738

39+
// Each $results is array<string, CodemapFileDto>
3840
$results = $generator->generate($path);
39-
foreach ($results as $fileName => $data) {
40-
$allResults[$fileName] = $data;
41+
42+
// Merge them by filename
43+
foreach ($results as $fileName => $dto) {
44+
$allResults[$fileName] = $dto;
4145
}
4246
}
4347

4448
$formatter = new TextCodemapFormatter;
49+
// Now $allResults is array<string, CodemapFileDto>
4550
$output = $formatter->format($allResults);
4651

4752
file_put_contents($outputFile, $output);

src/CodemapGenerator.php

Lines changed: 49 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44

55
namespace Kauffinger\Codemap;
66

7+
use Kauffinger\Codemap\Dto\CodemapClassDto;
8+
use Kauffinger\Codemap\Dto\CodemapFileDto;
9+
use Kauffinger\Codemap\Dto\CodemapMethodDto;
10+
use Kauffinger\Codemap\Dto\CodemapPropertyDto;
711
use PhpParser\Error;
812
use PhpParser\Node;
913
use PhpParser\Node\Stmt\Class_;
@@ -16,16 +20,16 @@
1620
use PhpParser\PhpVersion;
1721
use RecursiveDirectoryIterator;
1822
use RecursiveIteratorIterator;
23+
use SplFileInfo;
1924

2025
final class CodemapGenerator
2126
{
2227
/**
2328
* Scans the provided path (directory or single file).
24-
* If it's a directory, it scans recursively for PHP files.
25-
* If it's a single file, it parses just that file.
29+
* If it's a directory, scans recursively for PHP files.
30+
* If it's a single file, parses just that file.
2631
*
27-
* @param string $path Directory or file to parse.
28-
* @return array Parsed structure of classes, methods, and properties.
32+
* @return array<string, CodemapFileDto> A map of fileName => codemap DTO
2933
*/
3034
public function generate(string $path): array
3135
{
@@ -46,6 +50,7 @@ public function generate(string $path): array
4650
$results = [];
4751
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path));
4852

53+
/** @var SplFileInfo $file */
4954
foreach ($iterator as $file) {
5055
if ($file->isDir()) {
5156
continue;
@@ -55,17 +60,19 @@ public function generate(string $path): array
5560
}
5661

5762
$parsed = $this->processFile($file->getRealPath());
58-
$results = array_merge($results, $parsed);
63+
// Merge results by file name
64+
foreach ($parsed as $fileName => $dto) {
65+
$results[$fileName] = $dto;
66+
}
5967
}
6068

6169
return $results;
6270
}
6371

6472
/**
65-
* Processes a single PHP file, returning codemap data.
73+
* Processes a single PHP file, returning codemap data in a DTO.
6674
*
67-
* @param string $filePath The file to parse.
68-
* @return array The codemap results for this file.
75+
* @return array<string, CodemapFileDto> The codemap results for this file
6976
*/
7077
private function processFile(string $filePath): array
7178
{
@@ -75,6 +82,9 @@ private function processFile(string $filePath): array
7582

7683
$parser = (new ParserFactory)->createForVersion(PhpVersion::getHostVersion());
7784
$code = file_get_contents($filePath);
85+
if ($code === false) {
86+
return [];
87+
}
7888

7989
try {
8090
$ast = $parser->parse($code);
@@ -85,20 +95,16 @@ private function processFile(string $filePath): array
8595
}
8696

8797
$fileName = basename($filePath);
88-
$results = [
89-
$fileName => ['classes' => []],
90-
];
9198

92-
// Create a NodeVisitor to track classes, methods, and properties
9399
$visitor = new class extends NodeVisitorAbstract
94100
{
101+
/* @phpstan-ignore-next-line */
95102
public array $classes = [];
96103

97104
private ?string $currentClassName = null;
98105

99106
public function enterNode(Node $node)
100107
{
101-
// Capture class names
102108
if ($node instanceof Class_) {
103109
$this->currentClassName = $node->namespacedName
104110
? $node->namespacedName->toString()
@@ -108,9 +114,7 @@ public function enterNode(Node $node)
108114
'methods' => [],
109115
'properties' => [],
110116
];
111-
}
112-
// Capture methods
113-
elseif ($node instanceof ClassMethod && $this->currentClassName !== null) {
117+
} elseif ($node instanceof ClassMethod && $this->currentClassName !== null) {
114118
$visibility = $node->isPublic()
115119
? 'public'
116120
: ($node->isProtected() ? 'protected' : 'private');
@@ -129,9 +133,7 @@ public function enterNode(Node $node)
129133
'name' => $node->name->toString(),
130134
'returnType' => $returnType,
131135
];
132-
}
133-
// Capture properties
134-
elseif ($node instanceof Property && $this->currentClassName !== null) {
136+
} elseif ($node instanceof Property && $this->currentClassName !== null) {
135137
$visibility = $node->isPublic()
136138
? 'public'
137139
: ($node->isProtected() ? 'protected' : 'private');
@@ -143,18 +145,41 @@ public function enterNode(Node $node)
143145
];
144146
}
145147
}
148+
149+
return null;
146150
}
147151
};
148152

149-
// Traverse the AST
150153
$traverser = new NodeTraverser;
151154
$traverser->addVisitor(new NameResolver);
152155
$traverser->addVisitor($visitor);
153-
$traverser->traverse($ast);
156+
$traverser->traverse((array) $ast);
157+
158+
// Convert arrays to typed DTOs
159+
$classes = [];
160+
foreach ($visitor->classes as $className => $classData) {
161+
$methods = [];
162+
foreach ($classData['methods'] as $methodData) {
163+
$methods[] = new CodemapMethodDto(
164+
$methodData['visibility'],
165+
$methodData['name'],
166+
$methodData['returnType']
167+
);
168+
}
154169

155-
// Store the gathered class info for this file
156-
$results[$fileName]['classes'] = $visitor->classes;
170+
$properties = [];
171+
foreach ($classData['properties'] as $propData) {
172+
$properties[] = new CodemapPropertyDto(
173+
$propData['visibility'],
174+
$propData['name']
175+
);
176+
}
157177

158-
return $results;
178+
$classes[$className] = new CodemapClassDto($methods, $properties);
179+
}
180+
181+
$dto = new CodemapFileDto($classes);
182+
183+
return [$fileName => $dto];
159184
}
160185
}

src/Dto/CodemapClassDto.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Kauffinger\Codemap\Dto;
6+
7+
final class CodemapClassDto
8+
{
9+
/**
10+
* @param CodemapMethodDto[] $methods
11+
* @param CodemapPropertyDto[] $properties
12+
*/
13+
public function __construct(public array $methods = [], public array $properties = []) {}
14+
}

src/Dto/CodemapFileDto.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Kauffinger\Codemap\Dto;
6+
7+
final class CodemapFileDto
8+
{
9+
/**
10+
* @param array<string, CodemapClassDto> $classes
11+
*/
12+
public function __construct(
13+
/**
14+
* Map of fully qualified class names => CodemapClassDto
15+
*/
16+
public array $classes = []
17+
) {}
18+
}

src/Dto/CodemapMethodDto.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Kauffinger\Codemap\Dto;
6+
7+
final class CodemapMethodDto
8+
{
9+
public function __construct(
10+
public string $visibility,
11+
public string $name,
12+
public string $returnType
13+
) {}
14+
}

0 commit comments

Comments
 (0)