Skip to content

Commit 969120a

Browse files
committed
feat: refactor rule
1 parent f460c6f commit 969120a

File tree

3 files changed

+421
-149
lines changed

3 files changed

+421
-149
lines changed

docs/rules/no-use-computed-property-like-method.md

Lines changed: 186 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,44 @@ This rule disallows to use computed property like method.
5656
},
5757
},
5858
computed: {
59+
computedReturnDataString() {
60+
return this.dataString
61+
},
62+
computedReturnDataNumber() {
63+
return this.dataNumber
64+
},
65+
computedReturnDataObject() {
66+
return this.dataObject
67+
},
68+
computedReturnDataArray() {
69+
return this.dataArray
70+
},
71+
computedReturnDataBoolean() {
72+
return this.dataBoolean
73+
},
74+
computedReturnDataFunction() {
75+
return this.dataFunction
76+
},
77+
78+
computedReturnPropsString() {
79+
return this.propsString
80+
},
81+
computedReturnPropsNumber() {
82+
return this.propsNumber
83+
},
84+
computedReturnPropsObject() {
85+
return this.propsObject
86+
},
87+
computedReturnPropsArray() {
88+
return this.propsArray
89+
},
90+
computedReturnPropsBoolean() {
91+
return this.propsBoolean
92+
},
93+
computedReturnPropsFunction() {
94+
return this.propsFunction
95+
},
96+
5997
computedReturnString() {
6098
return 'computedReturnString'
6199
},
@@ -76,7 +114,24 @@ This rule disallows to use computed property like method.
76114
computedReturnFunction() {
77115
const fn = () => alert('computedReturnFunction')
78116
return fn
117+
},
118+
119+
computedReturnMethodsReturnString() {
120+
return this.methodsReturnString
121+
},
122+
computedReturnMethodsReturnNumber() {
123+
return this.methodsReturnNumber
124+
},
125+
computedReturnMethodsReturnObject() {
126+
return this.methodsReturnObject
127+
},
128+
computedReturnMethodsReturnArray() {
129+
return this.methodsReturnArray
130+
},
131+
computedReturnMethodsReturnBoolean() {
132+
return this.methodsReturnBoolean
79133
}
134+
80135
},
81136
methods: {
82137
methodsReturnString() {
@@ -97,7 +152,137 @@ This rule disallows to use computed property like method.
97152
return true
98153
},
99154
methodsReturnFunction() {
100-
console.log(this.dataObject.inside);
155+
const fn = () => alert('methodsReturnFunction')
156+
return fn
157+
},
158+
159+
fn() {
160+
/* Reference data */
161+
/* ✓ GOOD */
162+
this.computedReturnDataString
163+
this.computedReturnDataNumber
164+
this.computedReturnDataObject
165+
this.computedReturnDataArray
166+
this.computedReturnDataBoolean
167+
this.computedReturnDataFunction
168+
this.computedReturnDataFunction()
169+
/* ✗ BAD */
170+
this.computedReturnDataString()
171+
this.computedReturnDataNumber()
172+
this.computedReturnDataObject()
173+
this.computedReturnDataArray()
174+
this.computedReturnDataBoolean()
175+
176+
/* Reference props */
177+
/* ✓ GOOD */
178+
this.computedReturnPropsString
179+
this.computedReturnPropsNumber
180+
this.computedReturnPropsObject
181+
this.computedReturnPropsArray
182+
this.computedReturnPropsBoolean
183+
this.computedReturnPropsFunction
184+
this.computedReturnPropsFunction()
185+
/* ✗ BAD */
186+
this.computedReturnPropsString()
187+
this.computedReturnPropsNumber()
188+
this.computedReturnPropsObject()
189+
this.computedReturnPropsArray()
190+
this.computedReturnPropsBoolean()
191+
192+
/* ✓ GOOD */
193+
this.computedReturnString
194+
this.computedReturnNumber
195+
this.computedReturnObject
196+
this.computedReturnArray
197+
this.computedReturnBoolean
198+
this.computedReturnFunction
199+
this.computedReturnFunction()
200+
/* ✗ BAD */
201+
this.computedReturnString()
202+
this.computedReturnNumber()
203+
this.computedReturnObject()
204+
this.computedReturnArray()
205+
this.computedReturnBoolean()
206+
207+
/* Reference methods */
208+
/* ✓ GOOD */
209+
this.computedReturnMethodsReturnString
210+
this.computedReturnMethodsReturnNumber
211+
this.computedReturnMethodsReturnObject
212+
this.computedReturnMethodsReturnArray
213+
this.computedReturnMethodsReturnBoolean
214+
this.computedReturnMethodsReturnFunction
215+
this.computedReturnMethodsReturnFunction()
216+
/* ✗ BAD */
217+
this.computedReturnMethodsReturnString()
218+
this.computedReturnMethodsReturnNumber()
219+
this.computedReturnMethodsReturnObject()
220+
this.computedReturnMethodsReturnArray()
221+
this.computedReturnMethodsReturnBoolean()
222+
}
223+
}
224+
}
225+
</script>
226+
```
227+
228+
This rule can't check if props is used as array:
229+
</eslint-code-block>
230+
<eslint-code-block :rules="{'vue/no-use-computed-property-like-method': ['error']}">
231+
232+
```vue
233+
<template>
234+
<div>
235+
</div>
236+
</template>
237+
238+
<script>
239+
export default {
240+
props: {
241+
"propsString",
242+
"propsNumber",
243+
"propsObject",
244+
"propsArray",
245+
"propsBoolean",
246+
"propsFunction"
247+
},
248+
computed: {
249+
computedReturnPropsString() {
250+
return this.propsString
251+
},
252+
computedReturnPropsNumber() {
253+
return this.propsNumber
254+
},
255+
computedReturnPropsObject() {
256+
return this.propsObject
257+
},
258+
computedReturnPropsArray() {
259+
return this.propsArray
260+
},
261+
computedReturnPropsBoolean() {
262+
return this.propsBoolean
263+
},
264+
computedReturnPropsFunction() {
265+
return this.propsFunction
266+
},
267+
},
268+
methods: {
269+
fn() {
270+
/* Reference props */
271+
/* ✓ GOOD */
272+
this.computedReturnPropsString
273+
this.computedReturnPropsString()
274+
this.computedReturnPropsNumber
275+
this.computedReturnPropsNumber()
276+
this.computedReturnPropsObject
277+
this.computedReturnPropsObject()
278+
this.computedReturnPropsArray
279+
this.computedReturnPropsArray()
280+
this.computedReturnPropsBoolean
281+
this.computedReturnPropsBoolean()
282+
this.computedReturnPropsFunction
283+
this.computedReturnPropsFunction()
284+
/* ✗ BAD */
285+
/* Nope. everything is GOOD!! */
101286
}
102287
}
103288
}

