babel / babel-eslint

:tokyo_tower: A wrapper for Babel's parser used for ESLint (renamed to @babel/eslint-parser)
https://github.com/babel/babel/tree/main/eslint/babel-eslint-parser
MIT License
2.96k stars 208 forks source link

Template string failing with Cannot read property 'range' of null #799

Closed pbn04001 closed 4 years ago

pbn04001 commented 5 years ago

Upgraded to 10.0.3 and now everywhere in my .jsx I have template strings, it blows up with this error. TypeError: Cannot read property 'range' of null

This is my current list of devDependencies "@babel/core": "^7.2.0", "@babel/plugin-proposal-class-properties": "^7.1.0", "@babel/plugin-proposal-decorators": "^7.1.2", "@babel/plugin-proposal-do-expressions": "^7.0.0", "@babel/plugin-proposal-export-default-from": "^7.0.0", "@babel/plugin-proposal-export-namespace-from": "^7.0.0", "@babel/plugin-proposal-function-bind": "^7.0.0", "@babel/plugin-proposal-function-sent": "^7.0.0", "@babel/plugin-proposal-json-strings": "^7.0.0", "@babel/plugin-proposal-logical-assignment-operators": "^7.0.0", "@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0", "@babel/plugin-proposal-numeric-separator": "^7.0.0", "@babel/plugin-proposal-optional-chaining": "^7.0.0", "@babel/plugin-proposal-pipeline-operator": "^7.0.0", "@babel/plugin-proposal-throw-expressions": "^7.0.0", "@babel/plugin-syntax-dynamic-import": "^7.0.0", "@babel/plugin-syntax-import-meta": "^7.0.0", "@babel/plugin-transform-regenerator": "^7.0.0", "@babel/plugin-transform-runtime": "^7.0.0", "@babel/plugin-transform-template-literals": "^7.0.0", "@babel/polyfill": "^7.0.0", "@babel/preset-env": "^7.1.5", "@babel/preset-react": "^7.0.0", "@babel/register": "^7.6.0", "autoprefixer": "^9.1.3", "babel-eslint": "10.0.3", "babel-loader": "^8.0.0", "babel-plugin-add-module-exports": "^0.2.1", "babel-plugin-istanbul": "^5.2.0", "babel-plugin-lodash": "^3.3.4", "babel-preset-react-hmre": "^1.1.1", "chai": "^3.4.1", "chai-as-promised": "^5.1.0", "chai-enzyme": "^1.0.0-beta.1", "compression-webpack-plugin": "^1.1.11", "css-loader": "^3.2.0", "cssnano": "^4.1.0", "enzyme": "^3.7.0", "enzyme-adapter-react-16": "^1.6.0", "eslint": "^6.0.1", "eslint-config-airbnb": "^10.0.1", "eslint-loader": "^2.2.1", "eslint-plugin-babel": "^3.2.0", "eslint-plugin-import": "2.14.0", "eslint-plugin-jsx-a11y": "^2.2.3", "eslint-plugin-react": "^6.2.0", "extract-text-webpack-plugin": "^3.0.2", "fetch-mock": "^5.10.0", "file-loader": "^1.1.11", "fs-extra": "^0.30.0", "html-webpack-plugin": "^3.2.0", "image-webpack-loader": "^4.6.0", "ip": "^1.1.4", "js-md5": "^0.4.1", "karma": "^4.3.0", "karma-chai": "^0.1.0", "karma-chai-as-promised": "^0.1.2", "karma-chai-sinon": "^0.1.5", "karma-chrome-launcher": "^3.1.0", "karma-coverage": "^1.1.2", "karma-mocha": "^1.3.0", "karma-sourcemap-loader": "^0.3.7", "karma-spec-reporter": "0.0.26", "karma-webpack": "^4.0.0-beta.0", "koa-logger": "^1.3.0", "loader-utils": "^1.1.0", "lost": "^7.0.3", "macaddress": "~0.2.9", "mini-css-extract-plugin": "^0.3.0", "mocha": "~5.2.0", "node-noop": "^1.0.0", "nodemon": "^1.18.7", "optimize-css-assets-webpack-plugin": "^5.0.0", "postcss-custom-media": "^7.0.8", "postcss-focus-visible": "^3.0.0", "postcss-focus-within": "^2.0.0", "postcss-import": "^12.0.0", "postcss-loader": "^3.0.0", "postcss-nesting": "^6.0.0", "postcss-preset-env": "^5.3.0", "postcss-reporter": "^6.0.0", "puppeteer": "^1.19.0", "raw-loader": "^0.5.1", "react-hot-loader": "^3.0.0-beta.7", "react-text-truncate": "^0.12.0", "react-toastify": "^2.1.0", "redbox-react": "^1.5.0", "redux-devtools": "^3.4.1", "redux-devtools-dock-monitor": "^1.1.2", "redux-devtools-log-monitor": "^1.4.0", "redux-logger": "^3.0.6", "redux-mock-store": "^1.0.2", "sinon": "^1.17.2", "sinon-chai": "^2.8.0", "sonarqube-scanner": "^2.5.0", "style-loader": "^0.21.0", "stylelint": "^9.10.1", "stylelint-webpack-plugin": "^0.10.5", "svg-sprite-loader": "3.9.0", "svgo": "^1.3.0", "svgo-loader": "^2.1.0", "url-loader": "^1.1.2", "webpack": "^4.20.2", "webpack-cli": "^3.0.8", "webpack-dev-middleware": "^3.1.3", "webpack-hot-middleware": "^2.22.3", "webpack-merge": "^4.1.1", "webpack-modernizr-loader": "^4.0.1"

