1
0
Fork 0
mirror of https://we.phorge.it/source/arcanist.git synced 2025-01-01 10:20:58 +01:00

(stable) Promote 2015 Week 48

This commit is contained in:
epriestley 2015-11-28 05:52:29 -08:00
commit 76ea4e688d
75 changed files with 762 additions and 117 deletions

View file

@ -9,6 +9,10 @@
phutil_register_library_map(array(
'__library_version__' => 2,
'class' => array(
'ArcanistAbstractMethodBodyXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistAbstractMethodBodyXHPASTLinterRule.php',
'ArcanistAbstractMethodBodyXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistAbstractMethodBodyXHPASTLinterRuleTestCase.php',
'ArcanistAbstractPrivateMethodXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistAbstractPrivateMethodXHPASTLinterRule.php',
'ArcanistAbstractPrivateMethodXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistAbstractPrivateMethodXHPASTLinterRuleTestCase.php',
'ArcanistAliasFunctionXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistAliasFunctionXHPASTLinterRule.php',
'ArcanistAliasFunctionXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistAliasFunctionXHPASTLinterRuleTestCase.php',
'ArcanistAliasWorkflow' => 'workflow/ArcanistAliasWorkflow.php',
@ -55,6 +59,8 @@ phutil_register_library_map(array(
'ArcanistClassExtendsObjectXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistClassExtendsObjectXHPASTLinterRule.php',
'ArcanistClassExtendsObjectXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistClassExtendsObjectXHPASTLinterRuleTestCase.php',
'ArcanistClassFilenameMismatchXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistClassFilenameMismatchXHPASTLinterRule.php',
'ArcanistClassMustBeDeclaredAbstractXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistClassMustBeDeclaredAbstractXHPASTLinterRule.php',
'ArcanistClassMustBeDeclaredAbstractXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistClassMustBeDeclaredAbstractXHPASTLinterRuleTestCase.php',
'ArcanistClassNameLiteralXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistClassNameLiteralXHPASTLinterRule.php',
'ArcanistClassNameLiteralXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistClassNameLiteralXHPASTLinterRuleTestCase.php',
'ArcanistCloseRevisionWorkflow' => 'workflow/ArcanistCloseRevisionWorkflow.php',
@ -172,6 +178,10 @@ phutil_register_library_map(array(
'ArcanistInstallCertificateWorkflow' => 'workflow/ArcanistInstallCertificateWorkflow.php',
'ArcanistInstanceOfOperatorXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistInstanceOfOperatorXHPASTLinterRule.php',
'ArcanistInstanceofOperatorXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistInstanceofOperatorXHPASTLinterRuleTestCase.php',
'ArcanistInterfaceAbstractMethodXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistInterfaceAbstractMethodXHPASTLinterRule.php',
'ArcanistInterfaceAbstractMethodXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistInterfaceAbstractMethodXHPASTLinterRuleTestCase.php',
'ArcanistInterfaceMethodBodyXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistInterfaceMethodBodyXHPASTLinterRule.php',
'ArcanistInterfaceMethodBodyXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistInterfaceMethodBodyXHPASTLinterRuleTestCase.php',
'ArcanistInvalidDefaultParameterXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistInvalidDefaultParameterXHPASTLinterRule.php',
'ArcanistInvalidDefaultParameterXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistInvalidDefaultParameterXHPASTLinterRuleTestCase.php',
'ArcanistInvalidModifiersXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistInvalidModifiersXHPASTLinterRule.php',
@ -224,6 +234,8 @@ phutil_register_library_map(array(
'ArcanistMissingLinterException' => 'lint/linter/exception/ArcanistMissingLinterException.php',
'ArcanistModifierOrderingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistModifierOrderingXHPASTLinterRule.php',
'ArcanistModifierOrderingXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistModifierOrderingXHPASTLinterRuleTestCase.php',
'ArcanistNamespaceFirstStatementXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistNamespaceFirstStatementXHPASTLinterRule.php',
'ArcanistNamespaceFirstStatementXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistNamespaceFirstStatementXHPASTLinterRuleTestCase.php',
'ArcanistNamingConventionsXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistNamingConventionsXHPASTLinterRule.php',
'ArcanistNamingConventionsXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistNamingConventionsXHPASTLinterRuleTestCase.php',
'ArcanistNestedNamespacesXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistNestedNamespacesXHPASTLinterRule.php',
@ -347,11 +359,15 @@ phutil_register_library_map(array(
'ArcanistUnnecessaryFinalModifierXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistUnnecessaryFinalModifierXHPASTLinterRule.php',
'ArcanistUnnecessaryFinalModifierXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistUnnecessaryFinalModifierXHPASTLinterRuleTestCase.php',
'ArcanistUnnecessarySemicolonXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistUnnecessarySemicolonXHPASTLinterRule.php',
'ArcanistUnnecessarySymbolAliasXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistUnnecessarySymbolAliasXHPASTLinterRule.php',
'ArcanistUnnecessarySymbolAliasXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistUnnecessarySymbolAliasXHPASTLinterRuleTestCase.php',
'ArcanistUnsafeDynamicStringXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistUnsafeDynamicStringXHPASTLinterRule.php',
'ArcanistUnsafeDynamicStringXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistUnsafeDynamicStringXHPASTLinterRuleTestCase.php',
'ArcanistUpgradeWorkflow' => 'workflow/ArcanistUpgradeWorkflow.php',
'ArcanistUploadWorkflow' => 'workflow/ArcanistUploadWorkflow.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',
'ArcanistUselessOverridingMethodXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistUselessOverridingMethodXHPASTLinterRuleTestCase.php',
'ArcanistUserAbortException' => 'exception/usage/ArcanistUserAbortException.php',
@ -387,6 +403,10 @@ phutil_register_library_map(array(
),
'function' => array(),
'xmap' => array(
'ArcanistAbstractMethodBodyXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistAbstractMethodBodyXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistAbstractPrivateMethodXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistAbstractPrivateMethodXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistAliasFunctionXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistAliasFunctionXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistAliasWorkflow' => 'ArcanistWorkflow',
@ -433,6 +453,8 @@ phutil_register_library_map(array(
'ArcanistClassExtendsObjectXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistClassExtendsObjectXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistClassFilenameMismatchXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistClassMustBeDeclaredAbstractXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistClassMustBeDeclaredAbstractXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistClassNameLiteralXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistClassNameLiteralXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistCloseRevisionWorkflow' => 'ArcanistWorkflow',
@ -550,6 +572,10 @@ phutil_register_library_map(array(
'ArcanistInstallCertificateWorkflow' => 'ArcanistWorkflow',
'ArcanistInstanceOfOperatorXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistInstanceofOperatorXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistInterfaceAbstractMethodXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistInterfaceAbstractMethodXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistInterfaceMethodBodyXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistInterfaceMethodBodyXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistInvalidDefaultParameterXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistInvalidDefaultParameterXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistInvalidModifiersXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
@ -602,6 +628,8 @@ phutil_register_library_map(array(
'ArcanistMissingLinterException' => 'Exception',
'ArcanistModifierOrderingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistModifierOrderingXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistNamespaceFirstStatementXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistNamespaceFirstStatementXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistNamingConventionsXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistNamingConventionsXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistNestedNamespacesXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
@ -725,11 +753,15 @@ phutil_register_library_map(array(
'ArcanistUnnecessaryFinalModifierXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistUnnecessaryFinalModifierXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistUnnecessarySemicolonXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistUnnecessarySymbolAliasXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistUnnecessarySymbolAliasXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistUnsafeDynamicStringXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistUnsafeDynamicStringXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistUpgradeWorkflow' => 'ArcanistWorkflow',
'ArcanistUploadWorkflow' => 'ArcanistWorkflow',
'ArcanistUsageException' => 'Exception',
'ArcanistUseStatementNamespacePrefixXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistUseStatementNamespacePrefixXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistUselessOverridingMethodXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistUselessOverridingMethodXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistUserAbortException' => 'ArcanistUsageException',

View file

@ -225,6 +225,34 @@ abstract class ArcanistXHPASTLinterRule extends Phobject {
return AASTNodeList::newFromTreeAndNodes($root->getTree(), $nodes);
}
/**
* Get class/method modifiers.
*
* @param XHPASTNode A node of type `n_CLASS_DECLARATION` or
* `n_METHOD_DECLARATION`.
* @return map<string, bool> Class/method modifiers.
*/
final protected function getModifiers(XHPASTNode $node) {
$modifier_list = $node->getChildByIndex(0);
switch ($modifier_list->getTypeName()) {
case 'n_CLASS_ATTRIBUTES':
case 'n_METHOD_MODIFIER_LIST':
break;
default:
return array();
}
$modifiers = array();
foreach ($modifier_list->selectDescendantsOfType('n_STRING') as $modifier) {
$modifiers[strtolower($modifier->getConcreteString())] = true;
}
return $modifiers;
}
/**
* Get PHP superglobals.
*

View file

@ -0,0 +1,30 @@
<?php
final class ArcanistAbstractMethodBodyXHPASTLinterRule
extends ArcanistXHPASTLinterRule {
const ID = 108;
public function getLintName() {
return pht('`%s` Method Cannot Contain Body', 'abstract');
}
public function process(XHPASTNode $root) {
$methods = $root->selectDescendantsOfType('n_METHOD_DECLARATION');
foreach ($methods as $method) {
$modifiers = $this->getModifiers($method);
$body = $method->getChildByIndex(5);
if (idx($modifiers, 'abstract') && $body->getTypeName() != 'n_EMPTY') {
$this->raiseLintAtNode(
$body,
pht(
'`%s` methods cannot contain a body. This construct will '.
'cause a fatal error.',
'abstract'));
}
}
}
}

View file

@ -0,0 +1,37 @@
<?php
final class ArcanistAbstractPrivateMethodXHPASTLinterRule
extends ArcanistXHPASTLinterRule {
const ID = 107;
public function getLintName() {
return pht('`%s` Method Cannot Be Declared `%s`', 'abstract', 'private');
}
public function process(XHPASTNode $root) {
$methods = $root->selectDescendantsOfType('n_METHOD_DECLARATION');
foreach ($methods as $method) {
$method_modifiers = $method
->getChildOfType(0, 'n_METHOD_MODIFIER_LIST')
->selectDescendantsOfType('n_STRING');
$modifiers = array();
foreach ($method_modifiers as $modifier) {
$modifiers[strtolower($modifier->getConcreteString())] = true;
}
if (idx($modifiers, 'abstract') && idx($modifiers, 'private')) {
$this->raiseLintAtNode(
$method,
pht(
'`%s` method cannot be declared `%s`. '.
'This construct will cause a fatal error.',
'abstract',
'private'));
}
}
}
}

View file

@ -6,7 +6,7 @@ final class ArcanistArrayCombineXHPASTLinterRule
const ID = 84;
public function getLintName() {
return pht('%s Unreliable', 'array_combine()');
return pht('`%s` Unreliable', 'array_combine()');
}
public function getLintSeverity() {
@ -35,8 +35,8 @@ final class ArcanistArrayCombineXHPASTLinterRule
'Prior to PHP 5.4, `%s` fails when given empty arrays. '.
'Prefer to write `%s` as `%s`.',
'array_combine()',
'array_combine(x, x)',
'array_fuse(x)'));
'array_combine($x, $x)',
'array_fuse($x)'));
}
}
}

View file

@ -6,7 +6,7 @@ final class ArcanistClassExtendsObjectXHPASTLinterRule
const ID = 88;
public function getLintName() {
return pht('Class Not Extending %s', 'Phobject');
return pht('Class Not Extending `%s`', 'Phobject');
}
public function getLintSeverity() {
@ -29,8 +29,8 @@ final class ArcanistClassExtendsObjectXHPASTLinterRule
$this->raiseLintAtNode(
$class,
pht(
'Classes should extend from %s or from some other class. '.
'All classes (except for %s itself) should have a base class.',
'Classes should extend from `%s` or from some other class. '.
'All classes (except for `%s` itself) should have a base class.',
'Phobject',
'Phobject'));
}

View file

@ -47,7 +47,7 @@ final class ArcanistClassFilenameMismatchXHPASTLinterRule
$decl_name,
pht(
"The name of this file differs from the name of the ".
"class or interface it declares. Rename the file to '%s'.",
'class or interface it declares. Rename the file to `%s`.',
$rename));
}

View file

@ -0,0 +1,46 @@
<?php
final class ArcanistClassMustBeDeclaredAbstractXHPASTLinterRule
extends ArcanistXHPASTLinterRule {
const ID = 113;
public function getLintName() {
return pht(
'`%s` Containing `%s` Methods Must Be Declared `%s`',
'class',
'abstract',
'abstract');
}
public function process(XHPASTNode $root) {
$classes = $root->selectDescendantsOfType('n_CLASS_DECLARATION');
foreach ($classes as $class) {
$class_modifiers = $this->getModifiers($class);
$abstract_methods = array();
$methods = $class->selectDescendantsOfType('n_METHOD_DECLARATION');
foreach ($methods as $method) {
$method_modifiers = $this->getModifiers($method);
if (idx($method_modifiers, 'abstract')) {
$abstract_methods[] = $method;
}
}
if (!idx($class_modifiers, 'abstract') && $abstract_methods) {
$this->raiseLintAtNode(
$class,
pht(
'Class contains %s %s method(s) and must therefore '.
'be declared `%s`.',
phutil_count($abstract_methods),
'abstract',
'abstract'));
}
}
}
}

View file

@ -39,7 +39,7 @@ final class ArcanistClassNameLiteralXHPASTLinterRule
$this->raiseLintAtNode(
$string,
pht(
"Don't hard-code class names, use %s instead.",
"Don't hard-code class names, use `%s` instead.",
'__CLASS__'),
$replacement);
}

View file

@ -19,7 +19,10 @@ final class ArcanistCommentStyleXHPASTLinterRule
$this->raiseLintAtOffset(
$comment->getOffset(),
pht('Use "%s" single-line comments, not "%s".', '//', '#'),
pht(
'Use `%s` single-line comments, not `%s`.',
'//',
'#'),
'#',
preg_match('/^#\S/', $value) ? '// ' : '//');
}

View file

@ -78,7 +78,9 @@ final class ArcanistDeclarationParenthesesXHPASTLinterRule
if (!$before) {
$this->raiseLintAtOffset(
$use->getOffset(),
pht('Convention: space before `%s` token.', 'use'),
pht(
'Convention: space before `%s` token.',
'use'),
'',
' ');
}
@ -86,7 +88,9 @@ final class ArcanistDeclarationParenthesesXHPASTLinterRule
if (!$after) {
$this->raiseLintAtOffset(
$use->getOffset() + strlen($use->getValue()),
pht('Convention: space after `%s` token.', 'use'),
pht(
'Convention: space after `%s` token.',
'use'),
'',
' ');
}

View file

@ -6,7 +6,7 @@ final class ArcanistDynamicDefineXHPASTLinterRule
const ID = 12;
public function getLintName() {
return pht('Dynamic %s', 'define()');
return pht('Dynamic `%s`', 'define');
}
public function process(XHPASTNode $root) {
@ -20,8 +20,8 @@ final class ArcanistDynamicDefineXHPASTLinterRule
$this->raiseLintAtNode(
$defined,
pht(
'First argument to %s must be a string literal.',
'define()'));
'First argument to `%s` must be a string literal.',
'define'));
}
}
}

View file

@ -6,7 +6,7 @@ final class ArcanistElseIfUsageXHPASTLinterRule
const ID = 42;
public function getLintName() {
return pht('ElseIf Usage');
return pht('`elseif` Usage');
}
public function getLintSeverity() {
@ -19,7 +19,10 @@ final class ArcanistElseIfUsageXHPASTLinterRule
foreach ($tokens as $token) {
$this->raiseLintAtToken(
$token,
pht('Usage of `%s` is preferred over `%s`.', 'else if', 'elseif'),
pht(
'Usage of `%s` is preferred over `%s`.',
'else if',
'elseif'),
'else if');
}
}

View file

@ -21,7 +21,7 @@ final class ArcanistExitExpressionXHPASTLinterRule
const ID = 17;
public function getLintName() {
return pht('Exit Used as Expression');
return pht('`%s` Used as Expression', 'exit');
}
public function process(XHPASTNode $root) {
@ -34,7 +34,9 @@ final class ArcanistExitExpressionXHPASTLinterRule
if ($unary->getParentNode()->getTypeName() !== 'n_STATEMENT') {
$this->raiseLintAtNode(
$unary,
pht('Use `%s` as a statement, not an expression.', 'exit'));
pht(
'Use `%s` as a statement, not an expression.',
'exit'));
}
}
}

View file

@ -6,7 +6,7 @@ final class ArcanistExtractUseXHPASTLinterRule
const ID = 4;
public function getLintName() {
return pht('Use of %s', 'extract()');
return pht('Use of `%s`', 'extract');
}
public function process(XHPASTNode $root) {
@ -16,8 +16,8 @@ final class ArcanistExtractUseXHPASTLinterRule
$this->raiseLintAtNode(
$call,
pht(
'Avoid %s. It is confusing and hinders static analysis.',
'extract()'));
'Avoid `%s`. It is confusing and hinders static analysis.',
'extract'));
}
}

View file

@ -16,7 +16,7 @@ final class ArcanistFormattedStringXHPASTLinterRule
'xhpast.printf-functions' => array(
'type' => 'optional map<string, int>',
'help' => pht(
'%s-style functions which take a format string and list of values '.
'`%s`-style functions which take a format string and list of values '.
'as arguments. The value for the mapping is the start index of the '.
'function parameters (the index of the format string parameter).',
'printf()'),

View file

@ -24,9 +24,10 @@ final class ArcanistImplicitConstructorXHPASTLinterRule
$this->raiseLintAtNode(
$method_name_token,
pht(
'Name constructors %s explicitly. This method is a constructor '.
' because it has the same name as the class it is defined in.',
'__construct()'));
'Name constructors `%s` explicitly. This method is a '.
'constructor because it has the same name as the class '.
'it is defined in.',
'__construct'));
}
}
}

View file

@ -20,10 +20,10 @@ final class ArcanistImplicitFallthroughXHPASTLinterRule
'xhpast.switchhook' => array(
'type' => 'optional string',
'help' => pht(
'Name of a concrete subclass of %s which tunes the '.
'analysis of %s statements for this linter.',
'Name of a concrete subclass of `%s` which tunes the '.
'analysis of `%s` statements for this linter.',
'ArcanistXHPASTLintSwitchHook',
'switch()'),
'switch'),
),
);
}
@ -190,9 +190,9 @@ final class ArcanistImplicitFallthroughXHPASTLinterRule
$this->raiseLintAtToken(
head($tokens),
pht(
"This '%s' or '%s' has a nonempty block which does not end ".
"with '%s', '%s', '%s', '%s' or '%s'. Did you forget to add ".
"one of those? If you intend to fall through, add a '%s' ".
'This `%s` or `%s` has a nonempty block which does not end '.
'with `%s`, `%s`, `%s`, `%s` or `%s`. Did you forget to add '.
'one of those? If you intend to fall through, add a `%s` '.
"comment to silence this warning.",
'case',
'default',

View file

@ -6,7 +6,7 @@ final class ArcanistInstanceOfOperatorXHPASTLinterRule
const ID = 69;
public function getLintName() {
return pht('%s Operator', 'instanceof');
return pht('`%s` Operator', 'instanceof');
}
public function process(XHPASTNode $root) {
@ -26,7 +26,7 @@ final class ArcanistInstanceOfOperatorXHPASTLinterRule
$this->raiseLintAtNode(
$object,
pht(
'%s expects an object instance, constant given.',
'`%s` expects an object instance, constant given.',
'instanceof'));
}
}

View file

@ -0,0 +1,34 @@
<?php
final class ArcanistInterfaceAbstractMethodXHPASTLinterRule
extends ArcanistXHPASTLinterRule {
const ID = 118;
public function getLintName() {
return pht('`%s` Methods Cannot Be Marked `%s`', 'interface', 'abstract');
}
public function process(XHPASTNode $root) {
$interfaces = $root->selectDescendantsOfType('n_INTERFACE_DECLARATION');
foreach ($interfaces as $interface) {
$methods = $interface->selectDescendantsOfType('n_METHOD_DECLARATION');
foreach ($methods as $method) {
$modifiers = $this->getModifiers($method);
if (idx($modifiers, 'abstract')) {
$this->raiseLintAtNode(
$method,
pht(
'`%s` methods cannot be marked as `%s`. This construct will '.
'cause a fatal error.',
'interface',
'abstract'));
}
}
}
}
}

View file

@ -0,0 +1,33 @@
<?php
final class ArcanistInterfaceMethodBodyXHPASTLinterRule
extends ArcanistXHPASTLinterRule {
const ID = 114;
public function getLintName() {
return pht('`%s` Method Cannot Contain Body', 'interface');
}
public function process(XHPASTNode $root) {
$interfaces = $root->selectDescendantsOfType('n_INTERFACE_DECLARATION');
foreach ($interfaces as $interface) {
$methods = $interface->selectDescendantsOfType('n_METHOD_DECLARATION');
foreach ($methods as $method) {
$body = $method->getChildByIndex(5);
if ($body->getTypeName() != 'n_EMPTY') {
$this->raiseLintAtNode(
$body,
pht(
'`%s` methods cannot contain a body. This construct will '.
'cause a fatal error.',
'interface'));
}
}
}
}
}

View file

@ -39,8 +39,8 @@ final class ArcanistInvalidDefaultParameterXHPASTLinterRule
$this->raiseLintAtNode(
$default,
pht(
'Default value for parameters with %s type hint '.
'can only be an %s or %s.',
'Default value for parameters with `%s` type hint '.
'can only be an `%s` or `%s`.',
'array',
'array',
'null'));
@ -54,7 +54,8 @@ final class ArcanistInvalidDefaultParameterXHPASTLinterRule
$this->raiseLintAtNode(
$default,
pht(
'Default value for parameters with %s type hint can only be %s.',
'Default value for parameters with `%s` type hint '.
'can only be `%s`.',
'callable',
'null'));
break;
@ -69,7 +70,7 @@ final class ArcanistInvalidDefaultParameterXHPASTLinterRule
$default,
pht(
'Default value for parameters with a class type hint '.
'can only be %s.',
'can only be `%s`.',
'null'));
break;
}

View file

@ -30,7 +30,7 @@ final class ArcanistInvalidModifiersXHPASTLinterRule
$this->raiseLintAtNode(
$modifier,
pht(
'Properties cannot be declared %s.',
'Properties cannot be declared `%s`.',
'abstract'));
}
@ -38,7 +38,7 @@ final class ArcanistInvalidModifiersXHPASTLinterRule
$this->raiseLintAtNode(
$modifier,
pht(
'Multiple %s modifiers are not allowed.',
'Multiple `%s` modifiers are not allowed.',
'abstract'));
}
@ -46,7 +46,7 @@ final class ArcanistInvalidModifiersXHPASTLinterRule
$this->raiseLintAtNode(
$modifier,
pht(
'Cannot use the %s modifier on an %s class member',
'Cannot use the `%s` modifier on an `%s` class member',
'final',
'abstract'));
}
@ -59,7 +59,7 @@ final class ArcanistInvalidModifiersXHPASTLinterRule
$this->raiseLintAtNode(
$modifier,
pht(
'Cannot use the %s modifier on an %s class member',
'Cannot use the `%s` modifier on an `%s` class member',
'final',
'abstract'));
}
@ -68,7 +68,7 @@ final class ArcanistInvalidModifiersXHPASTLinterRule
$this->raiseLintAtNode(
$modifier,
pht(
'Multiple %s modifiers are not allowed.',
'Multiple `%s` modifiers are not allowed.',
'final'));
}
@ -91,7 +91,7 @@ final class ArcanistInvalidModifiersXHPASTLinterRule
$this->raiseLintAtNode(
$modifier,
pht(
'Multiple %s modifiers are not allowed.',
'Multiple `%s` modifiers are not allowed.',
'static'));
}
break;

View file

@ -89,7 +89,7 @@ final class ArcanistKeywordCasingXHPASTLinterRule
$this->raiseLintAtToken(
$keyword,
pht(
"Convention: spell keyword '%s' as '%s'.",
'Convention: spell keyword `%s` as `%s`.',
$value,
strtolower($value)),
strtolower($value));
@ -115,7 +115,7 @@ final class ArcanistKeywordCasingXHPASTLinterRule
$this->raiseLintAtNode(
$symbol,
pht(
"Convention: spell keyword '%s' as '%s'.",
'Convention: spell keyword `%s` as `%s`.',
$symbol_name,
strtolower($symbol_name)),
strtolower($symbol_name));

View file

@ -6,7 +6,7 @@ final class ArcanistLambdaFuncFunctionXHPASTLinterRule
const ID = 68;
public function getLintName() {
return pht('%s Function', '__lambda_func');
return pht('`%s` Function', '__lambda_func');
}
public function process(XHPASTNode $root) {
@ -28,10 +28,10 @@ final class ArcanistLambdaFuncFunctionXHPASTLinterRule
$this->raiseLintAtNode(
$function_declaration,
pht(
'Declaring a function named %s causes any call to %s to fail. '.
'This is because %s eval-declares the function %s, then '.
'Declaring a function named `%s` causes any call to %s to fail. '.
'This is because `%s` eval-declares the function `%s`, then '.
'modifies the symbol table so that the function is instead '.
'named %s, and returns that name.',
'named `%s`, and returns that name.',
'__lambda_func',
'create_function',
'create_function',

View file

@ -0,0 +1,36 @@
<?php
final class ArcanistNamespaceFirstStatementXHPASTLinterRule
extends ArcanistXHPASTLinterRule {
const ID = 98;
public function getLintName() {
return pht('`%s` Statement Must Be The First Statement', 'namespace');
}
public function process(XHPASTNode $root) {
$namespaces = $root->selectDescendantsOfType('n_NAMESPACE');
if (!count($namespaces)) {
return;
}
$statements = $root->getChildOfType(0, 'n_STATEMENT_LIST');
// Ignore the first statement, which should be `n_OPEN_TAG`.
$second_statement = $statements->getChildByIndex(1)->getChildByIndex(0);
if ($second_statement->getTypeName() != 'n_NAMESPACE') {
$this->raiseLintAtNode(
$second_statement,
pht(
'A script which contains a `%s` statement expects the very first '.
'statement to be a `%s` statement. Otherwise, a PHP fatal error '.
'will occur. %s',
'namespace',
'namespace', $second_statement->getTypeName()));
}
}
}

View file

@ -20,7 +20,7 @@ final class ArcanistNamingConventionsXHPASTLinterRule
'xhpast.naminghook' => array(
'type' => 'optional string',
'help' => pht(
'Name of a concrete subclass of %s which enforces more '.
'Name of a concrete subclass of `%s` which enforces more '.
'granular naming convention rules for symbols.',
'ArcanistXHPASTLintNamingHook'),
),
@ -56,8 +56,8 @@ final class ArcanistNamingConventionsXHPASTLinterRule
ArcanistXHPASTLintNamingHook::isUpperCamelCase($name_string)
? null
: pht(
'Follow naming conventions: classes should be named using '.
'UpperCamelCase.'),
'Follow naming conventions: classes should be named using `%s`.',
'UpperCamelCase'),
);
}
@ -72,8 +72,8 @@ final class ArcanistNamingConventionsXHPASTLinterRule
ArcanistXHPASTLintNamingHook::isUpperCamelCase($name_string)
? null
: pht(
'Follow naming conventions: interfaces should be named using '.
'UpperCamelCase.'),
'Follow naming conventions: interfaces should be named using `%s`.',
'UpperCamelCase'),
);
}
@ -94,8 +94,8 @@ final class ArcanistNamingConventionsXHPASTLinterRule
ArcanistXHPASTLintNamingHook::stripPHPFunction($name_string))
? null
: pht(
'Follow naming conventions: functions should be named using '.
'lowercase_with_underscores.'),
'Follow naming conventions: functions should be named using `%s`.',
'lowercase_with_underscores'),
);
}
@ -112,8 +112,8 @@ final class ArcanistNamingConventionsXHPASTLinterRule
ArcanistXHPASTLintNamingHook::stripPHPFunction($name_string))
? null
: pht(
'Follow naming conventions: methods should be named using '.
'lowerCamelCase.'),
'Follow naming conventions: methods should be named using `%s`.',
'lowerCamelCase'),
);
}
@ -137,8 +137,9 @@ final class ArcanistNamingConventionsXHPASTLinterRule
ArcanistXHPASTLintNamingHook::stripPHPVariable($name_string))
? null
: pht(
'Follow naming conventions: parameters should be named using '.
'lowercase_with_underscores.'),
'Follow naming conventions: parameters '.
'should be named using `%s`',
'lowercase_with_underscores'),
);
}
}
@ -157,8 +158,9 @@ final class ArcanistNamingConventionsXHPASTLinterRule
ArcanistXHPASTLintNamingHook::isUppercaseWithUnderscores($name_string)
? null
: pht(
'Follow naming conventions: class constants should be named '.
'using UPPERCASE_WITH_UNDERSCORES.'),
'Follow naming conventions: class constants '.
'should be named using `%s`',
'UPPERCASE_WITH_UNDERSCORES'),
);
}
}
@ -184,8 +186,9 @@ final class ArcanistNamingConventionsXHPASTLinterRule
ArcanistXHPASTLintNamingHook::stripPHPVariable($name_string))
? null
: pht(
'Follow naming conventions: class properties should be named '.
'using lowerCamelCase.'),
'Follow naming conventions: class properties '.
'should be named using `%s`.',
'lowerCamelCase'),
);
}
}
@ -269,8 +272,9 @@ final class ArcanistNamingConventionsXHPASTLinterRule
ArcanistXHPASTLintNamingHook::stripPHPVariable($var_string))
? null
: pht(
'Follow naming conventions: variables should be named using '.
'lowercase_with_underscores.'),
'Follow naming conventions: variables '.
'should be named using `%s`.',
'lowercase_with_underscores'),
);
}
}

View file

@ -38,7 +38,9 @@ final class ArcanistNewlineAfterOpenTagXHPASTLinterRule
$next = $token->getNextToken();
$this->raiseLintAtToken(
$next,
pht('`%s` should be separated from code by an empty line.', '<?php'),
pht(
'`%s` should be separated from code by an empty line.',
'<?php'),
"\n".$next->getValue());
}
}

View file

@ -34,7 +34,7 @@ final class ArcanistNoParentScopeXHPASTLinterRule
$this->raiseLintAtNode(
$static_access,
pht(
'Cannot access %s when current class scope has no parent.',
'Cannot access `%s` when current class scope has no parent.',
'parent::'));
}
}

View file

@ -6,7 +6,7 @@ final class ArcanistPHPCloseTagXHPASTLinterRule
const ID = 8;
public function getLintName() {
return pht('Use of Close Tag "%s"', '?>');
return pht('Use of Close Tag `%s`', '?>');
}
public function process(XHPASTNode $root) {
@ -19,7 +19,9 @@ final class ArcanistPHPCloseTagXHPASTLinterRule
foreach ($root->selectTokensOfType('T_CLOSE_TAG') as $token) {
$this->raiseLintAtToken(
$token,
pht('Do not use the PHP closing tag, "%s".', '?>'));
pht(
'Do not use the PHP closing tag, `%s`.',
'?>'));
}
}

View file

@ -6,7 +6,7 @@ final class ArcanistPHPEchoTagXHPASTLinterRule
const ID = 7;
public function getLintName() {
return pht('Use of Echo Tag "%s"', '<?=');
return pht('Use of Echo Tag `%s`', '<?=');
}
public function process(XHPASTNode $root) {
@ -16,7 +16,9 @@ final class ArcanistPHPEchoTagXHPASTLinterRule
if ($token->getTypeName() === 'T_OPEN_TAG_WITH_ECHO') {
$this->raiseLintAtToken(
$token,
pht('Avoid the PHP echo short form, "%s".', '<?='));
pht(
'Avoid the PHP echo short form, `%s`.',
'<?='));
}
}
}

View file

@ -22,8 +22,8 @@ final class ArcanistPHPOpenTagXHPASTLinterRule
$this->raiseLintAtToken(
$token,
pht(
'PHP files should start with "%s", which may be preceded by '.
'a "%s" line for scripts.',
'PHP files should start with `%s`, which may be preceded by '.
'a `%s` line for scripts.',
'<?php',
'#!'));
}

View file

@ -6,7 +6,7 @@ final class ArcanistPHPShortTagXHPASTLinterRule
const ID = 6;
public function getLintName() {
return pht('Use of Short Tag "%s"', '<?');
return pht('Use of Short Tag `%s`', '<?');
}
public function process(XHPASTNode $root) {
@ -18,7 +18,7 @@ final class ArcanistPHPShortTagXHPASTLinterRule
$this->raiseLintAtToken(
$token,
pht(
'Use the full form of the PHP open tag, "%s".',
'Use the full form of the PHP open tag, `%s`.',
'<?php'),
"<?php\n");
}

View file

@ -6,7 +6,7 @@ final class ArcanistParseStrUseXHPASTLinterRule
const ID = 80;
public function getLintName() {
return pht('Questionable Use of %s', 'parse_str()');
return pht('Questionable Use of `%s`', 'parse_str');
}
public function process(XHPASTNode $root) {
@ -19,9 +19,9 @@ final class ArcanistParseStrUseXHPASTLinterRule
$this->raiseLintAtNode(
$call,
pht(
'Avoid %s unless the second parameter is specified. '.
'Avoid `%s` unless the second parameter is specified. '.
'It is confusing and hinders static analysis.',
'parse_str()'));
'parse_str'));
}
}
}

View file

@ -26,9 +26,10 @@ final class ArcanistPlusOperatorOnStringsXHPASTLinterRule
$this->raiseLintAtNode(
$binop,
pht(
"In PHP, '%s' is the string concatenation operator, not '%s'. ".
"This expression uses '+' with a string literal as an operand.",
'In PHP, `%s` is the string concatenation operator, not `%s`. '.
'This expression uses `%s` with a string literal as an operand.',
'.',
'+',
'+'));
}
}

View file

@ -12,7 +12,7 @@ final class ArcanistPregQuoteMisuseXHPASTLinterRule
const ID = 14;
public function getLintName() {
return pht('Misuse of %s', 'preg_quote()');
return pht('Misuse of `%s`', 'preg_quote');
}
public function getLintSeverity() {
@ -33,8 +33,8 @@ final class ArcanistPregQuoteMisuseXHPASTLinterRule
'arguments to %s, so that %s knows which delimiter to escape.',
'//',
'()',
'preg_quote()',
'preg_quote()'));
'preg_quote',
'preg_quote'));
}
}
}

View file

@ -6,7 +6,7 @@ final class ArcanistRaggedClassTreeEdgeXHPASTLinterRule
const ID = 87;
public function getLintName() {
return pht('Class Not %s Or %s', 'abstract', 'final');
return pht('Class Not `%s` Or `%s`', 'abstract', 'final');
}
public function getLintSeverity() {
@ -42,8 +42,8 @@ final class ArcanistRaggedClassTreeEdgeXHPASTLinterRule
$this->raiseLintAtNode(
$class->getChildOfType(1, 'n_CLASS_NAME'),
pht(
"This class is neither '%s' nor '%s', and does not have ".
"a docblock marking it '%s'.",
'This class is neither `%s` nor `%s`, and does not have '.
'a docblock marking it `%s`.',
'final',
'abstract',
'@concrete-extensible'));

View file

@ -173,7 +173,7 @@ final class ArcanistReusedIteratorReferenceXHPASTLinterRule
$var,
pht(
'This variable was used already as a by-reference iterator '.
'variable. Such variables survive outside the %s loop, '.
'variable. Such variables survive outside the `%s` loop, '.
'do not reuse.',
'foreach'));
}

View file

@ -51,14 +51,14 @@ final class ArcanistSlownessXHPASTLinterRule
$this->raiseLintAtNode(
$strstr,
pht(
'Use %s for checking if the string contains something.',
'strpos()'));
'Use `%s` for checking if the string contains something.',
'strpos'));
} else if ($name === 'stristr') {
$this->raiseLintAtNode(
$strstr,
pht(
'Use %s for checking if the string contains something.',
'stripos()'));
'Use `%s` for checking if the string contains something.',
'stripos'));
}
}
}
@ -96,14 +96,14 @@ final class ArcanistSlownessXHPASTLinterRule
$this->raiseLintAtNode(
$strpos,
pht(
'Use %s for checking if the string starts with something.',
'strncmp()'));
'Use `%s` for checking if the string starts with something.',
'strncmp'));
} else if ($name === 'stripos') {
$this->raiseLintAtNode(
$strpos,
pht(
'Use %s for checking if the string starts with something.',
'strncasecmp()'));
'Use `%s` for checking if the string starts with something.',
'strncasecmp'));
}
}
}

View file

@ -6,7 +6,7 @@ final class ArcanistStaticThisXHPASTLinterRule
const ID = 13;
public function getLintName() {
return pht('Use of %s in Static Context', '$this');
return pht('Use of `%s` in Static Context', '$this');
}
public function process(XHPASTNode $root) {

View file

@ -6,7 +6,7 @@ final class ArcanistToStringExceptionXHPASTLinterRule
const ID = 67;
public function getLintName() {
return pht('Throwing Exception in %s Method', '__toString');
return pht('Throwing Exception in `%s` Method', '__toString');
}
public function process(XHPASTNode $root) {
@ -33,7 +33,7 @@ final class ArcanistToStringExceptionXHPASTLinterRule
$this->raiseLintAtNode(
$throw,
pht(
'It is not possible to throw an %s from within the %s method.',
'It is not possible to throw an `%s` from within the `%s` method.',
'Exception',
'__toString'));
}

View file

@ -33,6 +33,10 @@ final class ArcanistUnexpectedReturnValueXHPASTLinterRule
continue;
}
if ($this->isInAnonymousFunction($return)) {
continue;
}
$this->raiseLintAtNode(
$return,
pht(
@ -45,4 +49,15 @@ final class ArcanistUnexpectedReturnValueXHPASTLinterRule
}
}
private function isInAnonymousFunction(XHPASTNode $node) {
while ($node) {
if ($node->getTypeName() == 'n_FUNCTION_DECLARATION' &&
$node->getChildByIndex(2)->getTypeName() == 'n_EMPTY') {
return true;
}
$node = $node->getParentNode();
}
}
}

View file

@ -40,7 +40,7 @@ final class ArcanistUnnecessaryFinalModifierXHPASTLinterRule
$this->raiseLintAtNode(
$attribute,
pht(
'Unnecessary %s modifier in %s class.',
'Unnecessary `%s` modifier in `%s` class.',
'final',
'final'));
}

View file

@ -0,0 +1,43 @@
<?php
final class ArcanistUnnecessarySymbolAliasXHPASTLinterRule
extends ArcanistXHPASTLinterRule {
const ID = 99;
public function getLintName() {
return pht('Unnecessary Symbol Alias');
}
public function getLintSeverity() {
return ArcanistLintSeverity::SEVERITY_WARNING;
}
public function process(XHPASTNode $root) {
$uses = $root->selectDescendantsOfType('n_USE');
foreach ($uses as $use) {
$symbol = $use->getChildOfType(0, 'n_SYMBOL_NAME');
$alias = $use->getChildByIndex(1);
if ($alias->getTypeName() == 'n_EMPTY') {
continue;
}
$symbol_name = last(explode('\\', $symbol->getConcreteString()));
$alias_name = $alias->getConcreteString();
if ($symbol_name == $alias_name) {
$this->raiseLintAtNode(
$use,
pht(
'Importing `%s` with `%s` is unnecessary because the aliased '.
'name is identical to the imported symbol name.',
$symbol->getConcreteString(),
sprintf('as %s', $alias_name)),
$symbol->getConcreteString());
}
}
}
}

View file

@ -70,9 +70,11 @@ final class ArcanistUnsafeDynamicStringXHPASTLinterRule
AASTNodeList $calls,
array $safe) {
$safe = array_combine(
array_map('strtolower', array_keys($safe)),
$safe);
if ($safe) {
$safe = array_combine(
array_map('strtolower', array_keys($safe)),
$safe);
}
foreach ($calls as $call) {
$name = $call->getChildByIndex(0)->getConcreteString();
@ -92,10 +94,10 @@ final class ArcanistUnsafeDynamicStringXHPASTLinterRule
$this->raiseLintAtNode(
$call,
pht(
"Parameter %d of %s should be a scalar string, ".
"Parameter %d of `%s` should be a scalar string, ".
"otherwise it's not safe.",
$param + 1,
$name.'()'));
$name));
}
}
}

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,10 @@
<?php
final class ArcanistAbstractMethodBodyXHPASTLinterRuleTestCase
extends ArcanistXHPASTLinterRuleTestCase {
public function testLinter() {
$this->executeTestsInDirectory(dirname(__FILE__).'/abstract-method-body/');
}
}

View file

@ -0,0 +1,11 @@
<?php
final class ArcanistAbstractPrivateMethodXHPASTLinterRuleTestCase
extends ArcanistXHPASTLinterRuleTestCase {
public function testLinter() {
$this->executeTestsInDirectory(
dirname(__FILE__).'/abstract-private-method/');
}
}

View file

@ -0,0 +1,11 @@
<?php
final class ArcanistClassMustBeDeclaredAbstractXHPASTLinterRuleTestCase
extends ArcanistXHPASTLinterRuleTestCase {
public function testLinter() {
$this->executeTestsInDirectory(
dirname(__FILE__).'/class-must-be-declared-abstract/');
}
}

View file

@ -0,0 +1,11 @@
<?php
final class ArcanistInterfaceAbstractMethodXHPASTLinterRuleTestCase
extends ArcanistXHPASTLinterRuleTestCase {
public function testLinter() {
$this->executeTestsInDirectory(
dirname(__FILE__).'/interface-abstract-method/');
}
}

View file

@ -0,0 +1,10 @@
<?php
final class ArcanistInterfaceMethodBodyXHPASTLinterRuleTestCase
extends ArcanistXHPASTLinterRuleTestCase {
public function testLinter() {
$this->executeTestsInDirectory(dirname(__FILE__).'/interface-method-body/');
}
}

View file

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

View file

@ -0,0 +1,11 @@
<?php
final class ArcanistUnnecessarySymbolAliasXHPASTLinterRuleTestCase
extends ArcanistXHPASTLinterRuleTestCase {
public function testLinter() {
$this->executeTestsInDirectory(
dirname(__FILE__).'/unnecessary-symbol-alias/');
}
}

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,6 @@
<?php
abstract class SomeClass {
abstract public function someMethod() {}
}
~~~~~~~~~~
error:3:41

View file

@ -0,0 +1,5 @@
<?php
abstract class SomeClass {
abstract public function someMethod();
}
~~~~~~~~~~

View file

@ -0,0 +1,5 @@
<?php
abstract class SomeClass {
public function someMethod() {}
}
~~~~~~~~~~

View file

@ -0,0 +1,6 @@
<?php
abstract class SomeClass {
private abstract function someMethod();
}
~~~~~~~~~~
error:3:3

View file

@ -0,0 +1,5 @@
<?php
abstract class SomeClass {
abstract public function someMethod();
}
~~~~~~~~~~

View file

@ -0,0 +1,5 @@
<?php
class SomeClass {
public function someMethod();
}
~~~~~~~~~~

View file

@ -0,0 +1,6 @@
<?php
class SomeClass {
abstract public function someMethod();
}
~~~~~~~~~~
error:2:1

View file

@ -0,0 +1,7 @@
<?php
interface SomeInterface {
abstract public function someMethod();
}
~~~~~~~~~~
error:4:3

View file

@ -0,0 +1,6 @@
<?php
interface SomeInterface {
public function someMethod();
}
~~~~~~~~~~

View file

@ -0,0 +1,7 @@
<?php
interface SomeInterface {
public function someMethod() {}
}
~~~~~~~~~~
error:4:32

View file

@ -0,0 +1,6 @@
<?php
interface SomeInterface {
public function someMethod();
}
~~~~~~~~~~

View file

@ -0,0 +1,5 @@
<?php
class X {}
namespace X;
~~~~~~~~~~
error:2:1

View file

@ -0,0 +1,16 @@
<?php
/**
* This is actually perfectly valid, for some unknown reason.
*
* TODO: Maybe fix the handling of this edge case.
*/
1;
namespace X {
class C { }
echo 2;
}
~~~~~~~~~~
error:9:1

View file

@ -0,0 +1,7 @@
<?php
namespace X;
class X {}
namespace Y;
class Y {}
~~~~~~~~~~

View file

@ -0,0 +1,3 @@
<?php
class X {}
~~~~~~~~~~

View file

@ -0,0 +1,11 @@
<?php
class SomeClass {
private $closure;
public function __construct() {
$this->closure = function() {
return null;
};
}
}
~~~~~~~~~~

View file

@ -0,0 +1,16 @@
<?php
use A;
use B as B;
use C as D;
use E\F as F;
use G\H as I;
~~~~~~~~~~
warning:3:5
warning:5:5
~~~~~~~~~~
<?php
use A;
use B;
use C as D;
use E\F;
use G\H as I;

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;

View file

@ -521,6 +521,16 @@ final class ArcanistGitAPI extends ArcanistRepositoryAPI {
}
public function getRemoteURI() {
// Determine which remote to examine; default to 'origin'
$remote = 'origin';
$branch = $this->getBranchName();
if ($branch) {
$path = $this->getPathToUpstream($branch);
if ($path->isConnectedToRemote()) {
$remote = $path->getRemoteRemoteName();
}
}
// "git ls-remote --get-url" is the appropriate plumbing to get the remote
// URI. "git config remote.origin.url", on the other hand, may not be as
// accurate (for example, it does not take into account possible URL
@ -528,9 +538,9 @@ final class ArcanistGitAPI extends ArcanistRepositoryAPI {
// the --get-url flag requires git 1.7.5.
$version = $this->getGitVersion();
if (version_compare($version, '1.7.5', '>=')) {
list($stdout) = $this->execxLocal('ls-remote --get-url origin');
list($stdout) = $this->execxLocal('ls-remote --get-url %s', $remote);
} else {
list($stdout) = $this->execxLocal('config remote.origin.url');
list($stdout) = $this->execxLocal('config %s', "remote.{$remote}.url");
}
$uri = rtrim($stdout);

View file

@ -56,9 +56,11 @@ EOTEXT
$config = $configuration_manager->readUserConfigurationFile();
$console->writeOut(
"%s\n",
pht('Trying to connect to server...'));
$this->writeInfo(
pht('CONNECT'),
pht(
'Connecting to "%s"...',
$uri));
$conduit = $this->establishConduit()->getConduit();
try {
@ -194,10 +196,19 @@ EOTEXT
$uri = $conduit_uri;
}
$uri = new PhutilURI($uri);
$uri->setPath('/api/');
$uri_object = new PhutilURI($uri);
if (!$uri_object->getProtocol() || !$uri_object->getDomain()) {
throw new ArcanistUsageException(
pht(
'Server URI "%s" must include a protocol and domain. It should be '.
'in the form "%s".',
$uri,
'https://phabricator.example.com/'));
}
return (string)$uri;
$uri_object->setPath('/api/');
return (string)$uri_object;
}
}

View file

@ -1282,10 +1282,16 @@ EOTEXT
$err = $repository_api->execPassthru('push %s', $this->remote);
$cmd = 'hg push';
} else if ($this->isHg) {
$err = $repository_api->execPassthru(
'push -r %s %s',
$this->onto,
$this->remote);
if (strlen($this->remote)) {
$err = $repository_api->execPassthru(
'push -r %s %s',
$this->onto,
$this->remote);
} else {
$err = $repository_api->execPassthru(
'push -r %s',
$this->onto);
}
$cmd = 'hg push';
}