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

feat(eslint-plugin): [no-floating-promises] flag result of .map(async) #7897

Merged

Conversation

kirkwaiblinger
Copy link
Member

@kirkwaiblinger kirkwaiblinger commented Nov 11, 2023

PR Checklist

Overview

This PR adds functionality to the rule to check for unawaited arrays of promises, where we might expect to use Promise.all/Promise.allSettled, etc to handle the result.

async function rejectIn(t: number) {
  new Promise<void>((resolve) => {
    setTimeout(() => {
      resolve();
    }, t);
  });

  throw new Error();
}

// Unhandled rejections. Will now flag.
[1, 2, 3].map(async (t) => {
  await rejectIn(t);
});

I haven't attempted to add editor suggestions for fixes because the fixes seem rather complicated, depending on how you ended up with an array of promises and what you want to do with it. For example, we might fix the above code with

// should we use Promise.all(), Promise.allSettled(), Promise.race(), etc? 
// it's unclear to me that picking one for the user is a good idea.
// Plus, they will still have to handle the resulting promise with catch or something.
Promise.all(
  [1, 2, 3].map(async (t) => {
    await rejectIn(t);
  }),
).catch(() => {});

// This fix would seem plausible but actually violates no-misused-promises with checksVoidReturn: true.
// Also, seems like it would be challenging to implement since it involves inspecting how we got to the
// floating promise in the first place.
[1, 2, 3].forEach(async (t) => {
  await rejectIn(t);
});

// This one should be easy to implement.
void [1, 2, 3].map(async (t) => {
  await rejectIn(t);
});

This seems like enough of an edge case that maybe the user should be responsible for manually resolving it. Please advise if adding editor suggestion would be a requirement for this PR.

@typescript-eslint
Copy link
Contributor

Thanks for the PR, @kirkwaiblinger!

typescript-eslint is a 100% community driven project, and we are incredibly grateful that you are contributing to that community.

The core maintainers work on this in their personal time, so please understand that it may not be possible for them to review your work immediately.

Thanks again!


🙏 Please, if you or your company is finding typescript-eslint valuable, help us sustain the project by sponsoring it transparently on https://opencollective.com/typescript-eslint.

Copy link

netlify bot commented Nov 11, 2023

Deploy Preview for typescript-eslint ready!

Name Link
🔨 Latest commit 428b976
🔍 Latest deploy log https://app.netlify.com/sites/typescript-eslint/deploys/6571fd7e13e9b8000885b58e
😎 Deploy Preview https://deploy-preview-7897--typescript-eslint.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 98 (🟢 up 10 from production)
Accessibility: 100 (no change from production)
Best Practices: 92 (no change from production)
SEO: 98 (no change from production)
PWA: 80 (no change from production)
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify site configuration.

@kirkwaiblinger kirkwaiblinger changed the title flag arrays of promises fix(eslint-plugin): [no-floating-promises] Flag result of .map(async) Nov 11, 2023
@kirkwaiblinger kirkwaiblinger changed the title fix(eslint-plugin): [no-floating-promises] Flag result of .map(async) fix(eslint-plugin): [no-floating-promises] flag result of .map(async) Nov 11, 2023
errors: [{ line: 2, messageId: 'floatingPromiseArrayVoid' }],
},
{
code: `
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test case from the issue report

@kirkwaiblinger kirkwaiblinger marked this pull request as ready for review November 13, 2023 05:12
@bradzacher bradzacher added bug Something isn't working enhancement: plugin rule option New rule option for an existing eslint-plugin rule and removed bug Something isn't working labels Nov 13, 2023
@bradzacher bradzacher changed the title fix(eslint-plugin): [no-floating-promises] flag result of .map(async) feat(eslint-plugin): [no-floating-promises] flag result of .map(async) Nov 13, 2023
Copy link
Member

@Josh-Cena Josh-Cena left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests are great—I cannot devise new test cases. I'll also admit I don't completely understand the problem domain. Just a nit; the error message looks fine to me.

packages/eslint-plugin/src/rules/no-floating-promises.ts Outdated Show resolved Hide resolved
Copy link
Member

@JoshuaKGoldberg JoshuaKGoldberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Very close to approval, just some nits, cleaning up some testing, and (mainly) the message text. I'll wait a bit to approve and then merge in case another maintainer has an opinion on whether to add an option. But this is great stuff!

Cartoon Chip and Dale character in an office saying 'great stuff'

@JoshuaKGoldberg JoshuaKGoldberg added the awaiting response Issues waiting for a reply from the OP or another party label Dec 5, 2023
@github-actions github-actions bot removed the awaiting response Issues waiting for a reply from the OP or another party label Dec 12, 2023
Copy link
Member

@JoshuaKGoldberg JoshuaKGoldberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cartoony Octopus bringing up a 'SHIP IT' sign

@JoshuaKGoldberg JoshuaKGoldberg merged commit 5857356 into typescript-eslint:main Dec 29, 2023
55 of 58 checks passed
auvred pushed a commit to auvred/typescript-eslint that referenced this pull request Dec 29, 2023
typescript-eslint#7897)

* flag arrays of promises

* remove comment

* trying to trigger CI

* Substantial simplification

* add some grody test cases for generics

* flip if/else

* add detail to test case

* switch to isArrayLikeType

* Revert "switch to isArrayLikeType"

This reverts commit 2afe794.

* add checks for tuples

* One more test case!

* else if

* Remove unnecessary whitespace

* Remove invalid test case

* Add to docs

* Add test cases around array that's fine but tuple that isn't

* tweaks
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jan 6, 2024
@kirkwaiblinger kirkwaiblinger deleted the arrays-of-promises branch January 8, 2024 22:07
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement: plugin rule option New rule option for an existing eslint-plugin rule
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[no-floating-promises] flag .map(async) result
4 participants