Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit dfdbe1a

Browse filesBrowse files
authored
feat: add no-deprecated-delete-set rule (#2540)
1 parent d77fbf7 commit dfdbe1a
Copy full SHA for dfdbe1a

File tree

5 files changed

+565
-0
lines changed
Filter options

5 files changed

+565
-0
lines changed

‎docs/rules/index.md

Copy file name to clipboardExpand all lines: docs/rules/index.md
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ For example:
229229
| [vue/next-tick-style](./next-tick-style.md) | enforce Promise or callback style in `nextTick` | :wrench: | :hammer: |
230230
| [vue/no-bare-strings-in-template](./no-bare-strings-in-template.md) | disallow the use of bare strings in `<template>` | | :hammer: |
231231
| [vue/no-boolean-default](./no-boolean-default.md) | disallow boolean defaults | | :hammer: |
232+
| [vue/no-deprecated-delete-set](./no-deprecated-delete-set.md) | disallow using deprecated `$delete` and `$set` (in Vue.js 3.0.0+) | | :warning: |
232233
| [vue/no-deprecated-model-definition](./no-deprecated-model-definition.md) | disallow deprecated `model` definition (in Vue.js 3.0.0+) | :bulb: | :warning: |
233234
| [vue/no-duplicate-attr-inheritance](./no-duplicate-attr-inheritance.md) | enforce `inheritAttrs` to be set to `false` when using `v-bind="$attrs"` | | :hammer: |
234235
| [vue/no-empty-component-block](./no-empty-component-block.md) | disallow the `<template>` `<script>` `<style>` block to be empty | | :hammer: |
+52Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
---
2+
pageClass: rule-details
3+
sidebarDepth: 0
4+
title: vue/no-deprecated-delete-set
5+
description: disallow using deprecated `$delete` and `$set` (in Vue.js 3.0.0+)
6+
---
7+
8+
# vue/no-deprecated-delete-set
9+
10+
> disallow using deprecated `$delete` and `$set` (in Vue.js 3.0.0+)
11+
12+
- :exclamation: <badge text="This rule has not been released yet." vertical="middle" type="error"> _**This rule has not been released yet.**_ </badge>
13+
14+
## :book: Rule Details
15+
16+
This rule reports use of deprecated `$delete` and `$set`. (in Vue.js 3.0.0+).
17+
18+
<eslint-code-block :rules="{'vue/no-deprecated-delete-set': ['error']}">
19+
20+
```vue
21+
<script>
22+
import { set, del } from 'vue'
23+
export default {
24+
mounted () {
25+
/* ✗ BAD */
26+
this.$set(obj, key, value)
27+
this.$delete(obj, key)
28+
29+
Vue.set(obj, key, value)
30+
Vue.delete(obj, key)
31+
32+
set(obj, key, value)
33+
del(obj, key)
34+
}
35+
}
36+
</script>
37+
```
38+
39+
</eslint-code-block>
40+
41+
## :wrench: Options
42+
43+
Nothing.
44+
45+
## :books: Further Reading
46+
47+
- [Migration Guide - Removed APIs](https://v3-migration.vuejs.org/breaking-changes/#removed-apis)
48+
49+
## :mag: Implementation
50+
51+
- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/no-deprecated-delete-set.js)
52+
- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/no-deprecated-delete-set.js)

‎lib/index.js

