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

Prettier removing a piece of code when formatting multi-line conditions #532

Open
philcatterall opened this issue Dec 8, 2022 · 14 comments

Comments

@philcatterall
Copy link

Maybe this isn't a bug, but it's a scenario where prettier is changing code, and in your documentation, you said if prettier changes code, it shouldn't, so it should be reported.
Hence I am reporting.
If I have several "Anded" expressions, split across multiple lines (in my real example its quite long), prettier suggests a fix of "Replace &&·values.myProperty2 with ··values.myProperty2·&& eslintprettier/prettier"
However this fix removes a required "&&".
Yes, it turns out I should have my "&&"s on the same line (though I prefer them at the beginning, perhaps that is a different debate). But should prettier remove a required one ?

Hope this helps.

Prettier 2.8.1
Playground link

Input:

const values = {
  myProperty1: true,
  myProperty2: false,
  myProperty3: true,
  myProperty4: false,
  myProperty5: true,
  myProperty6: false,
  srvsys_sc_files_otherorgsdata_to_nfd_notingroup: true,
  srvsys_sc_search_owncustomers_against_nfd: true,
  srvsys_sc_search_othercustomers_nfd_ingroup: false,
  srvsys_sc_search_otherorgcustomers_nfd_notingroup: true
};

setValue(!values.myProperty1
  && values.myProperty2
  && !values.myProperty3
  && !values.myProperty4
  && values.myProperty5
  && !values.myProperty6
);

function setValue(newValue: boolean) {
  //do something
  console.log(newValue);
}
//Prettier suggested fix would remove the 1st &&
//Replace `&&·values.myProperty2` with `··values.myProperty2·&&`eslintprettier/prettier

Output:

setValue(!values.myProperty1
    values.myProperty2 &&
  && !values.myProperty3
  && !values.myProperty4
  && values.myProperty5
  && !values.myProperty6
);

Expected behavior:

@kachkaev
Copy link
Member

kachkaev commented Dec 8, 2022

👋 @philcatterall! I’m unable to reproduce this in Playground:

Prettier 2.8.1
Playground link

--parser babel

Input:

const values = {
  myProperty1: true,
  myProperty2: false,
  myProperty3: true,
  myProperty4: false,
  myProperty5: true,
  myProperty6: false,
  srvsys_sc_files_otherorgsdata_to_nfd_notingroup: true,
  srvsys_sc_search_owncustomers_against_nfd: true,
  srvsys_sc_search_othercustomers_nfd_ingroup: false,
  srvsys_sc_search_otherorgcustomers_nfd_notingroup: true
};

setValue(!values.myProperty1
  && values.myProperty2
  && !values.myProperty3
  && !values.myProperty4
  && values.myProperty5
  && !values.myProperty6
);

function setValue(newValue: boolean) {
  //do something
  console.log(newValue);
}
//Prettier suggested fix would remove the 1st &&
//Replace `&&·values.myProperty2` with `··values.myProperty2·&&`eslintprettier/prettier

Output:

const values = {
  myProperty1: true,
  myProperty2: false,
  myProperty3: true,
  myProperty4: false,
  myProperty5: true,
  myProperty6: false,
  srvsys_sc_files_otherorgsdata_to_nfd_notingroup: true,
  srvsys_sc_search_owncustomers_against_nfd: true,
  srvsys_sc_search_othercustomers_nfd_ingroup: false,
  srvsys_sc_search_otherorgcustomers_nfd_notingroup: true,
};

setValue(
  !values.myProperty1 &&
    values.myProperty2 &&
    !values.myProperty3 &&
    !values.myProperty4 &&
    values.myProperty5 &&
    !values.myProperty6
);

function setValue(newValue: boolean) {
  //do something
  console.log(newValue);
}
//Prettier suggested fix would remove the 1st &&
//Replace `&&·values.myProperty2` with `··values.myProperty2·&&`eslintprettier/prettier

The code might be removed by some other tooling. If that’s the case, this issue is out of this repo’s scope. If you think otherwise, it’d be helpful to see reproduction steps.

@philcatterall
Copy link
Author

@kachkaev in Playground, prettier (correctly) reformats the code.
If you open attached file in vsCode, you will see the issue. Prettier suggests a fix that breaks the code.
As per my report, if I change the code so that the "&&"s are at the end of each line, its fine, but the question remains. Should prettier make a change that breaks the code....
Not a biggy, but as you asked for issues that change code to be reported, I am reporting.
PrettierTest.zip

Cheers,

@brodycj
Copy link

brodycj commented Dec 8, 2022

babel vs typescript parser ??

@philcatterall
Copy link
Author

No, parser is @typescript-eslint/parser
.prettierrc.json

{
  "semi": true,
  "trailingComma": "all",
  "singleQuote": false,
  "printWidth": 120,
  "tabWidth": 2,
  "endOfLine": "auto"
}

.eslintrc.json

{
    "parser": "@typescript-eslint/parser",
    "env": {
        "browser": true,
        "commonjs": true,
        "es6": true,
        "jest": true,
        "jasmine": true
    },
    "extends": [
        "eslint:recommended",
        "plugin:@typescript-eslint/recommended",
        "plugin:prettier/recommended",
        "prettier"
    ],
    "parserOptions": {
        "project": "./tsconfig.json"
    },
    "settings": {},
    "plugins": [
        "@typescript-eslint",
        "prettier"
    ],
    "rules": {
        "prettier/prettier": "warn",
        "quotes": [
            "error",
            "double"
        ],
        "no-unused-vars": "warn",
        "@typescript-eslint/no-unused-vars": "warn"
    },
    "overrides": [
        {
            "files": [
                "*.ts"
            ],
            "rules": {
            }
        }
    ]
}

