Skip to content

Commit 85c7529

Browse files
committed
test: cover CakePHP extension rules
1 parent cf40fe8 commit 85c7529

20 files changed

Lines changed: 345 additions & 25 deletions

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ composer require --dev josbeir/cakephp-mago-rules carthage-software/mago
1919
Import the preset from the project's `mago.toml`:
2020

2121
```toml
22-
extends = "vendor/josbeir/cakephp-mago-rules/mago.cakephp.toml"
22+
extends = "vendor/josbeir/cakephp-mago-rules/cakephp.mago.toml"
2323
```
2424

2525
The imported configuration starts the package-owned extension worker. No
@@ -57,7 +57,7 @@ cyclomatic-complexity = { enabled = false }
5757
| PSR-12 layout, braces, imports, quotes, commas, casts and return spacing | Mago formatter with CakePHP settings |
5858
| Short arrays, braced blocks, short tags, silenced errors, assignments in conditions and redundant syntax | Native Mago rules |
5959
| Trait `Trait` suffix | `mago-cakephp/trait-suffix` |
60-
| Public method underscore prefix | `mago-cakephp/public-method-underscore` |
60+
| Method underscore prefixes, with Entity accessor/mutator exceptions | `mago-cakephp/public-method-underscore` |
6161
| `elseif` spelling | `mago-cakephp/elseif` |
6262
| Function and method docblocks outside tests | `mago-cakephp/function-docblock` |
6363
| One space after PHPDoc tags | `mago-cakephp/docblock-tag-spacing` |
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Import this file from a project's mago.toml with:
2-
# extends = "vendor/josbeir/cakephp-mago-rules/mago.cakephp.toml"
2+
# extends = "vendor/josbeir/cakephp-mago-rules/cakephp.mago.toml"
33

