diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index b9edae01e6a..c1de7347c65 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -46,6 +46,7 @@ "@typescript-eslint/scope-manager": "4.12.0", "debug": "^4.1.1", "functional-red-black-tree": "^1.0.1", + "lodash": "^4.17.15", "regexpp": "^3.0.0", "semver": "^7.3.2", "tsutils": "^3.17.1" diff --git a/packages/eslint-plugin/src/rules/no-redeclare.ts b/packages/eslint-plugin/src/rules/no-redeclare.ts index d85cb1dc241..fa67859f509 100644 --- a/packages/eslint-plugin/src/rules/no-redeclare.ts +++ b/packages/eslint-plugin/src/rules/no-redeclare.ts @@ -13,43 +13,6 @@ type Options = [ }, ]; -// https://github.com/lodash/lodash/blob/86a852fe763935bb64c12589df5391fd7d3bb14d/escapeRegExp.js -const reRegExpChar = /[\\^$.*+?()[\]{}|]/g; -const reHasRegExpChar = RegExp(reRegExpChar.source); -function escapeRegExp(str: string): string { - return str && reHasRegExpChar.test(str) - ? str.replace(reRegExpChar, '\\$&') - : str || ''; -} - -function getNameLocationInGlobalDirectiveComment( - sourceCode: TSESLint.SourceCode, - comment: TSESTree.Comment, - name: string, -): TSESTree.SourceLocation { - const namePattern = new RegExp( - `[\\s,]${escapeRegExp(name)}(?:$|[\\s,:])`, - 'gu', - ); - - // To ignore the first text "global". - namePattern.lastIndex = comment.value.indexOf('global') + 6; - - // Search a given variable name. - const match = namePattern.exec(comment.value); - - // Convert the index to loc. - const start = sourceCode.getLocFromIndex( - comment.range[0] + '/*'.length + (match ? match.index + 1 : 0), - ); - const end = { - line: start.line, - column: start.column + (match ? name.length : 1), - }; - - return { start, end }; -} - export default util.createRule({ name: 'no-redeclare', meta: { @@ -129,7 +92,7 @@ export default util.createRule({ yield { type: 'comment', node: comment, - loc: getNameLocationInGlobalDirectiveComment( + loc: util.getNameLocationInGlobalDirectiveComment( sourceCode, comment, variable.name, diff --git a/packages/eslint-plugin/src/rules/no-unused-vars.ts b/packages/eslint-plugin/src/rules/no-unused-vars.ts index 6b96151e959..968c8d51b54 100644 --- a/packages/eslint-plugin/src/rules/no-unused-vars.ts +++ b/packages/eslint-plugin/src/rules/no-unused-vars.ts @@ -4,7 +4,6 @@ import { TSESTree, } from '@typescript-eslint/experimental-utils'; import { PatternVisitor } from '@typescript-eslint/scope-manager'; -import { getNameLocationInGlobalDirectiveComment } from 'eslint/lib/rules/utils/ast-utils'; import * as util from '../util'; export type MessageIds = 'unusedVar'; @@ -388,7 +387,7 @@ export default util.createRule({ context.report({ node: programNode, - loc: getNameLocationInGlobalDirectiveComment( + loc: util.getNameLocationInGlobalDirectiveComment( sourceCode, directiveComment, unusedVar.name, diff --git a/packages/eslint-plugin/src/util/astUtils.ts b/packages/eslint-plugin/src/util/astUtils.ts index 12f003e98d0..53ad3f116e6 100644 --- a/packages/eslint-plugin/src/util/astUtils.ts +++ b/packages/eslint-plugin/src/util/astUtils.ts @@ -1,2 +1,43 @@ +import type { TSESLint, TSESTree } from '@typescript-eslint/experimental-utils'; +import escapeRegExp from 'lodash/escapeRegExp'; + // deeply re-export, for convenience export * from '@typescript-eslint/experimental-utils/dist/ast-utils'; + +// The following is copied from `eslint`'s source code since it doesn't exist in eslint@5. +// https://github.com/eslint/eslint/blob/145aec1ab9052fbca96a44d04927c595951b1536/lib/rules/utils/ast-utils.js#L1751-L1779 +// Could be export { getNameLocationInGlobalDirectiveComment } from 'eslint/lib/rules/utils/ast-utils' +/** + * Get the `loc` object of a given name in a `/*globals` directive comment. + * @param {SourceCode} sourceCode The source code to convert index to loc. + * @param {Comment} comment The `/*globals` directive comment which include the name. + * @param {string} name The name to find. + * @returns {SourceLocation} The `loc` object. + */ +export function getNameLocationInGlobalDirectiveComment( + sourceCode: TSESLint.SourceCode, + comment: TSESTree.Comment, + name: string, +): TSESTree.SourceLocation { + const namePattern = new RegExp( + `[\\s,]${escapeRegExp(name)}(?:$|[\\s,:])`, + 'gu', + ); + + // To ignore the first text "global". + namePattern.lastIndex = comment.value.indexOf('global') + 6; + + // Search a given variable name. + const match = namePattern.exec(comment.value); + + // Convert the index to loc. + const start = sourceCode.getLocFromIndex( + comment.range[0] + '/*'.length + (match ? match.index + 1 : 0), + ); + const end = { + line: start.line, + column: start.column + (match ? name.length : 1), + }; + + return { start, end }; +} diff --git a/packages/eslint-plugin/typings/eslint-rules.d.ts b/packages/eslint-plugin/typings/eslint-rules.d.ts index e25ce02f88b..ca726d6fb83 100644 --- a/packages/eslint-plugin/typings/eslint-rules.d.ts +++ b/packages/eslint-plugin/typings/eslint-rules.d.ts @@ -830,17 +830,3 @@ declare module 'eslint/lib/rules/prefer-const' { >; export = rule; } - -declare module 'eslint/lib/rules/utils/ast-utils' { - import { TSESLint, TSESTree } from '@typescript-eslint/experimental-utils'; - - const utils: { - getNameLocationInGlobalDirectiveComment( - sourceCode: TSESLint.SourceCode, - comment: TSESTree.Comment, - name: string, - ): TSESTree.SourceLocation; - }; - - export = utils; -}