From b19139acb71f3ac1bdac820f3cb1f7bddcce627d Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Fri, 18 Oct 2024 21:11:55 +0800 Subject: [PATCH] Support TLA for typescript parser (#16729) --- changelog_unreleased/typescript/16729.md | 13 +++++ src/language-js/parse/typescript.js | 29 ++++++++-- .../parse/utils/get-source-type.js | 4 +- .../__snapshots__/format.test.js.snap | 42 ++++++++++++++ tests/format/js/top-level-await/test.cjs | 1 + tests/format/js/top-level-await/test.js | 1 + tests/format/js/top-level-await/test.mjs | 1 + .../__snapshots__/format.test.js.snap | 15 +++++ .../format/jsx/top-level-await/format.test.js | 1 + tests/format/jsx/top-level-await/test.jsx | 1 + .../__snapshots__/format.test.js.snap | 57 +++++++++++++++++++ .../typescript/top-level-await/format.test.js | 1 + .../typescript/top-level-await/test.cts | 1 + .../typescript/top-level-await/test.mts | 1 + .../format/typescript/top-level-await/test.ts | 1 + .../typescript/top-level-await/test.tsx | 1 + 16 files changed, 162 insertions(+), 8 deletions(-) create mode 100644 changelog_unreleased/typescript/16729.md create mode 100644 tests/format/js/top-level-await/test.cjs create mode 100644 tests/format/js/top-level-await/test.js create mode 100644 tests/format/js/top-level-await/test.mjs create mode 100644 tests/format/jsx/top-level-await/__snapshots__/format.test.js.snap create mode 100644 tests/format/jsx/top-level-await/format.test.js create mode 100644 tests/format/jsx/top-level-await/test.jsx create mode 100644 tests/format/typescript/top-level-await/__snapshots__/format.test.js.snap create mode 100644 tests/format/typescript/top-level-await/format.test.js create mode 100644 tests/format/typescript/top-level-await/test.cts create mode 100644 tests/format/typescript/top-level-await/test.mts create mode 100644 tests/format/typescript/top-level-await/test.ts create mode 100644 tests/format/typescript/top-level-await/test.tsx diff --git a/changelog_unreleased/typescript/16729.md b/changelog_unreleased/typescript/16729.md new file mode 100644 index 000000000..515790d69 --- /dev/null +++ b/changelog_unreleased/typescript/16729.md @@ -0,0 +1,13 @@ +#### Support "Top-level await statements" (#16729 by @fisker) + + +```tsx +// Input +(await (await fetch()).json()).foo + +// Prettier stable +await(await fetch()).json().foo; + +// Prettier main +(await (await fetch()).json()).foo; +``` diff --git a/src/language-js/parse/typescript.js b/src/language-js/parse/typescript.js index 9cbd54e3f..86bf78d3f 100644 --- a/src/language-js/parse/typescript.js +++ b/src/language-js/parse/typescript.js @@ -3,6 +3,7 @@ import createError from "../../common/parser-create-error.js"; import tryCombinations from "../../utils/try-combinations.js"; import postprocess from "./postprocess/index.js"; import createParser from "./utils/create-parser.js"; +import getSourceType from "./utils/get-source-type.js"; import replaceHashbang from "./utils/replace-hashbang.js"; /** @import {TSESTreeOptions} from "@typescript-eslint/typescript-estree" */ @@ -50,18 +51,34 @@ const isKnownFileType = (filepath) => function getParseOptionsCombinations(text, options) { const filepath = options?.filepath; + + let combinations = [{ ...baseParseOptions, filePath: filepath }]; + + const sourceType = getSourceType(options); + if (sourceType) { + combinations = combinations.map((parseOptions) => ({ + ...parseOptions, + sourceType, + })); + } else { + /** @type {("module" | "script") []} */ + const sourceTypes = ["module", "script"]; + combinations = sourceTypes.flatMap((sourceType) => + combinations.map((parseOptions) => ({ ...parseOptions, sourceType })), + ); + } + if (filepath && isKnownFileType(filepath)) { - return [{ ...baseParseOptions, filePath: filepath }]; + return combinations; } const shouldEnableJsx = isProbablyJsx(text); - return [ - { ...baseParseOptions, jsx: shouldEnableJsx }, - { ...baseParseOptions, jsx: !shouldEnableJsx }, - ]; + return [shouldEnableJsx, !shouldEnableJsx].flatMap((jsx) => + combinations.map((parseOptions) => ({ ...parseOptions, jsx })), + ); } -function parse(text, options) { +function parse(text, options = {}) { const textToParse = replaceHashbang(text); const parseOptionsCombinations = getParseOptionsCombinations(text, options); diff --git a/src/language-js/parse/utils/get-source-type.js b/src/language-js/parse/utils/get-source-type.js index ce721f0c1..a8ac05c21 100644 --- a/src/language-js/parse/utils/get-source-type.js +++ b/src/language-js/parse/utils/get-source-type.js @@ -6,11 +6,11 @@ function getSourceType(options) { } filepath = filepath.toLowerCase(); - if (filepath.endsWith(".cjs")) { + if (filepath.endsWith(".cjs") || filepath.endsWith(".cts")) { return "script"; } - if (filepath.endsWith(".mjs")) { + if (filepath.endsWith(".mjs") || filepath.endsWith(".mts")) { return "module"; } } diff --git a/tests/format/js/top-level-await/__snapshots__/format.test.js.snap b/tests/format/js/top-level-await/__snapshots__/format.test.js.snap index 249b632a6..16fa17722 100644 --- a/tests/format/js/top-level-await/__snapshots__/format.test.js.snap +++ b/tests/format/js/top-level-await/__snapshots__/format.test.js.snap @@ -29,3 +29,45 @@ call(await something()); ================================================================================ `; + +exports[`test.cjs format 1`] = ` +====================================options===================================== +parsers: ["babel", "typescript"] +printWidth: 80 + | printWidth +=====================================input====================================== +await(1); + +=====================================output===================================== +await(1); + +================================================================================ +`; + +exports[`test.js format 1`] = ` +====================================options===================================== +parsers: ["babel", "typescript"] +printWidth: 80 + | printWidth +=====================================input====================================== +await(1); + +=====================================output===================================== +await 1; + +================================================================================ +`; + +exports[`test.mjs format 1`] = ` +====================================options===================================== +parsers: ["babel", "typescript"] +printWidth: 80 + | printWidth +=====================================input====================================== +await(1); + +=====================================output===================================== +await 1; + +================================================================================ +`; diff --git a/tests/format/js/top-level-await/test.cjs b/tests/format/js/top-level-await/test.cjs new file mode 100644 index 000000000..f3d5b23bd --- /dev/null +++ b/tests/format/js/top-level-await/test.cjs @@ -0,0 +1 @@ +await(1); diff --git a/tests/format/js/top-level-await/test.js b/tests/format/js/top-level-await/test.js new file mode 100644 index 000000000..f3d5b23bd --- /dev/null +++ b/tests/format/js/top-level-await/test.js @@ -0,0 +1 @@ +await(1); diff --git a/tests/format/js/top-level-await/test.mjs b/tests/format/js/top-level-await/test.mjs new file mode 100644 index 000000000..f3d5b23bd --- /dev/null +++ b/tests/format/js/top-level-await/test.mjs @@ -0,0 +1 @@ +await(1); diff --git a/tests/format/jsx/top-level-await/__snapshots__/format.test.js.snap b/tests/format/jsx/top-level-await/__snapshots__/format.test.js.snap new file mode 100644 index 000000000..0c2b4cbb7 --- /dev/null +++ b/tests/format/jsx/top-level-await/__snapshots__/format.test.js.snap @@ -0,0 +1,15 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`test.jsx format 1`] = ` +====================================options===================================== +parsers: ["babel", "typescript"] +printWidth: 80 + | printWidth +=====================================input====================================== +await(1); + +=====================================output===================================== +await 1; + +================================================================================ +`; diff --git a/tests/format/jsx/top-level-await/format.test.js b/tests/format/jsx/top-level-await/format.test.js new file mode 100644 index 000000000..98ba37cc2 --- /dev/null +++ b/tests/format/jsx/top-level-await/format.test.js @@ -0,0 +1 @@ +runFormatTest(import.meta, ["babel", "typescript"]); diff --git a/tests/format/jsx/top-level-await/test.jsx b/tests/format/jsx/top-level-await/test.jsx new file mode 100644 index 000000000..f3d5b23bd --- /dev/null +++ b/tests/format/jsx/top-level-await/test.jsx @@ -0,0 +1 @@ +await(1); diff --git a/tests/format/typescript/top-level-await/__snapshots__/format.test.js.snap b/tests/format/typescript/top-level-await/__snapshots__/format.test.js.snap new file mode 100644 index 000000000..84f20d71c --- /dev/null +++ b/tests/format/typescript/top-level-await/__snapshots__/format.test.js.snap @@ -0,0 +1,57 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`test.cts format 1`] = ` +====================================options===================================== +parsers: ["typescript"] +printWidth: 80 + | printWidth +=====================================input====================================== +await(1); + +=====================================output===================================== +await(1); + +================================================================================ +`; + +exports[`test.mts format 1`] = ` +====================================options===================================== +parsers: ["typescript"] +printWidth: 80 + | printWidth +=====================================input====================================== +await(1); + +=====================================output===================================== +await 1; + +================================================================================ +`; + +exports[`test.ts format 1`] = ` +====================================options===================================== +parsers: ["typescript"] +printWidth: 80 + | printWidth +=====================================input====================================== +await(1); + +=====================================output===================================== +await 1; + +================================================================================ +`; + +exports[`test.tsx format 1`] = ` +====================================options===================================== +parsers: ["typescript"] +printWidth: 80 + | printWidth +=====================================input====================================== +await(1); + +=====================================output===================================== +await 1; + +================================================================================ +`; diff --git a/tests/format/typescript/top-level-await/format.test.js b/tests/format/typescript/top-level-await/format.test.js new file mode 100644 index 000000000..116dcbd78 --- /dev/null +++ b/tests/format/typescript/top-level-await/format.test.js @@ -0,0 +1 @@ +runFormatTest(import.meta, ["typescript"]); diff --git a/tests/format/typescript/top-level-await/test.cts b/tests/format/typescript/top-level-await/test.cts new file mode 100644 index 000000000..f3d5b23bd --- /dev/null +++ b/tests/format/typescript/top-level-await/test.cts @@ -0,0 +1 @@ +await(1); diff --git a/tests/format/typescript/top-level-await/test.mts b/tests/format/typescript/top-level-await/test.mts new file mode 100644 index 000000000..f3d5b23bd --- /dev/null +++ b/tests/format/typescript/top-level-await/test.mts @@ -0,0 +1 @@ +await(1); diff --git a/tests/format/typescript/top-level-await/test.ts b/tests/format/typescript/top-level-await/test.ts new file mode 100644 index 000000000..f3d5b23bd --- /dev/null +++ b/tests/format/typescript/top-level-await/test.ts @@ -0,0 +1 @@ +await(1); diff --git a/tests/format/typescript/top-level-await/test.tsx b/tests/format/typescript/top-level-await/test.tsx new file mode 100644 index 000000000..f3d5b23bd --- /dev/null +++ b/tests/format/typescript/top-level-await/test.tsx @@ -0,0 +1 @@ +await(1);