diff --git a/.eslintrc.js b/.eslintrc.js index 280fb95ced..a914162418 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -28,7 +28,8 @@ module.exports = { { files: ['**/*.ts', '**/*.tsx'], rules: { - 'rulesdir/no-any-except-union-method-signature': 'error' + 'rulesdir/no-any-except-union-method-signature': 'error', + 'rulesdir/no-pr-in-user-strings': 'error' } } ] diff --git a/build/eslint-rules/index.js b/build/eslint-rules/index.js index 92c209e579..162d2780e0 100644 --- a/build/eslint-rules/index.js +++ b/build/eslint-rules/index.js @@ -8,4 +8,5 @@ module.exports = { 'public-methods-well-defined-types': require('./public-methods-well-defined-types'), 'no-any-except-union-method-signature': require('./no-any-except-union-method-signature'), + 'no-pr-in-user-strings': require('./no-pr-in-user-strings'), }; \ No newline at end of file diff --git a/build/eslint-rules/no-pr-in-user-strings.js b/build/eslint-rules/no-pr-in-user-strings.js new file mode 100644 index 0000000000..83665ad6fd --- /dev/null +++ b/build/eslint-rules/no-pr-in-user-strings.js @@ -0,0 +1,96 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +/** + * ESLint rule to detect the string "PR" in user-facing strings and suggest using "pull request" instead. + * This rule checks: + * - String literals passed to vscode.l10n.t() calls + * - String literals passed to l10n.t() calls + */ + +module.exports = { + meta: { + type: 'problem', + docs: { + description: 'Detect "PR" in user-facing strings and suggest using "pull request" instead', + category: 'Best Practices', + recommended: true, + }, + schema: [], + messages: { + noPrInUserString: 'Use "pull request" instead of "PR" in user-facing strings. Found: {{foundText}}', + }, + }, + + create(context) { + /** + * Check if a string contains "PR" as a standalone word + */ + function containsPR(str) { + // Use word boundary regex to match "PR" as a standalone word + const prRegex = /\bPR\b/; + return prRegex.test(str); + } + + /** + * Check if a node is a call to vscode.l10n.t or l10n.t + */ + function isL10nTCall(node) { + if (node.type !== 'CallExpression') { + return false; + } + + const callee = node.callee; + + // Handle l10n.t() calls + if (callee.type === 'MemberExpression' && + callee.property && + callee.property.name === 't') { + + // Check for vscode.l10n.t + if (callee.object.type === 'MemberExpression' && + callee.object.object && + callee.object.object.name === 'vscode' && + callee.object.property && + callee.object.property.name === 'l10n') { + return true; + } + + // Check for l10n.t + if (callee.object.type === 'Identifier' && + callee.object.name === 'l10n') { + return true; + } + } + + return false; + } + + return { + // Check CallExpression nodes for l10n.t calls + CallExpression(node) { + if (isL10nTCall(node)) { + // Check the first argument (string literal) + if (node.arguments && node.arguments.length > 0) { + const firstArg = node.arguments[0]; + if (firstArg.type === 'Literal' && typeof firstArg.value === 'string') { + if (containsPR(firstArg.value)) { + context.report({ + node: firstArg, + messageId: 'noPrInUserString', + data: { + foundText: firstArg.value + } + }); + } + } + } + } + } + }; + } +}; \ No newline at end of file diff --git a/src/issues/issueFeatureRegistrar.ts b/src/issues/issueFeatureRegistrar.ts index e4eb27be29..2b274a0026 100644 --- a/src/issues/issueFeatureRegistrar.ts +++ b/src/issues/issueFeatureRegistrar.ts @@ -510,7 +510,7 @@ export class IssueFeatureRegistrar extends Disposable { } else { const pullRequestModel = issue.pullRequestModel; const remote = pullRequestModel.githubRepository.remote; - commands.executeCommand(chatCommandID, vscode.l10n.t('@githubpr Summarize PR {0}/{1}#{2}', remote.owner, remote.repositoryName, pullRequestModel.number)); + commands.executeCommand(chatCommandID, vscode.l10n.t('@githubpr Summarize pull request {0}/{1}#{2}', remote.owner, remote.repositoryName, pullRequestModel.number)); } }), );