Skip to content

Commit 0e1ab34

Browse files
committed
Allow configuration with namespace aliases
1 parent 9d82d4a commit 0e1ab34

10 files changed

Lines changed: 364 additions & 227 deletions

SlevomatCodingStandard/Sniffs/Namespaces/ReferenceUsedNamesOnlySniff.php

Lines changed: 247 additions & 209 deletions
Large diffs are not rendered by default.

doc/namespaces.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,8 @@ Sniff provides the following settings:
129129
* `allowFallbackGlobalFunctions`: allows using global functions via fallback name without `use` (i.e. `phpversion()`).
130130
* `allowFallbackGlobalConstants`: allows using global constants via fallback name without `use` (i.e. `PHP_VERSION`).
131131
* `allowPartialUses` (default: `true`): allows using and referencing whole namespaces unless a more specific namespace rule applies.
132-
* `namespacesAllowedToUsePartially`: if set, only namespaces in this list may be referenced partially. The match uses namespace prefixes, so subnamespaces are covered as well. Useful when a codebase uses partial references for selected packages such as Doctrine ORM or Symfony Validator.
133-
* `namespacesRequiredToUsePartially`: namespaces in this list must be referenced partially, again matching by namespace prefix.
132+
* `namespacesAllowedToUsePartially`: if set, only namespaces in this list may be referenced partially. Use `Namespace\Name as Alias` when you want to require a specific alias like `use Some\SubNamespace as SubNamespace;`.
133+
* `namespacesRequiredToUsePartially`: namespaces in this list must be referenced partially. The same `Namespace\Name as Alias` syntax applies when you want to enforce a concrete alias.
134134
* `allowWhenNoNamespace` (default: `true`): force even when there's no namespace in the file.
135135

136136
#### SlevomatCodingStandard.Namespaces.UseDoesNotStartWithBackslash 🔧

tests/Helpers/NamespaceHelperTest.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,4 +418,15 @@ public function testParseNamespaceWithAlias(string $setting, string $namespace,
418418
], NamespaceHelper::parseNamespaceWithAlias($setting));
419419
}
420420

421+
public function testParseEmptyNamespaceWithAlias(): void
422+
{
423+
self::assertSame(
424+
[
425+
'namespace' => '',
426+
'alias' => '',
427+
],
428+
NamespaceHelper::parseNamespaceWithAlias(' '),
429+
);
430+
}
431+
421432
}

tests/Sniffs/Namespaces/ReferenceUsedNamesOnlySniffTest.php

Lines changed: 69 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -350,18 +350,38 @@ public function testAllowPartialUsesOnlyForConfiguredNamespaces(): void
350350
[
351351
'allowPartialUses' => false,
352352
'namespacesAllowedToUsePartially' => [
353-
'Doctrine\ORM',
354-
'Symfony\Component\Validator\Constraints',
353+
'Some\SubNamespace as SubNamespace',
354+
],
355+
],
356+
);
357+
358+
self::assertSame(1, $report->getErrorCount());
359+
self::assertSniffError(
360+
$report,
361+
17,
362+
ReferenceUsedNamesOnlySniff::CODE_PARTIAL_USE,
363+
'Partial use statements are not allowed except for Some\SubNamespace as SubNamespace, but referencing SomeFramework\\ObjectPrototype found.',
364+
);
365+
}
366+
367+
public function testAllowPartialUsesOnlyForConfiguredNamespacesWithoutAlias(): void
368+
{
369+
$report = self::checkFile(
370+
__DIR__ . '/data/partialUsesAllowedNamespaces.php',
371+
[
372+
'allowPartialUses' => false,
373+
'namespacesAllowedToUsePartially' => [
374+
'Some\SubNamespace',
355375
],
356376
],
357377
);
358378

359379
self::assertSame(1, $report->getErrorCount());
360380
self::assertSniffError(
361381
$report,
362-
18,
382+
17,
363383
ReferenceUsedNamesOnlySniff::CODE_PARTIAL_USE,
364-
'Partial use statements are not allowed except for Doctrine\ORM, Symfony\Component\Validator\Constraints, but referencing SomeFramework\\ObjectPrototype found.',
384+
'Partial use statements are not allowed except for Some\SubNamespace, but referencing SomeFramework\\ObjectPrototype found.',
365385
);
366386
}
367387

@@ -1336,7 +1356,7 @@ public function testRequirePartialUsesForConfiguredNamespaces(): void
13361356
'searchAnnotations' => true,
13371357
'allowPartialUses' => false,
13381358
'namespacesRequiredToUsePartially' => [
1339-
'Some\\SubNamespace',
1359+
'Some\\SubNamespace as SubNamespace',
13401360
],
13411361
],
13421362
);
@@ -1347,6 +1367,30 @@ public function testRequirePartialUsesForConfiguredNamespaces(): void
13471367
self::assertAllFixedInFile($report);
13481368
}
13491369

