ricardofbarros / linter-js-standard

Atom linter plugin for JavaScript, using JavaScript Standard Style
https://atom.io/packages/linter-js-standard
MIT License
99 stars 48 forks source link

Uncaught TypeError: Cannot read property 'messages' of undefined #214

Closed gorkarod closed 6 years ago

gorkarod commented 6 years ago

[Enter steps to reproduce:]

  1. ...
  2. ...

Atom: 1.22.1 x64 Electron: 1.6.15 OS: Mac OS X 10.11.6 Thrown From: linter-js-standard package 4.1.0

Stack Trace

Uncaught TypeError: Cannot read property 'messages' of undefined

At /Users/hartmut/.atom/packages/linter-js-standard/lib/utils/linter.js:33

TypeError: Cannot read property 'messages' of undefined
    at Object.module.exports (/packages/linter-js-standard/lib/utils/linter.js:33:31)
    at _combinedTickCallback (internal/process/next_tick.js:74:11)
    at process._tickCallback (internal/process/next_tick.js:98:9)

Commands

     -0:07.4.0 tree-view:show (atom-workspace.workspace.scrollbars-visible-when-scrolling)
     -0:04.5.0 core:save (input.hidden-input)

Non-Core Packages

advanced-open-file 0.16.7 
aligner 1.2.4 
aligner-coffeescript 1.0.1 
aligner-javascript 1.3.0 
aligner-php 1.2.0 
aligner-stylus 1.1.0 
atom-beautify 0.30.9 
atom-html-preview 0.2.5 
autocomplete-css-with-stylus-support 1.0.0 
autocomplete-php 0.3.7 
autohide-tree-view 0.25.1 
busy-signal 1.4.3 
color-picker 2.2.5 
copy-as-rtf 0.9.3 
dash 1.7.1 
duplicate-line-or-selection 0.9.0 
elm 0.1.0 
elm-format 3.0.0 
elmjutsu 7.1.5 
emmet 2.4.3 
file-icons 2.1.14 
FreshCut 1.0.0 
git-time-machine 1.5.9 
highlight-selected 0.13.1 
Hydrogen 2.1.0 
hyperclick 0.1.5 
incremental-search 5.2.2 
intentions 1.1.5 
js-hyperclick 1.12.2 
jumpy 4.1.1 
language-apache 1.7.0 
language-elm 1.5.0 
language-mjml 1.10.0 
language-pug 0.0.21 
language-vue 0.23.1 
language-vue-component 0.5.0 
linter 2.2.0 
linter-coffeescript 1.0.0 
linter-elm-make 0.27.2 
linter-htmlhint 1.4.0 
linter-js-standard 4.1.0 
linter-jshint 3.1.6 
linter-jsonlint 1.3.0 
linter-mjml 1.2.0 
linter-php 1.5.1 
linter-ui-default 1.6.10 
maximize-panes 0.2.0 
minimap-cursorline 0.2.0 
minimap-find-and-replace 4.5.2 
minimap-git-diff 4.3.1 
minimap-hide 0.3.0 
minimap-highlight-selected 4.6.1 
minimap-linter 2.1.3 
minimap-pigments 0.2.2 
minimap-plus 4.29.2 
mjml-preview 1.4.0 
node-debugger 1.10.1 
pigments 0.40.2 
prettier-atom 0.41.0 
pretty-json 1.6.4 
preview 0.17.0 
project-manager 3.3.5 
savey-wavey 0.3.0 
sort-lines 0.18.0 
standard-formatter 2.8.0 
standardjs-snippets 2.6.2 
Stylus 3.1.1 
stylus-autocompile 0.6.1 
svgo 2.8.5 
teletype 0.2.3 
toggle-quotes 1.0.1 
vue-stylefmt 0.5.0 
zentabs 0.8.9 
sonicdoe commented 6 years ago

Thanks for reporting this error. Are you able to reproduce this or was this a one-time error?

gorkarod commented 6 years ago

Sorry for keeping my reporting so short. In the meantime I did some investigation: Interestingly I have issues with a particular file in a particular project. When I copy it to e.g. desktop the problem disappears. Very strange …

