From 3c193984da6f415e406ce811c2ac1ff93d30a5e1 Mon Sep 17 00:00:00 2001 From: Joshua Spence Date: Thu, 3 Dec 2015 09:47:27 +1100 Subject: [PATCH] Add a "binary integer casing" linter rule Summary: Adds a linter rule which ensures that binary integers are written in lowercase (i.e. `0b1` instead of `0B1`). Test Plan: Added test cases. Reviewers: epriestley, #blessed_reviewers Reviewed By: epriestley, #blessed_reviewers Subscribers: Korvin Differential Revision: https://secure.phabricator.com/D14644 --- src/__phutil_library_map__.php | 4 ++ ...aryNumericScalarCasingXHPASTLinterRule.php | 49 +++++++++++++++++++ ...malNumericScalarCasingXHPASTLinterRule.php | 6 +-- ...icScalarCasingXHPASTLinterRuleTestCase.php | 11 +++++ .../binary.lint-test | 5 ++ 5 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 src/lint/linter/xhpast/rules/ArcanistBinaryNumericScalarCasingXHPASTLinterRule.php create mode 100644 src/lint/linter/xhpast/rules/__tests__/ArcanistBinaryNumericScalarCasingXHPASTLinterRuleTestCase.php create mode 100644 src/lint/linter/xhpast/rules/__tests__/binary-numeric-scalar-casing/binary.lint-test diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index f2f2d43f..9c9e09ed 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -32,6 +32,8 @@ phutil_register_library_map(array( 'ArcanistBaseXHPASTLinter' => 'lint/linter/ArcanistBaseXHPASTLinter.php', 'ArcanistBinaryExpressionSpacingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistBinaryExpressionSpacingXHPASTLinterRule.php', 'ArcanistBinaryExpressionSpacingXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistBinaryExpressionSpacingXHPASTLinterRuleTestCase.php', + 'ArcanistBinaryNumericScalarCasingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistBinaryNumericScalarCasingXHPASTLinterRule.php', + 'ArcanistBinaryNumericScalarCasingXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistBinaryNumericScalarCasingXHPASTLinterRuleTestCase.php', 'ArcanistBlacklistedFunctionXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistBlacklistedFunctionXHPASTLinterRule.php', 'ArcanistBlacklistedFunctionXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistBlacklistedFunctionXHPASTLinterRuleTestCase.php', 'ArcanistBookmarkWorkflow' => 'workflow/ArcanistBookmarkWorkflow.php', @@ -434,6 +436,8 @@ phutil_register_library_map(array( 'ArcanistBaseXHPASTLinter' => 'ArcanistFutureLinter', 'ArcanistBinaryExpressionSpacingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistBinaryExpressionSpacingXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', + 'ArcanistBinaryNumericScalarCasingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', + 'ArcanistBinaryNumericScalarCasingXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistBlacklistedFunctionXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistBlacklistedFunctionXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistBookmarkWorkflow' => 'ArcanistFeatureWorkflow', diff --git a/src/lint/linter/xhpast/rules/ArcanistBinaryNumericScalarCasingXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistBinaryNumericScalarCasingXHPASTLinterRule.php new file mode 100644 index 00000000..d9e7dfc9 --- /dev/null +++ b/src/lint/linter/xhpast/rules/ArcanistBinaryNumericScalarCasingXHPASTLinterRule.php @@ -0,0 +1,49 @@ +getBinaryNumericScalars($root); + + foreach ($binaries as $binary) { + $value = substr($binary->getConcreteString(), 2); + + if (!preg_match('/^0b[01]+$/', $binary->getConcreteString())) { + $this->raiseLintAtNode( + $binary, + pht( + 'For consistency, write binary integers with a leading `%s`.', + '0b'), + '0b'.$value); + } + } + } + + private function getBinaryNumericScalars(XHPASTNode $root) { + $numeric_scalars = $root->selectDescendantsOfType('n_NUMERIC_SCALAR'); + $binary_numeric_scalars = array(); + + foreach ($numeric_scalars as $numeric_scalar) { + $number = $numeric_scalar->getConcreteString(); + + if (preg_match('/^0b[01]+$/i', $number)) { + $binary_numeric_scalars[] = $numeric_scalar; + } + } + + return $binary_numeric_scalars; + + } + +} diff --git a/src/lint/linter/xhpast/rules/ArcanistHexadecimalNumericScalarCasingXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistHexadecimalNumericScalarCasingXHPASTLinterRule.php index 790526a4..d29b1f00 100644 --- a/src/lint/linter/xhpast/rules/ArcanistHexadecimalNumericScalarCasingXHPASTLinterRule.php +++ b/src/lint/linter/xhpast/rules/ArcanistHexadecimalNumericScalarCasingXHPASTLinterRule.php @@ -6,7 +6,7 @@ final class ArcanistHexadecimalNumericScalarCasingXHPASTLinterRule const ID = 127; public function getLintName() { - return pht('Hexadecimal Casing'); + return pht('Hexadecimal Integer Casing'); } public function getLintSeverity() { @@ -23,8 +23,8 @@ final class ArcanistHexadecimalNumericScalarCasingXHPASTLinterRule $this->raiseLintAtNode( $hexadecimal, pht( - 'For consistency, write hexadecimals in uppercase '. - 'with a leading `%s`.', + 'For consistency, write hexadecimals integers '. + 'in uppercase with a leading `%s`.', '0x'), '0x'.strtoupper($value)); } diff --git a/src/lint/linter/xhpast/rules/__tests__/ArcanistBinaryNumericScalarCasingXHPASTLinterRuleTestCase.php b/src/lint/linter/xhpast/rules/__tests__/ArcanistBinaryNumericScalarCasingXHPASTLinterRuleTestCase.php new file mode 100644 index 00000000..0215b639 --- /dev/null +++ b/src/lint/linter/xhpast/rules/__tests__/ArcanistBinaryNumericScalarCasingXHPASTLinterRuleTestCase.php @@ -0,0 +1,11 @@ +executeTestsInDirectory( + dirname(__FILE__).'/binary-numeric-scalar-casing/'); + } + +} diff --git a/src/lint/linter/xhpast/rules/__tests__/binary-numeric-scalar-casing/binary.lint-test b/src/lint/linter/xhpast/rules/__tests__/binary-numeric-scalar-casing/binary.lint-test new file mode 100644 index 00000000..406fe97c --- /dev/null +++ b/src/lint/linter/xhpast/rules/__tests__/binary-numeric-scalar-casing/binary.lint-test @@ -0,0 +1,5 @@ +