Page MenuHomePhabricator

D21763.id51882.diff
No OneTemporary

D21763.id51882.diff

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
@@ -424,6 +424,7 @@
'ArcanistPhutilXHPASTLinterStandard' => 'lint/linter/standards/phutil/ArcanistPhutilXHPASTLinterStandard.php',
'ArcanistPlusOperatorOnStringsXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistPlusOperatorOnStringsXHPASTLinterRule.php',
'ArcanistPlusOperatorOnStringsXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistPlusOperatorOnStringsXHPASTLinterRuleTestCase.php',
+ 'ArcanistProductNameLiteralXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistProductNameLiteralXHPASTLinterRule.php',
'ArcanistProjectConfigurationSource' => 'config/source/ArcanistProjectConfigurationSource.php',
'ArcanistPrompt' => 'toolset/ArcanistPrompt.php',
'ArcanistPromptResponse' => 'toolset/ArcanistPromptResponse.php',
@@ -914,6 +915,7 @@
'PhutilVeryWowEnglishLocale' => 'internationalization/locales/PhutilVeryWowEnglishLocale.php',
'PhutilWordPressFuture' => 'future/wordpress/PhutilWordPressFuture.php',
'PhutilXHPASTBinary' => 'parser/xhpast/bin/PhutilXHPASTBinary.php',
+ 'PlatformSymbols' => 'platform/PlatformSymbols.php',
'PytestTestEngine' => 'unit/engine/PytestTestEngine.php',
'TempFile' => 'filesystem/TempFile.php',
'TestAbstractDirectedGraph' => 'utils/__tests__/TestAbstractDirectedGraph.php',
@@ -1490,6 +1492,7 @@
'ArcanistPhutilXHPASTLinterStandard' => 'ArcanistLinterStandard',
'ArcanistPlusOperatorOnStringsXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistPlusOperatorOnStringsXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
+ 'ArcanistProductNameLiteralXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistProjectConfigurationSource' => 'ArcanistWorkingCopyConfigurationSource',
'ArcanistPrompt' => 'Phobject',
'ArcanistPromptResponse' => 'Phobject',
@@ -2007,6 +2010,7 @@
'PhutilVeryWowEnglishLocale' => 'PhutilLocale',
'PhutilWordPressFuture' => 'FutureProxy',
'PhutilXHPASTBinary' => 'Phobject',
+ 'PlatformSymbols' => 'Phobject',
'PytestTestEngine' => 'ArcanistUnitTestEngine',
'TempFile' => 'Phobject',
'TestAbstractDirectedGraph' => 'AbstractDirectedGraph',
diff --git a/src/lint/linter/xhpast/rules/ArcanistProductNameLiteralXHPASTLinterRule.php b/src/lint/linter/xhpast/rules/ArcanistProductNameLiteralXHPASTLinterRule.php
new file mode 100644
--- /dev/null
+++ b/src/lint/linter/xhpast/rules/ArcanistProductNameLiteralXHPASTLinterRule.php
@@ -0,0 +1,67 @@
+<?php
+
+final class ArcanistProductNameLiteralXHPASTLinterRule
+ extends ArcanistXHPASTLinterRule {
+
+ const ID = 134;
+
+ public function getLintName() {
+ return pht('Use of Product Name Literal');
+ }
+
+ public function getLintSeverity() {
+ return ArcanistLintSeverity::SEVERITY_WARNING;
+ }
+
+ public function process(XHPASTNode $root) {
+ $calls = $root->selectDescendantsOfType('n_FUNCTION_CALL');
+
+ $product_names = PlatformSymbols::getProductNames();
+ foreach ($product_names as $k => $product_name) {
+ $product_names[$k] = preg_quote($product_name);
+ }
+
+ $search_pattern = '(\b(?:'.implode('|', $product_names).')\b)i';
+
+ foreach ($calls as $call) {
+ $name = $call->getChildByIndex(0)->getConcreteString();
+
+ if ($name !== 'pht') {
+ continue;
+ }
+
+ $parameters = $call->getChildByIndex(1);
+
+ if (!$parameters->getChildren()) {
+ continue;
+ }
+
+ $identifier = $parameters->getChildByIndex(0);
+ if (!$identifier->isConstantString()) {
+ continue;
+ }
+
+ $literal_value = $identifier->getStringLiteralValue();
+
+ $matches = phutil_preg_match_all($search_pattern, $literal_value);
+ if (!$matches[0]) {
+ continue;
+ }
+
+ $name_list = array();
+ foreach ($matches[0] as $match) {
+ $name_list[phutil_utf8_strtolower($match)] = $match;
+ }
+ $name_list = implode(', ', $name_list);
+
+ $this->raiseLintAtNode(
+ $identifier,
+ pht(
+ 'Avoid use of product name literals in "pht()": use generic '.
+ 'language or an appropriate method from the "PlatformSymbols" class '.
+ 'instead so the software can be forked. String uses names: %s.',
+ $name_list));
+ }
+ }
+
+}
diff --git a/src/platform/PlatformSymbols.php b/src/platform/PlatformSymbols.php
new file mode 100644
--- /dev/null
+++ b/src/platform/PlatformSymbols.php
@@ -0,0 +1,21 @@
+<?php
+
+final class PlatformSymbols
+ extends Phobject {
+
+ public static function getPlatformClientName() {
+ return 'Arcanist';
+ }
+
+ public static function getPlatformServerName() {
+ return 'Phabricator';
+ }
+
+ public static function getProductNames() {
+ return array(
+ self::getPlatformClientName(),
+ self::getPlatformServerName(),
+ );
+ }
+
+}

File Metadata

Mime Type
text/plain
Expires
Tue, Mar 18, 3:17 AM (3 d, 16 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7662617
Default Alt Text
D21763.id51882.diff (4 KB)

Event Timeline