prettier / eslint-config-prettier

Turns off all rules that are unnecessary or might conflict with Prettier.
MIT License
5.39k stars 255 forks source link

Conflict between prettier and @typescript-eslint/no-extra-semi #198

Closed lmichelin closed 3 years ago

lmichelin commented 3 years ago

Hello, in this TypeScript example there is a conflict between eslint and prettier regarding the semicolon at the beginning of the line inside the brackets:

setTimeout(() => {
  ;(element as HTMLElement).classList.add("class") // eslint wants to remove the semicolon
}, 100)

setTimeout(() => {
  (element as HTMLElement).classList.add("class") // prettier wants to add a semicolon
}, 100)

eslint console output:

2:3   error    Unnecessary semicolon                     @typescript-eslint/no-extra-semi
6:3   error    Insert `;`                                prettier/prettier

.prettierrc:

{
  "semi": false
}

.eslintrc example to reproduce the issue:

{
  "extends": ["plugin:prettier/recommended"],
  "parserOptions": { "ecmaVersion": 2018 },
  "overrides": [
    {
      "files": ["*.ts"],
      "parser": "@typescript-eslint/parser",
      "parserOptions": { "project": ["./tsconfig.json"] },
      "extends": [
        "plugin:@typescript-eslint/recommended",
        "plugin:@typescript-eslint/recommended-requiring-type-checking"
      ]
    }
  ]
}

Packages versions:

"@typescript-eslint/eslint-plugin": "4.29.1",
"@typescript-eslint/parser": "4.29.1",
"eslint": "7.32.0",
"eslint-config-prettier": "8.3.0",
"eslint-plugin-prettier": "3.4.0",
"prettier": "2.3.2",
"typescript": "4.3.5",

I hope I provided enough details for you to reproduce the issue.

Thanks for your answer.

lydell commented 3 years ago

Hi!

@typescript-eslint/no-extra-semi is already turned off!

I think you need to add "prettier" to that second "entends" array:

{
  "extends": ["plugin:prettier/recommended"],
  "parserOptions": { "ecmaVersion": 2018 },
  "overrides": [
    {
      "files": ["*.ts"],
      "parser": "@typescript-eslint/parser",
      "parserOptions": { "project": ["./tsconfig.json"] },
      "extends": [
        "plugin:@typescript-eslint/recommended",
        "plugin:@typescript-eslint/recommended-requiring-type-checking"
+       ,"prettier"
      ]
    }
  ]
}

Can you try that? (Thanks for the nice repro information, but I don’t have time right now to try it out myself. I’ll do that if my suggestion doesn’t work.)

lmichelin commented 3 years ago

Hi @lydell,

Thanks for your answer.

You are right, it works :tada:

I guess it's because overridden extends come after base extends, and so 'prettier' is not the last value in the final 'extends' array, right?

lydell commented 3 years ago

I think so too! It’s always hard to understand how config extending/inheritance works – one can’t really reason about how it works, one needs to check the source code…

Can we close the issue, or is there something left to address?

lmichelin commented 3 years ago

Yes, you can close the issue, thanks ;)

lmichelin commented 3 years ago

Hi @lydell,

Actually I just found why I started to have the issue:

I used to have:

"extends": [
        "plugin:@typescript-eslint/recommended",
        "plugin:@typescript-eslint/recommended-requiring-type-checking",
        "prettier/@typescript-eslint"
]

and I removed "prettier/@typescript-eslint" since it has been merged into "prettier" in eslint-config-prettier v8 (https://github.com/prettier/eslint-config-prettier/blob/main/CHANGELOG.md#version-800-2021-02-21). I thought it was not necessary to keep the line since prettier was already taken into account in the base extends. Actually it was, but not in the right order, so I should have renamed "prettier/@typescript-eslint" into "prettier" instead of removing the line 😉

Sorry for the false positive 😅 and thanks for your help 👌

SaadAhmadSaddiqui commented 1 year ago
{
  "parser": "@typescript-eslint/parser",
  "extends": [
    "airbnb",
    "eslint:recommended",
    "plugin:react/recommended",
    "plugin:react-hooks/recommended",
    "plugin:import/typescript",
    "plugin:prettier/recommended",
    "plugin:@typescript-eslint/eslint-recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:@typescript-eslint/recommended-requiring-type-checking"
  ],
  "env": {
    "es6": true,
    "jest": true,
    "node": true
  },
  "globals": {
    "__DEV__": true
  },
  "plugins": ["babel", "import", "react", "react-native", "@typescript-eslint"],
  "parserOptions": {
    "ecmaVersion": 6,
    "ecmaFeatures": {
      "jsx": true
    },
    "sourceType": "module",
    "project": "./tsconfig.json"
  },
  "settings": {
    "import/resolver": {
      "node": {
        "extensions": [".js", ".jsx", ".android.js", ".ios.js", ".ts", ".tsx"]
      },
      "typescript": {}
    }
  },
  "rules": {
    "prettier/prettier": [
      "error",
      {
        "semi": false
      }
    ],
    "experimental-decorators": "off",
    "import/prefer-default-export": "off",
    "max-len": ["error", 150],
    "no-case-declarations": "off",
    "no-confusing-arrow": "off",
    "import/extensions": "off",
    "react/display-name": "off",
    "jsx-a11y/accessible-emoji": "off",
    "camelcase": "off",
    "no-unused-expressions": [
      1,
      {
        "allowShortCircuit": true
      }
    ],
    "no-use-before-define": "off",
    "no-console": [
      "error",
      {
        "allow": ["debug", "error", "warn"]
      }
    ],
    "no-nested-ternary": "off",
    "no-plusplus": "off",
    "no-restricted-syntax": "off",
    "no-underscore-dangle": "off",
    "radix": "off",
    "react/no-did-update-set-state": "off",
    "react/sort-comp": "warn",
    "react/jsx-curly-brace-presence": "off",
    "react-native/no-color-literals": "warn",
    "react-native/no-unused-styles": "warn",
    "react-native/split-platform-components": "error",
    "react/forbid-prop-types": "off",
    "react/jsx-filename-extension": "off",
    "react/prefer-stateless-function": [
      "error",
      {
        "ignorePureComponents": true
      }
    ],
    "react/require-default-props": "off",
    "semi": "off",
    "@typescript-eslint/member-delimiter-style": [
      "warn",
      {
        "multiline": {
          "delimiter": "none",
          "requireLast": true
        },
        "singleline": {
          "delimiter": "semi",
          "requireLast": false
        }
      }
    ],
    "no-unused-vars": "off",
    "import/order": [
      "error",
      {
        "groups": [
          "builtin",
          "external",
          "internal",
          ["parent", "sibling", "object", "index"]
        ],
        "pathGroups": [
          {
            "pattern": "react",
            "group": "builtin",
            "position": "before"
          },
          {
            "pattern": "react-native",
            "group": "builtin"
          },
          {
            "pattern": "assets/*",
            "group": "internal",
            "position": "after"
          }
        ],
        "pathGroupsExcludedImportTypes": ["react"],
        "alphabetize": {
          "order": "asc",
          "caseInsensitive": true
        },
        "newlines-between": "always"
      }
    ],
    "global-require": "off",
    "no-var-requires": "off",
    "@typescript-eslint/no-explicit-any": 0,
    "@typescript-eslint/no-unused-vars": [
      "warn",
      { "argsIgnorePattern": "^_", "varsIgnorePattern": "^_" }
    ],
    "@typescript-eslint/no-unsafe-member-access": 0,
    "@typescript-eslint/no-floating-promises": 0,
    "@typescript-eslint/no-misused-promises": 0,
    "@typescript-eslint/no-unsafe-assignment": 0,
    "@typescript-eslint/no-unsafe-return": 0,
    "@typescript-eslint/no-unsafe-call": 0,
    "@typescript-eslint/explicit-module-boundary-types": 0,
    "@typescript-eslint/no-var-requires": 0,
    "@typescript-eslint/no-unsafe-argument": 0,
    "@typescript-eslint/restrict-template-expressions": 0,
    "@typescript-eslint/no-namespace": 0,
    "no-void": 0,
    "no-param-reassign": 0,
    "react/jsx-indent": "off",
    "react/no-array-index-key": 0,
    "no-shadow": "off",
    "@typescript-eslint/no-shadow": ["error"]
  }
}

This is my .eslintrc, I tried adding the plugins as mentioned, but I'm still getting the same error. Any help?

lydell commented 1 year ago

@SaadAhmadSaddiqui Move Prettier last

{
  "parser": "@typescript-eslint/parser",
  "extends": [
    "airbnb",
    "eslint:recommended",
    "plugin:react/recommended",
    "plugin:react-hooks/recommended",
    "plugin:import/typescript",
-   "plugin:prettier/recommended",
    "plugin:@typescript-eslint/eslint-recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:@typescript-eslint/recommended-requiring-type-checking",
+   "plugin:prettier/recommended"
  ],
SaadAhmadSaddiqui commented 1 year ago

@lydell Thanks for the quick reply.

I tried that, too. But the error remains.

image

After format

image

 "extends": [
    "airbnb",
    "eslint:recommended",
    "plugin:react/recommended",
    "plugin:react-hooks/recommended",
    "plugin:import/typescript",
    "plugin:@typescript-eslint/eslint-recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:@typescript-eslint/recommended-requiring-type-checking",
    "plugin:prettier/recommended"
  ],
lydell commented 1 year ago

@SaadAhmadSaddiqui Then I don’t know. You’ll need to debug it. I suggest:

Then you’ll probably find what’s up.