gorkarod commented 6 years ago

The file looks like this

function main () {
  processMenuItems()
  insertMainMenuCover()
  handleLangMenu()
}

function handleLangMenu () {
  const langswitch = Array.from(document.getElementsByClassName('module-metamenu--langswitch'))[0]
  const langmenu = Array.from(document.getElementsByClassName('module-metamenu--langmenu'))[0]
  langswitch.addEventListener('click', function (event) {
    if (!hasClass(langmenu, '-expanded')) {
      addClass(langmenu, '-expanded')
    } else {
      removeClass(langmenu, '-expanded')
    }
  })
}

function processMenuItems () {
  let menuItems = Array.from(document.getElementsByClassName('module-mainmenu--level-0'))[0].childNodes

  // Zap separator items
  for (let i = 0; i < menuItems.length; i++) {
    let item = menuItems[i]
    if (hasClass(item, 'separator')) {
      item.parentNode.removeChild(item)
    }
  }

  // Process others
  for (let i = 0; i < menuItems.length; i++) {
    let item = menuItems[i]
    let anchor = item.childNodes[0]
    let ul = Array.from(item.childNodes).filter((item) => item.nodeName === 'UL')
    const title = anchor.textContent
    const id = item.className.slice(1)
    const itemTop = item.offsetTop
    // attach Click handler
    if (ul.length) {
      anchor.addEventListener('click', function (event) {
        event.preventDefault()
        event.stopPropagation()
        addClass(ul[0].parentNode, '-expanded')
        let cover = document.getElementsByClassName('module-mainmenu--cover')[0]
        addClass(cover, '-expanded')
        return false
      })
      let container = document.createElement('div')
      addClass(container, 'module-mainmenu--level-1-container')
      container.style.paddingTop = itemTop + 'px'
      wrapElement(ul[0], container)

      let backbutton = document.createElement('button')
      backbutton.innerHTML = 'zurück'
      backbutton.addEventListener('click', function (event) {
        removeClass(this.parentNode, '-expanded')
        let cover = document.getElementsByClassName('module-mainmenu--cover')[0]
        removeClass(cover, '-expanded')
      })
      // addClass(backbutton, 'module-mainmenu--level-1-backbutton')
      insertBefore(backbutton, ul[0])

      let submenuheader = document.createElement('h2')
      submenuheader.innerHTML = title
      addClass(submenuheader, '-' + id)
      insertBefore(submenuheader, ul[0])
    }
    // Add icon container, wrap text
    anchor.innerHTML = `<div class="module-mainmenu--icon-level-0 -${id}"></div><div class="module-mainmenu--link-level-0">${title}</div>`
  }

  // Show menu when ready
  document.getElementsByClassName('module-mainmenu--level-0')[0].style.visibility = 'visible'
}

function insertMainMenuCover () {
  const cover = document.createElement('div')
  addClass(cover, 'module-mainmenu--cover')
  insertBefore(cover, document.getElementsByClassName('module-mainmenu--level-0')[0])
}

function hasClass (el, className) {
  return el.classList ? el.classList.contains(className) : new RegExp('\\b' + className + '\\b').test(el.className)
}

function addClass (el, className) {
  if (el.classList) el.classList.add(className)
  else if (!hasClass(el, className)) el.className += ' ' + className
}

function removeClass (el, className) {
  if (el.classList) el.classList.remove(className)
  else el.className = el.className.replace(new RegExp('\\b' + className + '\\b', 'g'), '')
}

function insertBefore (el, referenceNode) {
  referenceNode.parentNode.insertBefore(el, referenceNode)
}

function wrapElement (toWrap, wrapper = document.createElement('div')) {
  toWrap.parentNode.appendChild(wrapper)
  return wrapper.appendChild(toWrap)
}

// ---------------------------------------------------------------------------

if (document.readyState !== 'loading') {
  main()
} else if (document.addEventListener) {
  document.addEventListener('DOMContentLoaded', main)
} else {
  document.attachEvent('onreadystatechange', function () {
    if (document.readyState === 'complete') main()
  })
}
sonicdoe commented 6 years ago

