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

lint-staged is not taking .eslintrc.js configuration. #677

Closed
pumanitro opened this issue Jul 31, 2019 · 20 comments
Closed

lint-staged is not taking .eslintrc.js configuration. #677

pumanitro opened this issue Jul 31, 2019 · 20 comments

Comments

@pumanitro
Copy link

pumanitro commented Jul 31, 2019

[BUG]

Description

I have created 2 package.json npm scripts:

     "lint-staged:test": "lint-staged",
     "eslint:test": "eslint --fix src/global/AppRouter/AppRouter.tsx",

My configuration for lint-staged looks like;

"lint-staged": {
    "*.tsx": [
      "eslint --fix",
      "git add"
    ]
  }

By running yarn eslint:test or npm run eslint:test I've got no errors.
Like on the image attached:
image

But by running second command ("lint-staged:test") I've got some errors related with the file that was checked with the first command. Image shows it:
image

Those are my rules for eslint (.eslinrc.js file):

module.exports = {
  parser: '@typescript-eslint/parser', // Specifies the ESLint parser
  extends: ['plugin:@typescript-eslint/recommended', 'plugin:react/recommended', 'plugin:prettier/recommended'],
  parserOptions: {
    ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features
    sourceType: 'module', // Allows for the use of imports
    ecmaFeatures: {
      jsx: true, // Allows for the parsing of JSX
    },
  },
  rules: {
    // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
    // e.g. "@typescript-eslint/explicit-function-return-type": "off",

    // note you must disable the base rule as it can report incorrect errors
    indent: 'off',
    '@typescript-eslint/indent': ['error', 2],
  },
  settings: {
    react: {
      version: 'detect', // Tells eslint-plugin-react to automatically detect the version of React to use
    },
  },
};

which are applied for the first command but are not applied for lint-staged.

Some possible solutions?

Environment

  • OS: Windows 10,
  • Node.js: v10.13.0,
  • lint-staged: 9.2.1,
  • eslint: 5.3.0",
@iiroj
Copy link
Member

iiroj commented Aug 1, 2019

In your eslint config you have specified this rule '@typescript-eslint/indent': ['error', 2],. When lint-staged runs, it is showing errors related to this rule. To me this seems correct.

I think your issue is the other way around: your plain eslint command is not picking up the configuration.

@pumanitro
Copy link
Author

Eslint errors show it wants 4 spaces instead of 2.

This rule says I want 2 spaces:
'@typescript-eslint/indent': ['error', 2],
And I have got them.

Eslint error says "Expected indentation of 4 spaces but found 2".

So eslint is using this rule:
'@typescript-eslint/indent': ['error', 4],

Anyway, I have solved this problem with:

  • changing .eslinrc.js file to JSON format instead of .js it is .eslintrc.json
  • commit with --no-verify flag (it looks like lint-staged messed up with some of my files or my IDE showed me them incorrectly - JetBrains WebStorm)

Anyway x2, solved.

@husseinbob
Copy link

I'm currently having the same problem, where the cli output from lint-staged is different to eslint. I'm using eslintrc.js but if i rename to .json and remove the module.exports I instead get another error about "m at position 0"

@iiroj
Copy link
Member

iiroj commented Feb 13, 2020

@husseinbob Please post your debug logs, otherwise nothing can be done.

@husseinbob
Copy link

I think I found the issue. my changes to .eslintrc.js also needed to be staged, by the looks of it? either way, git adding the eslintrc file stopped the error.

@iiroj
Copy link
Member

iiroj commented Feb 13, 2020

@husseinbob yeah, lint-staged will hide unstaged changes before running tasks, so at that point eslint would see the old version of your config.

@IAMtheIAM
Copy link

IAMtheIAM commented May 26, 2020

I confirm that it's not working when I run lint-staged whereas running eslint directly works fine - it's complaining about no parser found, because i'm running it on .HTML files, and there is no default parser configured.

C:\dev\file-upload.component.html 0:0 error Parsing error: Template parse errors: Parser Error: Unexpected token '=' at column 13 in [(locationId)=$event] in C:
[long errors list]

.eslintrc.js config

