diff --git a/lib/rules/multi-word-component-names.js b/lib/rules/multi-word-component-names.js index 6f73de294..8413bb5f0 100644 --- a/lib/rules/multi-word-component-names.js +++ b/lib/rules/multi-word-component-names.js @@ -111,7 +111,7 @@ module.exports = { 'Program:exit'(node) { if (hasName) return if (!hasVue && node.body.length > 0) return - const fileName = context.getFilename() + const fileName = utils.getPhysicalFilename(context) const componentName = path.basename(fileName, path.extname(fileName)) if ( utils.isVueFile(fileName) && diff --git a/lib/rules/no-multi-spaces.js b/lib/rules/no-multi-spaces.js index aa8b70a22..209a9f967 100644 --- a/lib/rules/no-multi-spaces.js +++ b/lib/rules/no-multi-spaces.js @@ -4,7 +4,7 @@ */ 'use strict' -const path = require('path') +const utils = require('../utils') // ------------------------------------------------------------------------------ // Rule Definition @@ -52,8 +52,8 @@ module.exports = { return { Program(node) { if (context.parserServices.getTemplateBodyTokenStore == null) { - const filename = context.getFilename() - if (path.extname(filename) === '.vue') { + const filename = utils.getPhysicalFilename(context) + if (utils.isVueFile(filename)) { context.report({ loc: { line: 1, column: 0 }, message: diff --git a/lib/rules/require-direct-export.js b/lib/rules/require-direct-export.js index 18897eb07..aef7530d1 100644 --- a/lib/rules/require-direct-export.js +++ b/lib/rules/require-direct-export.js @@ -31,7 +31,7 @@ module.exports = { }, /** @param {RuleContext} context */ create(context) { - const filePath = context.getFilename() + const filePath = utils.getPhysicalFilename(context) if (!utils.isVueFile(filePath)) return {} const disallowFunctional = (context.options[0] || {}) diff --git a/lib/utils/indent-common.js b/lib/utils/indent-common.js index 020b6373b..ab8690e8c 100644 --- a/lib/utils/indent-common.js +++ b/lib/utils/indent-common.js @@ -33,6 +33,7 @@ const { last } = require('./indent-utils') const { defineVisitor: tsDefineVisitor } = require('./indent-ts') +const utils = require('../utils') /** * @typedef {import('../../typings/eslint-plugin-vue/util-types/node').HasLocation} HasLocation @@ -205,7 +206,8 @@ module.exports.defineVisitor = function create( tokenStore, defaultOptions ) { - if (!context.getFilename().endsWith('.vue')) return {} + const filename = utils.getPhysicalFilename(context) + if (!utils.isVueFile(filename)) return {} const options = parseOptions( context.options[0], diff --git a/lib/utils/index.js b/lib/utils/index.js index 69cd84a31..68c63f034 100644 --- a/lib/utils/index.js +++ b/lib/utils/index.js @@ -311,6 +311,18 @@ function wrapContextToOverrideReportMethodToSkipDynamicArgument(context) { }) } +/** + * Return the full path of the file on disk, if not set, it will fallback to `context.getFilename()`. + * @param {RuleContext} context The ESLint rule context. + * @returns {string} + */ +function getPhysicalFilename(context) { + if (context.getPhysicalFilename) { + return context.getPhysicalFilename() + } + return context.getFilename() +} + // ------------------------------------------------------------------------------ // Exports // ------------------------------------------------------------------------------ @@ -1891,7 +1903,14 @@ module.exports = { } return true - } + }, + + /** + * Return the full path of the file on disk, if not set, it will fallback to `context.getFilename()`. + * @param {RuleContext} context The ESLint rule context. + * @returns {string} + */ + getPhysicalFilename } // ------------------------------------------------------------------------------ @@ -1987,8 +2006,8 @@ function defineTemplateBodyVisitor( options ) { if (context.parserServices.defineTemplateBodyVisitor == null) { - const filename = context.getFilename() - if (path.extname(filename) === '.vue') { + const filename = getPhysicalFilename(context) + if (isVueFile(filename)) { context.report({ loc: { line: 1, column: 0 }, message: @@ -2015,8 +2034,8 @@ function defineTemplateBodyVisitor( */ function defineDocumentVisitor(context, documentVisitor, options) { if (context.parserServices.defineDocumentVisitor == null) { - const filename = context.getFilename() - if (path.extname(filename) === '.vue') { + const filename = getPhysicalFilename(context) + if (isVueFile(filename)) { context.report({ loc: { line: 1, column: 0 }, message: @@ -2373,6 +2392,14 @@ function getVExpressionContainer(node) { * @param {string} path */ function isVueFile(path) { + /** + * When `path` is `context.getFilename()`, it returns the filename associated with the source or `` if not specified. + * When `path` is `context.getPhysicalFilename()`, it returns the full path of the file on disk or `` if not specified. + * If filename is not specified, we assume it's a vue file. + */ + if (['', ''].includes(path)) { + return true + } return path.endsWith('.vue') || path.endsWith('.jsx') } @@ -2583,7 +2610,7 @@ function isSFCObject(context, node) { if (node.type !== 'ObjectExpression') { return false } - const filePath = context.getFilename() + const filePath = getPhysicalFilename(context) const ext = path.extname(filePath) if (ext !== '.vue' && ext) { return false diff --git a/typings/eslint/index.d.ts b/typings/eslint/index.d.ts index 7bfda0245..efb35dd52 100644 --- a/typings/eslint/index.d.ts +++ b/typings/eslint/index.d.ts @@ -329,6 +329,15 @@ export namespace Rule { // eslint@6 does not have this method. getCwd?: () => string + + /** + * When linting a file, it returns the full path of the file on disk without any code block information. + * When linting text, it returns the value passed to `—stdin-filename` or `` if not specified. + * If not set, it will fallback to `getFilename()` + * This was added in eslint@7.28.0 + * @since 7.28.0 + */ + getPhysicalFilename?: () => string } type ReportDescriptor =