Skip to content
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

fix parser for computed properties with an explicit getter function #12

Merged
merged 7 commits into from
Oct 30, 2017
17 changes: 9 additions & 8 deletions lib/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,16 @@ class Parser extends EventEmitter {
entry.name = Object.keys(entry.value)[0]
entry.value = entry.value[entry.name]

if (entry.value instanceof utils.NodeFunction) {
switch (property.key.name) {
case 'computed':
entry.dependencies = utils.getDependencies(entry.value, this.source.script)
break

default:
entry.params = entry.value.params
if (property.key.name === 'computed') {
if (entry.value instanceof utils.NodeFunction) {
entry.dependencies = utils.getDependencies(entry.value, this.source.script)
} else if (entry.value instanceof Object && entry.value.get instanceof utils.NodeFunction) {
Copy link
Member

Choose a reason for hiding this comment

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

This branch need to be cover by unit tests

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added the unit tests, coverage is back up :-)

Copy link
Member

Choose a reason for hiding this comment

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

Good. Now you have to add a unit test to cover the case where we have a missing get() function. Some think like:

it('should parse computed prop with missing get() method', (done) => {
  const filename = './fixtures/checkbox.vue'
  const script = `
    export default {
      computed: {
        idGetter: {
          foo () {
            const value = this.value
            return this.name + value
          }
        }
      }
    }
  `
  const options = {
    source: { script },
    filename
  }
  const parser = new Parser(options)

  parser.walk().on('computed', (prop) => {
    if (prop.dependencies.length) {
      return done(new Error('Should parse computed prop without dependencies'))
    }
    done()
  })
})

Copy link
Member

Choose a reason for hiding this comment

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

Finally I think the else block is require to set entry.dependencie = [].
What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hi, ok I will change it to return an empty array and change the test.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done :-)

Copy link
Member

Choose a reason for hiding this comment

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

Great!!!
Thank you @pschmiedel for your PR.
I'll release it soon.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks a lot for the quick response!

entry.dependencies = utils.getDependencies(entry.value.get, this.source.script)
} else {
entry.dependencies = []
}
} else if (entry.value instanceof utils.NodeFunction) {
entry.params = entry.value.params
} else if (property.key.name === 'props') {
if (entry.describeModel) {
entry.name = 'v-model'
Expand Down
11 changes: 10 additions & 1 deletion test/integration.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,12 @@ describe('component.computed', () => {
},
type () {
return 'text'
},
getter: {
get () {
const value = this.value
return this.name + value
}
}
}
}
Expand All @@ -209,13 +215,16 @@ describe('component.computed', () => {
return parser.parse(options).then((component) => {
const computed = component.computed

assert.equal(computed.length, 2)
assert.equal(computed.length, 3)

assert.equal(computed[0].name, 'id')
assert.deepEqual(computed[0].dependencies, [ 'value', 'name' ])

assert.equal(computed[1].name, 'type')
assert.deepEqual(computed[1].dependencies, [])

assert.equal(computed[2].name, 'getter')
assert.deepEqual(computed[2].dependencies, [ 'value', 'name' ])
})
})
})
Expand Down
74 changes: 74 additions & 0 deletions test/parser.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,80 @@ describe('Parser', () => {
})
})

it('should successfully emit a computed property item with a getter', (done) => {
const filename = './fixtures/checkbox.vue'
const script = `
export default {
computed: {
/**
* ID computed prop
*
* @private
*/
idGetter: {
get () {
Copy link
Member

Choose a reason for hiding this comment

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

What if it's set()?
I think dependencies prop is about getter... is not it?
If right, the parser should only parse the getter and ignore the setter function.

Copy link
Member

Choose a reason for hiding this comment

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

I mistaken... your changes already cover this purpose.

const value = this.value
return this.name + value
}
}
}
}
`
const options = {
source: { script },
filename
}
const parser = new Parser(options)
const expected = {
name: 'idGetter',
keywords: [{ name: 'private', description: '' }],
visibility: 'private',
description: 'ID computed prop',
dependencies: ['value', 'name']
}

parser.walk().on('computed', (prop) => {
assert.equal(prop.name, expected.name)
assert.deepEqual(prop.keywords, expected.keywords)
assert.equal(prop.visibility, expected.visibility)
assert.equal(prop.description, expected.description)
assert.equal(prop.value.get.type, 'FunctionExpression')
assert.deepEqual(prop.dependencies, expected.dependencies)
done()
})
})

it('should ignore functions other than get on computed property', (done) => {
const filename = './fixtures/checkbox.vue'
const script = `
export default {
computed: {
/**
* ID computed prop
*
* @private
*/
idGetter: {
foo () {
const value = this.value
return this.name + value
}
}
}
}
`
const options = {
source: { script },
filename
}
const parser = new Parser(options)

parser.walk().on('computed', (prop) => {
assert.deepEqual(prop.dependencies, [])
done()
})
})

it('should successfully emit an unknow item', (done) => {
const filename = './fixtures/checkbox.vue'
const defaultMethodVisibility = 'public'
Expand Down