ethansisson commented 5 years ago

Same for me. Possibly related to #691. @hzoo are you aware of any recent changes that might have effected your fix for that issue?

ethansisson commented 5 years ago

Solution in https://github.com/babel/babel-eslint/issues/530#issuecomment-447511293 worked for me.

einarolafs commented 5 years ago

Same for me, I'm having issues where eslint after upgrading from v10.0.2to v10.0.3 breaks on the first file that contains a template string.

einarolafs commented 5 years ago

@ethansisson good point, for me simply just doing npm i @babel/types @babel/traverse --save-dev was enough to fix the issue.

LCINA commented 5 years ago

@ethansisson good point, for me simply just doing npm i @babel/types @babel/traverse --save-dev was enough to fix the issue.

Thanks man.

techsin commented 4 years ago

@einsiol it worked

yitomok commented 4 years ago

It shows same error on code with dynamic import, template literal inline and rule template-curly-spacing as follow:

Tested on:

babel-eslint@10.0.3 eslint@6.7.2

Sample code:

import(`${'package.json'}`)

.eslintrc.json

{
  "parser": "babel-eslint",
  "rules": {
    "template-curly-spacing": ["error", "never"]
  }
}

Workaround:

Declare the template literal in a const instead of inline

I was not knowledgeable enough to fix it, hope someone will.

EDIT:

It looks like the problem is actually coming from @babel/parser@7.7.7, which added ImportExpression.

KempfCreative commented 4 years ago

I resolved this by adding "@babel/parser": "7.7.5" to my package.json dependencies.

fangbinwei commented 4 years ago

works for me

eslint config

    "rules": {
      "indent": [
        "error",
        2,
        {
          "ignoredNodes": [
            "TemplateLiteral"
          ]
        }
      ],
      "template-curly-spacing": [
        "off"
      ]
    },
vesper8 commented 4 years ago

this suddenly started failing after a recent yarn upgrade

const res = await import(`../../lang/locale/${payload}.json`);

replaced by

const langFile = `../../lang/locale/${payload}.json`;
const res = await import(langFile);

Fixed the error, but now am getting this warning instead Critical dependency: the request of a dependency is an expression

Can also confirm that adding this to my eslint rules also works as an alternative

"indent": [
    "error",
    2,
    {
        "ignoredNodes": [
            "TemplateLiteral"
        ]
    }
],
Burtonium commented 4 years ago

@yitomok pretty much nails it I think.

Happens with a vue/airbnb setup as well:

    "babel-eslint": "^10.0.3",
    "eslint": "^6.8.0",
    "eslint-config-airbnb-base": "^14.0.0",
    "eslint-plugin-import": "^2.19.1",
    "eslint-plugin-vue": "^6.1.1"

I've yet to see a stack trace so here's mine:

TypeError: Cannot read property 'range' of null
Occurred while linting /home/burtonium/projects/eslint/index.js:2
    at SourceCode.getTokenBefore (/home/burtonium/projects/eslint/node_modules/eslint/lib/source-code/token-store/index.js:298:18)
    at checkSpacingBefore (/home/burtonium/projects/eslint/node_modules/eslint/lib/rules/template-curly-spacing.js:60:42)
    at TemplateElement (/home/burtonium/projects/eslint/node_modules/eslint/lib/rules/template-curly-spacing.js:119:17)
    at listeners.(anonymous function).forEach.listener (/home/burtonium/projects/eslint/node_modules/eslint/lib/linter/safe-emitter.js:45:58)
    at Array.forEach (<anonymous>)
    at Object.emit (/home/burtonium/projects/eslint/node_modules/eslint/lib/linter/safe-emitter.js:45:38)
    at NodeEventGenerator.applySelector (/home/burtonium/projects/eslint/node_modules/eslint/lib/linter/node-event-generator.js:254:26)
    at NodeEventGenerator.applySelectors (/home/burtonium/projects/eslint/node_modules/eslint/lib/linter/node-event-generator.js:283:22)
    at NodeEventGenerator.enterNode (/home/burtonium/projects/eslint/node_modules/eslint/lib/linter/node-event-generator.js:297:14)
    at CodePathAnalyzer.enterNode (/home/burtonium/projects/eslint/node_modules/eslint/lib/linter/code-path-analysis/code-path-analyzer.js:634:23)

