eslint-plugin-vue
Version:
Official ESLint plugin for Vue.js
133 lines (120 loc) • 3.53 kB
JavaScript
/**
* @author Wayne Zhang
* See LICENSE file in root directory for full license.
*/
'use strict'
const utils = require('../utils')
const { ReferenceTracker } = require('@eslint-community/eslint-utils')
/**
* @typedef {import('@eslint-community/eslint-utils').TYPES.TraceMap} TraceMap
*/
/** @type {TraceMap} */
const deletedImportApisMap = {
set: {
[ReferenceTracker.CALL]: true
},
del: {
[ReferenceTracker.CALL]: true
}
}
const deprecatedApis = new Set(['set', 'delete'])
const deprecatedDollarApis = new Set(['$set', '$delete'])
/**
* @param {Expression|Super} node
*/
function isVue(node) {
return node.type === 'Identifier' && node.name === 'Vue'
}
module.exports = {
meta: {
type: 'problem',
docs: {
description:
'disallow using deprecated `$delete` and `$set` (in Vue.js 3.0.0+)',
categories: ['vue3-essential'],
url: 'https://eslint.vuejs.org/rules/no-deprecated-delete-set.html'
},
fixable: null,
schema: [],
messages: {
deprecated: 'The `$delete`, `$set` is deprecated.'
}
},
/** @param {RuleContext} context */
create(context) {
/**
* @param {Identifier} identifier
* @param {RuleContext} context
* @returns {CallExpression|undefined}
*/
function getVueDeprecatedCallExpression(identifier, context) {
// Instance API: this.$set()
if (
deprecatedDollarApis.has(identifier.name) &&
identifier.parent.type === 'MemberExpression' &&
utils.isThis(identifier.parent.object, context) &&
identifier.parent.parent.type === 'CallExpression' &&
identifier.parent.parent.callee === identifier.parent
) {
return identifier.parent.parent
}
// Vue 2 Global API: Vue.set()
if (
deprecatedApis.has(identifier.name) &&
identifier.parent.type === 'MemberExpression' &&
isVue(identifier.parent.object) &&
identifier.parent.parent.type === 'CallExpression' &&
identifier.parent.parent.callee === identifier.parent
) {
return identifier.parent.parent
}
return undefined
}
const nodeVisitor = {
/** @param {Identifier} node */
Identifier(node) {
const callExpression = getVueDeprecatedCallExpression(node, context)
if (!callExpression) {
return
}
context.report({
node,
messageId: 'deprecated'
})
}
}
return utils.compositingVisitors(
utils.defineVueVisitor(context, nodeVisitor),
utils.defineScriptSetupVisitor(context, nodeVisitor),
{
/** @param {Program} node */
Program(node) {
const tracker = new ReferenceTracker(utils.getScope(context, node))
// import { set } from 'vue'; set()
const esmTraceMap = {
vue: {
[ReferenceTracker.ESM]: true,
...deletedImportApisMap
}
}
// const { set } = require('vue'); set()
const cjsTraceMap = {
vue: {
...deletedImportApisMap
}
}
for (const { node } of [
...tracker.iterateEsmReferences(esmTraceMap),
...tracker.iterateCjsReferences(cjsTraceMap)
]) {
const refNode = /** @type {CallExpression} */ (node)
context.report({
node: refNode.callee,
messageId: 'deprecated'
})
}
}
}
)
}
}