lib/rules/no-use-computed-property-like-method.js

Lines changed: 34 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ const eslitUtils = require('eslint-utils')
1111
const utils = require('../utils')
1212

1313
/**
14-
* @typedef {import('../utils').ComponentComputedProperty} ComponentComputedProperty
15-
* @typedef {import('../utils').ComponentObjectProp} ComponentObjectProp
1614
* @typedef {import('../utils').ComponentPropertyData} ComponentPropertyData
1715
* @typedef {import('../utils').ComponentObjectPropertyData} ComponentObjectPropertyData
1816
*
@@ -22,21 +20,6 @@ const utils = require('../utils')
2220
// Rule Definition
2321
// ------------------------------------------------------------------------------
2422

25-
function replacer(key, value) {
26-
if (key === 'parent') {
27-
return undefined
28-
}
29-
if (key === 'errors' && Array.isArray(value)) {
30-
return value.map((e) => ({
31-
message: e.message,
32-
index: e.index,
33-
lineNumber: e.lineNumber,
34-
column: e.column
35-
}))
36-
}
37-
return value
38-
}
39-
4023
/**
4124
*
4225
* @param {ComponentObjectPropertyData} property
@@ -70,32 +53,6 @@ const getComponetPropsType = (property) => {
7053
const getPrototypeType = (obj) =>
7154
Object.prototype.toString.call(obj).slice(8, -1)
7255

73-
/**
74-
*
75-
* @param {Expression | Super} objectOrCallee
76-
* @returns {string | null}
77-
*/
78-
// const getThisMember = (objectOrCallee) => {
79-
// if (objectOrCallee.type === 'MemberExpression') {
80-
// if (objectOrCallee.object.type === 'Identifier') return null
81-
82-
// if (
83-
// objectOrCallee.object.type === 'ThisExpression' &&
84-
// objectOrCallee.property.type === 'Identifier'
85-
// )
86-
// return objectOrCallee.property.name
87-
88-
// if (objectOrCallee.object.type === 'MemberExpression')
89-
// getThisMember(objectOrCallee.object)
90-
// }
91-
92-
// if (objectOrCallee.type === 'CallExpression') {
93-
// if (objectOrCallee.callee.type === 'Identifier') return null
94-
95-
// getThisMember(objectOrCallee.callee)
96-
// }
97-
// }
98-
9956
/**
10057
* Get return type of property.
10158
* @param {{ property: ComponentPropertyData, propertyMap: ProprtyMap }} args
@@ -130,27 +87,13 @@ const getValueType = ({ property, propertyMap }) => {
13087
if (!returnStatement || returnStatement.type !== 'ReturnStatement')
13188
return
13289

133-
// if (property.groupName === 'computed') {
134-
// if (
135-
// propertyMap &&
136-
// propertyMap[property.name] &&
137-
// returnStatement.argument
138-
// ) {
139-
// const thisMember = getThisMember(returnStatement.argument)
140-
// return {
141-
// type: propertyMap[thisMember].valueType.type
142-
// }
143-
// }
144-
// }
145-
146-
/**
147-
* TODO: consider this.xxx.xxx().xxx.xxx().xxx().....
148-
*/
149-
if (property.groupName === 'computed') {
90+
if (
91+
property.groupName === 'computed' &&
92+
propertyMap &&
93+
propertyMap[property.name] &&
94+
returnStatement.argument
95+
) {
15096
if (
151-
propertyMap &&
152-
propertyMap[property.name] &&
153-
returnStatement.argument &&
15497
returnStatement.argument.type === 'MemberExpression' &&
15598
returnStatement.argument.property.type === 'Identifier'
15699
)
@@ -161,9 +104,6 @@ const getValueType = ({ property, propertyMap }) => {
161104
}
162105

163106
if (
164-
propertyMap &&
165-
propertyMap[property.name] &&
166-
returnStatement.argument &&
167107
returnStatement.argument.type === 'CallExpression' &&
168108
returnStatement.argument.callee.type === 'MemberExpression' &&
169109
returnStatement.argument.callee.property.type === 'Identifier'
@@ -175,6 +115,18 @@ const getValueType = ({ property, propertyMap }) => {
175115
}
176116
}
177117

118+
/**
119+
* Use value as Object even if object includes method
120+
*/
121+
if (
122+
property.groupName === 'computed' &&
123+
returnStatement.argument.type === 'ObjectExpression'
124+
) {
125+
return {
126+
type: 'Object'
127+
}
128+
}
129+
178130
const evaluated = eslitUtils.getStaticValue(returnStatement.argument)
179131

180132
if (evaluated) {
@@ -223,11 +175,11 @@ module.exports = {
223175
const propertyMap = {}
224176

225177
/**@type ObjectExpression */
226-
let nodeMap = {}
178+
let vueNodeMap = {}
227179

228180
return utils.defineVueVisitor(context, {
229181
onVueObjectEnter(node) {
230-
nodeMap = node
182+
vueNodeMap = node
231183
const properties = utils.iterateProperties(node, groups)
232184

233185
for (const property of properties) {
@@ -239,12 +191,12 @@ module.exports = {
239191
}
240192
},
241193

242-
/** @param {MemberExpression} node */
194+
/**
195+
* Re-check propertyMap's valueType.
196+
* Because there is a possibility that propertyMap's member reference other propertyMap's member.
197+
*/
243198
'MemberExpression[object.type="ThisExpression"]'(node) {
244-
if (node.parent.type !== 'CallExpression') return
245-
if (node.property.type !== 'Identifier') return
246-
247-
const properties = utils.iterateProperties(nodeMap, groups)
199+
const properties = utils.iterateProperties(vueNodeMap, groups)
248200

249201
for (const property of properties) {
250202
propertyMap[property.name] = {
@@ -253,8 +205,16 @@ module.exports = {
253205
valueType: getValueType({ property, propertyMap })
254206
}
255207
}
208+
},
209+
210+
/** @param {ThisExpression} node */
211+
'ThisExpression[parent.type="MemberExpression"][parent.parent.type="CallExpression"]'(
212+
node
213+
) {
214+
if (node.parent.type !== 'MemberExpression') return
215+
if (node.parent.property.type !== 'Identifier') return
256216

257-
const thisMember = node.property.name
217+
const thisMember = node.parent.property.name
258218

259219
if (!propertyMap[thisMember].valueType.type) return
260220

0 commit comments

Comments
 (0)