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:
parent
c71fe67ccb
commit
ae210fda9f
4 changed files with 64 additions and 0 deletions
|
@ -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',
|
||||||
|
|
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class ArcanistUseStatementNamespacePrefixXHPASTLinterRuleTestCase
|
||||||
|
extends ArcanistXHPASTLinterRuleTestCase {
|
||||||
|
|
||||||
|
public function testLinter() {
|
||||||
|
$this->executeTestsInDirectory(
|
||||||
|
dirname(__FILE__).'/use-statement-namespace-prefix/');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
Loading…
Reference in a new issue