Skip to content

Commit efc3a7a

Browse files
committed
Chorale cleanup
1 parent 27d6b32 commit efc3a7a

File tree

4 files changed

+61
-57
lines changed

4 files changed

+61
-57
lines changed

tools/chorale/AGENTS.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@ Chorale is a CLI tool maintained in this repository.
66
- Add unit tests for new features in `src/Tests`.
77
- Run `composer install` and `./vendor/bin/phpunit` in this directory before committing changes.
88

9+
### Notes for Docblocks and Examples
10+
11+
- When documenting glob patterns inside PHP block comments, avoid using the exact sequence `*/` which terminates the comment. Prefer escaping as `*\/` (e.g., `src/*\/Lib`), or insert a space, to keep examples readable and parsable.
12+
913
## Roadmap
1014

1115
- Implement executors for remaining plan steps such as composer root rebuild and metadata sync.
1216
- Improve conflict resolution strategies for dependency merges.
1317
- Enhance documentation with more real-world examples as features grow.
14-

tools/chorale/src/Discovery/PatternMatcher.php

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
* Uses PathUtils::match to support '*', '?', and '**' semantics.
1212
*
1313
* Example:
14-
* - firstMatch([{match:'src/* /Lib'}], 'src/Acme/Lib') => 0
15-
* - allMatches([{match:'src/* /Lib'},{match:'src/Acme/*'}], 'src/Acme/Lib') => [0,1]
14+
* - firstMatch([{match:'src/*\/Lib'}], 'src/Acme/Lib') => 0
15+
* - allMatches([{match:'src/*\/Lib'},{match:'src/Acme/*'}], 'src/Acme/Lib') => [0,1]
1616
*/
1717
final readonly class PatternMatcher implements PatternMatcherInterface
1818
{
@@ -22,10 +22,10 @@ public function __construct(
2222

2323
public function firstMatch(array $patterns, string $path): ?int
2424
{
25-
foreach ($patterns as $i => $p) {
26-
$m = (string) ($p['match'] ?? '');
27-
if ($m !== '' && $this->paths->match($m, $path)) {
28-
return (int) $i;
25+
foreach ($patterns as $index => $patternEntry) {
26+
$patternString = (string) ($patternEntry['match'] ?? '');
27+
if ($patternString !== '' && $this->paths->match($patternString, $path)) {
28+
return (int) $index;
2929
}
3030
}
3131

@@ -34,14 +34,14 @@ public function firstMatch(array $patterns, string $path): ?int
3434

3535
public function allMatches(array $patterns, string $path): array
3636
{
37-
$hits = [];
38-
foreach ($patterns as $i => $p) {
39-
$pattern = (string) ($p['match'] ?? '');
40-
if ($pattern !== '' && $this->paths->match($pattern, $path)) {
41-
$hits[] = (int) $i;
37+
$matchIndexes = [];
38+
foreach ($patterns as $index => $patternEntry) {
39+
$patternString = (string) ($patternEntry['match'] ?? '');
40+
if ($patternString !== '' && $this->paths->match($patternString, $path)) {
41+
$matchIndexes[] = (int) $index;
4242
}
4343
}
4444

45-
return $hits;
45+
return $matchIndexes;
4646
}
4747
}

tools/chorale/src/Util/PathUtils.php

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -10,83 +10,84 @@
1010
* Examples:
1111
* - normalize('src//Foo/./Bar/..') => 'src/Foo'
1212
* - isUnder('src/Acme/Lib', 'src') => true
13-
* - match('src/* /Lib', 'src/Acme/Lib') => true (single-star within one segment)
14-
* - match('src/** /Lib', 'src/a/b/c/Lib') => true (double-star across directories)
13+
* - match('src/*\/Lib', 'src/Acme/Lib') => true (single-star within one segment)
14+
* - match('src/**\/Lib', 'src/a/b/c/Lib') => true (double-star across directories)
1515
* - leaf('src/Acme/Lib') => 'Lib'
1616
*/
1717
final class PathUtils implements PathUtilsInterface
1818
{
1919
public function normalize(string $path): string
2020
{
21-
$p = str_replace('\\', '/', $path);
21+
$normalizedPath = str_replace('\\', '/', $path);
2222
// remove multiple slashes
23-
$p = preg_replace('#/+#', '/', $p) ?? $p;
23+
$normalizedPath = preg_replace('#/+#', '/', $normalizedPath) ?? $normalizedPath;
2424
// remove trailing slash (except root '/')
25-
if ($p !== '/' && str_ends_with($p, '/')) {
26-
$p = rtrim($p, '/');
25+
if ($normalizedPath !== '/' && str_ends_with($normalizedPath, '/')) {
26+
$normalizedPath = rtrim($normalizedPath, '/');
2727
}
2828

2929
// resolve "." and ".." cheaply (string-level, not FS)
30-
$parts = [];
31-
foreach (explode('/', $p) as $seg) {
32-
if ($seg === '') {
30+
$resolvedSegments = [];
31+
foreach (explode('/', $normalizedPath) as $segment) {
32+
if ($segment === '') {
3333
continue;
3434
}
35-
if ($seg === '.') {
35+
36+
if ($segment === '.') {
3637
continue;
3738
}
3839

39-
if ($seg === '..') {
40-
array_pop($parts);
40+
if ($segment === '..') {
41+
array_pop($resolvedSegments);
4142
continue;
4243
}
4344

44-
$parts[] = $seg;
45+
$resolvedSegments[] = $segment;
4546
}
4647

47-
$out = implode('/', $parts);
48+
$out = implode('/', $resolvedSegments);
4849
return $out === '' ? '.' : $out;
4950
}
5051

5152
public function isUnder(string $path, string $root): bool
5253
{
53-
$p = $this->normalize($path);
54-
$r = $this->normalize($root);
55-
return $p === $r || str_starts_with($p, $r . '/');
54+
$normalizedPath = $this->normalize($path);
55+
$normalizedRoot = $this->normalize($root);
56+
return $normalizedPath === $normalizedRoot || str_starts_with($normalizedPath, $normalizedRoot . '/');
5657
}
5758

5859
public function match(string $pattern, string $path): bool
5960
{
60-
$pat = $this->normalize($pattern);
61-
$pth = $this->normalize($path);
61+
$normalizedPattern = $this->normalize($pattern);
62+
$normalizedPath = $this->normalize($path);
6263

6364
// Split into tokens while keeping the delimiters (** , * , ?)
64-
$parts = preg_split('/(\*\*|\*|\?)/', $pat, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
65-
if ($parts === false) {
65+
$tokens = preg_split('/(\*\*|\*|\?)/', $normalizedPattern, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
66+
if ($tokens === false) {
6667
return false;
6768
}
6869

6970
$regex = '';
70-
foreach ($parts as $part) {
71-
if ($part === '**') {
71+
foreach ($tokens as $token) {
72+
if ($token === '**') {
7273
$regex .= '.*'; // can cross slashes, zero or more
73-
} elseif ($part === '*') {
74+
} elseif ($token === '*') {
7475
$regex .= '[^/]*'; // single segment
75-
} elseif ($part === '?') {
76+
} elseif ($token === '?') {
7677
$regex .= '[^/]'; // one char in a segment
7778
} else {
78-
$regex .= preg_quote($part, '#'); // literal
79+
$regex .= preg_quote($token, '#'); // literal
7980
}
8081
}
8182

8283
// full-string, case-sensitive; add 'i' if you want case-insensitive
83-
return (bool) preg_match('#^' . $regex . '$#u', $pth);
84+
return (bool) preg_match('#^' . $regex . '$#u', $normalizedPath);
8485
}
8586

8687
public function leaf(string $path): string
8788
{
88-
$p = $this->normalize($path);
89-
$pos = strrpos($p, '/');
90-
return $pos === false ? $p : substr($p, $pos + 1);
89+
$normalizedPath = $this->normalize($path);
90+
$pos = strrpos($normalizedPath, '/');
91+
return $pos === false ? $normalizedPath : substr($normalizedPath, $pos + 1);
9192
}
9293
}

tools/chorale/src/Util/Sorting.php

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,16 @@ final class Sorting implements SortingInterface
1616
public function sortPatterns(array $patterns): array
1717
{
1818
usort($patterns, static function (array $a, array $b): int {
19-
$am = (string) ($a['match'] ?? '');
20-
$bm = (string) ($b['match'] ?? '');
21-
$al = strlen($am);
22-
$bl = strlen($bm);
23-
if ($al === $bl) {
24-
return $am <=> $bm;
19+
$matchA = (string) ($a['match'] ?? '');
20+
$matchB = (string) ($b['match'] ?? '');
21+
$lenA = strlen($matchA);
22+
$lenB = strlen($matchB);
23+
if ($lenA === $lenB) {
24+
return $matchA <=> $matchB;
2525
}
2626

2727
// longer match first (more specific wins)
28-
return $bl <=> $al;
28+
return $lenB <=> $lenA;
2929
});
3030

3131
return $patterns;
@@ -34,15 +34,15 @@ public function sortPatterns(array $patterns): array
3434
public function sortTargets(array $targets): array
3535
{
3636
usort($targets, static function (array $a, array $b): int {
37-
$ap = (string) ($a['path'] ?? '');
38-
$bp = (string) ($b['path'] ?? '');
39-
if ($ap === $bp) {
40-
$an = (string) ($a['name'] ?? '');
41-
$bn = (string) ($b['name'] ?? '');
42-
return $an <=> $bn;
37+
$pathA = (string) ($a['path'] ?? '');
38+
$pathB = (string) ($b['path'] ?? '');
39+
if ($pathA === $pathB) {
40+
$nameA = (string) ($a['name'] ?? '');
41+
$nameB = (string) ($b['name'] ?? '');
42+
return $nameA <=> $nameB;
4343
}
4444

45-
return $ap <=> $bp;
45+
return $pathA <=> $pathB;
4646
});
4747

4848
return $targets;

0 commit comments

Comments
 (0)