Interestingly I have issues with a particular file in a particular project.

Do you have standard installed as a development dependency in that project? Does running standard from the command line work correctly (for that particular file)?

gorkarod commented 6 years ago

Yes, if I e.g. put an extra semicolon at the end of a line and run node_modules/.bin/standard src/main/frontend/js/scripts.js I get a warning as expected.

sonicdoe commented 6 years ago

Which standard version do you have installed? Do you have any custom standard settings in your package.json?

Could you also try running the following command (after putting an extra semicolon at the end of a line)?

$ node --print "require('standard').lintTextSync(fs.readFileSync(path.resolve('src/main/frontend/js/scripts.js'), 'utf8'))"

This runs the linter using standard’s Node.js API (which linter-js-standard uses). It shouldn’t really differ from the command-line interface but I’d be interested in the output just to be sure.

hacknlove commented 6 years ago

I have this problem when I prepend any .js file with a dot

foo.js works fine .foo.js fails

It fails also if I prepend any parent folder with a dor

foo/bar.js works fine .foo/bar.js fails

TypeError: Cannot read property 'messages' of undefined
    at Object.module.exports (/home/pykiss/.atom/packages/linter-js-standard/lib/utils/linter.js:33:31)
    at _combinedTickCallback (internal/process/next_tick.js:74:11)
    at process._tickCallback (internal/process/next_tick.js:98:9)
gorkarod commented 6 years ago

Same here. I have a dot in the path as my file resides somewhere in ".eclipse-workspace"

And no, I don't have any special Version or settings in my package.json. If I run node --print "require( ... output looks like

{ results:
   [ { filePath: '<text>',
       messages: [Array],
       errorCount: 1,
       warningCount: 0,
       source: 'function main () {\n  processMenuItems()\n  insertMainMenuCover()\n  handleLangMenu();\n}\n\nfunction handleLangMenu () {\n  const langswitch = Array.from(document.getElementsByClassName(\'module-metamenu--langswitch\'))[0]\n  const langmenu = Array.from(document.getElementsByClassName(\'module-metamenu--langmenu\'))[0]\n  langswitch.addEventListener(\'click\', function (event) {\n    if (!hasClass(langmenu, \'-expanded\')) {\n      addClass(langmenu, \'-expanded\')\n    } else {\n      removeClass(langmenu, \'-expanded\')\n    }\n  })\n}\n\nfunction processMenuItems () {\n  let menuItems = Array.from(document.getElementsByClassName(\'module-mainmenu--level-0\'))[0].childNodes\n\n  // Zap separator items\n  for (let i = 0; i < menuItems.length; i++) {\n    let item = menuItems[i]\n    if (hasClass(item, \'separator\')) {\n      item.parentNode.removeChild(item)\n    }\n  }\n\n  // Process others\n  for (let i = 0; i < menuItems.length; i++) {\n    let item = menuItems[i]\n    let anchor = item.childNodes[0]\n    let ul = Array.from(item.childNodes).filter((item) => item.nodeName === \'UL\')\n    const title = anchor.textContent\n    const id = item.className.slice(1)\n    const itemTop = item.offsetTop\n    // attach Click handler\n    if (ul.length) {\n      anchor.addEventListener(\'click\', function (event) {\n        event.preventDefault()\n        event.stopPropagation()\n        addClass(ul[0].parentNode, \'-expanded\')\n        let cover = document.getElementsByClassName(\'module-mainmenu--cover\')[0]\n        addClass(cover, \'-expanded\')\n        return false\n      })\n      let container = document.createElement(\'div\')\n      addClass(container, \'module-mainmenu--level-1-container\')\n      container.style.paddingTop = itemTop + \'px\'\n      wrapElement(ul[0], container)\n\n      let backbutton = document.createElement(\'button\')\n      backbutton.innerHTML = \'zurück\'\n      backbutton.addEventListener(\'click\', function (event) {\n        removeClass(this.parentNode, \'-expanded\')\n        let cover = document.getElementsByClassName(\'module-mainmenu--cover\')[0]\n        removeClass(cover, \'-expanded\')\n      })\n      // addClass(backbutton, \'module-mainmenu--level-1-backbutton\')\n      insertBefore(backbutton, ul[0])\n\n      let submenuheader = document.createElement(\'h2\')\n      submenuheader.innerHTML = title\n      addClass(submenuheader, \'-\' + id)\n      insertBefore(submenuheader, ul[0])\n    }\n    // Add icon container, wrap text\n    anchor.innerHTML = `<div class="module-mainmenu--icon-level-0 -${id}"></div><div class="module-mainmenu--link-level-0">${title}</div>`\n  }\n\n  // Show menu when ready\n  document.getElementsByClassName(\'module-mainmenu--level-0\')[0].style.visibility = \'visible\'\n}\n\nfunction insertMainMenuCover () {\n  const cover = document.createElement(\'div\')\n  addClass(cover, \'module-mainmenu--cover\')\n  insertBefore(cover, document.getElementsByClassName(\'module-mainmenu--level-0\')[0])\n}\n\nfunction hasClass (el, className) {\n  return el.classList ? el.classList.contains(className) : new RegExp(\'\\\\b\' + className + \'\\\\b\').test(el.className)\n}\n\nfunction addClass (el, className) {\n  if (el.classList) el.classList.add(className)\n  else if (!hasClass(el, className)) el.className += \' \' + className\n}\n\nfunction removeClass (el, className) {\n  if (el.classList) el.classList.remove(className)\n  else el.className = el.className.replace(new RegExp(\'\\\\b\' + className + \'\\\\b\', \'g\'), \'\')\n}\n\nfunction insertBefore (el, referenceNode) {\n  referenceNode.parentNode.insertBefore(el, referenceNode)\n}\n\nfunction wrapElement (toWrap, wrapper = document.createElement(\'div\')) {\n  toWrap.parentNode.appendChild(wrapper)\n  return wrapper.appendChild(toWrap)\n}\n\n// ---------------------------------------------------------------------------\n\nif (document.readyState !== \'loading\') {\n  main()\n} else if (document.addEventListener) {\n  document.addEventListener(\'DOMContentLoaded\', main)\n} else {\n  document.attachEvent(\'onreadystatechange\', function () {\n    if (document.readyState === \'complete\') main()\n  })\n}\n' } ],
  errorCount: 1,
  warningCount: 0 }
