From 9e1038c0eb080da5b049a8689f0b9c08830e8fe3 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Tue, 16 Nov 2021 10:15:08 +0900 Subject: [PATCH] Support TypeScript 4.5 syntax (#11813) * Update dependencies * Add tests for type-only module specifiers * Add tests for ts import assertions * Add tests for ts private-fields-in-in * Update changelog * Update misc tests * Update SYNTAX_KIND_PROPERTY_DEFINITION * List typescript from error list --- changelog_unreleased/typescript/11721.md | 54 +++++++++++++++++-- package.json | 4 +- .../parse/postprocess/typescript.js | 2 +- .../__snapshots__/jsfmt.spec.js.snap | 7 --- tests/format/js/dynamic-import/jsfmt.spec.js | 1 - .../__snapshots__/jsfmt.spec.js.snap | 16 +++--- .../format/js/import-assertions/jsfmt.spec.js | 2 +- .../import/__snapshots__/jsfmt.spec.js.snap | 4 +- .../__snapshots__/jsfmt.spec.js.snap | 14 ----- .../misc/errors/typescript/dynamic-import.ts | 1 - .../typescript/module-attributes-dynamic.ts | 1 - .../__snapshots__/jsfmt.spec.js.snap | 30 ----------- .../__snapshots__/jsfmt.spec.js.snap | 43 +++++++++++++++ .../typescript/private-fields-in-in/basic.ts | 15 ++++++ .../private-fields-in-in/jsfmt.spec.js | 1 + .../__snapshots__/jsfmt.spec.js.snap | 31 +++++++++++ .../type-only-module-specifiers/basic.ts} | 0 .../type-only-module-specifiers/jsfmt.spec.js | 1 + yarn.lock | 38 ++++++------- 19 files changed, 175 insertions(+), 90 deletions(-) delete mode 100644 tests/format/misc/errors/typescript/dynamic-import.ts delete mode 100644 tests/format/misc/errors/typescript/module-attributes-dynamic.ts create mode 100644 tests/format/typescript/private-fields-in-in/__snapshots__/jsfmt.spec.js.snap create mode 100644 tests/format/typescript/private-fields-in-in/basic.ts create mode 100644 tests/format/typescript/private-fields-in-in/jsfmt.spec.js create mode 100644 tests/format/typescript/type-only-module-specifiers/__snapshots__/jsfmt.spec.js.snap rename tests/format/{misc/typescript-babel-only/type-only-module-specifiers.ts => typescript/type-only-module-specifiers/basic.ts} (100%) create mode 100644 tests/format/typescript/type-only-module-specifiers/jsfmt.spec.js diff --git a/changelog_unreleased/typescript/11721.md b/changelog_unreleased/typescript/11721.md index f29087232..5159197bb 100644 --- a/changelog_unreleased/typescript/11721.md +++ b/changelog_unreleased/typescript/11721.md @@ -1,11 +1,9 @@ -#### Support TypeScript 4.5 (#11721, #11723 by @sosukesuzuki) +#### Support TypeScript 4.5 (#11721, #11723, #11813 by @sosukesuzuki) Support new TypeScript 4.5 features. ##### [`type` Modifiers on Import Names](https://devblogs.microsoft.com/typescript/announcing-typescript-4-5-beta/#type-on-import-names) -Only supported by `babel-ts`. - ```ts // Input @@ -19,6 +17,56 @@ import { type A } from "mod"; ``` +##### [Private Field Presence Checks](https://devblogs.microsoft.com/typescript/announcing-typescript-4-5-rc/#private-field-presence-checks) + + +```ts +// Input +class Foo { + #prop1; + method() { + return #prop1 in this; + } +} + +// Prettier stable +SyntaxError: Private identifiers are not allowed outside class bodies. (4:12) + 2 | #prop1; + 3 | method() { +> 4 | return #prop1 in this; + | ^ + 5 | } + 6 | } + 7 | + +// Prettier main +class Foo { + #prop1; + method() { + return #prop1 in this; + } +} + +``` + +##### [Import Assertions](https://devblogs.microsoft.com/typescript/announcing-typescript-4-5-rc/#import-assertions) + + +```ts +// Input +import obj from "./something.json" assert { type: "json" }; + +// Prettier stable +SyntaxError: ';' expected. (1:36) +> 1 | import obj from "./something.json" assert { type: "json" }; + | ^ + 2 | + +// Prettier main +import obj from "./something.json" assert { type: "json" }; + +``` + ##### Handle `.mts` and `.cts` Handle new file extensions `.mts` and `.cts`. diff --git a/package.json b/package.json index 20f9e9747..eb4641358 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "@babel/parser": "7.16.3", "@glimmer/syntax": "0.83.1", "@iarna/toml": "2.2.5", - "@typescript-eslint/typescript-estree": "5.3.1", + "@typescript-eslint/typescript-estree": "5.4.0", "angular-estree-parser": "2.5.0", "angular-html-parser": "1.8.0", "camelcase": "6.2.0", @@ -79,7 +79,7 @@ "semver": "7.3.5", "string-width": "4.2.2", "strip-ansi": "6.0.0", - "typescript": "4.4.4", + "typescript": "4.5.1-rc", "unicode-regex": "3.0.0", "unified": "9.2.1", "vnopts": "1.0.2", diff --git a/src/language-js/parse/postprocess/typescript.js b/src/language-js/parse/postprocess/typescript.js index 2ee9bcac2..a90422a73 100644 --- a/src/language-js/parse/postprocess/typescript.js +++ b/src/language-js/parse/postprocess/typescript.js @@ -41,7 +41,7 @@ function throwErrorForInvalidDecorator( // Values of abstract property is removed since `@typescript-eslint/typescript-estree` v5 // https://github.com/typescript-eslint/typescript-eslint/releases/tag/v5.0.0 function throwErrorForInvalidAbstractProperty(tsNode, esTreeNode) { - const SYNTAX_KIND_PROPERTY_DEFINITION = 165; + const SYNTAX_KIND_PROPERTY_DEFINITION = 166; const SYNTAX_KIND_ABSTRACT_KEYWORD = 126; if ( tsNode.kind !== SYNTAX_KIND_PROPERTY_DEFINITION || diff --git a/tests/format/js/dynamic-import/__snapshots__/jsfmt.spec.js.snap b/tests/format/js/dynamic-import/__snapshots__/jsfmt.spec.js.snap index e35226160..75c07691c 100644 --- a/tests/format/js/dynamic-import/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/js/dynamic-import/__snapshots__/jsfmt.spec.js.snap @@ -21,13 +21,6 @@ exports[`assertions.js [meriyah] format 1`] = ` 2 |" `; -exports[`assertions.js [typescript] format 1`] = ` -"Dynamic import must have one specifier as an argument. (1:8) -> 1 | import(\\"./foo.json\\", { assert: { type: \\"json\\" } }); - | ^ - 2 |" -`; - exports[`assertions.js format 1`] = ` ====================================options===================================== parsers: ["babel", "flow", "typescript"] diff --git a/tests/format/js/dynamic-import/jsfmt.spec.js b/tests/format/js/dynamic-import/jsfmt.spec.js index 4fffde987..79e7e31fa 100644 --- a/tests/format/js/dynamic-import/jsfmt.spec.js +++ b/tests/format/js/dynamic-import/jsfmt.spec.js @@ -1,7 +1,6 @@ run_spec(__dirname, ["babel", "flow", "typescript"], { errors: { flow: ["assertions.js"], - typescript: ["assertions.js"], espree: ["assertions.js"], meriyah: ["assertions.js"], }, diff --git a/tests/format/js/import-assertions/__snapshots__/jsfmt.spec.js.snap b/tests/format/js/import-assertions/__snapshots__/jsfmt.spec.js.snap index 0f2a1173a..82047193a 100644 --- a/tests/format/js/import-assertions/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/js/import-assertions/__snapshots__/jsfmt.spec.js.snap @@ -16,7 +16,7 @@ exports[`dynamic-import.js [meriyah] format 1`] = ` exports[`dynamic-import.js format 1`] = ` ====================================options===================================== -parsers: ["babel"] +parsers: ["babel", "typescript"] printWidth: 80 | printWidth =====================================input====================================== @@ -50,7 +50,7 @@ exports[`empty.js [meriyah] format 1`] = ` exports[`empty.js format 1`] = ` ====================================options===================================== -parsers: ["babel"] +parsers: ["babel", "typescript"] printWidth: 80 | printWidth =====================================input====================================== @@ -89,7 +89,7 @@ exports[`multi-types.js [meriyah] format 1`] = ` exports[`multi-types.js format 1`] = ` ====================================options===================================== -parsers: ["babel"] +parsers: ["babel", "typescript"] printWidth: 80 | printWidth =====================================input====================================== @@ -117,7 +117,7 @@ exports[`non-type.js [meriyah] format 1`] = ` exports[`non-type.js format 1`] = ` ====================================options===================================== -parsers: ["babel"] +parsers: ["babel", "typescript"] printWidth: 80 | printWidth =====================================input====================================== @@ -131,7 +131,7 @@ import foo from "foo.json" assert { lazy: "true" }; exports[`not-import-assertions.js format 1`] = ` ====================================options===================================== -parsers: ["babel"] +parsers: ["babel", "typescript"] printWidth: 80 | printWidth =====================================input====================================== @@ -165,7 +165,7 @@ exports[`re-export.js [meriyah] format 1`] = ` exports[`re-export.js format 1`] = ` ====================================options===================================== -parsers: ["babel"] +parsers: ["babel", "typescript"] printWidth: 80 | printWidth =====================================input====================================== @@ -197,7 +197,7 @@ exports[`static-import.js [meriyah] format 1`] = ` exports[`static-import.js format 1`] = ` ====================================options===================================== -parsers: ["babel"] +parsers: ["babel", "typescript"] printWidth: 80 | printWidth =====================================input====================================== @@ -225,7 +225,7 @@ exports[`without-from.js [meriyah] format 1`] = ` exports[`without-from.js format 1`] = ` ====================================options===================================== -parsers: ["babel"] +parsers: ["babel", "typescript"] printWidth: 80 | printWidth =====================================input====================================== diff --git a/tests/format/js/import-assertions/jsfmt.spec.js b/tests/format/js/import-assertions/jsfmt.spec.js index 60cc36973..bc6d5c8c4 100644 --- a/tests/format/js/import-assertions/jsfmt.spec.js +++ b/tests/format/js/import-assertions/jsfmt.spec.js @@ -1,4 +1,4 @@ -run_spec(__dirname, ["babel"], { +run_spec(__dirname, ["babel", "typescript"], { errors: { espree: [ "dynamic-import.js", diff --git a/tests/format/misc/errors/js/import/__snapshots__/jsfmt.spec.js.snap b/tests/format/misc/errors/js/import/__snapshots__/jsfmt.spec.js.snap index c2989ca01..374bc3856 100644 --- a/tests/format/misc/errors/js/import/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/misc/errors/js/import/__snapshots__/jsfmt.spec.js.snap @@ -37,7 +37,7 @@ exports[`snippet: #0 [meriyah] format 1`] = ` `; exports[`snippet: #0 [typescript] format 1`] = ` -"Dynamic import must have one specifier as an argument. (1:8) +"Dynamic import requires exactly one or two arguments. (1:8) > 1 | import(); | ^" `; @@ -79,7 +79,7 @@ exports[`snippet: #1 [meriyah] format 1`] = ` `; exports[`snippet: #1 [typescript] format 1`] = ` -"Dynamic import must have one specifier as an argument. (1:8) +"Dynamic import requires exactly one or two arguments. (1:8) > 1 | import(/* comment */); | ^" `; diff --git a/tests/format/misc/errors/typescript/__snapshots__/jsfmt.spec.js.snap b/tests/format/misc/errors/typescript/__snapshots__/jsfmt.spec.js.snap index 703b695cd..b0f014358 100644 --- a/tests/format/misc/errors/typescript/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/misc/errors/typescript/__snapshots__/jsfmt.spec.js.snap @@ -7,13 +7,6 @@ exports[`default-escaped.ts [typescript] format 1`] = ` 2 |" `; -exports[`dynamic-import.ts [typescript] format 1`] = ` -"Dynamic import must have one specifier as an argument. (1:8) -> 1 | import('./prettier.mjs', {}) - | ^ - 2 |" -`; - exports[`export-declare.ts [typescript] format 1`] = ` "Declaration or statement expected. (1:1) > 1 | export declare foo; @@ -32,13 +25,6 @@ exports[`invalid-jsx-1.ts [typescript] format 1`] = ` exports[`issue-8773.ts [typescript] format 1`] = `"Comment \\"comment\\" was not printed. Please report this error!"`; -exports[`module-attributes-dynamic.ts [typescript] format 1`] = ` -"Dynamic import must have one specifier as an argument. (1:8) -> 1 | import(\\"foo.json\\", { with: { type: \\"json\\" } }) - | ^ - 2 |" -`; - exports[`module-attributes-static.ts [typescript] format 1`] = ` "';' expected. (1:28) > 1 | import foo from \\"foo.json\\" with type: \\"json\\"; diff --git a/tests/format/misc/errors/typescript/dynamic-import.ts b/tests/format/misc/errors/typescript/dynamic-import.ts deleted file mode 100644 index 2c6d4b2f3..000000000 --- a/tests/format/misc/errors/typescript/dynamic-import.ts +++ /dev/null @@ -1 +0,0 @@ -import('./prettier.mjs', {}) diff --git a/tests/format/misc/errors/typescript/module-attributes-dynamic.ts b/tests/format/misc/errors/typescript/module-attributes-dynamic.ts deleted file mode 100644 index baa60fc43..000000000 --- a/tests/format/misc/errors/typescript/module-attributes-dynamic.ts +++ /dev/null @@ -1 +0,0 @@ -import("foo.json", { with: { type: "json" } }) diff --git a/tests/format/misc/typescript-babel-only/__snapshots__/jsfmt.spec.js.snap b/tests/format/misc/typescript-babel-only/__snapshots__/jsfmt.spec.js.snap index a2a836752..4f08e7695 100644 --- a/tests/format/misc/typescript-babel-only/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/misc/typescript-babel-only/__snapshots__/jsfmt.spec.js.snap @@ -189,33 +189,3 @@ type T = [x: A]; ================================================================================ `; - -exports[`type-only-module-specifiers.ts format 1`] = ` -====================================options===================================== -parsers: ["babel-ts"] -printWidth: 80 - | printWidth -=====================================input====================================== -import { type A } from "foo"; -import { type B, C } from "foo"; -import { type D, type E } from "foo"; -import { type E as F } from "foo"; - -export { type A } from "foo"; -export { type B, C } from "foo"; -export { type D, type E } from "foo"; -export { type E as F } from "foo"; - -=====================================output===================================== -import { type A } from "foo"; -import { type B, C } from "foo"; -import { type D, type E } from "foo"; -import { type E as F } from "foo"; - -export { type A } from "foo"; -export { type B, C } from "foo"; -export { type D, type E } from "foo"; -export { type E as F } from "foo"; - -================================================================================ -`; diff --git a/tests/format/typescript/private-fields-in-in/__snapshots__/jsfmt.spec.js.snap b/tests/format/typescript/private-fields-in-in/__snapshots__/jsfmt.spec.js.snap new file mode 100644 index 000000000..99aa9a38c --- /dev/null +++ b/tests/format/typescript/private-fields-in-in/__snapshots__/jsfmt.spec.js.snap @@ -0,0 +1,43 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`basic.ts format 1`] = ` +====================================options===================================== +parsers: ["typescript"] +printWidth: 80 + | printWidth +=====================================input====================================== +class Person { + #name: string; + constructor(name: string) { + this.#name = name; + } + + equals(other: unknown) { + return ( + other && + typeof other === "object" && + #name in other && // <- this is new! + this.#name === other.#name + ); + } +} + +=====================================output===================================== +class Person { + #name: string; + constructor(name: string) { + this.#name = name; + } + + equals(other: unknown) { + return ( + other && + typeof other === "object" && + #name in other && // <- this is new! + this.#name === other.#name + ); + } +} + +================================================================================ +`; diff --git a/tests/format/typescript/private-fields-in-in/basic.ts b/tests/format/typescript/private-fields-in-in/basic.ts new file mode 100644 index 000000000..02c7403e0 --- /dev/null +++ b/tests/format/typescript/private-fields-in-in/basic.ts @@ -0,0 +1,15 @@ +class Person { + #name: string; + constructor(name: string) { + this.#name = name; + } + + equals(other: unknown) { + return ( + other && + typeof other === "object" && + #name in other && // <- this is new! + this.#name === other.#name + ); + } +} diff --git a/tests/format/typescript/private-fields-in-in/jsfmt.spec.js b/tests/format/typescript/private-fields-in-in/jsfmt.spec.js new file mode 100644 index 000000000..2ea3bb6eb --- /dev/null +++ b/tests/format/typescript/private-fields-in-in/jsfmt.spec.js @@ -0,0 +1 @@ +run_spec(__dirname, ["typescript"]); diff --git a/tests/format/typescript/type-only-module-specifiers/__snapshots__/jsfmt.spec.js.snap b/tests/format/typescript/type-only-module-specifiers/__snapshots__/jsfmt.spec.js.snap new file mode 100644 index 000000000..47896fb24 --- /dev/null +++ b/tests/format/typescript/type-only-module-specifiers/__snapshots__/jsfmt.spec.js.snap @@ -0,0 +1,31 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`basic.ts format 1`] = ` +====================================options===================================== +parsers: ["typescript"] +printWidth: 80 + | printWidth +=====================================input====================================== +import { type A } from "foo"; +import { type B, C } from "foo"; +import { type D, type E } from "foo"; +import { type E as F } from "foo"; + +export { type A } from "foo"; +export { type B, C } from "foo"; +export { type D, type E } from "foo"; +export { type E as F } from "foo"; + +=====================================output===================================== +import { type A } from "foo"; +import { type B, C } from "foo"; +import { type D, type E } from "foo"; +import { type E as F } from "foo"; + +export { type A } from "foo"; +export { type B, C } from "foo"; +export { type D, type E } from "foo"; +export { type E as F } from "foo"; + +================================================================================ +`; diff --git a/tests/format/misc/typescript-babel-only/type-only-module-specifiers.ts b/tests/format/typescript/type-only-module-specifiers/basic.ts similarity index 100% rename from tests/format/misc/typescript-babel-only/type-only-module-specifiers.ts rename to tests/format/typescript/type-only-module-specifiers/basic.ts diff --git a/tests/format/typescript/type-only-module-specifiers/jsfmt.spec.js b/tests/format/typescript/type-only-module-specifiers/jsfmt.spec.js new file mode 100644 index 000000000..2ea3bb6eb --- /dev/null +++ b/tests/format/typescript/type-only-module-specifiers/jsfmt.spec.js @@ -0,0 +1 @@ +run_spec(__dirname, ["typescript"]); diff --git a/yarn.lock b/yarn.lock index a10558d55..51e787937 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1773,10 +1773,10 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.0.0.tgz#25d93f6d269b2d25fdc51a0407eb81ccba60eb0f" integrity sha512-dU/pKBUpehdEqYuvkojmlv0FtHuZnLXFBn16zsDmlFF3LXkOpkAQ2vrKc3BidIIve9EMH2zfTlxqw9XM0fFN5w== -"@typescript-eslint/types@5.3.1": - version "5.3.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.3.1.tgz#afaa715b69ebfcfde3af8b0403bf27527912f9b7" - integrity sha512-bG7HeBLolxKHtdHG54Uac750eXuQQPpdJfCYuw4ZI3bZ7+GgKClMWM8jExBtp7NSP4m8PmLRM8+lhzkYnSmSxQ== +"@typescript-eslint/types@5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.4.0.tgz#b1c130f4b381b77bec19696c6e3366f9781ce8f2" + integrity sha512-GjXNpmn+n1LvnttarX+sPD6+S7giO+9LxDIGlRl4wK3a7qMWALOHYuVSZpPTfEIklYjaWuMtfKdeByx0AcaThA== "@typescript-eslint/typescript-estree@5.0.0": version "5.0.0" @@ -1791,13 +1791,13 @@ semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/typescript-estree@5.3.1": - version "5.3.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.3.1.tgz#50cc4bfb93dc31bc75e08ae52e29fcb786d606ec" - integrity sha512-PwFbh/PKDVo/Wct6N3w+E4rLZxUDgsoII/GrWM2A62ETOzJd4M6s0Mu7w4CWsZraTbaC5UQI+dLeyOIFF1PquQ== +"@typescript-eslint/typescript-estree@5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.4.0.tgz#fe524fb308973c68ebeb7428f3b64499a6ba5fc0" + integrity sha512-nhlNoBdhKuwiLMx6GrybPT3SFILm5Gij2YBdPEPFlYNFAXUJWX6QRgvi/lwVoadaQEFsizohs6aFRMqsXI2ewA== dependencies: - "@typescript-eslint/types" "5.3.1" - "@typescript-eslint/visitor-keys" "5.3.1" + "@typescript-eslint/types" "5.4.0" + "@typescript-eslint/visitor-keys" "5.4.0" debug "^4.3.2" globby "^11.0.4" is-glob "^4.0.3" @@ -1812,12 +1812,12 @@ "@typescript-eslint/types" "5.0.0" eslint-visitor-keys "^3.0.0" -"@typescript-eslint/visitor-keys@5.3.1": - version "5.3.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.3.1.tgz#c2860ff22939352db4f3806f34b21d8ad00588ba" - integrity sha512-3cHUzUuVTuNHx0Gjjt5pEHa87+lzyqOiHXy/Gz+SJOCW1mpw9xQHIIEwnKn+Thph1mgWyZ90nboOcSuZr/jTTQ== +"@typescript-eslint/visitor-keys@5.4.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.4.0.tgz#09bc28efd3621f292fe88c86eef3bf4893364c8c" + integrity sha512-PVbax7MeE7tdLfW5SA0fs8NGVVr+buMPrcj+CWYWPXsZCH8qZ1THufDzbXm1xrZ2b2PA1iENJ0sRq5fuUtvsJg== dependencies: - "@typescript-eslint/types" "5.3.1" + "@typescript-eslint/types" "5.4.0" eslint-visitor-keys "^3.0.0" "@webassemblyjs/ast@1.11.1": @@ -6554,10 +6554,10 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" -typescript@4.4.4: - version "4.4.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.4.tgz#2cd01a1a1f160704d3101fd5a58ff0f9fcb8030c" - integrity sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA== +typescript@4.5.1-rc: + version "4.5.1-rc" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.1-rc.tgz#02155eaa0579d11babb2a55dcbd796948a994bb3" + integrity sha512-tQBWW1DCFqweyhSzsAUSFgssJ3uuRBh0zyOkRV4CaFF2rMBkGU0I+MqPMch0qhGCUGXjOW7FgMrbQLS6PE3Z6Q== unbox-primitive@^1.0.1: version "1.0.1"