From 0f7c4fa34189ea290ae87260781928e0f9a1615e Mon Sep 17 00:00:00 2001 From: ota-meshi <otameshiyo23@gmail.com> Date: Wed, 29 Nov 2023 19:43:24 +0900 Subject: [PATCH 1/2] Improve compatibility with ESLint v9 --- eslint.config.js | 14 +++ lib/rules/block-order.js | 5 +- lib/rules/block-tag-newline.js | 7 +- lib/rules/comment-directive.js | 5 +- .../component-name-in-template-casing.js | 5 +- lib/rules/custom-event-name-casing.js | 15 ++- lib/rules/first-attribute-linebreak.js | 5 +- lib/rules/html-closing-bracket-newline.js | 5 +- lib/rules/html-closing-bracket-spacing.js | 4 +- lib/rules/html-indent.js | 5 +- lib/rules/html-self-closing.js | 4 +- lib/rules/max-attributes-per-line.js | 4 +- lib/rules/max-len.js | 4 +- lib/rules/max-lines-per-block.js | 5 +- .../multiline-html-element-content-newline.js | 6 +- lib/rules/mustache-interpolation-spacing.js | 5 +- lib/rules/next-tick-style.js | 5 +- lib/rules/no-async-in-computed-properties.js | 5 +- lib/rules/no-child-content.js | 4 +- lib/rules/no-dupe-keys.js | 7 +- lib/rules/no-dupe-v-else-if.js | 5 +- lib/rules/no-empty-component-block.js | 5 +- lib/rules/no-expose-after-await.js | 10 +- lib/rules/no-extra-parens.js | 5 +- lib/rules/no-lifecycle-after-await.js | 5 +- lib/rules/no-multi-spaces.js | 6 +- lib/rules/no-multiple-slot-args.js | 2 +- lib/rules/no-mutating-props.js | 2 +- lib/rules/no-restricted-block.js | 5 +- lib/rules/no-restricted-call-after-await.js | 2 +- lib/rules/no-restricted-custom-event.js | 10 +- lib/rules/no-setup-props-reactivity-loss.js | 18 +++- .../no-side-effects-in-computed-properties.js | 7 +- lib/rules/no-unused-emit-declarations.js | 9 +- lib/rules/no-useless-mustaches.js | 3 +- lib/rules/no-useless-v-bind.js | 2 +- lib/rules/no-watch-after-await.js | 5 +- lib/rules/padding-line-between-blocks.js | 5 +- lib/rules/prefer-separate-static-class.js | 3 +- lib/rules/require-explicit-emits.js | 9 +- lib/rules/require-expose.js | 9 +- lib/rules/require-slots-as-functions.js | 2 +- lib/rules/require-typed-ref.js | 6 +- lib/rules/return-in-computed-property.js | 5 +- ...singleline-html-element-content-newline.js | 6 +- lib/rules/syntaxes/slot-attribute.js | 4 +- lib/rules/syntaxes/slot-scope-attribute.js | 4 +- lib/rules/v-for-delimiter-style.js | 5 +- lib/rules/v-on-function-call.js | 4 +- lib/rules/v-on-handler-style.js | 7 +- lib/rules/valid-define-emits.js | 2 +- lib/rules/valid-define-options.js | 2 +- lib/rules/valid-define-props.js | 2 +- lib/rules/valid-next-tick.js | 2 +- lib/rules/valid-v-slot.js | 4 +- lib/utils/index.js | 92 +++++++++---------- lib/utils/scope.js | 30 ++++++ lib/utils/style-variables/index.js | 5 +- lib/utils/ts-utils/ts-ast.js | 11 ++- lib/utils/ts-utils/ts-types.js | 9 +- 60 files changed, 283 insertions(+), 165 deletions(-) create mode 100644 lib/utils/scope.js diff --git a/eslint.config.js b/eslint.config.js index abedce70b..3407dd3b4 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -160,6 +160,20 @@ module.exports = [ 'dot-notation': 'error', 'arrow-body-style': 'error', + 'no-restricted-properties': [ + 'error', + { + object: 'context', + property: 'parserServices', + message: 'Use sourceCode.parserServices' + }, + { + object: 'context', + property: 'getScope', + message: 'Use utils.getScope' + } + ], + 'unicorn/consistent-function-scoping': [ 'error', { checkArrowFunctions: false } diff --git a/lib/rules/block-order.js b/lib/rules/block-order.js index 91d3eaa6f..c93de09b2 100644 --- a/lib/rules/block-order.js +++ b/lib/rules/block-order.js @@ -106,9 +106,10 @@ module.exports = { function getOrderElement(element) { return orders.find((o) => o.selector.test(element)) } + const sourceCode = context.getSourceCode() const documentFragment = - context.parserServices.getDocumentFragment && - context.parserServices.getDocumentFragment() + sourceCode.parserServices.getDocumentFragment && + sourceCode.parserServices.getDocumentFragment() function getTopLevelHTMLElements() { if (documentFragment) { diff --git a/lib/rules/block-tag-newline.js b/lib/rules/block-tag-newline.js index bccecd834..22fb12870 100644 --- a/lib/rules/block-tag-newline.js +++ b/lib/rules/block-tag-newline.js @@ -84,15 +84,14 @@ module.exports = { }, /** @param {RuleContext} context */ create(context) { + const sourceCode = context.getSourceCode() const df = - context.parserServices.getDocumentFragment && - context.parserServices.getDocumentFragment() + sourceCode.parserServices.getDocumentFragment && + sourceCode.parserServices.getDocumentFragment() if (!df) { return {} } - const sourceCode = context.getSourceCode() - /** * @param {VStartTag} startTag * @param {string} beforeText diff --git a/lib/rules/comment-directive.js b/lib/rules/comment-directive.js index aeca98aef..655e222bd 100644 --- a/lib/rules/comment-directive.js +++ b/lib/rules/comment-directive.js @@ -313,9 +313,10 @@ module.exports = { const options = context.options[0] || {} /** @type {boolean} */ const reportUnusedDisableDirectives = options.reportUnusedDisableDirectives + const sourceCode = context.getSourceCode() const documentFragment = - context.parserServices.getDocumentFragment && - context.parserServices.getDocumentFragment() + sourceCode.parserServices.getDocumentFragment && + sourceCode.parserServices.getDocumentFragment() return { Program(node) { diff --git a/lib/rules/component-name-in-template-casing.js b/lib/rules/component-name-in-template-casing.js index 487af7714..629f51209 100644 --- a/lib/rules/component-name-in-template-casing.js +++ b/lib/rules/component-name-in-template-casing.js @@ -86,9 +86,10 @@ module.exports = { /** @type {string[]} */ const globals = (options.globals || []).map(casing.pascalCase) const registeredComponentsOnly = options.registeredComponentsOnly !== false + const sourceCode = context.getSourceCode() const tokens = - context.parserServices.getTemplateBodyTokenStore && - context.parserServices.getTemplateBodyTokenStore() + sourceCode.parserServices.getTemplateBodyTokenStore && + sourceCode.parserServices.getTemplateBodyTokenStore() /** @type { Set<string> } */ const registeredComponents = new Set(globals) diff --git a/lib/rules/custom-event-name-casing.js b/lib/rules/custom-event-name-casing.js index 2361badb1..09cc2fc36 100644 --- a/lib/rules/custom-event-name-casing.js +++ b/lib/rules/custom-event-name-casing.js @@ -210,7 +210,10 @@ module.exports = { return } // const emit = defineEmits() - const variable = findVariable(context.getScope(), emitParam) + const variable = findVariable( + utils.getScope(context, emitParam), + emitParam + ) if (!variable) { return } @@ -251,7 +254,10 @@ module.exports = { } const emitParam = emitProperty.value // `setup(props, {emit})` - const variable = findVariable(context.getScope(), emitParam) + const variable = findVariable( + utils.getScope(context, emitParam), + emitParam + ) if (!variable) { return } @@ -260,7 +266,10 @@ module.exports = { } } else { // `setup(props, context)` - const variable = findVariable(context.getScope(), contextParam) + const variable = findVariable( + utils.getScope(context, contextParam), + contextParam + ) if (!variable) { return } diff --git a/lib/rules/first-attribute-linebreak.js b/lib/rules/first-attribute-linebreak.js index bdaf078c9..c023762d4 100644 --- a/lib/rules/first-attribute-linebreak.js +++ b/lib/rules/first-attribute-linebreak.js @@ -39,9 +39,10 @@ module.exports = { const multiline = (context.options[0] && context.options[0].multiline) || 'below' + const sourceCode = context.getSourceCode() const template = - context.parserServices.getTemplateBodyTokenStore && - context.parserServices.getTemplateBodyTokenStore() + sourceCode.parserServices.getTemplateBodyTokenStore && + sourceCode.parserServices.getTemplateBodyTokenStore() /** * Report attribute diff --git a/lib/rules/html-closing-bracket-newline.js b/lib/rules/html-closing-bracket-newline.js index e1a746e42..c353c35d3 100644 --- a/lib/rules/html-closing-bracket-newline.js +++ b/lib/rules/html-closing-bracket-newline.js @@ -59,9 +59,10 @@ module.exports = { }, context.options[0] || {} ) + const sourceCode = context.getSourceCode() const template = - context.parserServices.getTemplateBodyTokenStore && - context.parserServices.getTemplateBodyTokenStore() + sourceCode.parserServices.getTemplateBodyTokenStore && + sourceCode.parserServices.getTemplateBodyTokenStore() return utils.defineDocumentVisitor(context, { /** @param {VStartTag | VEndTag} node */ diff --git a/lib/rules/html-closing-bracket-spacing.js b/lib/rules/html-closing-bracket-spacing.js index 0d5d477ba..daf42d540 100644 --- a/lib/rules/html-closing-bracket-spacing.js +++ b/lib/rules/html-closing-bracket-spacing.js @@ -80,8 +80,8 @@ module.exports = { create(context) { const sourceCode = context.getSourceCode() const tokens = - context.parserServices.getTemplateBodyTokenStore && - context.parserServices.getTemplateBodyTokenStore() + sourceCode.parserServices.getTemplateBodyTokenStore && + sourceCode.parserServices.getTemplateBodyTokenStore() const options = parseOptions(context.options[0], tokens) return utils.defineDocumentVisitor(context, { diff --git a/lib/rules/html-indent.js b/lib/rules/html-indent.js index 1670a3308..6a423ecca 100644 --- a/lib/rules/html-indent.js +++ b/lib/rules/html-indent.js @@ -11,9 +11,10 @@ const utils = require('../utils') module.exports = { /** @param {RuleContext} context */ create(context) { + const sourceCode = context.getSourceCode() const tokenStore = - context.parserServices.getTemplateBodyTokenStore && - context.parserServices.getTemplateBodyTokenStore() + sourceCode.parserServices.getTemplateBodyTokenStore && + sourceCode.parserServices.getTemplateBodyTokenStore() const visitor = indentCommon.defineVisitor(context, tokenStore, { baseIndent: 1 }) diff --git a/lib/rules/html-self-closing.js b/lib/rules/html-self-closing.js index 621cde6d1..9e626f41d 100644 --- a/lib/rules/html-self-closing.js +++ b/lib/rules/html-self-closing.js @@ -159,7 +159,7 @@ module.exports = { }, fix(fixer) { const tokens = - context.parserServices.getTemplateBodyTokenStore() + sourceCode.parserServices.getTemplateBodyTokenStore() const close = tokens.getLastToken(node.startTag) if (close.type !== 'HTMLTagClose') { return null @@ -183,7 +183,7 @@ module.exports = { }, fix(fixer) { const tokens = - context.parserServices.getTemplateBodyTokenStore() + sourceCode.parserServices.getTemplateBodyTokenStore() const close = tokens.getLastToken(node.startTag) if (close.type !== 'HTMLSelfClosingTagClose') { return null diff --git a/lib/rules/max-attributes-per-line.js b/lib/rules/max-attributes-per-line.js index b1665c17d..443826fe0 100644 --- a/lib/rules/max-attributes-per-line.js +++ b/lib/rules/max-attributes-per-line.js @@ -124,8 +124,8 @@ module.exports = { const multilineMaximum = configuration.multiline const singlelinemMaximum = configuration.singleline const template = - context.parserServices.getTemplateBodyTokenStore && - context.parserServices.getTemplateBodyTokenStore() + sourceCode.parserServices.getTemplateBodyTokenStore && + sourceCode.parserServices.getTemplateBodyTokenStore() return utils.defineTemplateBodyVisitor(context, { VStartTag(node) { diff --git a/lib/rules/max-len.js b/lib/rules/max-len.js index 588f2de75..9347ea78b 100644 --- a/lib/rules/max-len.js +++ b/lib/rules/max-len.js @@ -307,8 +307,8 @@ module.exports = { const scriptTokens = sourceCode.ast.tokens const scriptComments = sourceCode.getAllComments() - if (context.parserServices.getTemplateBodyTokenStore && templateBody) { - const tokenStore = context.parserServices.getTemplateBodyTokenStore() + if (sourceCode.parserServices.getTemplateBodyTokenStore && templateBody) { + const tokenStore = sourceCode.parserServices.getTemplateBodyTokenStore() const templateTokens = tokenStore.getTokens(templateBody, { includeComments: true diff --git a/lib/rules/max-lines-per-block.js b/lib/rules/max-lines-per-block.js index bcb82d563..c778ef40b 100644 --- a/lib/rules/max-lines-per-block.js +++ b/lib/rules/max-lines-per-block.js @@ -65,9 +65,10 @@ module.exports = { } const code = context.getSourceCode() + const sourceCode = context.getSourceCode() const documentFragment = - context.parserServices.getDocumentFragment && - context.parserServices.getDocumentFragment() + sourceCode.parserServices.getDocumentFragment && + sourceCode.parserServices.getDocumentFragment() function getTopLevelHTMLElements() { if (documentFragment) { diff --git a/lib/rules/multiline-html-element-content-newline.js b/lib/rules/multiline-html-element-content-newline.js index dc4111864..bfe0c79f7 100644 --- a/lib/rules/multiline-html-element-content-newline.js +++ b/lib/rules/multiline-html-element-content-newline.js @@ -98,10 +98,10 @@ module.exports = { const ignores = options.ignores const ignoreWhenEmpty = options.ignoreWhenEmpty const allowEmptyLines = options.allowEmptyLines - const template = - context.parserServices.getTemplateBodyTokenStore && - context.parserServices.getTemplateBodyTokenStore() const sourceCode = context.getSourceCode() + const template = + sourceCode.parserServices.getTemplateBodyTokenStore && + sourceCode.parserServices.getTemplateBodyTokenStore() /** @type {VElement | null} */ let inIgnoreElement = null diff --git a/lib/rules/mustache-interpolation-spacing.js b/lib/rules/mustache-interpolation-spacing.js index 51b19c616..79bae0543 100644 --- a/lib/rules/mustache-interpolation-spacing.js +++ b/lib/rules/mustache-interpolation-spacing.js @@ -30,9 +30,10 @@ module.exports = { /** @param {RuleContext} context */ create(context) { const options = context.options[0] || 'always' + const sourceCode = context.getSourceCode() const template = - context.parserServices.getTemplateBodyTokenStore && - context.parserServices.getTemplateBodyTokenStore() + sourceCode.parserServices.getTemplateBodyTokenStore && + sourceCode.parserServices.getTemplateBodyTokenStore() return utils.defineTemplateBodyVisitor(context, { /** @param {VExpressionContainer} node */ diff --git a/lib/rules/next-tick-style.js b/lib/rules/next-tick-style.js index 34e0c3db6..08cc85a1b 100644 --- a/lib/rules/next-tick-style.js +++ b/lib/rules/next-tick-style.js @@ -43,7 +43,10 @@ function getVueNextTickCallExpression(identifier, context) { identifier.parent.type === 'CallExpression' && identifier.parent.callee === identifier ) { - const variable = findVariable(context.getScope(), identifier) + const variable = findVariable( + utils.getScope(context, identifier), + identifier + ) if (variable != null && variable.defs.length === 1) { const def = variable.defs[0] diff --git a/lib/rules/no-async-in-computed-properties.js b/lib/rules/no-async-in-computed-properties.js index 2df1e55c0..6ee4373f1 100644 --- a/lib/rules/no-async-in-computed-properties.js +++ b/lib/rules/no-async-in-computed-properties.js @@ -260,8 +260,9 @@ module.exports = { return utils.compositingVisitors( { - Program() { - const tracker = new ReferenceTracker(context.getScope()) + /** @param {Program} program */ + Program(program) { + const tracker = new ReferenceTracker(utils.getScope(context, program)) const traceMap = utils.createCompositionApiTraceMap({ [ReferenceTracker.ESM]: true, computed: { diff --git a/lib/rules/no-child-content.js b/lib/rules/no-child-content.js index 6ccf10d18..62de865b8 100644 --- a/lib/rules/no-child-content.js +++ b/lib/rules/no-child-content.js @@ -123,8 +123,8 @@ module.exports = { if (elementNode.endTag === null) { return } - - const tokenStore = context.parserServices.getTemplateBodyTokenStore() + const sourceCode = context.getSourceCode() + const tokenStore = sourceCode.parserServices.getTemplateBodyTokenStore() const elementComments = tokenStore.getTokensBetween( elementNode.startTag, elementNode.endTag, diff --git a/lib/rules/no-dupe-keys.js b/lib/rules/no-dupe-keys.js index c690d8aa5..dd8b51c6d 100644 --- a/lib/rules/no-dupe-keys.js +++ b/lib/rules/no-dupe-keys.js @@ -118,7 +118,10 @@ module.exports = { for (const prop of props) { if (!prop.propName) continue - const variable = findVariable(context.getScope(), prop.propName) + const variable = findVariable( + utils.getScope(context, node), + prop.propName + ) if (!variable || variable.defs.length === 0) continue if ( @@ -149,7 +152,7 @@ module.exports = { */ function extractReferences(node) { if (node.type === 'Identifier') { - const variable = findVariable(context.getScope(), node) + const variable = findVariable(utils.getScope(context, node), node) if (!variable) { return [] } diff --git a/lib/rules/no-dupe-v-else-if.js b/lib/rules/no-dupe-v-else-if.js index 5102f6dc4..dc7c18c0b 100644 --- a/lib/rules/no-dupe-v-else-if.js +++ b/lib/rules/no-dupe-v-else-if.js @@ -83,9 +83,10 @@ module.exports = { }, /** @param {RuleContext} context */ create(context) { + const sourceCode = context.getSourceCode() const tokenStore = - context.parserServices.getTemplateBodyTokenStore && - context.parserServices.getTemplateBodyTokenStore() + sourceCode.parserServices.getTemplateBodyTokenStore && + sourceCode.parserServices.getTemplateBodyTokenStore() /** * Determines whether the two given nodes are considered to be equal. In particular, given that the nodes * represent expressions in a boolean context, `||` and `&&` can be considered as commutative operators. diff --git a/lib/rules/no-empty-component-block.js b/lib/rules/no-empty-component-block.js index 8a9420fc2..b2e428bc7 100644 --- a/lib/rules/no-empty-component-block.js +++ b/lib/rules/no-empty-component-block.js @@ -57,10 +57,11 @@ module.exports = { * @returns {RuleListener} AST event handlers. */ create(context) { - if (!context.parserServices.getDocumentFragment) { + const sourceCode = context.getSourceCode() + if (!sourceCode.parserServices.getDocumentFragment) { return {} } - const documentFragment = context.parserServices.getDocumentFragment() + const documentFragment = sourceCode.parserServices.getDocumentFragment() if (!documentFragment) { return {} } diff --git a/lib/rules/no-expose-after-await.js b/lib/rules/no-expose-after-await.js index 64661f1f3..e5ede6444 100644 --- a/lib/rules/no-expose-after-await.js +++ b/lib/rules/no-expose-after-await.js @@ -192,7 +192,10 @@ module.exports = { // `setup(props, {emit})` const variable = exposeParam.type === 'Identifier' - ? findVariable(context.getScope(), exposeParam) + ? findVariable( + utils.getScope(context, exposeParam), + exposeParam + ) : null if (!variable) { return @@ -205,7 +208,10 @@ module.exports = { } } else if (contextParam.type === 'Identifier') { // `setup(props, context)` - const variable = findVariable(context.getScope(), contextParam) + const variable = findVariable( + utils.getScope(context, contextParam), + contextParam + ) if (!variable) { return } diff --git a/lib/rules/no-extra-parens.js b/lib/rules/no-extra-parens.js index 7264677cc..afd0e061b 100644 --- a/lib/rules/no-extra-parens.js +++ b/lib/rules/no-extra-parens.js @@ -84,10 +84,11 @@ function isIIFE(node) { * @returns {TemplateListener} AST event handlers. */ function createForVueSyntax(context) { - if (!context.parserServices.getTemplateBodyTokenStore) { + const sourceCode = context.getSourceCode() + if (!sourceCode.parserServices.getTemplateBodyTokenStore) { return {} } - const tokenStore = context.parserServices.getTemplateBodyTokenStore() + const tokenStore = sourceCode.parserServices.getTemplateBodyTokenStore() /** * Checks if the given node turns into a filter when unwraped. diff --git a/lib/rules/no-lifecycle-after-await.js b/lib/rules/no-lifecycle-after-await.js index 6a54f1c58..21416f893 100644 --- a/lib/rules/no-lifecycle-after-await.js +++ b/lib/rules/no-lifecycle-after-await.js @@ -60,8 +60,9 @@ module.exports = { return utils.compositingVisitors( { - Program() { - const tracker = new ReferenceTracker(context.getScope()) + /** @param {Program} program */ + Program(program) { + const tracker = new ReferenceTracker(utils.getScope(context, program)) const traceMap = { /** @type {TraceMap} */ vue: { diff --git a/lib/rules/no-multi-spaces.js b/lib/rules/no-multi-spaces.js index 1dbac86e2..7e8f192a1 100644 --- a/lib/rules/no-multi-spaces.js +++ b/lib/rules/no-multi-spaces.js @@ -52,7 +52,8 @@ module.exports = { return { Program(node) { - if (context.parserServices.getTemplateBodyTokenStore == null) { + const sourceCode = context.getSourceCode() + if (sourceCode.parserServices.getTemplateBodyTokenStore == null) { const filename = context.getFilename() if (path.extname(filename) === '.vue') { context.report({ @@ -65,8 +66,7 @@ module.exports = { if (!node.templateBody) { return } - const sourceCode = context.getSourceCode() - const tokenStore = context.parserServices.getTemplateBodyTokenStore() + const tokenStore = sourceCode.parserServices.getTemplateBodyTokenStore() const tokens = tokenStore.getTokens(node.templateBody, { includeComments: true }) diff --git a/lib/rules/no-multiple-slot-args.js b/lib/rules/no-multiple-slot-args.js index 1b57832af..86bd63037 100644 --- a/lib/rules/no-multiple-slot-args.js +++ b/lib/rules/no-multiple-slot-args.js @@ -75,7 +75,7 @@ module.exports = { * @param {Identifier} node The node to verify */ function verifyReferences(node) { - const variable = findVariable(context.getScope(), node) + const variable = findVariable(utils.getScope(context, node), node) if (!variable) { return } diff --git a/lib/rules/no-mutating-props.js b/lib/rules/no-mutating-props.js index 57a191991..c00a92242 100644 --- a/lib/rules/no-mutating-props.js +++ b/lib/rules/no-mutating-props.js @@ -224,7 +224,7 @@ module.exports = { * @param {string[]} path */ function verifyPropVariable(prop, path) { - const variable = findVariable(context.getScope(), prop) + const variable = findVariable(utils.getScope(context, prop), prop) if (!variable) { return } diff --git a/lib/rules/no-restricted-block.js b/lib/rules/no-restricted-block.js index 8fc2b51be..87b4bda3e 100644 --- a/lib/rules/no-restricted-block.js +++ b/lib/rules/no-restricted-block.js @@ -90,9 +90,10 @@ module.exports = { /** @type {ParsedOption[]} */ const options = context.options.map(parseOption) + const sourceCode = context.getSourceCode() const documentFragment = - context.parserServices.getDocumentFragment && - context.parserServices.getDocumentFragment() + sourceCode.parserServices.getDocumentFragment && + sourceCode.parserServices.getDocumentFragment() function getTopLevelHTMLElements() { if (documentFragment) { diff --git a/lib/rules/no-restricted-call-after-await.js b/lib/rules/no-restricted-call-after-await.js index d2b2a1414..b235896a3 100644 --- a/lib/rules/no-restricted-call-after-await.js +++ b/lib/rules/no-restricted-call-after-await.js @@ -144,7 +144,7 @@ module.exports = { { /** @param {Program} node */ Program(node) { - const tracker = new ReferenceTracker(context.getScope()) + const tracker = new ReferenceTracker(utils.getScope(context, node)) for (const option of context.options) { const modules = normalizeModules(option.module, node) diff --git a/lib/rules/no-restricted-custom-event.js b/lib/rules/no-restricted-custom-event.js index f153b6921..98a87d807 100644 --- a/lib/rules/no-restricted-custom-event.js +++ b/lib/rules/no-restricted-custom-event.js @@ -213,7 +213,10 @@ module.exports = { } const emitParam = emitProperty.value // `setup(props, {emit})` - const variable = findVariable(context.getScope(), emitParam) + const variable = findVariable( + utils.getScope(context, emitParam), + emitParam + ) if (!variable) { return } @@ -222,7 +225,10 @@ module.exports = { } } else { // `setup(props, context)` - const variable = findVariable(context.getScope(), contextParam) + const variable = findVariable( + utils.getScope(context, contextParam), + contextParam + ) if (!variable) { return } diff --git a/lib/rules/no-setup-props-reactivity-loss.js b/lib/rules/no-setup-props-reactivity-loss.js index 1292ace7a..fc0406ba9 100644 --- a/lib/rules/no-setup-props-reactivity-loss.js +++ b/lib/rules/no-setup-props-reactivity-loss.js @@ -123,9 +123,10 @@ module.exports = { /** * @param {Pattern | null} node * @param {FunctionDeclaration | FunctionExpression | ArrowFunctionExpression | Program} scopeNode + * @param {import('eslint').Scope.Scope} currentScope * @param {string} scopeName */ - function processPattern(node, scopeNode, scopeName) { + function processPattern(node, scopeNode, currentScope, scopeName) { if (!node) { // no arguments return @@ -143,14 +144,14 @@ module.exports = { return } - const variable = findVariable(context.getScope(), node) + const variable = findVariable(currentScope, node) if (!variable) { return } const propsReferenceIds = new Set() for (const reference of variable.references) { // If reference is in another scope, we can't check it. - if (reference.from !== context.getScope()) { + if (reference.from !== currentScope) { continue } @@ -258,13 +259,20 @@ module.exports = { } else if (target.parent.type === 'AssignmentExpression') { id = target.parent.right === target ? target.parent.left : null } - processPattern(id, context.getSourceCode().ast, '<script setup>') + const currentScope = utils.getScope(context, node) + processPattern( + id, + context.getSourceCode().ast, + currentScope, + '<script setup>' + ) } }), utils.defineVueVisitor(context, { onSetupFunctionEnter(node) { + const currentScope = utils.getScope(context, node) const propsParam = utils.skipDefaultParamValue(node.params[0]) - processPattern(propsParam, node, 'setup()') + processPattern(propsParam, node, currentScope, 'setup()') } }) ) diff --git a/lib/rules/no-side-effects-in-computed-properties.js b/lib/rules/no-side-effects-in-computed-properties.js index 903cf43e7..76127c37f 100644 --- a/lib/rules/no-side-effects-in-computed-properties.js +++ b/lib/rules/no-side-effects-in-computed-properties.js @@ -135,7 +135,7 @@ module.exports = { return } - const variable = findVariable(context.getScope(), node) + const variable = findVariable(utils.getScope(context, node), node) if (!variable || variable.defs.length !== 1) { return } @@ -180,8 +180,9 @@ module.exports = { } return utils.compositingVisitors( { - Program() { - const tracker = new ReferenceTracker(context.getScope()) + /** @param {Program} program */ + Program(program) { + const tracker = new ReferenceTracker(utils.getScope(context, program)) const traceMap = utils.createCompositionApiTraceMap({ [ReferenceTracker.ESM]: true, computed: { diff --git a/lib/rules/no-unused-emit-declarations.js b/lib/rules/no-unused-emit-declarations.js index 1414b50c4..f96004a36 100644 --- a/lib/rules/no-unused-emit-declarations.js +++ b/lib/rules/no-unused-emit-declarations.js @@ -253,7 +253,7 @@ module.exports = { // `setup(props, {emit})` const variable = emitParam.type === 'Identifier' - ? findVariable(context.getScope(), emitParam) + ? findVariable(utils.getScope(context, emitParam), emitParam) : null if (!variable) { return @@ -263,7 +263,10 @@ module.exports = { } } else if (contextParam.type === 'Identifier') { // `setup(props, context)` - const variable = findVariable(context.getScope(), contextParam) + const variable = findVariable( + utils.getScope(context, contextParam), + contextParam + ) for (const reference of variable.references) { contextReferenceIds.add(reference.identifier) } @@ -294,7 +297,7 @@ module.exports = { const emitParam = node.parent.id const variable = emitParam.type === 'Identifier' - ? findVariable(context.getScope(), emitParam) + ? findVariable(utils.getScope(context, emitParam), emitParam) : null if (!variable) { return diff --git a/lib/rules/no-useless-mustaches.js b/lib/rules/no-useless-mustaches.js index 884cdf7a5..f4f858d9e 100644 --- a/lib/rules/no-useless-mustaches.js +++ b/lib/rules/no-useless-mustaches.js @@ -92,8 +92,7 @@ module.exports = { } else { return } - - const tokenStore = context.parserServices.getTemplateBodyTokenStore() + const tokenStore = sourceCode.parserServices.getTemplateBodyTokenStore() const hasComment = tokenStore .getTokens(node, { includeComments: true }) .some((t) => t.type === 'Block' || t.type === 'Line') diff --git a/lib/rules/no-useless-v-bind.js b/lib/rules/no-useless-v-bind.js index c78cd6b4b..34f0ad033 100644 --- a/lib/rules/no-useless-v-bind.js +++ b/lib/rules/no-useless-v-bind.js @@ -76,7 +76,7 @@ module.exports = { return } - const tokenStore = context.parserServices.getTemplateBodyTokenStore() + const tokenStore = sourceCode.parserServices.getTemplateBodyTokenStore() const hasComment = tokenStore .getTokens(value, { includeComments: true }) .some((t) => t.type === 'Block' || t.type === 'Line') diff --git a/lib/rules/no-watch-after-await.js b/lib/rules/no-watch-after-await.js index f566fb248..cbe1772bd 100644 --- a/lib/rules/no-watch-after-await.js +++ b/lib/rules/no-watch-after-await.js @@ -75,8 +75,9 @@ module.exports = { return utils.compositingVisitors( { - Program() { - const tracker = new ReferenceTracker(context.getScope()) + /** @param {Program} program */ + Program(program) { + const tracker = new ReferenceTracker(utils.getScope(context, program)) const traceMap = { vue: { [ReferenceTracker.ESM]: true, diff --git a/lib/rules/padding-line-between-blocks.js b/lib/rules/padding-line-between-blocks.js index e962488dd..f07655722 100644 --- a/lib/rules/padding-line-between-blocks.js +++ b/lib/rules/padding-line-between-blocks.js @@ -132,10 +132,11 @@ module.exports = { }, /** @param {RuleContext} context */ create(context) { - if (!context.parserServices.getDocumentFragment) { + const sourceCode = context.getSourceCode() + if (!sourceCode.parserServices.getDocumentFragment) { return {} } - const df = context.parserServices.getDocumentFragment() + const df = sourceCode.parserServices.getDocumentFragment() if (!df) { return {} } diff --git a/lib/rules/prefer-separate-static-class.js b/lib/rules/prefer-separate-static-class.js index 7adc68cb9..f01de1222 100644 --- a/lib/rules/prefer-separate-static-class.js +++ b/lib/rules/prefer-separate-static-class.js @@ -169,8 +169,9 @@ module.exports = { return } + const sourceCode = context.getSourceCode() const tokenStore = - context.parserServices.getTemplateBodyTokenStore() + sourceCode.parserServices.getTemplateBodyTokenStore() if (elements.length === 1) { yield* removeNodeWithComma(fixer, tokenStore, listNode) diff --git a/lib/rules/require-explicit-emits.js b/lib/rules/require-explicit-emits.js index 8b9645f51..7e06bf478 100644 --- a/lib/rules/require-explicit-emits.js +++ b/lib/rules/require-explicit-emits.js @@ -285,7 +285,7 @@ module.exports = { const emitParam = node.parent.id const variable = emitParam.type === 'Identifier' - ? findVariable(context.getScope(), emitParam) + ? findVariable(utils.getScope(context, emitParam), emitParam) : null if (!variable) { return @@ -361,7 +361,7 @@ module.exports = { // `setup(props, {emit})` const variable = emitParam.type === 'Identifier' - ? findVariable(context.getScope(), emitParam) + ? findVariable(utils.getScope(context, emitParam), emitParam) : null if (!variable) { return @@ -375,7 +375,10 @@ module.exports = { } } else if (contextParam.type === 'Identifier') { // `setup(props, context)` - const variable = findVariable(context.getScope(), contextParam) + const variable = findVariable( + utils.getScope(context, contextParam), + contextParam + ) if (!variable) { return } diff --git a/lib/rules/require-expose.js b/lib/rules/require-expose.js index c7e4e1126..41578839e 100644 --- a/lib/rules/require-expose.js +++ b/lib/rules/require-expose.js @@ -121,7 +121,7 @@ module.exports = { return true } if (node.type === 'Identifier') { - const variable = findVariable(context.getScope(), node) + const variable = findVariable(utils.getScope(context, node), node) if (variable) { for (const def of variable.defs) { if (def.type === 'FunctionName') { @@ -167,7 +167,7 @@ module.exports = { // `setup(props, {emit})` const variable = exposeParam.type === 'Identifier' - ? findVariable(context.getScope(), exposeParam) + ? findVariable(utils.getScope(context, exposeParam), exposeParam) : null if (!variable) { return @@ -180,7 +180,10 @@ module.exports = { } } else if (contextParam.type === 'Identifier') { // `setup(props, context)` - const variable = findVariable(context.getScope(), contextParam) + const variable = findVariable( + utils.getScope(context, contextParam), + contextParam + ) if (!variable) { return } diff --git a/lib/rules/require-slots-as-functions.js b/lib/rules/require-slots-as-functions.js index 671623cb3..686677ea8 100644 --- a/lib/rules/require-slots-as-functions.js +++ b/lib/rules/require-slots-as-functions.js @@ -78,7 +78,7 @@ module.exports = { * @param {Expression} reportNode The node to report */ function verifyReferences(node, reportNode) { - const variable = findVariable(context.getScope(), node) + const variable = findVariable(utils.getScope(context, node), node) if (!variable) { return } diff --git a/lib/rules/require-typed-ref.js b/lib/rules/require-typed-ref.js index e26ac1339..60a82432a 100644 --- a/lib/rules/require-typed-ref.js +++ b/lib/rules/require-typed-ref.js @@ -53,7 +53,11 @@ module.exports = { return {} } - const defines = iterateDefineRefs(context.getScope()) + const defines = iterateDefineRefs( + /** @type {import('eslint').Scope.Scope} */ ( + context.getSourceCode().scopeManager.globalScope + ) + ) /** * @param {string} name diff --git a/lib/rules/return-in-computed-property.js b/lib/rules/return-in-computed-property.js index 41860eba8..54d2553a1 100644 --- a/lib/rules/return-in-computed-property.js +++ b/lib/rules/return-in-computed-property.js @@ -54,8 +54,9 @@ module.exports = { return Object.assign( { - Program() { - const tracker = new ReferenceTracker(context.getScope()) + /** @param {Program} program */ + Program(program) { + const tracker = new ReferenceTracker(utils.getScope(context, program)) const traceMap = utils.createCompositionApiTraceMap({ [ReferenceTracker.ESM]: true, computed: { diff --git a/lib/rules/singleline-html-element-content-newline.js b/lib/rules/singleline-html-element-content-newline.js index d89fd940a..69d50734f 100644 --- a/lib/rules/singleline-html-element-content-newline.js +++ b/lib/rules/singleline-html-element-content-newline.js @@ -92,10 +92,10 @@ module.exports = { const ignores = new Set([...options.ignores, ...options.externalIgnores]) const ignoreWhenNoAttributes = options.ignoreWhenNoAttributes const ignoreWhenEmpty = options.ignoreWhenEmpty - const template = - context.parserServices.getTemplateBodyTokenStore && - context.parserServices.getTemplateBodyTokenStore() const sourceCode = context.getSourceCode() + const template = + sourceCode.parserServices.getTemplateBodyTokenStore && + sourceCode.parserServices.getTemplateBodyTokenStore() /** @type {VElement | null} */ let inIgnoreElement = null diff --git a/lib/rules/syntaxes/slot-attribute.js b/lib/rules/syntaxes/slot-attribute.js index 3292cd9de..002907fe6 100644 --- a/lib/rules/syntaxes/slot-attribute.js +++ b/lib/rules/syntaxes/slot-attribute.js @@ -13,8 +13,8 @@ module.exports = { createTemplateBodyVisitor(context) { const sourceCode = context.getSourceCode() const tokenStore = - context.parserServices.getTemplateBodyTokenStore && - context.parserServices.getTemplateBodyTokenStore() + sourceCode.parserServices.getTemplateBodyTokenStore && + sourceCode.parserServices.getTemplateBodyTokenStore() /** * Checks whether the given node can convert to the `v-slot`. diff --git a/lib/rules/syntaxes/slot-scope-attribute.js b/lib/rules/syntaxes/slot-scope-attribute.js index 53a54d6de..7332c5b7d 100644 --- a/lib/rules/syntaxes/slot-scope-attribute.js +++ b/lib/rules/syntaxes/slot-scope-attribute.js @@ -18,8 +18,8 @@ module.exports = { createTemplateBodyVisitor(context, { fixToUpgrade } = {}) { const sourceCode = context.getSourceCode() const tokenStore = - context.parserServices.getTemplateBodyTokenStore && - context.parserServices.getTemplateBodyTokenStore() + sourceCode.parserServices.getTemplateBodyTokenStore && + sourceCode.parserServices.getTemplateBodyTokenStore() /** * Checks whether the given node can convert to the `v-slot`. diff --git a/lib/rules/v-for-delimiter-style.js b/lib/rules/v-for-delimiter-style.js index c0e3df654..3a4944803 100644 --- a/lib/rules/v-for-delimiter-style.js +++ b/lib/rules/v-for-delimiter-style.js @@ -32,9 +32,10 @@ module.exports = { return utils.defineTemplateBodyVisitor(context, { /** @param {VForExpression} node */ VForExpression(node) { + const sourceCode = context.getSourceCode() const tokenStore = - context.parserServices.getTemplateBodyTokenStore && - context.parserServices.getTemplateBodyTokenStore() + sourceCode.parserServices.getTemplateBodyTokenStore && + sourceCode.parserServices.getTemplateBodyTokenStore() const delimiterToken = /** @type {Token} */ ( tokenStore.getTokenAfter( diff --git a/lib/rules/v-on-function-call.js b/lib/rules/v-on-function-call.js index ba91b92b3..efd5b6fa1 100644 --- a/lib/rules/v-on-function-call.js +++ b/lib/rules/v-on-function-call.js @@ -126,7 +126,9 @@ module.exports = { return } - const tokenStore = context.parserServices.getTemplateBodyTokenStore() + const sourceCode = context.getSourceCode() + const tokenStore = + sourceCode.parserServices.getTemplateBodyTokenStore() const tokens = tokenStore.getTokens(node.parent, { includeComments: true }) diff --git a/lib/rules/v-on-handler-style.js b/lib/rules/v-on-handler-style.js index 890965156..10ff9b6b1 100644 --- a/lib/rules/v-on-handler-style.js +++ b/lib/rules/v-on-handler-style.js @@ -236,7 +236,8 @@ module.exports = { * @param {VExpressionContainer} node */ function getVExpressionContainerTokenInfo(node) { - const tokenStore = context.parserServices.getTemplateBodyTokenStore() + const sourceCode = context.getSourceCode() + const tokenStore = sourceCode.parserServices.getTemplateBodyTokenStore() const tokens = tokenStore.getTokens(node, { includeComments: true }) @@ -432,7 +433,9 @@ module.exports = { return } yield fixer.insertTextBeforeRange(rangeWithoutQuotes, '() => ') - const tokenStore = context.parserServices.getTemplateBodyTokenStore() + const sourceCode = context.getSourceCode() + const tokenStore = + sourceCode.parserServices.getTemplateBodyTokenStore() const firstToken = tokenStore.getFirstToken(node) const lastToken = tokenStore.getLastToken(node) if (firstToken.value === '{' && lastToken.value === '}') return diff --git a/lib/rules/valid-define-emits.js b/lib/rules/valid-define-emits.js index 2c83faa2b..6f6085cb0 100644 --- a/lib/rules/valid-define-emits.js +++ b/lib/rules/valid-define-emits.js @@ -69,7 +69,7 @@ module.exports = { Identifier(node) { for (const defineEmits of emitsDefExpressions) { if (utils.inRange(defineEmits.range, node)) { - const variable = findVariable(context.getScope(), node) + const variable = findVariable(utils.getScope(context, node), node) if ( variable && variable.references.some((ref) => ref.identifier === node) && diff --git a/lib/rules/valid-define-options.js b/lib/rules/valid-define-options.js index fad893b41..71dff3258 100644 --- a/lib/rules/valid-define-options.js +++ b/lib/rules/valid-define-options.js @@ -86,7 +86,7 @@ module.exports = { Identifier(node) { for (const defineOptions of optionsDefExpressions) { if (utils.inRange(defineOptions.range, node)) { - const variable = findVariable(context.getScope(), node) + const variable = findVariable(utils.getScope(context, node), node) if ( variable && variable.references.some((ref) => ref.identifier === node) && diff --git a/lib/rules/valid-define-props.js b/lib/rules/valid-define-props.js index 7e3b0a34c..bd1e41bdc 100644 --- a/lib/rules/valid-define-props.js +++ b/lib/rules/valid-define-props.js @@ -70,7 +70,7 @@ module.exports = { Identifier(node) { for (const defineProps of propsDefExpressions) { if (utils.inRange(defineProps.range, node)) { - const variable = findVariable(context.getScope(), node) + const variable = findVariable(utils.getScope(context, node), node) if ( variable && variable.references.some((ref) => ref.identifier === node) && diff --git a/lib/rules/valid-next-tick.js b/lib/rules/valid-next-tick.js index f9743fc1d..969488cbf 100644 --- a/lib/rules/valid-next-tick.js +++ b/lib/rules/valid-next-tick.js @@ -35,7 +35,7 @@ function getVueNextTickNode(identifier, context) { } // Vue 3 Global API: import { nextTick as nt } from 'vue'; nt() - const variable = findVariable(context.getScope(), identifier) + const variable = findVariable(utils.getScope(context, identifier), identifier) if (variable != null && variable.defs.length === 1) { const def = variable.defs[0] diff --git a/lib/rules/valid-v-slot.js b/lib/rules/valid-v-slot.js index c33107966..d16084722 100644 --- a/lib/rules/valid-v-slot.js +++ b/lib/rules/valid-v-slot.js @@ -278,8 +278,8 @@ module.exports = { create(context) { const sourceCode = context.getSourceCode() const tokenStore = - context.parserServices.getTemplateBodyTokenStore && - context.parserServices.getTemplateBodyTokenStore() + sourceCode.parserServices.getTemplateBodyTokenStore && + sourceCode.parserServices.getTemplateBodyTokenStore() const options = context.options[0] || {} const allowModifiers = options.allowModifiers === true diff --git a/lib/utils/index.js b/lib/utils/index.js index 4073b6915..9bfef3577 100644 --- a/lib/utils/index.js +++ b/lib/utils/index.js @@ -5,6 +5,8 @@ */ 'use strict' +const { getScope } = require('./scope') + /** * @typedef {import('eslint').Rule.RuleModule} RuleModule * @typedef {import('estree').Position} Position @@ -71,7 +73,7 @@ const { const componentComments = new WeakMap() /** @type { Map<string, RuleModule> | null } */ -let ruleMap = null +let coreRuleMap = null /** * Get the core rule implementation from the rule name * @param {string} name @@ -79,8 +81,15 @@ let ruleMap = null */ function getCoreRule(name) { const eslint = require('eslint') - const map = ruleMap || (ruleMap = new eslint.Linter().getRules()) - return map.get(name) || null + try { + const map = coreRuleMap || (coreRuleMap = new eslint.Linter().getRules()) + return map.get(name) || null + } catch { + // getRules() is no longer available in flat config. + } + + const { builtinRules } = require('eslint/use-at-your-own-risk') + return /** @type {any} */ (builtinRules.get(name) || null) } /** @@ -129,8 +138,8 @@ function newProxy(target, ...propsArray) { function wrapContextToOverrideTokenMethods(context, tokenStore, options) { const eslintSourceCode = context.getSourceCode() const rootNode = options.applyDocument - ? context.parserServices.getDocumentFragment && - context.parserServices.getDocumentFragment() + ? eslintSourceCode.parserServices.getDocumentFragment && + eslintSourceCode.parserServices.getDocumentFragment() : eslintSourceCode.ast.templateBody /** @type {Token[] | null} */ let tokensAndComments = null @@ -427,9 +436,10 @@ module.exports = { } = options || {} return { create(context) { + const sourceCode = context.getSourceCode() const tokenStore = - context.parserServices.getTemplateBodyTokenStore && - context.parserServices.getTemplateBodyTokenStore() + sourceCode.parserServices.getTemplateBodyTokenStore && + sourceCode.parserServices.getTemplateBodyTokenStore() // The `context.getSourceCode()` cannot access the tokens of templates. // So override the methods which access to tokens by the `tokenStore`. @@ -603,9 +613,9 @@ module.exports = { if (node.value.expression != null) { return false } - + const sourceCode = context.getSourceCode() const valueNode = node.value - const tokenStore = context.parserServices.getTemplateBodyTokenStore() + const tokenStore = sourceCode.parserServices.getTemplateBodyTokenStore() let quote1 = null let quote2 = null // `node.value` may be only comments, so cannot get the correct tokens with `tokenStore.getTokens(node.value)`. @@ -1606,6 +1616,7 @@ module.exports = { * @property {boolean} hasReturn * @property {boolean} hasReturnValue * @property {ArrowFunctionExpression | FunctionExpression | FunctionDeclaration} node + * @property {CodePathSegment[]} currentSegments */ /** @type {FuncInfo | null} */ @@ -1615,10 +1626,7 @@ module.exports = { if (!funcInfo) { return true } - if ( - funcInfo.codePath && - funcInfo.codePath.currentSegments.some((segment) => segment.reachable) - ) { + if (funcInfo.currentSegments.some((segment) => segment.reachable)) { return false } return !treatUndefinedAsUnspecified || funcInfo.hasReturnValue @@ -1637,6 +1645,7 @@ module.exports = { ) { funcInfo = { codePath, + currentSegments: [], funcInfo, hasReturn: false, hasReturnValue: false, @@ -1644,6 +1653,12 @@ module.exports = { } } }, + onCodePathSegmentStart(segment) { + funcInfo?.currentSegments.push(segment) + }, + onCodePathSegmentEnd() { + funcInfo?.currentSegments.pop() + }, onCodePathEnd() { funcInfo = funcInfo && funcInfo.funcInfo }, @@ -1821,7 +1836,7 @@ module.exports = { return false } - const variable = findVariable(context.getScope(), node) + const variable = findVariable(getScope(context, node), node) if (variable != null && variable.defs.length === 1) { const def = variable.defs[0] @@ -2050,7 +2065,8 @@ function defineTemplateBodyVisitor( scriptVisitor, options ) { - if (context.parserServices.defineTemplateBodyVisitor == null) { + const sourceCode = context.getSourceCode() + if (sourceCode.parserServices.defineTemplateBodyVisitor == null) { const filename = context.getFilename() if (path.extname(filename) === '.vue') { context.report({ @@ -2061,7 +2077,7 @@ function defineTemplateBodyVisitor( } return {} } - return context.parserServices.defineTemplateBodyVisitor( + return sourceCode.parserServices.defineTemplateBodyVisitor( templateBodyVisitor, scriptVisitor, options @@ -2078,7 +2094,8 @@ function defineTemplateBodyVisitor( * @returns {RuleListener} The merged visitor. */ function defineDocumentVisitor(context, documentVisitor, options) { - if (context.parserServices.defineDocumentVisitor == null) { + const sourceCode = context.getSourceCode() + if (sourceCode.parserServices.defineDocumentVisitor == null) { const filename = context.getFilename() if (path.extname(filename) === '.vue') { context.report({ @@ -2089,7 +2106,10 @@ function defineDocumentVisitor(context, documentVisitor, options) { } return {} } - return context.parserServices.defineDocumentVisitor(documentVisitor, options) + return sourceCode.parserServices.defineDocumentVisitor( + documentVisitor, + options + ) } /** @@ -2134,33 +2154,6 @@ function findVariableByIdentifier(context, node) { return findVariable(getScope(context, node), node) } -/** - * Gets the scope for the current node - * @param {RuleContext} context The rule context - * @param {ESNode} currentNode The node to get the scope of - * @returns { import('eslint').Scope.Scope } The scope information for this node - */ -function getScope(context, currentNode) { - // On Program node, get the outermost scope to avoid return Node.js special function scope or ES modules scope. - const inner = currentNode.type !== 'Program' - const scopeManager = context.getSourceCode().scopeManager - - /** @type {ESNode | null} */ - let node = currentNode - for (; node; node = /** @type {ESNode | null} */ (node.parent)) { - const scope = scopeManager.acquire(node, inner) - - if (scope) { - if (scope.type === 'function-expression-name') { - return scope.childScopes[0] - } - return scope - } - } - - return scopeManager.scopes[0] -} - /** * Finds the property with the given name from the given ObjectExpression node. * @param {ObjectExpression} node @@ -2462,9 +2455,10 @@ function isScriptSetup(context) { * @returns {VElement | null} the element of `<script setup>` */ function getScriptSetupElement(context) { + const sourceCode = context.getSourceCode() const df = - context.parserServices.getDocumentFragment && - context.parserServices.getDocumentFragment() + sourceCode.parserServices.getDocumentFragment && + sourceCode.parserServices.getDocumentFragment() if (!df) { return null } @@ -2720,7 +2714,7 @@ function isSFCObject(context, node) { ) { return false } - const variable = findVariable(context.getScope(), parent.id) + const variable = findVariable(getScope(context, node), parent.id) if (!variable) { return false } @@ -3181,7 +3175,7 @@ function getObjectOrArray(context, node) { return node } if (node.type === 'Identifier') { - const variable = findVariable(context.getScope(), node) + const variable = findVariable(getScope(context, node), node) if (variable != null && variable.defs.length === 1) { const def = variable.defs[0] diff --git a/lib/utils/scope.js b/lib/utils/scope.js new file mode 100644 index 000000000..bc34c6425 --- /dev/null +++ b/lib/utils/scope.js @@ -0,0 +1,30 @@ +module.exports = { + getScope +} + +/** + * Gets the scope for the current node + * @param {RuleContext} context The rule context + * @param {ESNode} currentNode The node to get the scope of + * @returns { import('eslint').Scope.Scope } The scope information for this node + */ +function getScope(context, currentNode) { + // On Program node, get the outermost scope to avoid return Node.js special function scope or ES modules scope. + const inner = currentNode.type !== 'Program' + const scopeManager = context.getSourceCode().scopeManager + + /** @type {ESNode | null} */ + let node = currentNode + for (; node; node = /** @type {ESNode | null} */ (node.parent)) { + const scope = scopeManager.acquire(node, inner) + + if (scope) { + if (scope.type === 'function-expression-name') { + return scope.childScopes[0] + } + return scope + } + } + + return scopeManager.scopes[0] +} diff --git a/lib/utils/style-variables/index.js b/lib/utils/style-variables/index.js index 841f72f55..66f224306 100644 --- a/lib/utils/style-variables/index.js +++ b/lib/utils/style-variables/index.js @@ -40,9 +40,10 @@ const cache = new WeakMap() * @returns {StyleVariablesContext | null} */ function getStyleVariablesContext(context) { + const sourceCode = context.getSourceCode() const df = - context.parserServices.getDocumentFragment && - context.parserServices.getDocumentFragment() + sourceCode.parserServices.getDocumentFragment && + sourceCode.parserServices.getDocumentFragment() if (!df) { return null } diff --git a/lib/utils/ts-utils/ts-ast.js b/lib/utils/ts-utils/ts-ast.js index 3a7356a2a..ddbb9de05 100644 --- a/lib/utils/ts-utils/ts-ast.js +++ b/lib/utils/ts-utils/ts-ast.js @@ -1,3 +1,4 @@ +const { getScope } = require('../scope') const { findVariable } = require('@eslint-community/eslint-utils') const { inferRuntimeTypeFromTypeNode } = require('./ts-types') /** @@ -279,7 +280,10 @@ function flattenTypeNodes(context, node) { node.typeName.type === 'Identifier' ) { const refName = node.typeName.name - const variable = findVariable(context.getScope(), refName) + const variable = findVariable( + getScope(context, /** @type {any} */ (node)), + refName + ) if (variable && variable.defs.length === 1) { const defNode = /** @type {TSESTreeNode} */ (variable.defs[0].node) if (defNode.type === 'TSInterfaceDeclaration') { @@ -372,7 +376,10 @@ function inferRuntimeType(context, node, checked = new Set()) { } case 'TSTypeReference': { if (node.typeName.type === 'Identifier') { - const variable = findVariable(context.getScope(), node.typeName.name) + const variable = findVariable( + getScope(context, /** @type {any} */ (node)), + node.typeName.name + ) if (variable && variable.defs.length === 1) { const defNode = /** @type {TSESTreeNode} */ (variable.defs[0].node) if (defNode.type === 'TSInterfaceDeclaration') { diff --git a/lib/utils/ts-utils/ts-types.js b/lib/utils/ts-utils/ts-types.js index e684831e4..abb303862 100644 --- a/lib/utils/ts-utils/ts-types.js +++ b/lib/utils/ts-utils/ts-types.js @@ -45,14 +45,15 @@ module.exports = { * @returns {Services|null} */ function getTSParserServices(context) { - const tsNodeMap = context.parserServices.esTreeNodeToTSNodeMap + const sourceCode = context.getSourceCode() + const tsNodeMap = sourceCode.parserServices.esTreeNodeToTSNodeMap if (!tsNodeMap) return null const hasFullTypeInformation = - context.parserServices.hasFullTypeInformation !== false + sourceCode.parserServices.hasFullTypeInformation !== false const checker = (hasFullTypeInformation && - context.parserServices.program && - context.parserServices.program.getTypeChecker()) || + sourceCode.parserServices.program && + sourceCode.parserServices.program.getTypeChecker()) || null if (!checker) return null const ts = getTypeScript() From b564976e161b860bd129cfff4f498fbf3f0c6815 Mon Sep 17 00:00:00 2001 From: ota-meshi <otameshiyo23@gmail.com> Date: Wed, 29 Nov 2023 20:05:21 +0900 Subject: [PATCH 2/2] fix site --- .../build-system/shim/eslint/use-at-your-own-risk.mjs | 3 +++ docs/.vitepress/config.mts | 4 ++++ 2 files changed, 7 insertions(+) create mode 100644 docs/.vitepress/build-system/shim/eslint/use-at-your-own-risk.mjs diff --git a/docs/.vitepress/build-system/shim/eslint/use-at-your-own-risk.mjs b/docs/.vitepress/build-system/shim/eslint/use-at-your-own-risk.mjs new file mode 100644 index 000000000..0db0b01c2 --- /dev/null +++ b/docs/.vitepress/build-system/shim/eslint/use-at-your-own-risk.mjs @@ -0,0 +1,3 @@ +export default { + /* empty */ +} diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index 66e0f3e3a..0e1e21730 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -145,6 +145,10 @@ export default async () => { plugins: [vitePluginRequireResolve(), viteCommonjs()], resolve: { alias: { + 'eslint/use-at-your-own-risk': path.join( + dirname, + './build-system/shim/eslint/use-at-your-own-risk.mjs' + ), eslint: path.join(dirname, './build-system/shim/eslint.mjs'), assert: path.join(dirname, './build-system/shim/assert.mjs'), path: path.join(dirname, './build-system/shim/path.mjs'),