Copy file name to clipboardExpand all lines: lib/index.js
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ const plugin = {
9797
'no-constant-condition': require('./rules/no-constant-condition'),
9898
'no-custom-modifiers-on-v-model': require('./rules/no-custom-modifiers-on-v-model'),
9999
'no-deprecated-data-object-declaration': require('./rules/no-deprecated-data-object-declaration'),
100+
'no-deprecated-delete-set': require('./rules/no-deprecated-delete-set'),
100101
'no-deprecated-destroyed-lifecycle': require('./rules/no-deprecated-destroyed-lifecycle'),
101102
'no-deprecated-dollar-listeners-api': require('./rules/no-deprecated-dollar-listeners-api'),
102103
'no-deprecated-dollar-scopedslots-api': require('./rules/no-deprecated-dollar-scopedslots-api'),

‎lib/rules/no-deprecated-delete-set.js

Copy file name to clipboard
+132Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
/**
2+
* @author Wayne Zhang
3+
* See LICENSE file in root directory for full license.
4+
*/
5+
'use strict'
6+
7+
const utils = require('../utils')
8+
const { ReferenceTracker } = require('@eslint-community/eslint-utils')
9+
10+
/**
11+
* @typedef {import('@eslint-community/eslint-utils').TYPES.TraceMap} TraceMap
12+
*/
13+
14+
/** @type {TraceMap} */
15+
const deletedImportApisMap = {
16+
set: {
17+
[ReferenceTracker.CALL]: true
18+
},
19+
del: {
20+
[ReferenceTracker.CALL]: true
21+
}
22+
}
23+
const deprecatedApis = new Set(['set', 'delete'])
24+
const deprecatedDollarApis = new Set(['$set', '$delete'])
25+
26+
/**
27+
* @param {Expression|Super} node
28+
*/
29+
function isVue(node) {
30+
return node.type === 'Identifier' && node.name === 'Vue'
31+
}
32+
33+
module.exports = {
34+
meta: {
35+
type: 'problem',
36+
docs: {
37+
description:
38+
'disallow using deprecated `$delete` and `$set` (in Vue.js 3.0.0+)',
39+
categories: undefined,
40+
url: 'https://eslint.vuejs.org/rules/no-deprecated-delete-set.html'
41+
},
42+
fixable: null,
43+
schema: [],
44+
messages: {
45+
deprecated: 'The `$delete`, `$set` is deprecated.'
46+
}
47+
},
48+
/** @param {RuleContext} context */
49+
create(context) {
50+
/**
51+
* @param {Identifier} identifier
52+
* @param {RuleContext} context
53+
* @returns {CallExpression|undefined}
54+
*/
55+
function getVueDeprecatedCallExpression(identifier, context) {
56+
// Instance API: this.$set()
57+
if (
58+
deprecatedDollarApis.has(identifier.name) &&
59+
identifier.parent.type === 'MemberExpression' &&
60+
utils.isThis(identifier.parent.object, context) &&
61+
identifier.parent.parent.type === 'CallExpression' &&
62+
identifier.parent.parent.callee === identifier.parent
63+
) {
64+
return identifier.parent.parent
65+
}
66+
67+
// Vue 2 Global API: Vue.set()
68+
if (
69+
deprecatedApis.has(identifier.name) &&
70+
identifier.parent.type === 'MemberExpression' &&
71+
isVue(identifier.parent.object) &&
72+
identifier.parent.parent.type === 'CallExpression' &&
73+
identifier.parent.parent.callee === identifier.parent
74+
) {
75+
return identifier.parent.parent
76+
}
77+
78+
return undefined
79+
}
80+
81+
const nodeVisitor = {
82+
/** @param {Identifier} node */
83+
Identifier(node) {
84+
const callExpression = getVueDeprecatedCallExpression(node, context)
85+
if (!callExpression) {
86+
return
87+
}
88+
89+
context.report({
90+
node,
91+
messageId: 'deprecated'
92+
})
93+
}
94+
}
95+
96+
return utils.compositingVisitors(
97+
utils.defineVueVisitor(context, nodeVisitor),
98+
utils.defineScriptSetupVisitor(context, nodeVisitor),
99+
{
100+
/** @param {Program} node */
101+
Program(node) {
102+
const tracker = new ReferenceTracker(utils.getScope(context, node))
103+
104+
// import { set } from 'vue'; set()
105+
const esmTraceMap = {
106+
vue: {
107+
[ReferenceTracker.ESM]: true,
108+
...deletedImportApisMap
109+
}
110+
}
111+
// const { set } = require('vue'); set()
112+
const cjsTraceMap = {
113+
vue: {
114+
...deletedImportApisMap
115+
}
116+
}
117+
118+
for (const { node } of [
119+
...tracker.iterateEsmReferences(esmTraceMap),
120+
...tracker.iterateCjsReferences(cjsTraceMap)
121+
]) {
122+
const refNode = /** @type {CallExpression} */ (node)
123+
context.report({
124+
node: refNode.callee,
125+
messageId: 'deprecated'
126+
})
127+
}
128+
}
129+
}
130+
)
131+
}
132+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.