I had the same problem as mentioned in the question above, however I figured out how to solve it in a way that not only could the "indent" setting be kept, but so it can be adjusted, allowing for tabWidth to be set as you like.
First I want to note, so we're all on the same page, what the set-up I am using for linting/formatting exactly is:
- Source Code Editor: V.S. Code
- Linting Utility: ESLint
- Opinionated Formatter: Prettier
- Style-Guide: AirBnB
Additionally I also equip the following, which I download using NPM:
- eslint-plugin-prettier
- eslint-config-prettier
- eslint-config-airbnb
For those familiar with linting while using V.S. Code, you guys know that what I am using is actually the short list. There is all kinds of other configs, plugins & extensions that can be obtained. The important thing to note here, is that I am using a tried & true setup, that allows Prettier, and ESLint to work harmoniously together.
With that said, even having a good configuration, and all the correct extensions I still had a problem with the above rule, the same as the developer who posted the question. I knew the problem had to do with ESLint's rules, and how they were being configured in my .eslintrc.json file. After much research, and near mastering ESLint, I found that I was correct. There are a few ESLint rules, (3 ESLint rules, and 1 Prettier Setting), that you need to have configured properly, however; at the same time you need to make sure your .prettierrc file settings are in-sync with your .eslintrc.json file rules. Once you understand it all, it is actually not as complicated as it sounds.
STEP #1 Know what tabWidth you want and set it in .prettierrc
First off you need to decide what you want your styles tab-width to be. (Most Style-Guides set there tab-width at (2x Space-Width), but many dev's will change there settings to a (4x Space-Width). Any thing other than 2x and 4x is considered taboo.)
Go ahead and open your .prettierrc file (or what ever mimetype of prettier configuration file you use), then set 'tabWidth' to your liking, just make sure that you stick with a consistant tabWidth from here on out, becuase ESLint needs to be in sync with prettier.
Your '.prettierrc' file should look similar to this:
{
"printWidth": 90,
"tabWidth": 4,
"useTabs": false,
"trailingComma": "all",
"singleQuote": true,
"semi": true,
"bracketSpacing": false,
}
STEP #2: set the "max-len" rule in .eslintrc.json**
- open up your .eslintrc.json file (or whatever version of ESLint configuration file mime-type that you use), and set the "max-len" rule in the rules property of your eslintrc.json. The rule is not in the file by default so you will have to write it in. To see how, review the Example I Created Below.
- Be sure that the "tabWidth" property within ESLint's "max-len" rule, holds exactly the same value, as the "tabWidth" setting within your .prettierrc file.
- There are some other rule options here that are important to set properly as well. The first, 'code', sets the max amount of chars each line can hold, aka(max-line-length). When "code" is set ESlint will not allow more characters than what "code" has been set to. The catch is that you absolutely must Make sure that the "printWidth" setting in your .prettierrc file, which you probably will have to write in, is set to the same value as the "code" property's value in your .eslintrc.json max-len rule.
- "ignoreUrls" can be set either way and make sure the rule does throw an error by leaving the word "error" as it is.
Here is an example of my max-len rule in ESLint
"rules": {
"max-len": [
"error",
{
"code": 90,
"tabWidth": 4,
"ignoreUrls": true
}
],
}
See the .prettierrc example above, to view how to set "printWidth"
STEP #3: ESLint's "no-tabs" Rule
- The "no-tabs" rule, is a 'must set', w/o it your linting & formatting > can unsynchronize.
- You can set "allowIndentationTabs" as you like, Allowing for, or disallowing indentation tabs won't make a difference.
What the no-tabs rule should look like:
"rules": {
"no-tabs": ["error", {"allowIndentationTabs": true}],
"max-len": [
"error",
{
"code": 90,
"tabWidth": 4,
"ignoreUrls": true
}
],
}
STEP #4: ESLint's "indent" Rule, by far the most important rule of this discussion
Seriously this one is important. Its the one that gets thrown out in an attempt to fix the switch indentation problem, which doesn't give you control over other settings, like setting your own tab-width. The "indent" rule.
- First make sure indent is active by setting error to error as you see it, you could also set it to warn, but its better to set it as error so prettier knows to fix it imeadiatly. The next setting is the width of your indentations, which has to be the same exact value as your tabWidth in your .prettierrc file, and as in the "max-len" ESLint rule.
"indent": ["error", 4, {"SwitchCase": 1}],
- The last settings in the brackets, "SwitchCase" can be confusing. No one explained any of this to me at first so I had to figure it out on my own, and this screwed me up a bit. The number that "SwitchCase" gets set to is not like the 4 before it. The 4 that comes before it is the initial setting of the "indent" rule and can stand alone like this:
"indent": 4; // throws error
// or
"indent": ["warn", 4] // Throws warning, which is somtimes less annoying than an error
So it is important to note that the value 4 that you see in the "indent" rule, is how many spaces an indent will be. This led me to believe that the 1 after "SwitchCase" meant how many spaces that the switch keyword case will be indented.
Example:
switch (x) {
case 1:
break;
}
That is not how it works though. The number that rule "SwitchCase" is set to, tells the editor how many times to indent the keyword 'case'. So if the "indent" rule is set to 4, and the "SwitchCase" rule is set to 4, then ESLint will expect an indentation of 4x4=16. At the end of the day ESLint will actually expect more than 16, because ESLint is going to take on all the indentation from different levels of blocks that the switch statement is found in, this ends up leading to ESLint expecting 24-36 spaces of indentation, that's crazy.
"SwitchCase" needs to be set to 1.
"rules": {
"indent": ["error", 4, {"SwitchCase": 1}],
"no-tabs": ["error", {"allowIndentationTabs": true}],
"max-len": [
"error",
{
"code": 90,
"tabWidth": 4,
"ignoreUrls": true
}
],
}
If you set all the rules right that should work for you
If it is still not working, try starting with a clean slate, delete your .eslintrc.json file, and create a new eslintrc.json file, and build it anew. You shouldn't have to start over with a new .prettierrc file.
To Wrap Up
Prettier wants to indent everything uninformed like. So if tabWidth is set to 4, and tabWidth & indent is set to 4 in ESlint then every block gets indented 4 spaces be prettier, no more and no less.
The whole problem initially is that, the style guides often ask that the keyword case not be indented, so when ESLint is setup, that is what it is configured to do by the NPM config you install upon initializing ESLint. However that does not work with prettier.
This answer wound up much longer than I thought it would. Getting Prettier, ESLint & VS Code to work harmoniously together is a very involved task, especially for first timers. I use Babel on top of this AST stack (I made that term up lol, what else would you call it?). If you want to be able to lint documents that contain TC39 ECMAScript Stage-3 Proposals, this includes features such as Private-Members, Static Methods, ect..., then you will need to use configure ESLint to use Babel's parser.