1
0
Fork 0
mirror of https://we.phorge.it/source/arcanist.git synced 2024-11-26 00:32:41 +01:00

Add a linter rule for use statement namespace prefixes

Summary:
When importing or aliases a symbol with a `use` statement, the leading namespace separator is optional and does not modify the behavior. That is, `use \X` is equivalent to `use X`. As such, the latter syntax should be preferred because it is more concise.

According to the [[http://php.net/manual/en/language.namespaces.importing.php | PHP documentation]]:

> Note that for namespaced names (fully qualified namespace names containing namespace separator, such as `Foo\Bar` as opposed to global names that do not, such as `FooBar`), the leading backslash is unnecessary and not recommended, as import names must be fully qualified, and are not processed relative to the current namespace.

Test Plan: Added test cases.

Reviewers: epriestley, #blessed_reviewers

Reviewed By: epriestley, #blessed_reviewers

Subscribers: epriestley

Differential Revision: https://secure.phabricator.com/D14517
This commit is contained in:
Joshua Spence 2015-11-24 06:42:39 +11:00
parent c71fe67ccb
commit ae210fda9f
4 changed files with 64 additions and 0 deletions

View file

@ -352,6 +352,8 @@ phutil_register_library_map(array(
'ArcanistUpgradeWorkflow' => 'workflow/ArcanistUpgradeWorkflow.php', 'ArcanistUpgradeWorkflow' => 'workflow/ArcanistUpgradeWorkflow.php',
'ArcanistUploadWorkflow' => 'workflow/ArcanistUploadWorkflow.php', 'ArcanistUploadWorkflow' => 'workflow/ArcanistUploadWorkflow.php',
'ArcanistUsageException' => 'exception/ArcanistUsageException.php', 'ArcanistUsageException' => 'exception/ArcanistUsageException.php',
'ArcanistUseStatementNamespacePrefixXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistUseStatementNamespacePrefixXHPASTLinterRule.php',
'ArcanistUseStatementNamespacePrefixXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistUseStatementNamespacePrefixXHPASTLinterRuleTestCase.php',
'ArcanistUselessOverridingMethodXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistUselessOverridingMethodXHPASTLinterRule.php', 'ArcanistUselessOverridingMethodXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistUselessOverridingMethodXHPASTLinterRule.php',
'ArcanistUselessOverridingMethodXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistUselessOverridingMethodXHPASTLinterRuleTestCase.php', 'ArcanistUselessOverridingMethodXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistUselessOverridingMethodXHPASTLinterRuleTestCase.php',
'ArcanistUserAbortException' => 'exception/usage/ArcanistUserAbortException.php', 'ArcanistUserAbortException' => 'exception/usage/ArcanistUserAbortException.php',
@ -730,6 +732,8 @@ phutil_register_library_map(array(
'ArcanistUpgradeWorkflow' => 'ArcanistWorkflow', 'ArcanistUpgradeWorkflow' => 'ArcanistWorkflow',
'ArcanistUploadWorkflow' => 'ArcanistWorkflow', 'ArcanistUploadWorkflow' => 'ArcanistWorkflow',
'ArcanistUsageException' => 'Exception', 'ArcanistUsageException' => 'Exception',
'ArcanistUseStatementNamespacePrefixXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistUseStatementNamespacePrefixXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistUselessOverridingMethodXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistUselessOverridingMethodXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistUselessOverridingMethodXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistUselessOverridingMethodXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistUserAbortException' => 'ArcanistUsageException', 'ArcanistUserAbortException' => 'ArcanistUsageException',

View file

@ -0,0 +1,38 @@
<?php
final class ArcanistUseStatementNamespacePrefixXHPASTLinterRule
extends ArcanistXHPASTLinterRule {
const ID = 97;
public function getLintName() {
return pht('`%s` Statement Namespace Prefix', 'use');
}
public function getLintSeverity() {
return ArcanistLintSeverity::SEVERITY_WARNING;
}
public function process(XHPASTNode $root) {
$use_lists = $root->selectDescendantsOfType('n_USE_LIST');
foreach ($use_lists as $use_list) {
$uses = $use_list->selectDescendantsOfType('n_USE');
foreach ($uses as $use) {
$symbol = $use->getChildOfType(0, 'n_SYMBOL_NAME');
$symbol_name = $symbol->getConcreteString();
if ($symbol_name[0] == '\\') {
$this->raiseLintAtNode(
$symbol,
pht(
'Imported symbols should not be prefixed with `%s`.',
'\\'),
substr($symbol_name, 1));
}
}
}
}
}

View file

@ -0,0 +1,11 @@
<?php
final class ArcanistUseStatementNamespacePrefixXHPASTLinterRuleTestCase
extends ArcanistXHPASTLinterRuleTestCase {
public function testLinter() {
$this->executeTestsInDirectory(
dirname(__FILE__).'/use-statement-namespace-prefix/');
}
}

View file

@ -0,0 +1,11 @@
<?php
namespace SomeNamespace;
use X\Y\Z;
use \X\Y\Z;
~~~~~~~~~~
warning:4:5
~~~~~~~~~~
<?php
namespace SomeNamespace;
use X\Y\Z;
use X\Y\Z;