You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
130 lines
3.5 KiB
130 lines
3.5 KiB
/** |
|
* @author Yosuke Ota <https://github.com/ota-meshi> |
|
* See LICENSE file in root directory for full license. |
|
*/ |
|
'use strict' |
|
|
|
const utils = require('../utils') |
|
|
|
module.exports = { |
|
meta: { |
|
type: 'suggestion', |
|
docs: { |
|
description: 'enforce use of `defineOptions` instead of default export', |
|
categories: undefined, |
|
url: 'https://eslint.vuejs.org/rules/prefer-define-options.html' |
|
}, |
|
fixable: 'code', |
|
schema: [], |
|
messages: { |
|
preferDefineOptions: 'Use `defineOptions` instead of default export.' |
|
} |
|
}, |
|
/** |
|
* @param {RuleContext} context |
|
* @returns {RuleListener} |
|
*/ |
|
create(context) { |
|
const scriptSetup = utils.getScriptSetupElement(context) |
|
if (!scriptSetup) { |
|
return {} |
|
} |
|
|
|
/** @type {CallExpression | null} */ |
|
let defineOptionsNode = null |
|
/** @type {ExportDefaultDeclaration | null} */ |
|
let exportDefaultDeclaration = null |
|
/** @type {ImportDeclaration|null} */ |
|
let lastImportDeclaration = null |
|
|
|
return utils.compositingVisitors( |
|
utils.defineScriptSetupVisitor(context, { |
|
ImportDeclaration(node) { |
|
lastImportDeclaration = node |
|
}, |
|
onDefineOptionsEnter(node) { |
|
defineOptionsNode = node |
|
} |
|
}), |
|
{ |
|
ExportDefaultDeclaration(node) { |
|
exportDefaultDeclaration = node |
|
}, |
|
'Program:exit'() { |
|
if (!exportDefaultDeclaration) { |
|
return |
|
} |
|
context.report({ |
|
node: exportDefaultDeclaration, |
|
messageId: 'preferDefineOptions', |
|
fix: defineOptionsNode |
|
? null |
|
: buildFix(exportDefaultDeclaration, scriptSetup) |
|
}) |
|
} |
|
} |
|
) |
|
|
|
/** |
|
* @param {ExportDefaultDeclaration} node |
|
* @param {VElement} scriptSetup |
|
* @returns {(fixer: RuleFixer) => Fix[]} |
|
*/ |
|
function buildFix(node, scriptSetup) { |
|
return (fixer) => { |
|
const sourceCode = context.getSourceCode() |
|
|
|
// Calc remove range |
|
/** @type {Range} */ |
|
let removeRange = [...node.range] |
|
|
|
const script = scriptSetup.parent.children |
|
.filter(utils.isVElement) |
|
.find( |
|
(node) => |
|
node.name === 'script' && !utils.hasAttribute(node, 'setup') |
|
) |
|
if ( |
|
script && |
|
script.endTag && |
|
sourceCode |
|
.getTokensBetween(script.startTag, script.endTag, { |
|
includeComments: true |
|
}) |
|
.every( |
|
(token) => |
|
removeRange[0] <= token.range[0] && |
|
token.range[1] <= removeRange[1] |
|
) |
|
) { |
|
removeRange = [...script.range] |
|
} |
|
const removeStartLoc = sourceCode.getLocFromIndex(removeRange[0]) |
|
if ( |
|
sourceCode.lines[removeStartLoc.line - 1] |
|
.slice(0, removeStartLoc.column) |
|
.trim() === '' |
|
) { |
|
removeRange[0] = |
|
removeStartLoc.line === 1 |
|
? 0 |
|
: sourceCode.getIndexFromLoc({ |
|
line: removeStartLoc.line - 1, |
|
column: sourceCode.lines[removeStartLoc.line - 2].length |
|
}) |
|
} |
|
|
|
/** @type {VStartTag | ImportDeclaration} */ |
|
const insertAfterTag = lastImportDeclaration || scriptSetup.startTag |
|
|
|
return [ |
|
fixer.removeRange(removeRange), |
|
fixer.insertTextAfter( |
|
insertAfterTag, |
|
`\ndefineOptions(${sourceCode.getText(node.declaration)})\n` |
|
) |
|
] |
|
} |
|
} |
|
} |
|
}
|
|
|