diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -315,6 +315,8 @@ 'ArcanistTasksWorkflow' => 'workflow/ArcanistTasksWorkflow.php', 'ArcanistTautologicalExpressionXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistTautologicalExpressionXHPASTLinterRule.php', 'ArcanistTautologicalExpressionXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistTautologicalExpressionXHPASTLinterRuleTestCase.php', + 'ArcanistTernaryExpressionSpacingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistTernaryExpressionSpacingXHPASTLinterRule.php', + 'ArcanistTernaryExpressionSpacingXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistTernaryExpressionSpacingXHPASTLinterRuleTestCase.php', 'ArcanistTestResultParser' => 'unit/parser/ArcanistTestResultParser.php', 'ArcanistTestXHPASTLintSwitchHook' => 'lint/linter/__tests__/ArcanistTestXHPASTLintSwitchHook.php', 'ArcanistTextLinter' => 'lint/linter/ArcanistTextLinter.php', @@ -693,6 +695,8 @@ 'ArcanistTasksWorkflow' => 'ArcanistWorkflow', 'ArcanistTautologicalExpressionXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistTautologicalExpressionXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', + 'ArcanistTernaryExpressionSpacingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', + 'ArcanistTernaryExpressionSpacingXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistTestResultParser' => 'Phobject', 'ArcanistTestXHPASTLintSwitchHook' => 'ArcanistXHPASTLintSwitchHook', 'ArcanistTextLinter' => 'ArcanistLinter', diff --git a/src/lint/linter/xhpast/rules/ArcanistTernaryExpressionSpacingXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistTernaryExpressionSpacingXHPASTLinterRule.php new file mode 100644 --- /dev/null +++ b/src/lint/linter/xhpast/rules/ArcanistTernaryExpressionSpacingXHPASTLinterRule.php @@ -0,0 +1,60 @@ +selectDescendantsOfType('n_TERNARY_EXPRESSION'); + + foreach ($expressions as $expression) { + $operators = $expression->selectTokensOfTypes(array('?', ':')); + $shorthand = $expression->getChildByIndex(2)->getTypeName() == 'n_EMPTY'; + + foreach ($operators as $operator) { + $before = $operator->getNonsemanticTokensBefore(); + $after = $operator->getNonsemanticTokensBefore(); + + $operator_value = $operator->getValue(); + $replace = null; + + switch ($operator_value) { + case '?': + if ($shorthand) { + $replace = " {$operator_value}"; + } else { + $replace = " {$operator_value} "; + } + break; + + case ':': + if ($shorthand) { + $replace = "{$operator_value} "; + } else { + $replace = " {$operator_value} "; + } + break; + } + + if ($replace !== null) { + $this->raiseLintAtToken( + $operator, + pht( + 'Convention: ternary operators should be '. + 'surrounded by whitespace.'), + $replace); + } + } + } + } + +} diff --git a/src/lint/linter/xhpast/rules/__tests__/ArcanistTernaryExpressionSpacingXHPASTLinterRuleTestCase.php b/src/lint/linter/xhpast/rules/__tests__/ArcanistTernaryExpressionSpacingXHPASTLinterRuleTestCase.php new file mode 100644 --- /dev/null +++ b/src/lint/linter/xhpast/rules/__tests__/ArcanistTernaryExpressionSpacingXHPASTLinterRuleTestCase.php @@ -0,0 +1,11 @@ +executeTestsInDirectory( + dirname(__FILE__).'/ternary-expression-spacing/'); + } + +} diff --git a/src/lint/linter/xhpast/rules/__tests__/ternary-expression-spacing/ternary-expression-spacing.lint-test b/src/lint/linter/xhpast/rules/__tests__/ternary-expression-spacing/ternary-expression-spacing.lint-test new file mode 100644 --- /dev/null +++ b/src/lint/linter/xhpast/rules/__tests__/ternary-expression-spacing/ternary-expression-spacing.lint-test @@ -0,0 +1,20 @@ +