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

Conversation

pschmiedel
Copy link
Contributor

Hi, I added a small fix for parsing computed properties that use the getter/setter syntax. Currently this breaks with the following error:

/path/to/node_modules/@vuedoc/md/lib/markdown.js:130
      if (prop.dependencies.length) {
                           ^

TypeError: Cannot read property 'length' of undefined
    at props.forEach (/path/to/node_modules/@vuedoc/md/lib/markdown.js:130:28)
    at Array.forEach (native)
    at Object.computed (/path/to/node_modules/@vuedoc/md/lib/markdown.js:121:11)
    at options.printOrder.forEach (/path/to/node_modules/@vuedoc/md/lib/markdown.js:218:19)
    at Array.forEach (native)
    at process.nextTick (/path/to/node_modules/@vuedoc/md/lib/markdown.js:207:24)
    at _combinedTickCallback (internal/process/next_tick.js:73:7)
    at process._tickCallback (internal/process/next_tick.js:104:9)

I'd appreciate it if you could merge this PR.

@coveralls
Copy link

Coverage Status

Coverage decreased (-1.4%) to 98.133% when pulling e47c626 on pschmiedel:master into c1728d7 on vuedoc:master.

@demsking
Copy link
Member

Thanks for your PR. :-)
The coverage decreased of -1.8%. Could you just add unit tests to cover your changes please?

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()
  })
})

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.2%) to 99.378% when pulling 05c8f74 on pschmiedel:master into c1728d7 on vuedoc:master.

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.2%) to 99.378% when pulling cd503e0 on pschmiedel:master into c1728d7 on vuedoc:master.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.009%) to 99.587% when pulling 3a6278e on pschmiedel:master into c1728d7 on vuedoc:master.

* @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.

lib/parser.js Outdated
@@ -60,6 +60,7 @@ class Parser extends EventEmitter {
entry.value = entry.value[entry.name]

if (property.key.name === 'computed') {
/* istanbul ignore else */
Copy link
Member

Choose a reason for hiding this comment

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

Hum... I don't like istanbul ignore ... statement. It may a problem if we add the else statement and forget to remove the istanbul statement. I prefer to add a unit test to cover the else branch

lib/parser.js Outdated
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) {
entry.dependencies = utils.getDependencies(entry.value.get, this.source.script)
} else {
const error = new Error('Computed property must be a function or an object with a get() 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 think the parser should not emit Vue syntax error here. Syntax error must be throwed by #13
The parser should only parse the get function and ignore the others one.

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 this case because otherwise the coverage will go down (slightly) as there is no "else" case. It is fine by me to remove the else block here, should I do that?

Copy link
Member

Choose a reason for hiding this comment

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

Yes, the else branch is not required in this case.

* @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.

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

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.2%) to 99.378% when pulling 3e99e20 on pschmiedel:master into c1728d7 on vuedoc:master.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.007%) to 99.585% when pulling 1025369 on pschmiedel:master into c1728d7 on vuedoc:master.

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.

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!

@pschmiedel
Copy link
Contributor Author

I added a test for an invalid computed property, coverage is back up :-)

@coveralls
Copy link

Coverage Status

Coverage increased (+0.008%) to 99.586% when pulling af38128 on pschmiedel:master into c1728d7 on vuedoc:master.

@demsking demsking merged commit 2b04304 into vuedoc:master Oct 30, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
3 participants