@einsiol's solution did not work for me either. Here's my setup:

eslintrc.js

module.exports = {
  root: true,
  env: {
    browser: true,
    node: true
  },
  parserOptions: {
    parser: 'babel-eslint',
  },
  extends: [
    'airbnb-base',
    'plugin:vue/essential',
   ],
}

package.json

{
  "name": "eslint-test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "lint": "eslint --ext .js,.vue --ignore-path .gitignore ."
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/traverse": "^7.7.4",
    "@babel/types": "^7.7.4",
    "babel-eslint": "^10.0.1",
    "eslint": "^6.8.0",
    "eslint-config-airbnb-base": "^14.0.0",
    "eslint-plugin-import": "^2.19.1",
    "eslint-plugin-vue": "^6.1.1",
    "i": "^0.3.6",
    "npm": "^6.13.4"
  }
}

index.js

export default {
  fileLoader: (filename) => import(`./files/${filename}`),
};
hawkeye64 commented 4 years ago

Adding this to package.json is a temporary work-around:

 "resolutions": {
    "@babel/parser": "7.7.5"
  }

Then delete node_modules, package-lock.json/yarn.lock and then run npm install or yarn

roland-reed commented 4 years ago

It shows same error on code with dynamic import, template literal inline and rule template-curly-spacing as follow:

Tested on:

babel-eslint@10.0.3 eslint@6.7.2

Sample code:

import(`${'package.json'}`)

.eslintrc.json

{
  "parser": "babel-eslint",
  "rules": {
    "template-curly-spacing": ["error", "never"]
  }
}

Workaround:

Declare the template literal in a const instead of inline

I was not knowledgeable enough to fix it, hope someone will.

EDIT:

It looks like the problem is actually coming from @babel/parser@7.7.7, which added ImportExpression.

I'm facing the same situation, when TemplateLiteral is inside a dynamic import statement, error occurs. I found the SourceCode.getFirstToken() returns null instead of a Token, and function checkSpacingBefore() throws due to token is null.

wandersonpjbkn commented 4 years ago

I resolved this by adding "@babel/parser": "7.7.5" to my package.json dependencies.

This worked for me! I tried all the others solutions, but none of them worked.

Until this one, just added "@babel/parser": "7.7.5"

s3bul commented 4 years ago

If you use package where @babel/parser is in dependencies, add "@babel/parser": "<7.7.7" in resolutions in package.json file, something like that

"resolutions": {
    "@babel/parser": "<7.7.7"
},
patrickmonteiro commented 4 years ago

Adding this to package.json is a temporary work-around:

 "resolutions": {
    "@babel/parser": "7.7.5"
  }

Then delete node_modules, package-lock.json/yarn.lock and then run npm install or yarn

It worked for me. thanks!

demaet commented 4 years ago

npm install does not work for me as "resolutions" seems to be ignored.

I had to install yarn beforehand with (warning: the ubuntu package of yarn seems buggy for now) sudo npm install -g yarn

falcon03 commented 4 years ago

Same issue here. Assigning the template to a const is not a viable option for me, as to do so breaks the webpack chunk naming mechanism. As I don't like messing up with dependencies I've disabled the problematic rules for now, but I hope for a better solution soon....

ogonkov commented 4 years ago

Why this issue is appears again and again?

ogonkov commented 4 years ago

Adding this to package.json is a temporary work-around:

 "resolutions": {
    "@babel/parser": "7.7.5"
  }

Then delete node_modules, package-lock.json/yarn.lock and then run npm install or yarn

npm i -D @babel/parser@7.7.5
npm remove @babel/parser

Updates package-lock.json and fix issue aswell.

MartinX3 commented 4 years ago

Upgraded from 10.0.3 to 10.1.0 and now I have the same error.

I would like to avoid this curly rule workaround and stay on 10.0.3 for now. (Using vueJS & vuetify)

ntnyq commented 4 years ago

Got this issue again with v10.1.0.

vladimyr commented 4 years ago

Adding this to package.json is a temporary work-around:

 "resolutions": {
    "@babel/parser": "7.7.5"
  }

Then delete node_modules, package-lock.json/yarn.lock and then run npm install or yarn

⚠️ Never ever delete the lockfile!

Use @ogonkov's solution: https://github.com/babel/babel-eslint/issues/799#issuecomment-585978781

hawkeye64 commented 4 years ago

@vladimyr If you don't delete the lock file, yarn/npm will read from that and try to put everything back. The lock file always contains your latest, even though your package.json may have ^1.0.0 for a package. Therefore, if you don't delete the lock file, you will get back the version of the parser you are trying to downgrade.