sonicdoe commented 6 years ago

@hacknlove @gorkarod Thanks for the info, I was now able to reproduce this error.

standard ignores hidden files and folders by default. Since we’re passing filename to lintText() in v4.1.0, standard ignores the file causing results to be empty.

I’ll take a closer look at fixing this soon. Any help would be appreciated though 🙂

gorkarod commented 6 years ago

Great! Thanks @sonicdoe!

sonicdoe commented 6 years ago

This error has been fixed in https://github.com/ricardofbarros/linter-js-standard/commit/f553b4997e779725e565befdf73a1891d5907ac9 which will be included in the next major release.

I have also reverted the original commit introducing this error (https://github.com/ricardofbarros/linter-js-standard/commit/2d719175a161ec28a2e5cc3822e81dc580e36d1a) and published v4.2.0. Therefore, using v4.2.0, you should no longer run into this issue.

technology-studio-apiary commented 6 years ago

@sonicdoe Hi, I don't really understand why you reverted given option. If standard ignores, given files, then they should be ignored.

But is there way to do at least trade-off to introduce settings which allows disables/enables sending file to standard engine.

Reverting the commit introduces back original problem #212. (Guys we have spent lot of time to identify given issue).

sonicdoe commented 6 years ago

I agree that if standard ignores a file, linter-js-standard should too. I will add passing the filename to lintText() back in the next major release. The reason I’ve reverted it in v4.2.0 is that v4.1.0 introduced a breaking change in a minor version (which goes against the Semantic Versioning spec).

rostislav-simonik commented 6 years ago

@sonicdoe ok, thanks for update. Until 5.0.0 released, we manually stick with 4.1.0.

sonicdoe commented 6 years ago

v5.0.0 has now been released and includes this fix.