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 =