@kachkaev
Copy link
Member

kachkaev commented Dec 8, 2022

Looking at your .eslintrc.json I suspect that the issue is to do with eslint-plugin-prettier. If there was a bug in Prettier Core (which could be the case), we would see it in Prettier Playground.

@kachkaev
Copy link
Member

kachkaev commented Dec 8, 2022

We can transfer this issue to https://github.com/prettier/eslint-plugin-prettier. I don’t have access to that repo so let’s wait for someone else to do this. Alternatively, you can close this issue and recreate it in another repo yourself.

In general, I would recommend using Prettier without eslint-plugin-prettier. You can still use ESLint, just disable all rules conflicting with Prettier via eslint-config-prettier. Prettier will still format your files on save, after ESLint applies its autofixes. Red squiggly lines will only show for semantic issues in your files rather than for something trivial like a missing space.

@philcatterall
Copy link
Author

Well no worries, just thought you should be aware that prettier changed and broke the code by removing a needed "&&
If you see screen shot in zip file its coming from prettier as far as I can see.
Whilst I prefer my "&&"s at the beginning, rather than the end, of the line, I've now given up and accepted to go with prettier's opiniated style.
That is, after all , what prettier is about !!

@kachkaev
Copy link
Member

kachkaev commented Dec 8, 2022

That is, after all , what prettier is about !!

Yep, exactly! 💯 🙂

I also prefer && etc. at the beginning of lines but don’t mind about Prettier’s preference. There is a chance that operators will be placed at the beginning of lines one day: prettier/prettier#3806

I’ll keep this issue open for other moderators to transfer or close it.

@philcatterall
Copy link
Author

We can transfer this issue to https://github.com/prettier/eslint-plugin-prettier. I don’t have access to that repo so let’s wait for someone else to do this. Alternatively, you can close this issue and recreate it in another repo yourself.

In general, I would recommend using Prettier without eslint-plugin-prettier. You can still use ESLint, just disable all rules conflicting with Prettier via eslint-config-prettier. Prettier will still format your files on save, after ESLint applies its autofixes. Red squiggly lines will only show for semantic issues in your files rather than for something like a missing space.

OK I'll give that a go. Interesting suggestion, all the .eslintrc examples I have seen so far (including the examples from Microsoft) suggest eslint-plugin-prettier
I'll close this off. Thanks for the input and such a fast response.

@fisker fisker transferred this issue from prettier/prettier Dec 8, 2022
@fisker
Copy link
Member

fisker commented Dec 8, 2022

Transfered to eslint-plugin-prettier.

@fisker
Copy link
Member

fisker commented Dec 8, 2022

To fix this issue, we need find out what's the conflictting rule and extend it's fix range.

@philcatterall
Copy link
Author

@kachkaev Hey Alex, out of curiosity (even though I've now abided by Prettier's "opinion" :-), I was fiddling with the .eslintrc settings, bearing in mind your feedback, playing with different settings. After several hours of googling, and experimentation, I think I'm now more confused than ever, given the high number of combinations of extends, parseroptions, settings, plugins and rules !!!. So I hope you don't mind me asking, but could you post for me your recommended settings ? I'm using vsCode and mostly coding in Typescript, with a bit of Javascript and some JSON files. Also for some projects using React. Any guidance you could give me would be very welcome. Many thanks, Phil

@kachkaev
Copy link
Member

kachkaev commented Dec 9, 2022

Yeah there are a few ways to integrate ESLint and Prettier for historical reasons, which can be confusing indeed:
https://prettier.io/docs/en/related-projects.html#eslint-integrations

You can find some thoughts on this topic in this answer: prettier/prettier#13925 (comment).

As of project examples, I can’t recall anything that would be easy to copy-paste. My .prettierrc.cjs and .eslintrc.cjs files often depend on custom packages with rules which is a bit bespoke but is helpful for maintaining several projects. You can explore these packages but please keep in mind that these are not a community standard, just my own approach to linting side projects. When using VSCode, I enable Prettier and ESLint extensions and make sure that they both run on save. Prettier runs second automatically (the order is important here). Editor extensions call both tools similarly to how you can do this from CLI. CLI scripts can be launched from GitHub Workflows, thus helping your team to spot any regressions in linting.

This is a bit offtopic, so please feel free to create a discussion and tag me there if you need more help.

@philcatterall
Copy link
Author

Yeah there are a few ways to integrate ESLint and Prettier for historical reasons, which can be confusing indeed: https://prettier.io/docs/en/related-projects.html#eslint-integrations

You can find some thoughts on this topic in this answer: prettier/prettier#13925 (comment).

As of project examples, I can’t recall anything that would be easy to copy-paste. My .prettierrc.cjs and .eslintrc.cjs files often depend on custom packages with rules which is a bit bespoke but is helpful for maintaining several projects. You can explore these packages but please keep in mind that these are not a community standard, just my own approach to linting side projects. When using VSCode, I enable Prettier and ESLint extensions and make sure that they both run on save. Prettier runs second automatically (the order is important here). Editor extensions call both tools similarly to how you can do this from CLI. CLI scripts can be launched from GitHub Workflows, thus helping your team to spot any regressions in linting.

This is a bit offtopic, so please feel free to create a discussion and tag me there if you need more help.

Hi Alex, many thanks, and yes sorry, it is a bit off-topic, but your reply is sincerely appreciated. I will follow the rules from now and continue in discussions if I need, (embracing fully Prettier's ethos !! Cheers

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants
@fisker @kachkaev @brodycj @philcatterall and others