Skip to content

Add no-side-effects-in-computed-properties rule #69

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Jul 19, 2017

Conversation

michalsnik
Copy link
Member

@michalsnik michalsnik commented Jul 4, 2017

This PR implements rule proposed in #58

This rule checks for existance of any of the following inside all computed properties:

  • AssignmentExpression that starts with this. (e.g. this.x = 'asd', this.x += 1)
  • UpdateExpression that starts with this. (e.g this.x++)
  • CallExpression that starts with this. and calls one of the mutable methods (push, pop, shift, unshift, reverse, splice, sort, copyWithin, fill) not followed by any of those that remove the reference (like: slice, map, filter, concat)

Feel free to comment if I missed anything. At this point I'd like to stick with those simple checks and then we can investigate it further if we can check anything more than that. If believe this is a good starting point.

Left to do:

  • Add one more case - simple CallExpression this.anything( that is not assigned anywhere should be considered unexpected side effect
  • Add more test scenarios
  • Clean current solution (I'm considering using regex for checking AssignmentExpression and UpdateExpression too, instead of parsing those simple chunks of AST)

@michalsnik michalsnik force-pushed the add-no-side-effects-in-computed-properties-rule branch from 878dd5c to 774a169 Compare July 6, 2017 08:01

const computedProperties = computedPropertiesNode.value.properties

return computedProperties.map(cp => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in case when there is only

computed: {
  foo: {
    set () {}
  }
}

returned value is going to be

return [
  {
    key: '....',
    value: undefined
  }
]

And code when its used has to check for that case or we should filter it here

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, thanks @armano2

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@michalsnik i think its better to check it here cus we are going propably to add rule about checking if computed propery has get and we can do that by just checking it .value is not undefined

@mysticatea
Copy link
Member

We should be careful about nested functions if we use ThisExpression to lint.
thiss of nested functions often are bound to different instances.

@michalsnik
Copy link
Member Author

Agree @mysticatea, but given the way vue works and the this bound to a component in default scope I think other thiss inside computed property or any other place in vue component should be considered harmful. Messing different contexts seems like a very bad idea to me and I think users should above else use parameters instead (e.g. when using forEach loop). I'd go with current implementation and see how it works in the wild. Please take a look once again and approve if you agree :)


if (cp.value.type === 'FunctionExpression') {
value = cp.value.body
} else if (cp.value.type === 'ObjectExpression') {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

coverage from unit test never enters this part ObjectExpression

p.value.type === 'ObjectExpression'
)[0]

if (!computedPropertiesNode) { return [] }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unit test never enters this if


return computedProperties
.map(cp => {
const key = cp.key.name
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@michalsnik cp.key can be undefined if you are using experimentalObjectRestSpread
Solution: if cp.type === 'Property'

TypeError: Cannot read property 'name' of undefined

example:

export default {
  computed: {
    ...mapGetters({})
  }
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very good point, thank you @armano2 for pointing that!


if (memberExpression.type === 'ThisExpression') {
members.push('this')
} else if (memberExpression.type === 'Identifier') {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unit test never enters here

},
// this.xxx <++|-->
'UpdateExpression > MemberExpression' (node) {
if (parseMemberExpression(node)[0] === 'this') {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all tests are for this.

…hub.com:vuejs/eslint-plugin-vue into add-no-side-effects-in-computed-properties-rule
@michalsnik
Copy link
Member Author

Thanks for suggestions @armano2! I moved two helper functions to utils and added separate tests for them. Please take another look.

Copy link
Contributor

@armano2 armano2 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems fine right now

@michalsnik
Copy link
Member Author

Okay, let's push this forward. We're still in beta phase and it's not enabled by default so I think it's good to go.

@michalsnik michalsnik merged commit 455e9b9 into master Jul 19, 2017
@michalsnik michalsnik deleted the add-no-side-effects-in-computed-properties-rule branch July 19, 2017 14:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants