Eslint no-extra-parens rule does not work - vue.js

I have a vue project with an ESLint and prettier config like so:
"#typescript-eslint/eslint-plugin": "^4.26.1",
"#typescript-eslint/parser": "^4.26.1",
"#vue/eslint-config-prettier": "^6.0.0",
"#vue/eslint-config-typescript": "^7.0.0",
"eslint": "^7.28.0",
"eslint-plugin-prettier": "^3.4.0",
"eslint-plugin-vue": "^7.9.0",
"prettier": "^2.3.1",
All of the packages should be up to date.
I get this error in VSCode and in the console, which I would like to supress because I want to allow such parantheses for better reading:
As far as I can read, this is what the no-extra-parens rule is for, but I cannot get it to work.
The documentation (https://eslint.org/docs/rules/no-extra-parens) states that it has an object option with several adjustments to this rule. If I, for an example, try any of these options:
"no-extra-parens": "0",
or
"no-extra-parens" :{
"returnAssign": false,
"nestedBinaryExpressions": false,
"ignoreJSX": "none|all|multi-line|single-line",
"enforceForArrowConditionals": false,
"enforceForSequenceExpressions": false,
"enforceForNewInMemberExpressions": false,
"enforceForFunctionPrototypeMethods": false
},
... the error in VSCode dissapears, and everything seems to be working fine. But upon serve the console throws this error:
I´ve tried with
"no-extra-parens": 0,
as the console says, but then the rule is ignored and the first rule break error is shown.
I´ve tried to define the rule in alot of different ways with arrays and objects, setting it to "off", etc. But either the rule does not work in VSCode, or the console states that the rule definition is invalid.
This is my .eslintrc.js file:
module.exports = {
root: true,
env: {
node: true
},
extends: [
"plugin:vue/essential",
"eslint:recommended",
"#vue/typescript/recommended",
"#vue/prettier",
"#vue/prettier/#typescript-eslint"
],
parserOptions: {
ecmaVersion: 2020,
ecmaFeatures: {
"jsx": false
},
},
rules: {
"no-extra-parens": 0,
"no-console": ["warn", { allow: ["warn", "error"] }],
"no-debugger": "warn",
"curly": "error",
"quotes": [
"error",
"single"
],
"#typescript-eslint/ban-ts-comment": "off",
"#typescript-eslint/ban-ts-ignore": "off",
"#typescript-eslint/no-explicit-any": "off",
"#typescript-eslint/no-non-null-assertion": "off",
"#typescript-eslint/no-inferrable-types": "off",
"#typescript-eslint/no-use-before-define" : "off",
"#typescript-eslint/consistent-type-assertions" : "off",
"#typescript-eslint/no-empty-function": "warn",
"#typescript-eslint/interface-name-prefix": "off",
"#typescript-eslint/explicit-module-boundary-types": "off",
"#typescript-eslint/no-var-requires" : "off",
"#typescript-eslint/no-extra-parens": ["error"]
}
};
Any clue? 🤔

ESLint uses #typescript-eslint/no-extra-parens and doesn't need no-extra-parens, #typescript-eslint/* are supposed to aggregate * rules with same names, with the addition of features specific to TypeScript.
It's Prettier that affects this code, changing ESLint rules without disabling Prettier won't change the way it works.
The use of parentheses in this piece of code is redundant, as any as ... is a common construct in TypeScript and can be read and processed without parentheses:
const foo = bar as any as Foo;
Double as can be avoided in this case with:
const foo: Foo = bar as any;
Parentheses are necessary where type assertion is used as a part of an expression, in this case they will be kept by Prettier:
(bar as any as Foo).baz()
Prettier provides a consistent way to format the code with little configurability, this is its purpose, it shouldn't be expected to be fine-tuned for specific styles.
In case it's vital for the code to be formatted the way it is, and the setup uses Prettier through ESLint, it can be disabled where needed:
// eslint-disable-next-line prettier/prettier

Related

Vue 2 - ESLint + Standard + Prettier

How do I create a Vue 2 project that uses ESLint + StandardJS + Prettier?
StandardJS's rules should naturally take precedence over Prettier's.
vue create only provides the following options:
ESLint + Standard
ESLint + Prettier
I tried 2 things:
I mixed the eslint configurations of both of the above options. It resulted in a dependency hell, and once that was solved it didn't really work as expected.
I added the prettier-standard package to my eslintrc.js, it didn't work as expected either. It's worth mentioning that prettier-standard works well when manually executing it from the command line.
I'm of course looking to set this up at the project config level and not at the IDE level.
Can you try this repo I've just created? Looks like it's working great from what I've tested.
https://github.com/kissu/so-eslint-standard-prettier-config
Notes
I created 2 projects and dumped the configuration of the standard one into the Prettier one, the changes can be seen in this commit
CLI's current version of #vue/eslint-config-standard is throwing an error (Environment key "es2021" is unknown) because it requires ESlint 7 to work, as shown in this changelog
bumping ESlint to the latest version 7.29.0, fixed the issue
to check your project's current version of ESlint, you can run npx eslint --version
of course, you need to have the ESlint extension enabled and Prettier one disabled (if using VScode), otherwise it may conflict
I've tried to remove #vue/prettier from
extends: ['plugin:vue/essential', 'eslint:recommended', '#vue/standard', '#vue/prettier']
and see if it's successfully removes any ; and it does!
The errors are indeed coming from ESlint (if we do remove #vue/prettier), and they're fixed by ESlint only upon save (after an ESlint server + VScode restart)!
Putting Prettier back works fine of course.
Luckly, I had a new PC, hence had the opportunity to try a whole fresh config with VScode.
I had to install ESlint only and have those settings into my settings.json
{
"editor.codeActionsOnSave": {
"source.organizeImports": false,
"source.fixAll": true,
"source.fixAll.eslint": true,
"source.fixAll.stylelint": true
}
}
The formatting works perfectly and nothing more is required.
I have eslint 7.8.1 with Vue Prettier on and i don't have any problem, maybe the version of eslint that you have is not compatible with Prettier or maybe your eslint have some errors?
In each way i will put my eslint configuration and maybe it will help you!
module.exports = {
env: {
'browser': true,
'es6': true,
'node': true
},
parserOptions: {
'parser': 'babel-eslint'
},
extends: [
'#vue/standard',
'plugin:vue/recommended'
],
rules: {
"vue/html-indent": ["error", 4, {
"attribute": 1,
"closeBracket": 0,
"switchCase": 0,
"ignores": []
}],
"vue/max-attributes-per-line": [2, {
"singleline": 10,
"multiline": {
"max": 1,
"allowFirstLine": false
}
}],
'indent': ['error', 4],
'vue/component-name-in-template-casing': ['error', 'kebab-case'],
'vue/script-indent': [
'error',
4,
{ 'baseIndent': 1 }
],
'space-before-function-paren': ['error', 'never'],
'semi': [2, "never"],
'vue/singleline-html-element-content-newline': 'off',
'vue/multiline-html-element-content-newline': 'off'
},
overrides: [
{
'files': ['*.vue'],
'rules': {
'indent': 'off'
}
}
]
}
Also maybe you have forgot some of the devDependecies on package.json, those are mine
"eslint": "^7.8.1",
"eslint-plugin-import": "^2.22.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.1",
"eslint-plugin-vue": "^6.2.2"
Hope that those will help you !

Definition for rule '#typescript-eslint/no-shadow' was not found

Not sure what's going on here.
I am working on migrating from tslint to eslint. The basic migration seems to have gone smoothly (well, "smoothly" -- got some kinds in the rules that need to get worked out apparently), but I've run across this and I have no idea how to get past it:
1:1 error Definition for rule '#typescript-eslint/no-shadow' was not
found #typescript-eslint/no-shadow
I've modified the .eslintrc.js file like so (parts snipped for brevity):
module.exports = {
"env": {
"browser": true,
"es6": true,
"node": true
},
"parser": "#typescript-eslint/parser",
"parserOptions": {
"project": "tsconfig.json",
"sourceType": "module"
},
"plugins": [
"eslint-plugin-import",
"#angular-eslint/eslint-plugin",
"#typescript-eslint",
"#typescript-eslint/tslint"
],
"rules": {
// Many unrelated plugins, all rules, none mentioning no-shadow
"no-shadow": "off",
"#typescript-eslint/no-shadow": ["error", { "hoist": "all" }],
// Many other unrelated plugins, all rules, none mentioning no-shadow. But I thought
// This next one may be helpful.
"#typescript-eslint/tslint/config": [
"error",
{
"rules": {
"import-spacing": true,
"whitespace": [
true,
"check-branch",
"check-decl",
"check-operator",
"check-separator",
"check-type"
]
}
}
]
}
};
The versions of the plugins I'm working with are (copied from package.json):
"eslint-plugin-import": "^2.19.1",
"#typescript-eslint/eslint-plugin": "^2.34.0",
"#typescript-eslint/parser": "^2.34.0",
I'm at a loss as to what's going on, and my google searches have turned up nothing aside from "use "no-shadow": "off", which I do.
v2.34.0 of the typescript-eslint packages is 9 months old.
Upgrade to a more recent version of typescript-eslint.
#typescript-eslint/no-shadow was added in v4.0.0

Why I can't use debugger or console.log on my Vue app

I just created a new Vue app through Vue CLI but I can't use either debugger or console.log otherwise I get an error in the browser, why and how can I allow it ?
Unexpected 'debugger' statement (no-debugger) at src/components/SomeComponent.vue:48:7
In my case it was because I went with the default configs when creating my project and it includes eslint:
So in order to allow debugger and console.log statements I modified the rules on my package.json file like this:
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"rules": {
"no-console": 1,
"no-debugger": 1
},
"parserOptions": {
"parser": "babel-eslint"
}
}
This way I still get a warning when compiling so I don't forget to remove them before committing but I can run my app and use those statements.
You can use:
//eslint-disable-next-line no-console
only if your really have to use console.log()
otherwise I highly recommend to use a logger like 'vuejs-logger'.
What happens is like in production you still have these console.log lines that I actually don't like a lot... plus the warning during rebuilding prevents you from using the hot reload of your app during development.

Vue-CLI with 4 space identation

I am totally new to Vue.
I want to use the CLI and I want to have 4 space indentation (with typescript and vuex). But after 24 hours of struggling I am no closer to getting anything working. If it is impossible let me know too.
I thought that tslint was the way to go, but could not find a solution. So I tried eslint and added this to package.json
"devDependencies": {
"#vue/cli-plugin-eslint": "^3.0.4",
"#vue/cli-plugin-pwa": "^3.0.4",
"#vue/cli-plugin-typescript": "^3.0.4",
"#vue/cli-service": "^3.0.4",
"#vue/eslint-config-prettier": "^3.0.4",
"#vue/eslint-config-typescript": "^3.0.4",
"eslint": "^5.6.1",
"eslint-plugin-vue": "^5.0.0-beta.3", // <------------------
"typescript": "^3.0.0",
"vue-template-compiler": "^2.5.17"
}
Then is eslintrc I have
module.exports = {
root: true,
env: {
node: true
},
extends: ["plugin:vue/essential", "#vue/prettier", "#vue/typescript"],
rules: {
"no-console": process.env.NODE_ENV === "production" ? "error" : "off",
"no-debugger": process.env.NODE_ENV === "production" ? "error" : "off",
"vue/script-indent": ["error", 4, { baseIndent: 1 }],
indent: ["error", 4]
},
parserOptions: {
parser: "typescript-eslint-parser"
}
};
then when I run
$ npx eslint --fix *.js
=============
WARNING: You are currently running a version of TypeScript which is not officially supported by typescript-eslint-parser.
You may find that it works just fine, or you may not.
SUPPORTED TYPESCRIPT VERSIONS: ~3.0.1
YOUR TYPESCRIPT VERSION: 3.1.1
Please only submit bug reports when using the officially supported version.
=============
/Users/x/code/sync/vue/restos2/postcss.config.js
2:1 error Expected indentation of 4 spaces but found 2 indent
3:1 error Expected indentation of 8 spaces but found 4 indent
4:1 error Expected indentation of 4 spaces but found 2 indent
✖ 3 problems (3 errors, 0 warnings)
3 errors and 0 warnings potentially fixable with the `--fix` option.
but the problem is that no files ever get changed.
As described in the tslint doc, the indent rule doesnt fix wrong amount of indentation characters, it only fixes the character type, this means that it can convert tabs to spaces and vice versa, but it doesnt fix 4 spaces to 2 spaces
NOTE: auto-fixing will only convert invalid indent whitespace to the desired type, it will not fix invalid whitespace sizes.
https://palantir.github.io/tslint/rules/indent/
So yeah, you'd have to go with eslint. I dont see you full eslintrc file, but I think that the main problem may be this line: indent: ["error", 4]. Try removing that.
This eslint config is working for me:
{
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended",
"#vue/typescript"
],
"rules": {
"vue/script-indent": ["error",2,{"baseIndent": 1}]
},
"parserOptions": {
"parser": "typescript-eslint-parser"
}
}
And run with npm run lint

Can't get correct autoformat on save in Visual Studio Code with ESLint and Prettier

in Visual Studio Code with ESLint and Prettier when working on .vue files, it seems I can't get vue/max-attributes-per-line to auto-fix correctly.
For example, with vue/max-attributes-per-line set to 'off', and I try to add line breaks manually it corrects it to always have every element on no more than one line, no matter if it is 81, 120, 200, or more characters wide. How can I figure out what is forcing my markup elements onto exactly one line?
I am using ESLint version 5.1.0 and Visual Studio Code (without the Prettier Extension), with Prettier 1.14.2.
Here's the example in a .vue file-- I cannot make this go on multiple lines no matter what I do, when 'vue/max-attributes-per-line': 'off'. Every time I save, it forces the long line of markup to be all on one line.
<template>
<font-awesome-icon v-if="statusOptions.icon" :icon="statusOptions.icon" :spin="statusOptions.isIconSpin" :class="['saving-indicator', 'pl-1', 'pt-1', statusOptions.iconClasses]" />
</template>
If I set 'vue/max-attributes-per-line': 2, it formats like so, with one line break(which is quite wrong as well).
<font-awesome-icon
v-if="statusOptions.icon"
:icon="statusOptions.icon"
:spin="statusOptions.isIconSpin"
:class="['saving-indicator', 'pl-1', 'pt-1', statusOptions.iconClasses]"
/>
If I try to reformat it manually, it just reverts to the above when I save.
Additionally, it seems to reformat twice when I hit Ctrl+S: first it reformats to put it all on one line, then a half-second later the formatting above results. Any ideas? What is causing this weirdness--are there multiple reformatters running? How do I figure out what the first one is to disable it?
VS Code workspace settings:
{
"editor.formatOnType": false,
"editor.formatOnPaste": false,
"editor.formatOnSave": true,
"[javascript]": {
"editor.tabSize": 2
},
"[vue]": {
"editor.tabSize": 2
},
"[csharp]": {
"editor.tabSize": 4
},
"javascript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": true,
"javascript.referencesCodeLens.enabled": true,
"vetur.validation.script": false,
"vetur.validation.template": false,
"eslint.autoFixOnSave": true,
"eslint.alwaysShowStatus": true,
"eslint.options": {
"extensions": [
".html",
".js",
".vue",
".jsx"
]
},
"eslint.validate": [
{
"language": "html",
"autoFix": true
},
{
"language": "vue",
"autoFix": true
},
"vue-html",
{
"language": "javascript",
"autoFix": true
},
{
"language": "javascriptreact",
"autoFix": true
}
],
"editor.rulers": [
80,
100
]
}
.eslintrc.js:
module.exports = {
parserOptions: {
parser: 'babel-eslint'
},
env: {
browser: true,
node: true,
jest: true
},
globals: {
expect: true
},
extends: [
'prettier',
'plugin:vue/recommended', // /base, /essential, /strongly-recommended, /recommended
'plugin:prettier/recommended', // turns off all ESLINT rules that are unnecessary due to Prettier or might conflict with Prettier.
'eslint:recommended'
],
plugins: ['vue', 'prettier'],
rules: {
'vue/max-attributes-per-line': 'off',
'prettier/prettier': [ // customizing prettier rules (not many of them are customizable)
'error',
{
singleQuote: true,
semi: false,
tabWidth: 2
},
],
'no-console': 'off'
}
}
Without changing any settings, ESLint --fix does indeed format properly--breaking all my .vue template elements into many lines properly. So any ideas how I whip VS Code into shape? The above settings didn't help, but I am at a loss how as to even know what is interfering. Any ideas?
To emphasize, when I save in VS Code, a long HTML element will collapse to one line then break to two lines a half-second later, all from one save operation. I'm expecting it instead to break it up into many lines. It would be okay if it took several saves, but instead the first save shows this behavior as well as every subsequent save.
Short answer: I needed: "editor.formatOnSave": false, "javascript.format.enable": false.
I finally found the magical combination of settings, thanks to this thread from Wes Bos on Twitter. I was right in my suspicion that there seem to be multiple conflicting formatters. Though I'm not sure what they actually are, I was able to turn off all but eslint as follows:
In the VS Code settings, I need:
"editor.formatOnSave": false,
"javascript.format.enable": false,
"eslint.autoFixOnSave": true,
"eslint.alwaysShowStatus": true,
"eslint.options": {
"extensions": [ ".html", ".js", ".vue", ".jsx" ]
},
"eslint.validate": [
{ "language": "html", "autoFix": true },
{ "language": "vue", "autoFix": true },
{ "language": "javascript", "autoFix": true },
{ "language": "javascriptreact", "autoFix": true }
]
In .eslintrc.js, then I can use the settings in my original post and then also change 'vue/max-attributes-per-line' as desired. Then VS Code's ESLint plugin will format code one step at a time on every save, much as kenjiru wrote. One last snag: HMR won't pick up these changes, so rebuild from scratch.
With 'vue/max-attributes-per-line': 'off' the rule is disabled so VSCode does not try to fix the long line on autosave. Other eslint fixes are applied, as expected.
With 'vue/max-attributes-per-line': 1 VSCode fixes only one error per save. This is a known limitation of vscode-eslint
vscode-eslint only does a single pass in order to keep to a minimum the amount of edits generated by the plugin. The goal is to keep as many markers (like break points) in the file as possible.
VSCode has a time limit of 1 second for all the plugins to compute the change set on save. If one of the plugins causes the other plugins to not run for 3 times in a row, it will be disabled.
eslint --fix runs all the rules in a loop until there are no more linting errors. I think it has a limit of 10 iterations maximum.
See these links for more details:
https://github.com/Microsoft/vscode-eslint/issues/154
I've created a minimal setup to demonstrate this issue:
https://github.com/kenjiru/vscode-eslint-onsave-issue
I know this is old but in case anyone should find this and not have success with the posted solutions, the fix for me was to add:
"editor.codeActionsOnSave": {
"source.fixAll": true
}
I did not need "editor.formatOnSave": true for some reason. I do not have Prettier installed - only ESLint - but this now performs any fixes automatically when I save.
This is the setup I ended up going with in VSC settings.json file.
Works perfectly for locally set up eslint disabling the default vetur settings (if the plugin is installed).
"files.autoSave": "onFocusChange",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"editor.formatOnSave": false,
"javascript.format.enable": false,
"eslint.alwaysShowStatus": true,
"eslint.options": {
"extensions": [ ".html", ".js", ".vue", ".jsx" ]
},
"eslint.validate": [
"html",
"javascript",
"vue"
],
I tried this things and it didn't worked.
"typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": false,
"javascript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": false,
"typescript.format.insertSpaceAfterOpeningAndBeforeClosingEmptyBraces": false,
but it at last i tried this. and worked
"diffEditor.wordWrap": "off",
I bumped into the same issue, and surprisingly found that prettier and vetur were conflicting. I had to disable vetur formatter and it now works as expected.
If you have this section in your editor's settings.json and you have prettier installed,
{
"[vue]": {
"editor.defaultFormatter": "octref.vetur",
},
}
chances are, these two formatters are conflicting and thus the unexpected behaviour.
A quick workaround is to comment it as below, or simply delete it permanently.
{
"[vue]": {
// "editor.defaultFormatter": "octref.vetur",
},
}
I've struggled through a similar problem. I tried the solution above but didn't work for me, unfortunately. I'm using eslint and Vetur, didn't install prettier plugin but configured it via eslint and enabled "eslint.autoFixOnSave": true. I finally got the correct autoformat on save by removing the following configuration in settings.json. Not sure why but it's working for me.
"eslint.options": {
"extensions": [".html", ".js", ".vue", ".jsx"]
},
"eslint.validate": [{
"language": "html",
"autoFix": true
},
{
"language": "vue",
"autoFix": true
},
{
"language": "javascript",
"autoFix": true
},
{
"language": "javascriptreact",
"autoFix": true
}
]
Will update this answer if I get other issues related to this.