module.exports = {
    "env": {
        "browser": true,
        "es6": true,
        "node": true
    },
    "overrides": [
        {
            "files": ["*.ts"],
            extends: [
                "plugin:@angular-eslint/recommended", // Rules specific to angular
                "eslint:recommended", // The set of rules which are recommended for all projects by the ESLint Team
                "plugin:@typescript-eslint/eslint-recommended", // As noted in the root README, not all ESLint core rules are compatible with TypeScript, so you need to add both eslint:recommended and plugin:@typescript-eslint/eslint-recommended (which will adjust the one from ESLint appropriately for TypeScript) to your config
                "plugin:@typescript-eslint/recommended" // Uses the recommended rules from the @typescript-eslint/eslint-plugin
            ],
            "parser": "@typescript-eslint/parser",
            "parserOptions": {
                "ecmaVersion": 2020, // Allows for the parsing of modern ECMAScript features
                "project": "./tsconfig.json",
                "sourceType": "module"
            },
            "plugins": [
                "import",
                "@angular-eslint",
                "@typescript-eslint"
            ],
            "rules": {
                "@angular-eslint/component-class-suffix": "error",
                "@angular-eslint/contextual-lifecycle": "error",
                "@angular-eslint/directive-class-suffix": "error",
                "@angular-eslint/no-host-metadata-property": "error",
                "@angular-eslint/no-input-rename": "error",
                "@angular-eslint/no-inputs-metadata-property": "error",
                "@angular-eslint/no-output-on-prefix": "error",
                "@angular-eslint/no-output-rename": "error",
                "@angular-eslint/no-outputs-metadata-property": "error",
                "@angular-eslint/use-component-view-encapsulation": "error",
                "@angular-eslint/use-lifecycle-interface": "error",
                "@angular-eslint/use-pipe-decorator": "error",
                "@angular-eslint/use-pipe-transform-interface": "error",
                "@typescript-eslint/naming-convention": [
                    "error",
                    {
                        "selector": "variableLike", // matches the same as `variable`, `function` and `parameter`
                        "format": [], // required, even as an empty array if using custom regex
                        "custom": {
                            "regex": "(([a-z][a-z0-9]+)((d)|([A-Z0-9][a-z0-9]+))*([A-Z])?)|(^[A-Z]+(?:_[A-Z]+)*$)|([a-z])", // this checks for camelCaseVars that allow multiple humps i.e. capitals in the middle, but not consecutively, for UPPER_CASE_VARS, and also a single a-z lowercase var
                            "match": true
                        }
                    },
                    {
                        "selector": "memberLike",
                        "format": [], // required, even as an empty array if using custom regex
                        "custom": {
                            "regex": "(([a-z][a-z0-9]+)((\d)|([A-Z0-9][a-z0-9]+))*([A-Z])?)|^(\\d*|\\D*)$", // this check for a camelCaseConst that allows multiple humps i.e. capitals in the middle, but not consecutively, and also any set of numbers only (22334455) or any set of letters only (abcdef) but not alphanumeric (mixed123Like567This)
                            "match": true
                        }
                    },
                    {
                        "selector": "memberLike",
                        "modifiers": ["private"],
                        "format": [], // required, even as an empty array if using custom regex
                        "custom": {
                            "regex": "([a-z][a-z0-9]+)((\d)|([A-Z0-9][a-z0-9]+))*([A-Z])?", // this check for a camelCaseConst that allows multiple humps i.e. capitals in the middle, but not consecutively.
                            "match": true
                        },
                        "leadingUnderscore": "allow"
                    },
                    {
                        "selector": "enumMember",
                        "format": ["PascalCase"]
                    },
                    {
                        "selector": "variable",
                        "types": ["boolean"],
                        "format": [], // required, even as an empty array if using custom regex
                        "custom": {
                            "regex": "([a-z][a-z0-9]+)?((\d)|([A-Z0-9][a-z0-9]+))*([A-Z])?", // this check for a camelCaseConst that allows multiple humps i.e. capitals in the middle, but not consecutively.
                            "match": true
                        },
                        "prefix": ["is", "should", "has", "can", "did", "will"]
                    },
                    {
                        "selector": "typeParameter",
                        "format": ["PascalCase"],
                        "prefix": ["T"]
                    }, {
                        "selector": "class",
                        "format": ["PascalCase"]
                    },
                    {
                        "selector": "typeLike",
                        "format": ["PascalCase"]
                    }
                ],
                "@typescript-eslint/consistent-type-definitions": "error",
                "@typescript-eslint/dot-notation": "off",
                "@typescript-eslint/explicit-function-return-type": [
                    "error",
                    {
                        "allowExpressions": true
                    }
                ],
                "@typescript-eslint/explicit-member-accessibility": [
                    "off",
                    {
                        "accessibility": "explicit"
                    }
                ],
                "@typescript-eslint/indent": [
                    "error", 4,
                    { SwitchCase: 1 }
                ],
                "@typescript-eslint/member-delimiter-style": [
                    "error",
                    {
                        "multiline": {
                            "delimiter": "semi",
                            "requireLast": true
                        },
                        "singleline": {
                            "delimiter": "semi",
                            "requireLast": false
                        }
                    }
                ],
                "@typescript-eslint/member-ordering": "error",
                "@typescript-eslint/no-empty-function": "off",
                "@typescript-eslint/no-empty-interface": "error",
                "@typescript-eslint/no-explicit-any": 0,
                "@typescript-eslint/no-inferrable-types": "error",
                "@typescript-eslint/no-misused-new": "error",
                "@typescript-eslint/no-non-null-assertion": "error",
                "@typescript-eslint/no-unused-expressions": "error",
                "@typescript-eslint/no-use-before-define": "error",
                "@typescript-eslint/prefer-function-type": "error",
                "@typescript-eslint/explicit-module-boundary-types": 0,
                "@typescript-eslint/quotes": [
                    "error",
                    "single"
                ],
                "@typescript-eslint/semi": [
                    "error",
                    "always"
                ],
                "@typescript-eslint/type-annotation-spacing": "error",
                "@typescript-eslint/unified-signatures": "error",
                "arrow-body-style": "error",
                "brace-style": [
                    "error",
                    "1tbs"
                ],
                "camelcase": "off",
                "constructor-super": "error",
                "curly": "error",
                "eol-last": "error",
                "eqeqeq": [
                    "error",
                    "smart"
                ],
                "guard-for-in": "error",
                "id-blacklist": "off",
                "id-match": "off",
                "import/no-deprecated": "warn",
                "key-spacing": [
                    "error",
                    {
                        'singleLine': {
                            'beforeColon': false,
                            'afterColon': true
                        },
                        "align": {
                            "beforeColon": false,
                            "afterColon": true,
                            "on": "value"
                        }
                    }],
                "lines-between-class-members": ["error", "always", { exceptAfterSingleLine: true }],
                "max-classes-per-file": [
                    "error",
                    2
                ],
                "max-len": [
                    "error",
                    {
                        "ignoreComments": true,
                        "ignoreUrls": true,
                        "ignoreStrings": true,
                        "ignoreRegExpLiterals": true,
                        "ignoreTemplateLiterals": true,
                        "code": 180
                    }
                ],
                "no-bitwise": "error",
                "no-caller": "error",
                "no-console": process.env.NODE_ENV === "production" ? ["error", { allow: ["warn", "error"] }] : "off",
                "no-debugger": process.env.NODE_ENV === "production" ? "error" : "off",
                "no-empty": "off",
                "no-eval": "error",
                "no-fallthrough": "error",
                "no-new-wrappers": "error",
                "no-restricted-imports": [
                    "error",
                    "rxjs/Rx"
                ],
                "no-restricted-syntax": 0,
                "no-shadow": [
                    "error",
                    {
                        "hoist": "all"
                    }
                ],
                "no-throw-literal": "error",
                "no-trailing-spaces": "error",
                "no-undef-init": "error",
                "no-underscore-dangle": "off",
                "no-unused-labels": "error",
                "no-var": "error",
                "padded-blocks": ["error", "never"],
                "prefer-const": "error",
                "radix": "error",
                "keyword-spacing": [
                    2, {
                        "before": true,
                        "after": true,
                        "overrides": {}
                    }],
                "spaced-comment": [
                    "error",
                    "always",
                    {
                        "markers": [
                            "/"
                        ]
                    }
                ],
                "@angular-eslint/directive-selector": [
                    "error",
                    {
                        "type": "attribute",
                        "prefix": "app",
                        "style": "camelCase"
                    }
                ],
                "@angular-eslint/component-selector": [
                    "error",
                    {
                        "type": "element",
                        "prefix": "app",
                        "style": "kebab-case"
                    }
                ]
            }
        },
        {
            files: ["*.component.html"],
            parser: "@angular-eslint/template-parser",
            plugins: ["@angular-eslint/template"],
            rules: {
                "@angular-eslint/template/banana-in-a-box": "error",
                "@angular-eslint/template/no-negated-async": "error"
            }
        }
    ]
};