vladimyr commented 4 years ago

@hawkeye64 So it will affect only @babel/parser, right? We can simply ignore hundreds if not thousands of other side effects?! :man_facepalming: I kindly suggest that you learn stuff in deep before you start giving out hazardous advice. Here is a good starting point: https://code-trotter.com/web/mastering-yarn-lock-file/

pitaj commented 4 years ago

For people who were having this same issue as me. This error shows up as the following with eslint@7.1.0, @babel/parser@7.9.6, babel-eslint@10.1.0:

TypeError: Cannot read property 'value' of null

This work-around worked for me (npm@6.4.1):

npm i -D @babel/parser@7.7.5
GeorgeWL commented 4 years ago

I'm having this happen on the new ?? operator instead

https://gist.github.com/GeorgeWL/0a7ce21622259e84d39a929b8cd72c81 for the full logs and details

lint command in my package json is

"lint": "eslint . -c .eslintrc.js --ext js,jsx --fix"

https://gist.github.com/GeorgeWL/0a7ce21622259e84d39a929b8cd72c81#file-error-reports-from-here-js-L4 is the source of the error

PatrickSchuster commented 4 years ago

I too had issues after using nullish coalescing (?? operator) in a vuejs project. After upgrading the eslint dependencies to a version which supported it, it resolved the issue for me. I used the following dependencies to make it work:

"@vue/cli-plugin-eslint": "^4.4.5",
"@vue/eslint-config-standard": "^4.0.0",
"@vue/eslint-config-standard": "^5.1.2",
"@vue/eslint-config-typescript": "^4.0.0",
"@vue/eslint-config-typescript": "^5.0.2",
"eslint": "^5.16.0",
"eslint": "^6.8.0",
"eslint-plugin-vue": "^5.0.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-vue": "^6.2.2",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.1",
"eslint-plugin-import": "^2.21.2",
"@typescript-eslint/eslint-plugin": "^2.34.0",
"@typescript-eslint/parser": "^2.34.0"
pitaj commented 4 years ago

Looks like you just switched from the Babel eslint parser to the typescript eslint parser, which isn't really relevant to this issue, and will not work for everyone depending on which Babel plugins they're using.

pi0 commented 4 years ago

Hi! While we are in the same boat for this issue, a better version for resulutions workaround is:

  "resolutions": {
    "babel-eslint/@babel/parser": "7.7.5"
  },

This helps only using old @babel/parser for babel-eslint

For the alternative workaround, there was a difference for switch-case ident. So i used:

{
  "rules": {
    "indent": [
      "error",
      2,
      {
        "SwitchCase": 1,
        "ignoredNodes": [
          "TemplateLiteral"
        ]
      }
    ],
    "template-curly-spacing": 0
  }
}
GeorgeWL commented 4 years ago

The template string issue may be a separate issue from the nullish coalescing issue, so I'm gonna open a new ticket for the nullish coalescing and ref this thread.

joemaffei commented 4 years ago

My workaround was to not use backticks to interpolate strings. I refactored this:

import(`./${path}`)

into this:

import('./' + path)

and voila, it worked.

Strahinja commented 4 years ago

@joemaffei I'm having this issue with a Vue.js component containing this code:

        this.dynamicComponent = () => import('~/static/blog/${this.fileName}.md').then((loaded) => {
                        // ...

but, unfortunately, turning it into

        this.dynamicComponent = () => import('~/static/blog/' 
            + this.fileName + '.md').then((loaded) => {
                        // ...

didn't work. I'm still getting TypeError: Cannot read property 'range' of null. Running

$ npx eslint --version

gives v7.5.0. I have this in my .eslintrc.json:

    "parser": "vue-eslint-parser",
    "parserOptions": {
        "parser": "babel-eslint",
        "ecmaVersion": 2018,
        "sourceType": "module"
    },

because before that ESlint complained about "unexpected import".

Edit: What ultimately worked for me is the "resolutions": { "babel-eslint/@babel/parser": "7.7.5" } workaround.

JLHwung commented 4 years ago

Fixed in @babel/eslint-parser 7.11.0, please see https://babel.dev/blog/2020/07/13/the-state-of-babel-eslint#the-future for the renaming guide.

miikka commented 4 years ago

@JLHwung I'm still experiencing this issue with @babel/eslint-parser 7.11.0 (with eslint 7.5.0 and @babel/core 7.11.0) 😞 Specifically with an import expression:

const foo = import(`${bar}`);

I've created a small repo to reproduce this issue: https://github.com/miikka/babel-eslint-799-repro

kaicataldo commented 4 years ago

Thank you for the PR. Now that @babel/eslint-parser has been released, we are making this repository read-only. If this is a change you would still like to advocate for, please reopen this in the babel/babel monorepo.