44
[extension-hosts.cakephp]
55
command = ["php", "vendor/josbeir/cakephp-mago-rules/bin/mago-cakephp-worker"]

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"carthage-software/mago": "^1.47"
99
},
1010
"require-dev": {
11-
"phpunit/phpunit": "^10.5 || ^11.0"
11+
"phpunit/phpunit": "^13.0"
1212
},
1313
"autoload": {
1414
"psr-4": {

mago.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
extends = "mago.cakephp.toml"
1+
extends = "cakephp.mago.toml"
22

33
[source]
44
paths = ["src", "tests/Unit"]

scripts/check-fixes.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ cp "$repo_root/tests/consumer/mago.toml" "$fixture_dir/mago.toml"
1515
ln -s "$repo_root" "$fixture_dir/vendor/josbeir/cakephp-mago-rules"
1616

1717
"$repo_root/vendor/bin/mago" --workspace "$fixture_dir" lint --fix --format-after-fix --fail-on-remaining --only \
18-
mago-cakephp/elseif,mago-cakephp/docblock-tag-spacing
18+
mago-cakephp/elseif,mago-cakephp/docblock-tag-spacing,mago-cakephp/inherit-doc
1919

2020
"$repo_root/vendor/bin/mago" --workspace "$fixture_dir" lint --fix --format-after-fix --fail-on-remaining --only \
21-
mago-cakephp/elseif,mago-cakephp/docblock-tag-spacing
21+
mago-cakephp/elseif,mago-cakephp/docblock-tag-spacing,mago-cakephp/inherit-doc
2222

2323
diff -u "$repo_root/tests/fixer/expected.php" "$fixture_dir/src/Rules.php"

src/Linter/Rules/InheritDocRule.php

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,18 @@ public function lint(LintContext $context): void
4444
$docblock->span->start + $match[0][1],
4545
$docblock->span->start + $match[0][1] + strlen($match[0][0]),
4646
);
47-
if ($match[0][0] !== '@inheritDoc') {
47+
$content = $docblock->content();
48+
if (strcasecmp($content, '{@inheritDoc}') === 0) {
49+
$wrappedSpan = new Span($span->start - 1, $span->end + 1);
4850
$context->report(Issue::new(
49-
'@inheritDoc must use CakePHP capitalization.',
50-
$span,
51-
)->withEdit(TextEdit::replace($span, '@inheritDoc')));
51+
'Use @inheritDoc when inheriting the complete docblock.',
52+
$wrappedSpan,
53+
)->withEdit(TextEdit::replace($wrappedSpan, '@inheritDoc')));
5254
continue;
5355
}
54-
$content = $docblock->content();
55-
if ($content === '{@inheritDoc}') {
56+
if ($match[0][0] !== '@inheritDoc') {
5657
$context->report(Issue::new(
57-
'Use @inheritDoc when inheriting the complete docblock.',
58+
'@inheritDoc must use CakePHP capitalization.',
5859
$span,
5960
)->withEdit(TextEdit::replace($span, '@inheritDoc')));
6061
continue;

src/Linter/Rules/PublicUnderscoreMethodRule.php

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ public function getDefinition(): RuleDefinition
2020
{
2121
return new RuleDefinition(
2222
code: 'mago-cakephp/public-method-underscore',
23-
name: 'CakePHP public method naming',
24-
description: 'Disallows an underscore prefix on public non-magic methods.',
23+
name: 'CakePHP method naming',
24+
description: 'Disallows underscore-prefixed methods except CakePHP entity accessors and mutators.',
2525
defaultLevel: Level::Error,
2626
defaultEnabled: true,
2727
targets: [NodeKind::Method],
@@ -33,21 +33,20 @@ public function getDefinition(): RuleDefinition
3333
*/
3434
public function lint(LintContext $context): void
3535
{
36-
$isPublic = false;
36+
$isPublic = true;
3737
foreach ($context->getChildren() as $child) {
3838
if ($child->kind !== NodeKind::Modifier) {
3939
continue;
4040
}
41-
if (strtolower($context->file->getText($child)) !== 'public') {
41+
42+
$modifier = strtolower($context->file->getText($child));
43+
if (!in_array($modifier, ['public', 'protected', 'private'], strict: true)) {
4244
continue;
4345
}
4446

45-
$isPublic = true;
47+
$isPublic = $modifier === 'public';
4648
break;
4749
}
48-
if (!$isPublic) {
49-
return;
50-
}
5150

5251
$nameNode = $context->file->getFirstDescendant(
5352
$context->node,
@@ -81,8 +80,14 @@ public function lint(LintContext $context): void
8180
return;
8281
}
8382

83+
if (!$isPublic && preg_match('/^_(?:get|set)[A-Z]/', $name) === 1) {
84+
return;
85+
}
86+
8487
$context->report(Issue::new(
85-
sprintf('Public method name "%s" must not be prefixed with underscore.', $name),
88+
$isPublic
89+
? sprintf('Public method name "%s" must not be prefixed with underscore.', $name)
90+
: sprintf('Non-public method name "%s" should not be prefixed with underscore.', $name),
8691
$nameNode->span,
8792
));
8893
}

tests/Unit/RuleIntegrationTest.php

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace MagoCakePHP\Tests\Unit;
6+
7+
use PHPUnit\Framework\Attributes\DataProvider;
8+
use PHPUnit\Framework\TestCase;
9+
10+
final class RuleIntegrationTest extends TestCase
11+
{
12+
/**
13+
* @return iterable<string, array{string, list<string>}>
14+
*/
15+
public static function rules(): iterable
16+
{
17+
yield 'trait suffix' => ['mago-cakephp/trait-suffix', ['rules/TraitSuffix.php']];
18+
yield 'method underscore' => ['mago-cakephp/public-method-underscore', ['rules/PublicMethodUnderscore.php']];
19+
yield 'elseif' => ['mago-cakephp/elseif', ['rules/ElseIf.php']];
20+
yield 'function docblock' => [
21+
'mago-cakephp/function-docblock',
22+
['rules/FunctionDocblock.php', 'rules/tests/FunctionDocblockTest.php'],
23+
];
24+
yield 'docblock tag spacing' => ['mago-cakephp/docblock-tag-spacing', ['rules/DocblockTagSpacing.php']];
25+
yield 'throws tag' => ['mago-cakephp/throws-tag', ['rules/ThrowsTag.php']];
26+
yield 'inheritDoc' => ['mago-cakephp/inherit-doc', ['rules/InheritDoc.php']];
27+
}
28+
29+
/**
30+
* Runs a rule through Mago's parser and extension protocol.
31+
*
32+
* @param list<string> $fixtures
33+
*/
34+
#[DataProvider('rules')]
35+
public function testRuleFixtures(string $rule, array $fixtures): void
36+
{
37+
$root = dirname(path: __DIR__, levels: 2);
38+
$command = [
39+
$root . '/vendor/bin/mago',
40+
'--workspace',
41+
$root . '/tests/corpus',
42+
'lint',
43+
'--only',
44+
$rule,
45+
'--reporting-format',
46+
'short',
47+
...$fixtures,
48+
];
49+
$pipes = [];
50+
$process = proc_open(
51+
$command,
52+
[1 => ['pipe', 'w'], 2 => ['pipe', 'w']],
53+
$pipes,
54+
$root,
55+
);
56+
57+
self::assertIsResource($process);
58+
$output = stream_get_contents($pipes[1]) . stream_get_contents($pipes[2]);
59+
fclose($pipes[1]);
60+
fclose($pipes[2]);
61+
62+
self::assertSame(0, proc_close($process), $output);
63+
}
64+
}

tests/consumer/mago.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
version = "1.47"
22
php-version = "8.4"
3-
extends = "vendor/josbeir/cakephp-mago-rules/mago.cakephp.toml"
3+
extends = "vendor/josbeir/cakephp-mago-rules/cakephp.mago.toml"
44

55
[source]
66
paths = ["src", "tests"]
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
final class DocblockTagSpacing
6+
{
7+
// @mago-expect lint:mago-cakephp/docblock-tag-spacing
8+
/**
9+
* @param string $value
10+
* @return string
11+
*/
12+
public function doubledSpace(string $value): string
13+
{
14+
return $value;
15+
}
16+
17+
// @mago-expect lint:mago-cakephp/docblock-tag-spacing
18+
/**
19+
* @return string
20+
*/
21+
public function tab(): string
22+
{
23+
return 'value';
24+
}
25+
26+
/**
27+
* @deprecated
28+
*/
29+
public function tagWithoutValue(): void
30+
{
31+
}
32+
}

0 commit comments

Comments
 (0)