package.json

scripts: {
       // this works
        "lint": "cross-env TIMING=1 eslint '**/*.{ts,component.html}' --ignore-pattern '*.d.ts' --fix",
    },
    "lint-staged": {
        "*.{ts,component.html}": "eslint --cache --fix", // this doesn't work
        "*.html": "prettier --write"
    }

UPDATE:

I found out that running eslint --debug shows that both eslint and lint-staged do in fact load the config. See output

2020-05-26T21:31:35.496Z eslint:config-array-factory Config file found: C:\dev\.eslintrc.js

So it isn't due to not loading the config, at least not on initial pass. It's something with the way eslint is parsing it during the --fix flag.

@emhagman
Copy link

I started running into this issue too and running the eslint --fix command by itself works but when run via lint-staged the config seems to be being dropped

@Lonli-Lokli
Copy link

Moreover, I would like to say that with --fix or --quiet eslint part taking too much time and sometims even fails with heap error, my assumption is that with addtional parameters it's ignoring the fact that only single file should be processed.

@okonet
Copy link
Collaborator

okonet commented Mar 1, 2021

Did ESLint change the way they handle arguments maybe?

@MDOR
Copy link

MDOR commented Aug 10, 2021

I work with a monorepo structure, I ran into the same error.

I tried the following configuration into the .lintstagerc.json