1370+
public function testRequirePartialUsesAllowedForConfiguredAlias(): void
1371+
{
1372+
$report = self::checkFile(
1373+
__DIR__ . '/data/partialUsesAllowedNamespaces.php',
1374+
[
1375+
'allowPartialUses' => false,
1376+
'namespacesAllowedToUsePartially' => [
1377+
'Some\SubNamespace as SubNamespace',
1378+
],
1379+
'namespacesRequiredToUsePartially' => [
1380+
'Some\SubNamespace as SubNamespace',
1381+
],
1382+
],
1383+
);
1384+
1385+
self::assertSame(1, $report->getErrorCount());
1386+
self::assertSniffError(
1387+
$report,
1388+
17,
1389+
ReferenceUsedNamesOnlySniff::CODE_PARTIAL_USE,
1390+
'Partial use statements are not allowed except for Some\SubNamespace as SubNamespace, but referencing SomeFramework\\ObjectPrototype found.',
1391+
);
1392+
}
1393+
13501394
public function testRequirePartialUsesSkipsNonMatchingNamespaces(): void
13511395
{
13521396
$report = self::checkFile(
@@ -1355,8 +1399,8 @@ public function testRequirePartialUsesSkipsNonMatchingNamespaces(): void
13551399
'searchAnnotations' => true,
13561400
'allowPartialUses' => false,
13571401
'namespacesRequiredToUsePartially' => [
1358-
'Other\\Namespace',
1359-
'Some\\SubNamespace',
1402+
'Other\\Namespace as OtherNamespace',
1403+
'Some\\SubNamespace as SubNamespace',
13601404
],
13611405
],
13621406
);
@@ -1384,6 +1428,24 @@ public function testRequirePartialUsesForExactNamespace(): void
13841428
self::assertAllFixedInFile($report);
13851429
}
13861430

1431+
public function testRequirePartialUsesForConfiguredAlias(): void
1432+
{
1433+
$report = self::checkFile(
1434+
__DIR__ . '/data/referenceUsedNamesOnlyWithRequiredPartialAlias.php',
1435+
[
1436+
'allowPartialUses' => false,
1437+
'namespacesRequiredToUsePartially' => [
1438+
'Some\SubNamespace as SubNamespace',
1439+
],
1440+
],
1441+
);
1442+
1443+
self::assertSame(2, $report->getErrorCount());
1444+
self::assertSniffError($report, 10, ReferenceUsedNamesOnlySniff::CODE_REFERENCE_VIA_FULLY_QUALIFIED_NAME);
1445+
self::assertSniffError($report, 11, ReferenceUsedNamesOnlySniff::CODE_REFERENCE_VIA_FULLY_QUALIFIED_NAME);
1446+
self::assertAllFixedInFile($report);
1447+
}
1448+
13871449
public function testReservedWord(): void
13881450
{
13891451
$report = self::checkFile(__DIR__ . '/data/referenceUsedNamesReservedWord.php');

tests/Sniffs/Namespaces/data/partialUsesAllowedNamespaces.php

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,18 @@
22

33
namespace Whatever;
44

5-
use Doctrine\ORM as ORM;
5+
use Some\SubNamespace as SubNamespace;
66
use SomeFramework;
7-
use Symfony\Component\Validator\Constraints as Assert;
87

98
class Foo
109
{
1110

12-
#[ORM\Entity]
13-
#[Assert\Choice(['fiction', 'non-fiction'])]
11+
#[SubNamespace\A]
12+
#[SubNamespace\B]
1413
public function test(): void
1514
{
16-
new ORM\Table();
17-
new Assert\NotBlank();
15+
new SubNamespace\A();
16+
new SubNamespace\B();
1817
new SomeFramework\ObjectPrototype();
1918
}
2019
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace Whatever;
4+
use Some\SubNamespace as SubNamespace;
5+
6+
class Foo
7+
{
8+
9+
public function test(): void
10+
{
11+
new SubNamespace\A();
12+
new SubNamespace\B();
13+
}
14+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace Whatever;
4+
5+
class Foo
6+
{
7+
8+
public function test(): void
9+
{
10+
new \Some\SubNamespace\A();
11+
new \Some\SubNamespace\B();
12+
}
13+
}

tests/Sniffs/Namespaces/data/referenceUsedNamesOnlyWithRequiredPartialExact.fixed.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@ class Foo
88

99
public function test()
1010
{
11-
return SubNamespace::class;
11+
new SubNamespace();
1212
}
1313
}

tests/Sniffs/Namespaces/data/referenceUsedNamesOnlyWithRequiredPartialExact.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ class Foo
77

88
public function test()
99
{
10-
return \Some\SubNamespace::class;
10+
new \Some\SubNamespace();
1111
}
1212
}

tests/Sniffs/Namespaces/data/referenceUsedNamesOnlyWithSubNamespacesRequiredPartial.fixed.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
namespace Whatever;
44

55
use F\Q\N;
6-
use Some\SubNamespace;
6+
use Some\SubNamespace as SubNamespace;
77

88
class Foo
99
{

0 commit comments

Comments
 (0)