Skip to content

Commit

Permalink
Add composition api's computed function support to vue/return-in-comp…
Browse files Browse the repository at this point in the history
…uted-property refs #1393 (#1406)
  • Loading branch information
sapphi-red committed Jan 21, 2021
1 parent 10824ec commit d7eacd6
Show file tree
Hide file tree
Showing 3 changed files with 191 additions and 5 deletions.
39 changes: 36 additions & 3 deletions docs/rules/return-in-computed-property.md
Expand Up @@ -2,18 +2,18 @@
pageClass: rule-details
sidebarDepth: 0
title: vue/return-in-computed-property
description: enforce that a return statement is present in computed property
description: enforce that a return statement is present in computed property and function
since: v3.7.0
---
# vue/return-in-computed-property

> enforce that a return statement is present in computed property
> enforce that a return statement is present in computed property and function
- :gear: This rule is included in all of `"plugin:vue/vue3-essential"`, `"plugin:vue/essential"`, `"plugin:vue/vue3-strongly-recommended"`, `"plugin:vue/strongly-recommended"`, `"plugin:vue/vue3-recommended"` and `"plugin:vue/recommended"`.

## :book: Rule Details

This rule enforces that a `return` statement is present in `computed` properties.
This rule enforces that a `return` statement is present in `computed` properties and functions.

<eslint-code-block :rules="{'vue/return-in-computed-property': ['error']}">

Expand Down Expand Up @@ -46,6 +46,39 @@ export default {

</eslint-code-block>

<eslint-code-block :rules="{'vue/return-in-computed-property': ['error']}">

```vue
<script>
import {computed} from 'vue'
export default {
setup() {
const foobar = useFoobar()
/* ✓ GOOD */
const foo = computed(() => {
if (foobar.bar) {
return foobar.baz
} else {
return foobar.baf
}
})
const bar = computed(() => false)
/* ✗ BAD */
const baz = computed(() => {
if (foobar.baf) {
return foobar.baf
}
})
const baf = computed(() => {})
}
}
</script>
```

</eslint-code-block>

## :wrench: Options

```json
Expand Down
35 changes: 33 additions & 2 deletions lib/rules/return-in-computed-property.js
Expand Up @@ -3,7 +3,7 @@
* @author Armano
*/
'use strict'

const { ReferenceTracker } = require('eslint-utils')
const utils = require('../utils')

/**
Expand Down Expand Up @@ -47,13 +47,36 @@ module.exports = {
* @type {Set<ComponentComputedProperty>}
*/
const computedProperties = new Set()
/** @type {(FunctionExpression | ArrowFunctionExpression)[]} */
const computedFunctionNodes = []

// ----------------------------------------------------------------------
// Public
// ----------------------------------------------------------------------

return Object.assign(
{},
{
Program() {
const tracker = new ReferenceTracker(context.getScope())
const traceMap = utils.createCompositionApiTraceMap({
[ReferenceTracker.ESM]: true,
computed: {
[ReferenceTracker.CALL]: true
}
})

for (const { node } of tracker.iterateEsmReferences(traceMap)) {
if (node.type !== 'CallExpression') {
continue
}

const getter = utils.getGetterBodyFromComputedFunction(node)
if (getter) {
computedFunctionNodes.push(getter)
}
}
}
},
utils.defineVueVisitor(context, {
onVueObjectEnter(obj) {
for (const computedProperty of utils.getComputedProperties(obj)) {
Expand All @@ -76,6 +99,14 @@ module.exports = {
})
}
})
computedFunctionNodes.forEach((cf) => {
if (cf === node) {
context.report({
node,
message: 'Expected to return a value in computed function.'
})
}
})
}
)
)
Expand Down
122 changes: 122 additions & 0 deletions tests/lib/rules/return-in-computed-property.js
Expand Up @@ -104,6 +104,56 @@ ruleTester.run('return-in-computed-property', rule, {
`,
parserOptions,
options: [{ treatUndefinedAsUnspecified: false }]
},
{
filename: 'test.vue',
code: `
import {computed} from 'vue'
export default {
setup() {
const foo = computed(() => true)
const bar = computed(function() {
return false
})
const bar3 = computed({
set: () => true,
get: () => true
})
const bar4 = computed(() => {
if (foo) {
return true
} else {
return false
}
})
const foo2 = computed(() => {
const options = []
this.matches.forEach((match) => {
options.push(match)
})
return options
})
}
}
`,
parserOptions
},
{
filename: 'test.vue',
code: `
import {computed} from 'vue'
export default {
setup() {
const foo = computed({
get: () => {
return
}
})
}
}
`,
parserOptions,
options: [{ treatUndefinedAsUnspecified: false }]
}
],

Expand Down Expand Up @@ -272,6 +322,78 @@ ruleTester.run('return-in-computed-property', rule, {
line: 5
}
]
},
{
filename: 'test.vue',
code: `
import {computed} from 'vue'
export default {
setup() {
const foo = computed(() => {})
const foo2 = computed(function() {})
const foo3 = computed(() => {
if (a) {
return
}
})
const foo4 = computed({
set: () => {},
get: () => {}
})
const foo5 = computed(() => {
const bar = () => {
return this.baz * 2
}
bar()
})
}
}
`,
parserOptions,
errors: [
{
message: 'Expected to return a value in computed function.',
line: 5
},
{
message: 'Expected to return a value in computed function.',
line: 6
},
{
message: 'Expected to return a value in computed function.',
line: 7
},
{
message: 'Expected to return a value in computed function.',
line: 14
},
{
message: 'Expected to return a value in computed function.',
line: 16
}
]
},
{
filename: 'test.vue',
code: `
import {computed} from 'vue'
export default {
setup() {
const foo = computed(() => {})
const baz = computed(() => {
return
})
}
}
`,
parserOptions,
options: [{ treatUndefinedAsUnspecified: false }],
errors: [
{
message: 'Expected to return a value in computed function.',
line: 5
}
]
}
]
})

0 comments on commit d7eacd6

Please sign in to comment.