It used to be:

{
  "*.{js,jsx}": ["prettier --write", "eslint --fix --quiet", "git add"],
  "*.{ts,tsx}": ["prettier --write", "eslint --fix --quiet", "git add"],
  "*.{scss,scss,css,md,html}": ["prettier --write", "git add"]
}

Now it looks like this:

{
  "*.{js,jsx}": ["prettier --write", "eslint --fix --quiet --config .eslintrc.json --resolve-plugins-relative-to .", "git add"],
  "*.{ts,tsx}": ["prettier --write", "eslint --fix --quiet --config .eslintrc.json --resolve-plugins-relative-to .", "git add"],
  "*.{scss,scss,css,md,html}": ["prettier --write", "git add"]
}

No issues after that, you should give it a try.

The following config --resolve-plugins-relative-to . is related to a eslint-plugin-@typescript-eslint, so probably won't be relevant.

@loolooii
Copy link

Same problem here with a monorepo. What @MDOR proposed doesn't work for me. My problem is a path with alias not being resolved. tsconfig and vite.config.ts are set up correctly and running eslint --fix from the package itself works fine. Running it with lint-staged can't resolve the path, though.

@eliw00d
Copy link

eliw00d commented Feb 15, 2022

I was also having difficulties with a monorepo and was not able to get @MDOR 's solution to work for me. I believe the reason for this is that in --resolve-plugins-relative-to . the . refers to the CWD (which is the root of the monorepo for us, as that is where lint-staged is installed) and not the absolute paths passed to ESLint by lint-staged. If I run eslint --resolve-plugins-relative-to . --fix path/to/the/matched/file from the root, independently of lint-staged, I get the same error(s) that lint-staged gets when running eslint --resolve-plugins-relative-to . --fix.

The way I was able to get around this was to add a .lintstagedrc to each workspace and change directory to the workspace so that the --resolve-plugins-relative-to . would work correctly:

"*.{js,jsx,ts,tsx}": "cd path/to/workspace && eslint --resolve-plugins-relative-to . --fix"

Obviously, this is not ideal, but it did let me get around it for now.

Of note, I do something similar for running eslint through yarn berry:

"g:eslint": "cd $INIT_CWD && eslint --resolve-plugins-relative-to . --ext .js,.jsx,.ts,.tsx .",

where $INIT_CWD is a yarn berry env var for getting the CWD of the workspace that used the script.

@eliw00d
Copy link

eliw00d commented Feb 16, 2022

Using cd in the lint-staged command itself doesn't work if files from multiple workspaces have changed, but I did find this and ended up doing the same thing - and that works in all cases!

@Lonli-Lokli
Copy link

Not everyone use yarn worspaces, some use Nx, other lerna or bit.

@eliw00d
Copy link

eliw00d commented Feb 16, 2022

Not everyone use yarn worspaces, some use Nx, other lerna or bit.

Of course not, but I hope it is still helpful to know that you need to change directories somehow (and then back afterwards) to make use of --resolve-plugins-relative-to ..

@Manubi
Copy link

Manubi commented May 5, 2022

I am having the same issue with a pnpm monorepo. If i run pnpm lint all the linting runs fine. As soon as husky runs npx lint-staged the terminal complains about: ESLint couldn't find a configuration file.
Does anyone have a repo or idea how to fix it?
Thanks!

@loolooii
Copy link

loolooii commented May 5, 2022

I am having the same issue with a pnpm monorepo. If i run pnpm lint all the linting runs fine. As soon as husky runs npx lint-staged the terminal complains about: ESLint couldn't find a configuration file. Does anyone have a repo or idea how to fix it? Thanks!

I would have a eslintrc file in the root of your project and let your packages extend it. Then it will work.

@mike-odom
Copy link

I tried a few solutions in this thread and found that upgrading lint-staged from 9.2.5 to 12.5.0 worked for me. (I can't use 13 because this project is on Node 12 still)
Previously, eslint was completely ignoring my .eslintrc file in the root, even if I specified it on the command line.

To really test this, put garbage text in your .eslintrc file and run eslint to see if it fails on parsing that

@wilsinneto
Copy link

wilsinneto commented Dec 29, 2022

I was able to solve it by adding the following settings to the .eslintrc.json file:

"extends": [
  "standard"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
  "ecmaVersion": 12
},
"plugins": [
  "@typescript-eslint"
],

@iiroj iiroj closed this as completed Dec 29, 2022
bqi343 added a commit to cpinitiative/usaco-guide that referenced this issue Mar 7, 2023
thecodingwizard pushed a commit to cpinitiative/usaco-guide that referenced this issue Mar 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests