Skip to content

Commit

Permalink
feat(eslint-plugin): [await-thenable] added suggestion fixer (#7437)
Browse files Browse the repository at this point in the history
* feat(eslint-plugin): added suggestion fixer to await-thenable

* Aha, getFirstToken
  • Loading branch information
JoshuaKGoldberg committed Sep 8, 2023
1 parent 4908905 commit b284370
Show file tree
Hide file tree
Showing 2 changed files with 149 additions and 53 deletions.
20 changes: 20 additions & 0 deletions packages/eslint-plugin/src/rules/await-thenable.ts
@@ -1,3 +1,4 @@
import type { TSESLint } from '@typescript-eslint/utils';
import * as tsutils from 'ts-api-utils';

import * as util from '../util';
Expand All @@ -10,8 +11,10 @@ export default util.createRule({
recommended: 'recommended',
requiresTypeChecking: true,
},
hasSuggestions: true,
messages: {
await: 'Unexpected `await` of a non-Promise (non-"Thenable") value.',
removeAwait: 'Remove unnecessary `await`.',
},
schema: [],
type: 'problem',
Expand All @@ -35,6 +38,23 @@ export default util.createRule({
context.report({
messageId: 'await',
node,
suggest: [
{
messageId: 'removeAwait',
fix(fixer): TSESLint.RuleFix {
const sourceCode = context.getSourceCode();
const awaitKeyword = util.nullThrows(
sourceCode.getFirstToken(node, util.isAwaitKeyword),
util.NullThrowsReasons.MissingToken(
'await',
'await expression',
),
);

return fixer.remove(awaitKeyword);
},
},
],
});
}
},
Expand Down
182 changes: 129 additions & 53 deletions packages/eslint-plugin/tests/rules/await-thenable.test.ts
@@ -1,4 +1,4 @@
import { RuleTester } from '@typescript-eslint/rule-tester';
import { noFormat, RuleTester } from '@typescript-eslint/rule-tester';

import rule from '../../src/rules/await-thenable';
import { getFixturesRootDir } from '../RuleTester';
Expand Down Expand Up @@ -202,33 +202,83 @@ const doSomething = async (

invalid: [
{
code: `
async function test() {
await 0;
await 'value';
await (Math.random() > 0.5 ? '' : 0);
class NonPromise extends Array {}
await new NonPromise();
}
`,
code: 'await 0;',
errors: [
{
line: 3,
line: 1,
messageId,
suggestions: [
{
messageId: 'removeAwait',
output: ' 0;',
},
],
},
],
},
{
code: "await 'value';",
errors: [
{
line: 1,
messageId,
suggestions: [
{
messageId: 'removeAwait',
output: " 'value';",
},
],
},
],
},
{
code: "async () => await (Math.random() > 0.5 ? '' : 0);",
errors: [
{
line: 4,
line: 1,
messageId,
suggestions: [
{
messageId: 'removeAwait',
output: "async () => (Math.random() > 0.5 ? '' : 0);",
},
],
},
],
},
{
code: noFormat`async () => await(Math.random() > 0.5 ? '' : 0);`,
errors: [
{
line: 6,
line: 1,
messageId,
suggestions: [
{
messageId: 'removeAwait',
output: "async () => (Math.random() > 0.5 ? '' : 0);",
},
],
},
],
},
{
code: `
class NonPromise extends Array {}
await new NonPromise();
`,
errors: [
{
line: 9,
line: 3,
messageId,
suggestions: [
{
messageId: 'removeAwait',
output: `
class NonPromise extends Array {}
new NonPromise();
`,
},
],
},
],
},
Expand All @@ -247,58 +297,84 @@ async function test() {
{
line: 8,
messageId,
suggestions: [
{
messageId: 'removeAwait',
output: `
async function test() {
class IncorrectThenable {
then() {}
}
const thenable = new IncorrectThenable();
thenable;
}
`,
},
],
},
],
},
{
code: `
const doSomething = async (
obj1: { a?: { b?: { c?: () => void } } },
obj2: { a?: { b?: { c: () => void } } },
obj3: { a?: { b: { c?: () => void } } },
obj4: { a: { b: { c?: () => void } } },
obj5: { a?: () => { b?: { c?: () => void } } },
obj6?: { a: { b: { c?: () => void } } },
callback?: () => void,
): Promise<void> => {
await obj1.a?.b?.c?.();
await obj2.a?.b?.c();
await obj3.a?.b.c?.();
await obj4.a.b.c?.();
await obj5.a?.().b?.c?.();
await obj6?.a.b.c?.();
await callback?.();
};
declare const callback: (() => void) | undefined;
await callback?.();
`,
errors: [
{
line: 11,
messageId,
},
{
line: 12,
messageId,
},
{
line: 13,
messageId,
},
{
line: 14,
messageId,
},
{
line: 15,
line: 3,
messageId,
suggestions: [
{
messageId: 'removeAwait',
output: `
declare const callback: (() => void) | undefined;
callback?.();
`,
},
],
},
],
},
{
code: `
declare const obj: { a?: { b?: () => void } };
await obj.a?.b?.();
`,
errors: [
{
line: 16,
line: 3,
messageId,
suggestions: [
{
messageId: 'removeAwait',
output: `
declare const obj: { a?: { b?: () => void } };
obj.a?.b?.();
`,
},
],
},
],
},
{
code: `
declare const obj: { a: { b: { c?: () => void } } } | undefined;
await obj?.a.b.c?.();
`,
errors: [
{
line: 18,
line: 3,
messageId,
suggestions: [
{
messageId: 'removeAwait',
output: `
declare const obj: { a: { b: { c?: () => void } } } | undefined;
obj?.a.b.c?.();
`,
},
],
},
],
},
Expand Down

0 comments on commit b284370

Please sign in to comment.