From 81793210e6337ad8d20f2b7e44e9489687c2d29c Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Wed, 10 Jan 2024 06:15:24 +0000 Subject: [PATCH 01/11] Update package-lock.json --- package-lock.json | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index ea7118978788e..4e5578da633f4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1011,9 +1011,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.10.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.7.tgz", - "integrity": "sha512-fRbIKb8C/Y2lXxB5eVMj4IU7xpdox0Lh8bUPEdtLysaylsml1hOOx1+STloRs/B9nf7C6kPRmmg/V7aQW7usNg==", + "version": "20.10.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.8.tgz", + "integrity": "sha512-f8nQs3cLxbAFc00vEU59yf9UyGUftkPaLGfvbVOIDdx2i1b8epBqj2aNGyP19fiyXWvlmZ7qC1XLjAzw/OKIeA==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -2153,9 +2153,9 @@ "dev": true }, "node_modules/fast-xml-parser": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.3.2.tgz", - "integrity": "sha512-rmrXUXwbJedoXkStenj1kkljNF7ugn5ZjR9FJcwmCfcCbtOMDghPajbc+Tck6vE6F5XsDmx+Pr2le9fw8+pXBg==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.3.3.tgz", + "integrity": "sha512-coV/D1MhrShMvU6D0I+VAK3umz6hUaxxhL0yp/9RjfiYUfAv14rDhGQL+PLForhMdr0wq3PiV07WtkkNjJjNHg==", "dev": true, "funding": [ { @@ -4736,9 +4736,9 @@ "dev": true }, "@types/node": { - "version": "20.10.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.7.tgz", - "integrity": "sha512-fRbIKb8C/Y2lXxB5eVMj4IU7xpdox0Lh8bUPEdtLysaylsml1hOOx1+STloRs/B9nf7C6kPRmmg/V7aQW7usNg==", + "version": "20.10.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.8.tgz", + "integrity": "sha512-f8nQs3cLxbAFc00vEU59yf9UyGUftkPaLGfvbVOIDdx2i1b8epBqj2aNGyP19fiyXWvlmZ7qC1XLjAzw/OKIeA==", "dev": true, "requires": { "undici-types": "~5.26.4" @@ -5572,9 +5572,9 @@ "dev": true }, "fast-xml-parser": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.3.2.tgz", - "integrity": "sha512-rmrXUXwbJedoXkStenj1kkljNF7ugn5ZjR9FJcwmCfcCbtOMDghPajbc+Tck6vE6F5XsDmx+Pr2le9fw8+pXBg==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.3.3.tgz", + "integrity": "sha512-coV/D1MhrShMvU6D0I+VAK3umz6hUaxxhL0yp/9RjfiYUfAv14rDhGQL+PLForhMdr0wq3PiV07WtkkNjJjNHg==", "dev": true, "requires": { "strnum": "^1.0.5" From 385db449f5395ab4d8f24c5f531e85aebbe228c7 Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Wed, 10 Jan 2024 10:15:58 -0800 Subject: [PATCH 02/11] With `allowJs`, process JS files found searching node_modules when they have a realpath outside node_modules (#56946) --- src/compiler/program.ts | 3 +- .../allowJsCrossMonorepoPackage.symbols | 22 +++ .../allowJsCrossMonorepoPackage.trace.json | 159 ++++++++++++++++++ .../allowJsCrossMonorepoPackage.types | 23 +++ .../compiler/allowJsCrossMonorepoPackage.ts | 44 +++++ 5 files changed, 250 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/allowJsCrossMonorepoPackage.symbols create mode 100644 tests/baselines/reference/allowJsCrossMonorepoPackage.trace.json create mode 100644 tests/baselines/reference/allowJsCrossMonorepoPackage.types create mode 100644 tests/cases/compiler/allowJsCrossMonorepoPackage.ts diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 067b66dca5714..6dd6cb6de43fe 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -254,6 +254,7 @@ import { parseJsonSourceFileConfigFileContent, parseNodeFactory, Path, + pathContainsNodeModules, pathIsAbsolute, pathIsRelative, Program, @@ -4039,7 +4040,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg const isFromNodeModulesSearch = resolution.isExternalLibraryImport; const isJsFile = !resolutionExtensionIsTSOrJson(resolution.extension); - const isJsFileFromNodeModules = isFromNodeModulesSearch && isJsFile; + const isJsFileFromNodeModules = isFromNodeModulesSearch && isJsFile && (!resolution.originalPath || pathContainsNodeModules(resolution.resolvedFileName)); const resolvedFileName = resolution.resolvedFileName; if (isFromNodeModulesSearch) { diff --git a/tests/baselines/reference/allowJsCrossMonorepoPackage.symbols b/tests/baselines/reference/allowJsCrossMonorepoPackage.symbols new file mode 100644 index 0000000000000..dbdc37a135b01 --- /dev/null +++ b/tests/baselines/reference/allowJsCrossMonorepoPackage.symbols @@ -0,0 +1,22 @@ +//// [tests/cases/compiler/allowJsCrossMonorepoPackage.ts] //// + +=== /packages/main/index.ts === +import { x } from "shared"; +>x : Symbol(x, Decl(index.ts, 0, 8)) + +=== /node_modules/pkg/index.d.ts === +export declare function pkg(): "pkg"; +>pkg : Symbol(pkg, Decl(index.d.ts, 0, 0)) + +=== /packages/shared/utils.js === +export { pkg } from "pkg"; +>pkg : Symbol(pkg, Decl(utils.js, 0, 8)) + +=== /packages/shared/index.js === +import { pkg } from "./utils.js"; +>pkg : Symbol(pkg, Decl(index.js, 0, 8)) + +export const x = pkg(); +>x : Symbol(x, Decl(index.js, 1, 12)) +>pkg : Symbol(pkg, Decl(index.js, 0, 8)) + diff --git a/tests/baselines/reference/allowJsCrossMonorepoPackage.trace.json b/tests/baselines/reference/allowJsCrossMonorepoPackage.trace.json new file mode 100644 index 0000000000000..17b86da7c4b24 --- /dev/null +++ b/tests/baselines/reference/allowJsCrossMonorepoPackage.trace.json @@ -0,0 +1,159 @@ +[ + "======== Resolving module 'shared' from '/packages/main/index.ts'. ========", + "Explicitly specified module resolution kind: 'Bundler'.", + "Resolving in CJS mode with conditions 'import', 'types'.", + "Found 'package.json' at '/packages/main/package.json'.", + "Loading module 'shared' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.", + "Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.", + "Found 'package.json' at '/packages/main/node_modules/shared/package.json'.", + "Using 'exports' subpath '.' with target './index.js'.", + "File name '/packages/main/node_modules/shared/index.js' has a '.js' extension - stripping it.", + "File '/packages/main/node_modules/shared/index.ts' does not exist.", + "File '/packages/main/node_modules/shared/index.tsx' does not exist.", + "File '/packages/main/node_modules/shared/index.d.ts' does not exist.", + "Directory '/packages/main/node_modules/@types' does not exist, skipping all lookups in it.", + "Directory '/packages/node_modules' does not exist, skipping all lookups in it.", + "File '/node_modules/shared.ts' does not exist.", + "File '/node_modules/shared.tsx' does not exist.", + "File '/node_modules/shared.d.ts' does not exist.", + "Directory '/node_modules/@types' does not exist, skipping all lookups in it.", + "Searching all ancestor node_modules directories for fallback extensions: JavaScript, JSON.", + "File '/packages/main/node_modules/shared/package.json' exists according to earlier cached lookups.", + "Using 'exports' subpath '.' with target './index.js'.", + "File name '/packages/main/node_modules/shared/index.js' has a '.js' extension - stripping it.", + "File '/packages/main/node_modules/shared/index.js' exists - use it as a name resolution result.", + "Resolution of non-relative name failed; trying with modern Node resolution features disabled to see if npm library needs configuration update.", + "File '/packages/main/package.json' exists according to earlier cached lookups.", + "Loading module 'shared' from 'node_modules' folder, target file types: TypeScript, Declaration.", + "Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.", + "File '/packages/main/node_modules/shared/package.json' exists according to earlier cached lookups.", + "File '/packages/main/node_modules/shared.ts' does not exist.", + "File '/packages/main/node_modules/shared.tsx' does not exist.", + "File '/packages/main/node_modules/shared.d.ts' does not exist.", + "'package.json' does not have a 'typesVersions' field.", + "'package.json' does not have a 'typings' field.", + "'package.json' does not have a 'types' field.", + "'package.json' does not have a 'main' field.", + "File '/packages/main/node_modules/shared/index.ts' does not exist.", + "File '/packages/main/node_modules/shared/index.tsx' does not exist.", + "File '/packages/main/node_modules/shared/index.d.ts' does not exist.", + "Directory '/packages/main/node_modules/@types' does not exist, skipping all lookups in it.", + "Directory '/packages/node_modules' does not exist, skipping all lookups in it.", + "File '/node_modules/shared.ts' does not exist.", + "File '/node_modules/shared.tsx' does not exist.", + "File '/node_modules/shared.d.ts' does not exist.", + "Directory '/node_modules/@types' does not exist, skipping all lookups in it.", + "Resolving real path for '/packages/main/node_modules/shared/index.js', result '/packages/shared/index.js'.", + "======== Module name 'shared' was successfully resolved to '/packages/shared/index.js' with Package ID 'shared/index.js@1.0.0'. ========", + "======== Resolving module './utils.js' from '/packages/shared/index.js'. ========", + "Explicitly specified module resolution kind: 'Bundler'.", + "Resolving in CJS mode with conditions 'import', 'types'.", + "Loading module as file / folder, candidate module location '/packages/shared/utils.js', target file types: TypeScript, JavaScript, Declaration, JSON.", + "File name '/packages/shared/utils.js' has a '.js' extension - stripping it.", + "File '/packages/shared/utils.ts' does not exist.", + "File '/packages/shared/utils.tsx' does not exist.", + "File '/packages/shared/utils.d.ts' does not exist.", + "File '/packages/shared/utils.js' exists - use it as a name resolution result.", + "======== Module name './utils.js' was successfully resolved to '/packages/shared/utils.js'. ========", + "======== Resolving module 'pkg' from '/packages/shared/utils.js'. ========", + "Explicitly specified module resolution kind: 'Bundler'.", + "Resolving in CJS mode with conditions 'import', 'types'.", + "Found 'package.json' at '/packages/shared/package.json'.", + "Loading module 'pkg' from 'node_modules' folder, target file types: TypeScript, JavaScript, Declaration, JSON.", + "Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.", + "Directory '/packages/shared/node_modules' does not exist, skipping all lookups in it.", + "Directory '/packages/node_modules' does not exist, skipping all lookups in it.", + "File '/node_modules/pkg/package.json' does not exist.", + "File '/node_modules/pkg.ts' does not exist.", + "File '/node_modules/pkg.tsx' does not exist.", + "File '/node_modules/pkg.d.ts' does not exist.", + "File '/node_modules/pkg/index.ts' does not exist.", + "File '/node_modules/pkg/index.tsx' does not exist.", + "File '/node_modules/pkg/index.d.ts' exists - use it as a name resolution result.", + "Resolving real path for '/node_modules/pkg/index.d.ts', result '/node_modules/pkg/index.d.ts'.", + "======== Module name 'pkg' was successfully resolved to '/node_modules/pkg/index.d.ts'. ========", + "======== Resolving module '@typescript/lib-es5' from '/packages/main/__lib_node_modules_lookup_lib.es5.d.ts__.ts'. ========", + "Explicitly specified module resolution kind: 'Node10'.", + "Loading module '@typescript/lib-es5' from 'node_modules' folder, target file types: TypeScript, Declaration.", + "Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.", + "Directory '/packages/main/node_modules/@types' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-es5'", + "Directory '/packages/node_modules' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-es5'", + "Directory '/node_modules/@types' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-es5'", + "Loading module '@typescript/lib-es5' from 'node_modules' folder, target file types: JavaScript.", + "Searching all ancestor node_modules directories for fallback extensions: JavaScript.", + "Directory '/packages/node_modules' does not exist, skipping all lookups in it.", + "======== Module name '@typescript/lib-es5' was not resolved. ========", + "======== Resolving module '@typescript/lib-decorators' from '/packages/main/__lib_node_modules_lookup_lib.decorators.d.ts__.ts'. ========", + "Explicitly specified module resolution kind: 'Node10'.", + "Loading module '@typescript/lib-decorators' from 'node_modules' folder, target file types: TypeScript, Declaration.", + "Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.", + "Directory '/packages/main/node_modules/@types' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-decorators'", + "Directory '/packages/node_modules' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-decorators'", + "Directory '/node_modules/@types' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-decorators'", + "Loading module '@typescript/lib-decorators' from 'node_modules' folder, target file types: JavaScript.", + "Searching all ancestor node_modules directories for fallback extensions: JavaScript.", + "Directory '/packages/node_modules' does not exist, skipping all lookups in it.", + "======== Module name '@typescript/lib-decorators' was not resolved. ========", + "======== Resolving module '@typescript/lib-decorators/legacy' from '/packages/main/__lib_node_modules_lookup_lib.decorators.legacy.d.ts__.ts'. ========", + "Explicitly specified module resolution kind: 'Node10'.", + "Loading module '@typescript/lib-decorators/legacy' from 'node_modules' folder, target file types: TypeScript, Declaration.", + "Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.", + "Directory '/packages/main/node_modules/@types' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-decorators/legacy'", + "Directory '/packages/node_modules' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-decorators/legacy'", + "Directory '/node_modules/@types' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-decorators/legacy'", + "Loading module '@typescript/lib-decorators/legacy' from 'node_modules' folder, target file types: JavaScript.", + "Searching all ancestor node_modules directories for fallback extensions: JavaScript.", + "Directory '/packages/node_modules' does not exist, skipping all lookups in it.", + "======== Module name '@typescript/lib-decorators/legacy' was not resolved. ========", + "======== Resolving module '@typescript/lib-dom' from '/packages/main/__lib_node_modules_lookup_lib.dom.d.ts__.ts'. ========", + "Explicitly specified module resolution kind: 'Node10'.", + "Loading module '@typescript/lib-dom' from 'node_modules' folder, target file types: TypeScript, Declaration.", + "Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.", + "Directory '/packages/main/node_modules/@types' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-dom'", + "Directory '/packages/node_modules' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-dom'", + "Directory '/node_modules/@types' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-dom'", + "Loading module '@typescript/lib-dom' from 'node_modules' folder, target file types: JavaScript.", + "Searching all ancestor node_modules directories for fallback extensions: JavaScript.", + "Directory '/packages/node_modules' does not exist, skipping all lookups in it.", + "======== Module name '@typescript/lib-dom' was not resolved. ========", + "======== Resolving module '@typescript/lib-webworker/importscripts' from '/packages/main/__lib_node_modules_lookup_lib.webworker.importscripts.d.ts__.ts'. ========", + "Explicitly specified module resolution kind: 'Node10'.", + "Loading module '@typescript/lib-webworker/importscripts' from 'node_modules' folder, target file types: TypeScript, Declaration.", + "Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.", + "Directory '/packages/main/node_modules/@types' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-webworker/importscripts'", + "Directory '/packages/node_modules' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-webworker/importscripts'", + "Directory '/node_modules/@types' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-webworker/importscripts'", + "Loading module '@typescript/lib-webworker/importscripts' from 'node_modules' folder, target file types: JavaScript.", + "Searching all ancestor node_modules directories for fallback extensions: JavaScript.", + "Directory '/packages/node_modules' does not exist, skipping all lookups in it.", + "======== Module name '@typescript/lib-webworker/importscripts' was not resolved. ========", + "======== Resolving module '@typescript/lib-scripthost' from '/packages/main/__lib_node_modules_lookup_lib.scripthost.d.ts__.ts'. ========", + "Explicitly specified module resolution kind: 'Node10'.", + "Loading module '@typescript/lib-scripthost' from 'node_modules' folder, target file types: TypeScript, Declaration.", + "Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.", + "Directory '/packages/main/node_modules/@types' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-scripthost'", + "Directory '/packages/node_modules' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-scripthost'", + "Directory '/node_modules/@types' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-scripthost'", + "Loading module '@typescript/lib-scripthost' from 'node_modules' folder, target file types: JavaScript.", + "Searching all ancestor node_modules directories for fallback extensions: JavaScript.", + "Directory '/packages/node_modules' does not exist, skipping all lookups in it.", + "======== Module name '@typescript/lib-scripthost' was not resolved. ========" +] \ No newline at end of file diff --git a/tests/baselines/reference/allowJsCrossMonorepoPackage.types b/tests/baselines/reference/allowJsCrossMonorepoPackage.types new file mode 100644 index 0000000000000..8a0ecbf103606 --- /dev/null +++ b/tests/baselines/reference/allowJsCrossMonorepoPackage.types @@ -0,0 +1,23 @@ +//// [tests/cases/compiler/allowJsCrossMonorepoPackage.ts] //// + +=== /packages/main/index.ts === +import { x } from "shared"; +>x : "pkg" + +=== /node_modules/pkg/index.d.ts === +export declare function pkg(): "pkg"; +>pkg : () => "pkg" + +=== /packages/shared/utils.js === +export { pkg } from "pkg"; +>pkg : () => "pkg" + +=== /packages/shared/index.js === +import { pkg } from "./utils.js"; +>pkg : () => "pkg" + +export const x = pkg(); +>x : "pkg" +>pkg() : "pkg" +>pkg : () => "pkg" + diff --git a/tests/cases/compiler/allowJsCrossMonorepoPackage.ts b/tests/cases/compiler/allowJsCrossMonorepoPackage.ts new file mode 100644 index 0000000000000..2af955d311deb --- /dev/null +++ b/tests/cases/compiler/allowJsCrossMonorepoPackage.ts @@ -0,0 +1,44 @@ +// @Filename: /node_modules/pkg/index.d.ts +export declare function pkg(): "pkg"; + +// @Filename: /packages/shared/package.json +{ + "name": "shared", + "version": "1.0.0", + "type": "module", + "exports": "./index.js" +} + +// @Filename: /packages/shared/utils.js +export { pkg } from "pkg"; + +// @Filename: /packages/shared/index.js +import { pkg } from "./utils.js"; +export const x = pkg(); + +// @Filename: /packages/main/package.json +{ + "name": "main", + "version": "1.0.0", + "type": "module", + "dependencies": { + "shared": "workspace:*" + } +} + +// @Filename: /packages/main/tsconfig.json +{ + "compilerOptions": { + "noEmit": true, + "checkJs": true, + "strict": true, + "module": "esnext", + "moduleResolution": "bundler", + "traceResolution": true, + } +} + +// @link: /packages/shared -> /packages/main/node_modules/shared + +// @Filename: /packages/main/index.ts +import { x } from "shared"; From 9999f264830fe881a6ab1fa1b27d823f686a8f22 Mon Sep 17 00:00:00 2001 From: "Babak K. Shandiz" Date: Wed, 10 Jan 2024 23:04:05 +0000 Subject: [PATCH 03/11] Improve binding element type inference using CheckMode (rebased) (#56753) Signed-off-by: Babak K. Shandiz --- src/compiler/checker.ts | 40 ++++++-- ...ingArrayBindingPatternAndAssignment3.types | 12 +-- ...PatternAndAssignment5SiblingInitializer.js | 48 ++++++++++ ...rnAndAssignment5SiblingInitializer.symbols | 63 ++++++++++++ ...ternAndAssignment5SiblingInitializer.types | 85 +++++++++++++++++ ...PatternAndAssignment9SiblingInitializer.js | 48 ++++++++++ ...rnAndAssignment9SiblingInitializer.symbols | 73 ++++++++++++++ ...ternAndAssignment9SiblingInitializer.types | 95 +++++++++++++++++++ ...PatternAndAssignment5SiblingInitializer.ts | 26 +++++ ...PatternAndAssignment9SiblingInitializer.ts | 26 +++++ 10 files changed, 500 insertions(+), 16 deletions(-) create mode 100644 tests/baselines/reference/destructuringArrayBindingPatternAndAssignment5SiblingInitializer.js create mode 100644 tests/baselines/reference/destructuringArrayBindingPatternAndAssignment5SiblingInitializer.symbols create mode 100644 tests/baselines/reference/destructuringArrayBindingPatternAndAssignment5SiblingInitializer.types create mode 100644 tests/baselines/reference/destructuringObjectBindingPatternAndAssignment9SiblingInitializer.js create mode 100644 tests/baselines/reference/destructuringObjectBindingPatternAndAssignment9SiblingInitializer.symbols create mode 100644 tests/baselines/reference/destructuringObjectBindingPatternAndAssignment9SiblingInitializer.types create mode 100644 tests/cases/conformance/es6/destructuring/destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts create mode 100644 tests/cases/conformance/es6/destructuring/destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 508f6bb323706..4f80bcb783442 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11460,7 +11460,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // contextual type or, if the element itself is a binding pattern, with the type implied by that binding // pattern. const contextualType = isBindingPattern(element.name) ? getTypeFromBindingPattern(element.name, /*includePatternInType*/ true, /*reportErrors*/ false) : unknownType; - return addOptionality(widenTypeInferredFromInitializer(element, checkDeclarationInitializer(element, CheckMode.Normal, contextualType))); + return addOptionality(widenTypeInferredFromInitializer(element, checkDeclarationInitializer(element, reportErrors ? CheckMode.Normal : CheckMode.Contextual, contextualType))); } if (isBindingPattern(element.name)) { return getTypeFromBindingPattern(element.name, includePatternInType, reportErrors); @@ -11618,16 +11618,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return false; } - function getTypeOfVariableOrParameterOrProperty(symbol: Symbol): Type { + function getTypeOfVariableOrParameterOrProperty(symbol: Symbol, checkMode?: CheckMode): Type { const links = getSymbolLinks(symbol); if (!links.type) { - const type = getTypeOfVariableOrParameterOrPropertyWorker(symbol); + const type = getTypeOfVariableOrParameterOrPropertyWorker(symbol, checkMode); // For a contextually typed parameter it is possible that a type has already // been assigned (in assignTypeToParameterAndFixTypeParameters), and we want // to preserve this type. In fact, we need to _prefer_ that type, but it won't // be assigned until contextual typing is complete, so we need to defer in // cases where contextual typing may take place. - if (!links.type && !isParameterOfContextSensitiveSignature(symbol)) { + if (!links.type && !isParameterOfContextSensitiveSignature(symbol) && !checkMode) { links.type = type; } return type; @@ -11635,7 +11635,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return links.type; } - function getTypeOfVariableOrParameterOrPropertyWorker(symbol: Symbol): Type { + function getTypeOfVariableOrParameterOrPropertyWorker(symbol: Symbol, checkMode?: CheckMode): Type { // Handle prototype property if (symbol.flags & SymbolFlags.Prototype) { return getTypeOfPrototypeProperty(symbol); @@ -11678,6 +11678,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (symbol.flags & SymbolFlags.ValueModule && !(symbol.flags & SymbolFlags.Assignment)) { return getTypeOfFuncClassEnumModule(symbol); } + + // When trying to get the *contextual* type of a binding element, it's possible to fall in a loop and therefore + // end up in a circularity-like situation. This is not a true circularity so we should not report such an error. + // For example, here the looping could happen when trying to get the type of `a` (binding element): + // + // const { a, b = a } = { a: 0 } + // + if (isBindingElement(declaration) && checkMode === CheckMode.Contextual) { + return errorType; + } return reportCircularityError(symbol); } let type: Type; @@ -11750,6 +11760,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (symbol.flags & SymbolFlags.ValueModule && !(symbol.flags & SymbolFlags.Assignment)) { return getTypeOfFuncClassEnumModule(symbol); } + + // When trying to get the *contextual* type of a binding element, it's possible to fall in a loop and therefore + // end up in a circularity-like situation. This is not a true circularity so we should not report such an error. + // For example, here the looping could happen when trying to get the type of `a` (binding element): + // + // const { a, b = a } = { a: 0 } + // + if (isBindingElement(declaration) && checkMode === CheckMode.Contextual) { + return type; + } return reportCircularityError(symbol); } return type; @@ -12032,7 +12052,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return getTypeOfSymbol(symbol); } - function getTypeOfSymbol(symbol: Symbol): Type { + function getTypeOfSymbol(symbol: Symbol, checkMode?: CheckMode): Type { const checkFlags = getCheckFlags(symbol); if (checkFlags & CheckFlags.DeferredType) { return getTypeOfSymbolWithDeferredType(symbol); @@ -12047,7 +12067,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return getTypeOfReverseMappedSymbol(symbol as ReverseMappedSymbol); } if (symbol.flags & (SymbolFlags.Variable | SymbolFlags.Property)) { - return getTypeOfVariableOrParameterOrProperty(symbol); + return getTypeOfVariableOrParameterOrProperty(symbol, checkMode); } if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.Enum | SymbolFlags.ValueModule)) { return getTypeOfFuncClassEnumModule(symbol); @@ -29069,8 +29089,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function getNarrowedTypeOfSymbol(symbol: Symbol, location: Identifier) { - const type = getTypeOfSymbol(symbol); + function getNarrowedTypeOfSymbol(symbol: Symbol, location: Identifier, checkMode?: CheckMode) { + const type = getTypeOfSymbol(symbol, checkMode); const declaration = symbol.valueDeclaration; if (declaration) { // If we have a non-rest binding element with no initializer declared as a const variable or a const-like @@ -29233,7 +29253,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { checkNestedBlockScopedBinding(node, symbol); - let type = getNarrowedTypeOfSymbol(localOrExportSymbol, node); + let type = getNarrowedTypeOfSymbol(localOrExportSymbol, node, checkMode); const assignmentKind = getAssignmentTargetKind(node); if (assignmentKind) { diff --git a/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment3.types b/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment3.types index 72aaa6378e5af..791ba83c243dc 100644 --- a/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment3.types +++ b/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment3.types @@ -2,16 +2,16 @@ === destructuringArrayBindingPatternAndAssignment3.ts === const [a, b = a] = [1]; // ok ->a : any ->b : any ->a : any +>a : number +>b : number +>a : number >[1] : [number] >1 : 1 const [c, d = c, e = e] = [1]; // error for e = e ->c : any ->d : any ->c : any +>c : number +>d : number +>c : number >e : any >e : any >[1] : [number] diff --git a/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment5SiblingInitializer.js b/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment5SiblingInitializer.js new file mode 100644 index 0000000000000..47eaab26cd17b --- /dev/null +++ b/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment5SiblingInitializer.js @@ -0,0 +1,48 @@ +//// [tests/cases/conformance/es6/destructuring/destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts] //// + +//// [destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts] +// To be inferred as `number` +function f1() { + const [a1, b1 = a1] = [1]; + const [a2, b2 = 1 + a2] = [1]; +} + +// To be inferred as `string` +function f2() { + const [a1, b1 = a1] = ['hi']; + const [a2, b2 = a2 + '!'] = ['hi']; +} + +// To be inferred as `string | number` +function f3() { + const [a1, b1 = a1] = ['hi', 1]; + const [a2, b2 = a2 + '!'] = ['hi', 1]; +} + +// Based on comment: +// - https://github.com/microsoft/TypeScript/issues/49989#issuecomment-1852694486 +declare const yadda: [number, number] | undefined +function f4() { + const [ a, b = a ] = yadda ?? []; +} + + +//// [destructuringArrayBindingPatternAndAssignment5SiblingInitializer.js] +// To be inferred as `number` +function f1() { + var _a = [1], a1 = _a[0], _b = _a[1], b1 = _b === void 0 ? a1 : _b; + var _c = [1], a2 = _c[0], _d = _c[1], b2 = _d === void 0 ? 1 + a2 : _d; +} +// To be inferred as `string` +function f2() { + var _a = ['hi'], a1 = _a[0], _b = _a[1], b1 = _b === void 0 ? a1 : _b; + var _c = ['hi'], a2 = _c[0], _d = _c[1], b2 = _d === void 0 ? a2 + '!' : _d; +} +// To be inferred as `string | number` +function f3() { + var _a = ['hi', 1], a1 = _a[0], _b = _a[1], b1 = _b === void 0 ? a1 : _b; + var _c = ['hi', 1], a2 = _c[0], _d = _c[1], b2 = _d === void 0 ? a2 + '!' : _d; +} +function f4() { + var _a = yadda !== null && yadda !== void 0 ? yadda : [], a = _a[0], _b = _a[1], b = _b === void 0 ? a : _b; +} diff --git a/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment5SiblingInitializer.symbols b/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment5SiblingInitializer.symbols new file mode 100644 index 0000000000000..2ff79c20083f2 --- /dev/null +++ b/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment5SiblingInitializer.symbols @@ -0,0 +1,63 @@ +//// [tests/cases/conformance/es6/destructuring/destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts] //// + +=== destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts === +// To be inferred as `number` +function f1() { +>f1 : Symbol(f1, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 0, 0)) + + const [a1, b1 = a1] = [1]; +>a1 : Symbol(a1, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 2, 11)) +>b1 : Symbol(b1, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 2, 14)) +>a1 : Symbol(a1, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 2, 11)) + + const [a2, b2 = 1 + a2] = [1]; +>a2 : Symbol(a2, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 3, 11)) +>b2 : Symbol(b2, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 3, 14)) +>a2 : Symbol(a2, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 3, 11)) +} + +// To be inferred as `string` +function f2() { +>f2 : Symbol(f2, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 4, 1)) + + const [a1, b1 = a1] = ['hi']; +>a1 : Symbol(a1, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 8, 11)) +>b1 : Symbol(b1, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 8, 14)) +>a1 : Symbol(a1, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 8, 11)) + + const [a2, b2 = a2 + '!'] = ['hi']; +>a2 : Symbol(a2, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 9, 11)) +>b2 : Symbol(b2, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 9, 14)) +>a2 : Symbol(a2, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 9, 11)) +} + +// To be inferred as `string | number` +function f3() { +>f3 : Symbol(f3, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 10, 1)) + + const [a1, b1 = a1] = ['hi', 1]; +>a1 : Symbol(a1, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 14, 11)) +>b1 : Symbol(b1, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 14, 14)) +>a1 : Symbol(a1, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 14, 11)) + + const [a2, b2 = a2 + '!'] = ['hi', 1]; +>a2 : Symbol(a2, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 15, 11)) +>b2 : Symbol(b2, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 15, 14)) +>a2 : Symbol(a2, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 15, 11)) +} + +// Based on comment: +// - https://github.com/microsoft/TypeScript/issues/49989#issuecomment-1852694486 +declare const yadda: [number, number] | undefined +>yadda : Symbol(yadda, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 20, 13)) + +function f4() { +>f4 : Symbol(f4, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 20, 49)) + + const [ a, b = a ] = yadda ?? []; +>a : Symbol(a, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 22, 11)) +>b : Symbol(b, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 22, 14)) +>a : Symbol(a, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 22, 11)) +>yadda : Symbol(yadda, Decl(destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts, 20, 13)) +} + diff --git a/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment5SiblingInitializer.types b/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment5SiblingInitializer.types new file mode 100644 index 0000000000000..009a62ee2d987 --- /dev/null +++ b/tests/baselines/reference/destructuringArrayBindingPatternAndAssignment5SiblingInitializer.types @@ -0,0 +1,85 @@ +//// [tests/cases/conformance/es6/destructuring/destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts] //// + +=== destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts === +// To be inferred as `number` +function f1() { +>f1 : () => void + + const [a1, b1 = a1] = [1]; +>a1 : number +>b1 : number +>a1 : number +>[1] : [number] +>1 : 1 + + const [a2, b2 = 1 + a2] = [1]; +>a2 : number +>b2 : number +>1 + a2 : number +>1 : 1 +>a2 : number +>[1] : [number] +>1 : 1 +} + +// To be inferred as `string` +function f2() { +>f2 : () => void + + const [a1, b1 = a1] = ['hi']; +>a1 : string +>b1 : string +>a1 : string +>['hi'] : [string] +>'hi' : "hi" + + const [a2, b2 = a2 + '!'] = ['hi']; +>a2 : string +>b2 : string +>a2 + '!' : string +>a2 : string +>'!' : "!" +>['hi'] : [string] +>'hi' : "hi" +} + +// To be inferred as `string | number` +function f3() { +>f3 : () => void + + const [a1, b1 = a1] = ['hi', 1]; +>a1 : string +>b1 : string | number +>a1 : string +>['hi', 1] : [string, number] +>'hi' : "hi" +>1 : 1 + + const [a2, b2 = a2 + '!'] = ['hi', 1]; +>a2 : string +>b2 : string | number +>a2 + '!' : string +>a2 : string +>'!' : "!" +>['hi', 1] : [string, number] +>'hi' : "hi" +>1 : 1 +} + +// Based on comment: +// - https://github.com/microsoft/TypeScript/issues/49989#issuecomment-1852694486 +declare const yadda: [number, number] | undefined +>yadda : [number, number] + +function f4() { +>f4 : () => void + + const [ a, b = a ] = yadda ?? []; +>a : number +>b : number +>a : number +>yadda ?? [] : [number, number] | [] +>yadda : [number, number] +>[] : [] +} + diff --git a/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment9SiblingInitializer.js b/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment9SiblingInitializer.js new file mode 100644 index 0000000000000..92a7a56842bfc --- /dev/null +++ b/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment9SiblingInitializer.js @@ -0,0 +1,48 @@ +//// [tests/cases/conformance/es6/destructuring/destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts] //// + +//// [destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts] +// To be inferred as `number` +function f1() { + const { a1, b1 = a1 } = { a1: 1 }; + const { a2, b2 = 1 + a2 } = { a2: 1 }; +} + +// To be inferred as `string` +function f2() { + const { a1, b1 = a1 } = { a1: 'hi' }; + const { a2, b2 = a2 + '!' } = { a2: 'hi' }; +} + +// To be inferred as `string | number` +function f3() { + const { a1, b1 = a1 } = { a1: 'hi', b1: 1 }; + const { a2, b2 = a2 + '!' } = { a2: 'hi', b2: 1 }; +} + +// Based on comment: +// - https://github.com/microsoft/TypeScript/issues/49989#issuecomment-1852694486 +declare const yadda: { a?: number, b?: number } | undefined +function f4() { + const { a, b = a } = yadda ?? {}; +} + + +//// [destructuringObjectBindingPatternAndAssignment9SiblingInitializer.js] +// To be inferred as `number` +function f1() { + var _a = { a1: 1 }, a1 = _a.a1, _b = _a.b1, b1 = _b === void 0 ? a1 : _b; + var _c = { a2: 1 }, a2 = _c.a2, _d = _c.b2, b2 = _d === void 0 ? 1 + a2 : _d; +} +// To be inferred as `string` +function f2() { + var _a = { a1: 'hi' }, a1 = _a.a1, _b = _a.b1, b1 = _b === void 0 ? a1 : _b; + var _c = { a2: 'hi' }, a2 = _c.a2, _d = _c.b2, b2 = _d === void 0 ? a2 + '!' : _d; +} +// To be inferred as `string | number` +function f3() { + var _a = { a1: 'hi', b1: 1 }, a1 = _a.a1, _b = _a.b1, b1 = _b === void 0 ? a1 : _b; + var _c = { a2: 'hi', b2: 1 }, a2 = _c.a2, _d = _c.b2, b2 = _d === void 0 ? a2 + '!' : _d; +} +function f4() { + var _a = yadda !== null && yadda !== void 0 ? yadda : {}, a = _a.a, _b = _a.b, b = _b === void 0 ? a : _b; +} diff --git a/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment9SiblingInitializer.symbols b/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment9SiblingInitializer.symbols new file mode 100644 index 0000000000000..3c76a5d2b045d --- /dev/null +++ b/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment9SiblingInitializer.symbols @@ -0,0 +1,73 @@ +//// [tests/cases/conformance/es6/destructuring/destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts] //// + +=== destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts === +// To be inferred as `number` +function f1() { +>f1 : Symbol(f1, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 0, 0)) + + const { a1, b1 = a1 } = { a1: 1 }; +>a1 : Symbol(a1, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 2, 11)) +>b1 : Symbol(b1, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 2, 15)) +>a1 : Symbol(a1, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 2, 11)) +>a1 : Symbol(a1, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 2, 29)) + + const { a2, b2 = 1 + a2 } = { a2: 1 }; +>a2 : Symbol(a2, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 3, 11)) +>b2 : Symbol(b2, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 3, 15)) +>a2 : Symbol(a2, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 3, 11)) +>a2 : Symbol(a2, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 3, 33)) +} + +// To be inferred as `string` +function f2() { +>f2 : Symbol(f2, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 4, 1)) + + const { a1, b1 = a1 } = { a1: 'hi' }; +>a1 : Symbol(a1, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 8, 11)) +>b1 : Symbol(b1, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 8, 15)) +>a1 : Symbol(a1, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 8, 11)) +>a1 : Symbol(a1, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 8, 29)) + + const { a2, b2 = a2 + '!' } = { a2: 'hi' }; +>a2 : Symbol(a2, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 9, 11)) +>b2 : Symbol(b2, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 9, 15)) +>a2 : Symbol(a2, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 9, 11)) +>a2 : Symbol(a2, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 9, 35)) +} + +// To be inferred as `string | number` +function f3() { +>f3 : Symbol(f3, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 10, 1)) + + const { a1, b1 = a1 } = { a1: 'hi', b1: 1 }; +>a1 : Symbol(a1, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 14, 11)) +>b1 : Symbol(b1, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 14, 15)) +>a1 : Symbol(a1, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 14, 11)) +>a1 : Symbol(a1, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 14, 29)) +>b1 : Symbol(b1, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 14, 39)) + + const { a2, b2 = a2 + '!' } = { a2: 'hi', b2: 1 }; +>a2 : Symbol(a2, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 15, 11)) +>b2 : Symbol(b2, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 15, 15)) +>a2 : Symbol(a2, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 15, 11)) +>a2 : Symbol(a2, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 15, 35)) +>b2 : Symbol(b2, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 15, 45)) +} + +// Based on comment: +// - https://github.com/microsoft/TypeScript/issues/49989#issuecomment-1852694486 +declare const yadda: { a?: number, b?: number } | undefined +>yadda : Symbol(yadda, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 20, 13)) +>a : Symbol(a, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 20, 22)) +>b : Symbol(b, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 20, 34)) + +function f4() { +>f4 : Symbol(f4, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 20, 59)) + + const { a, b = a } = yadda ?? {}; +>a : Symbol(a, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 22, 11)) +>b : Symbol(b, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 22, 14)) +>a : Symbol(a, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 22, 11)) +>yadda : Symbol(yadda, Decl(destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts, 20, 13)) +} + diff --git a/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment9SiblingInitializer.types b/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment9SiblingInitializer.types new file mode 100644 index 0000000000000..c5ebaabe82453 --- /dev/null +++ b/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment9SiblingInitializer.types @@ -0,0 +1,95 @@ +//// [tests/cases/conformance/es6/destructuring/destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts] //// + +=== destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts === +// To be inferred as `number` +function f1() { +>f1 : () => void + + const { a1, b1 = a1 } = { a1: 1 }; +>a1 : number +>b1 : number +>a1 : number +>{ a1: 1 } : { a1: number; b1?: number; } +>a1 : number +>1 : 1 + + const { a2, b2 = 1 + a2 } = { a2: 1 }; +>a2 : number +>b2 : number +>1 + a2 : number +>1 : 1 +>a2 : number +>{ a2: 1 } : { a2: number; b2?: number; } +>a2 : number +>1 : 1 +} + +// To be inferred as `string` +function f2() { +>f2 : () => void + + const { a1, b1 = a1 } = { a1: 'hi' }; +>a1 : string +>b1 : string +>a1 : string +>{ a1: 'hi' } : { a1: string; b1?: string; } +>a1 : string +>'hi' : "hi" + + const { a2, b2 = a2 + '!' } = { a2: 'hi' }; +>a2 : string +>b2 : string +>a2 + '!' : string +>a2 : string +>'!' : "!" +>{ a2: 'hi' } : { a2: string; b2?: string; } +>a2 : string +>'hi' : "hi" +} + +// To be inferred as `string | number` +function f3() { +>f3 : () => void + + const { a1, b1 = a1 } = { a1: 'hi', b1: 1 }; +>a1 : string +>b1 : string | number +>a1 : string +>{ a1: 'hi', b1: 1 } : { a1: string; b1?: number; } +>a1 : string +>'hi' : "hi" +>b1 : number +>1 : 1 + + const { a2, b2 = a2 + '!' } = { a2: 'hi', b2: 1 }; +>a2 : string +>b2 : string | number +>a2 + '!' : string +>a2 : string +>'!' : "!" +>{ a2: 'hi', b2: 1 } : { a2: string; b2?: number; } +>a2 : string +>'hi' : "hi" +>b2 : number +>1 : 1 +} + +// Based on comment: +// - https://github.com/microsoft/TypeScript/issues/49989#issuecomment-1852694486 +declare const yadda: { a?: number, b?: number } | undefined +>yadda : { a?: number; b?: number; } +>a : number +>b : number + +function f4() { +>f4 : () => void + + const { a, b = a } = yadda ?? {}; +>a : number +>b : number +>a : number +>yadda ?? {} : { a?: number; b?: number; } +>yadda : { a?: number; b?: number; } +>{} : {} +} + diff --git a/tests/cases/conformance/es6/destructuring/destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts b/tests/cases/conformance/es6/destructuring/destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts new file mode 100644 index 0000000000000..6183e22b61fbf --- /dev/null +++ b/tests/cases/conformance/es6/destructuring/destructuringArrayBindingPatternAndAssignment5SiblingInitializer.ts @@ -0,0 +1,26 @@ +// @noImplicitAny: true + +// To be inferred as `number` +function f1() { + const [a1, b1 = a1] = [1]; + const [a2, b2 = 1 + a2] = [1]; +} + +// To be inferred as `string` +function f2() { + const [a1, b1 = a1] = ['hi']; + const [a2, b2 = a2 + '!'] = ['hi']; +} + +// To be inferred as `string | number` +function f3() { + const [a1, b1 = a1] = ['hi', 1]; + const [a2, b2 = a2 + '!'] = ['hi', 1]; +} + +// Based on comment: +// - https://github.com/microsoft/TypeScript/issues/49989#issuecomment-1852694486 +declare const yadda: [number, number] | undefined +function f4() { + const [ a, b = a ] = yadda ?? []; +} diff --git a/tests/cases/conformance/es6/destructuring/destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts b/tests/cases/conformance/es6/destructuring/destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts new file mode 100644 index 0000000000000..d4d5cd7c6cd4d --- /dev/null +++ b/tests/cases/conformance/es6/destructuring/destructuringObjectBindingPatternAndAssignment9SiblingInitializer.ts @@ -0,0 +1,26 @@ +// @noImplicitAny: true + +// To be inferred as `number` +function f1() { + const { a1, b1 = a1 } = { a1: 1 }; + const { a2, b2 = 1 + a2 } = { a2: 1 }; +} + +// To be inferred as `string` +function f2() { + const { a1, b1 = a1 } = { a1: 'hi' }; + const { a2, b2 = a2 + '!' } = { a2: 'hi' }; +} + +// To be inferred as `string | number` +function f3() { + const { a1, b1 = a1 } = { a1: 'hi', b1: 1 }; + const { a2, b2 = a2 + '!' } = { a2: 'hi', b2: 1 }; +} + +// Based on comment: +// - https://github.com/microsoft/TypeScript/issues/49989#issuecomment-1852694486 +declare const yadda: { a?: number, b?: number } | undefined +function f4() { + const { a, b = a } = yadda ?? {}; +} From 72d497352fe5aa747ee9008395fe5999bb63a356 Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Thu, 11 Jan 2024 01:35:04 +0200 Subject: [PATCH 04/11] fix(55994): Type-check Import Attributes in static imports (#56034) --- src/compiler/checker.ts | 46 +++ src/compiler/types.ts | 1 + src/compiler/utilities.ts | 6 + src/harness/fourslashImpl.ts | 8 +- src/services/completions.ts | 18 + tests/baselines/reference/api/typescript.d.ts | 1 + ...completionListForImportAttributes.baseline | 334 ++++++++++++++++++ .../completionPropertyFromConstraint.baseline | 2 +- .../importAssertionNonstring.errors.txt | 30 +- .../reference/importAttributes6.errors.txt | 30 +- .../reference/importAttributes9.errors.txt | 41 +++ .../baselines/reference/importAttributes9.js | 36 ++ .../reference/importAttributes9.symbols | 40 +++ .../reference/importAttributes9.types | 45 +++ .../importAttributes/importAttributes9.ts | 22 ++ .../completionListForImportAttributes.ts | 22 ++ 16 files changed, 678 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/completionListForImportAttributes.baseline create mode 100644 tests/baselines/reference/importAttributes9.errors.txt create mode 100644 tests/baselines/reference/importAttributes9.js create mode 100644 tests/baselines/reference/importAttributes9.symbols create mode 100644 tests/baselines/reference/importAttributes9.types create mode 100644 tests/cases/conformance/importAttributes/importAttributes9.ts create mode 100644 tests/cases/fourslash/completionListForImportAttributes.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4f80bcb783442..5bc244600b953 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -325,6 +325,7 @@ import { getModeForUsageLocation, getModifiers, getModuleInstanceState, + getNameFromImportAttribute, getNameFromIndexInfo, getNameOfDeclaration, getNameOfExpando, @@ -407,6 +408,7 @@ import { IdentifierTypePredicate, idText, IfStatement, + ImportAttribute, ImportAttributes, ImportCall, ImportClause, @@ -553,6 +555,7 @@ import { isIdentifierTypePredicate, isIdentifierTypeReference, isIfStatement, + isImportAttributes, isImportCall, isImportClause, isImportDeclaration, @@ -2179,6 +2182,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { var deferredGlobalImportMetaType: ObjectType; var deferredGlobalImportMetaExpressionType: ObjectType; var deferredGlobalImportCallOptionsType: ObjectType | undefined; + var deferredGlobalImportAttributesType: ObjectType | undefined; var deferredGlobalDisposableType: ObjectType | undefined; var deferredGlobalAsyncDisposableType: ObjectType | undefined; var deferredGlobalExtractSymbol: Symbol | undefined; @@ -11555,6 +11559,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return widenTypeForVariableLikeDeclaration(getTypeForVariableLikeDeclaration(declaration, /*includeOptionality*/ true, CheckMode.Normal), declaration, reportErrors); } + function getTypeFromImportAttributes(node: ImportAttributes): Type { + const links = getNodeLinks(node); + if (!links.resolvedType) { + const symbol = createSymbol(SymbolFlags.ObjectLiteral, InternalSymbolName.ImportAttributes); + const members = createSymbolTable(); + forEach(node.elements, attr => { + const member = createSymbol(SymbolFlags.Property, getNameFromImportAttribute(attr)); + member.parent = symbol; + member.links.type = checkImportAttribute(attr); + member.links.target = member; + members.set(member.escapedName, member); + }); + const type = createAnonymousType(symbol, members, emptyArray, emptyArray, emptyArray); + type.objectFlags |= ObjectFlags.ObjectLiteral | ObjectFlags.NonInferrableType; + links.resolvedType = type; + } + return links.resolvedType; + } + function isGlobalSymbolConstructor(node: Node) { const symbol = getSymbolOfNode(node); const globalSymbol = getGlobalESSymbolConstructorTypeSymbol(/*reportErrors*/ false); @@ -16417,6 +16440,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return (deferredGlobalImportCallOptionsType ||= getGlobalType("ImportCallOptions" as __String, /*arity*/ 0, reportErrors)) || emptyObjectType; } + function getGlobalImportAttributesType(reportErrors: boolean) { + return (deferredGlobalImportAttributesType ||= getGlobalType("ImportAttributes" as __String, /*arity*/ 0, reportErrors)) || emptyObjectType; + } + function getGlobalESSymbolConstructorSymbol(reportErrors: boolean): Symbol | undefined { return deferredGlobalESSymbolConstructorSymbol ||= getGlobalValueSymbol("Symbol" as __String, reportErrors); } @@ -30904,6 +30931,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.JsxOpeningElement: case SyntaxKind.JsxSelfClosingElement: return getContextualJsxElementAttributesType(parent as JsxOpeningLikeElement, contextFlags); + case SyntaxKind.ImportAttribute: + return getContextualImportAttributeType(parent as ImportAttribute); } return undefined; } @@ -30950,6 +30979,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } + function getContextualImportAttributeType(node: ImportAttribute) { + return getTypeOfPropertyOfContextualType(getGlobalImportAttributesType(/*reportErrors*/ false), getNameFromImportAttribute(node)); + } + function getContextualJsxElementAttributesType(node: JsxOpeningLikeElement, contextFlags: ContextFlags | undefined) { if (isJsxOpeningElement(node) && contextFlags !== ContextFlags.Completions) { const index = findContextualNode(node.parent, /*includeCaches*/ !contextFlags); @@ -45991,6 +46024,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkImportAttributes(declaration: ImportDeclaration | ExportDeclaration) { const node = declaration.attributes; if (node) { + const importAttributesType = getGlobalImportAttributesType(/*reportErrors*/ true); + if (importAttributesType !== emptyObjectType) { + checkTypeAssignableTo(getTypeFromImportAttributes(node), getNullableType(importAttributesType, TypeFlags.Undefined), node); + } + const validForTypeAttributes = isExclusivelyTypeOnlyImportOrExport(declaration); const override = getResolutionModeOverride(node, validForTypeAttributes ? grammarErrorOnNode : undefined); const isImportAttributes = declaration.attributes.token === SyntaxKind.WithKeyword; @@ -46020,6 +46058,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } + function checkImportAttribute(node: ImportAttribute) { + return getRegularTypeOfLiteralType(checkExpressionCached(node.value)); + } + function checkImportDeclaration(node: ImportDeclaration) { if (checkGrammarModuleElementContext(node, isInJSFile(node) ? Diagnostics.An_import_declaration_can_only_be_used_at_the_top_level_of_a_module : Diagnostics.An_import_declaration_can_only_be_used_at_the_top_level_of_a_namespace_or_module)) { // If we hit an import declaration in an illegal context, just bail out to avoid cascading errors. @@ -47700,6 +47742,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return checkMetaPropertyKeyword(node.parent); } + if (isImportAttributes(node)) { + return getGlobalImportAttributesType(/*reportErrors*/ false); + } + return errorType; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 23873de4824a8..e25a8d0bceb6b 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -5971,6 +5971,7 @@ export const enum InternalSymbolName { Default = "default", // Default export symbol (technically not wholly internal, but included here for usability) This = "this", InstantiationExpression = "__instantiationExpression", // Instantiation expressions + ImportAttributes = "__importAttributes", } /** diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 36fb67860a32b..ba51391f71916 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -220,6 +220,7 @@ import { idText, IfStatement, ignoredPaths, + ImportAttribute, ImportCall, ImportClause, ImportDeclaration, @@ -10656,3 +10657,8 @@ export function replaceFirstStar(s: string, replacement: string): string { // Attempt to defeat this analysis by indirectly calling the method. return stringReplace.call(s, "*", replacement); } + +/** @internal */ +export function getNameFromImportAttribute(node: ImportAttribute) { + return isIdentifier(node.name) ? node.name.escapedText : escapeLeadingUnderscores(node.name.text); +} diff --git a/src/harness/fourslashImpl.ts b/src/harness/fourslashImpl.ts index 2842fd6896a5f..7d9d3c6c9f9bb 100644 --- a/src/harness/fourslashImpl.ts +++ b/src/harness/fourslashImpl.ts @@ -2448,7 +2448,13 @@ export class TestState { const annotations = this.annotateContentWithTooltips( result, "completions", - item => item.optionalReplacementSpan, + item => { + if (item.optionalReplacementSpan) { + const { start, length } = item.optionalReplacementSpan; + return start && length === 0 ? { start, length: 1 } : item.optionalReplacementSpan; + } + return undefined; + }, item => item.entries?.flatMap( entry => diff --git a/src/services/completions.ts b/src/services/completions.ts index 155d048562b78..234a4072c76a5 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -95,6 +95,7 @@ import { getLineStartPositionForPosition, getLocalSymbolForExportDefault, getModifiers, + getNameFromImportAttribute, getNameOfDeclaration, getNameTable, getNewLineCharacter, @@ -169,6 +170,7 @@ import { isIdentifier, isIdentifierText, isImportableFile, + isImportAttributes, isImportDeclaration, isImportEqualsDeclaration, isImportKeyword, @@ -3768,6 +3770,7 @@ function getCompletionData( || tryGetObjectLikeCompletionSymbols() || tryGetImportCompletionSymbols() || tryGetImportOrExportClauseCompletionSymbols() + || tryGetImportAttributesCompletionSymbols() || tryGetLocalNamedExportCompletionSymbols() || tryGetConstructorCompletion() || tryGetClassLikeCompletionSymbols() @@ -4455,6 +4458,21 @@ function getCompletionData( return GlobalsSearch.Success; } + /** + * import { x } from "foo" with { | } + */ + function tryGetImportAttributesCompletionSymbols(): GlobalsSearch { + if (contextToken === undefined) return GlobalsSearch.Continue; + + const importAttributes = contextToken.kind === SyntaxKind.OpenBraceToken || contextToken.kind === SyntaxKind.CommaToken ? tryCast(contextToken.parent, isImportAttributes) : + contextToken.kind === SyntaxKind.ColonToken ? tryCast(contextToken.parent.parent, isImportAttributes) : undefined; + if (importAttributes === undefined) return GlobalsSearch.Continue; + + const existing = new Set(importAttributes.elements.map(getNameFromImportAttribute)); + symbols = filter(typeChecker.getTypeAtLocation(importAttributes).getApparentProperties(), attr => !existing.has(attr.escapedName)); + return GlobalsSearch.Success; + } + /** * Adds local declarations for completions in named exports: * diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index fe1a414ef6f51..6cd050855d321 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -7076,6 +7076,7 @@ declare namespace ts { Default = "default", This = "this", InstantiationExpression = "__instantiationExpression", + ImportAttributes = "__importAttributes", } /** * This represents a string whose leading underscore have been escaped by adding extra leading underscores. diff --git a/tests/baselines/reference/completionListForImportAttributes.baseline b/tests/baselines/reference/completionListForImportAttributes.baseline new file mode 100644 index 0000000000000..2629823d733cd --- /dev/null +++ b/tests/baselines/reference/completionListForImportAttributes.baseline @@ -0,0 +1,334 @@ +// === Completions === +=== /tests/cases/fourslash/./b.ts === +// declare global { +// interface ImportAttributes { +// type: "json", +// "resolution-mode": "import" +// } +// } +// const str = "hello"; +// +// import * as t1 from "./a" with { }; +// ^ +// | ---------------------------------------------------------------------- +// | (property) ImportAttributes["resolution-mode"]: "import" +// | (property) ImportAttributes.type: "json" +// | ---------------------------------------------------------------------- +// import * as t2 from "./a" with { type: "" }; +// ^ +// | ---------------------------------------------------------------------- +// | json +// | ---------------------------------------------------------------------- +// import * as t3 from "./a" with { type: "json", }; +// ^ +// | ---------------------------------------------------------------------- +// | (property) ImportAttributes["resolution-mode"]: "import" +// | ---------------------------------------------------------------------- +// import * as t4 from "./a" with { type: }; +// ^ +// | ---------------------------------------------------------------------- +// | "json" +// | (property) ImportAttributes["resolution-mode"]: "import" +// | ---------------------------------------------------------------------- + +[ + { + "marker": { + "fileName": "/tests/cases/fourslash/./b.ts", + "position": 171, + "name": "1" + }, + "item": { + "flags": 0, + "isGlobalCompletion": false, + "isMemberCompletion": false, + "isNewIdentifierLocation": false, + "entries": [ + { + "name": "resolution-mode", + "kind": "property", + "kindModifiers": "declare", + "sortText": "11", + "displayParts": [ + { + "text": "(", + "kind": "punctuation" + }, + { + "text": "property", + "kind": "text" + }, + { + "text": ")", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "ImportAttributes", + "kind": "interfaceName" + }, + { + "text": "[", + "kind": "punctuation" + }, + { + "text": "\"resolution-mode\"", + "kind": "stringLiteral" + }, + { + "text": "]", + "kind": "punctuation" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "\"import\"", + "kind": "stringLiteral" + } + ], + "documentation": [] + }, + { + "name": "type", + "kind": "property", + "kindModifiers": "declare", + "sortText": "11", + "displayParts": [ + { + "text": "(", + "kind": "punctuation" + }, + { + "text": "property", + "kind": "text" + }, + { + "text": ")", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "ImportAttributes", + "kind": "interfaceName" + }, + { + "text": ".", + "kind": "punctuation" + }, + { + "text": "type", + "kind": "propertyName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "\"json\"", + "kind": "stringLiteral" + } + ], + "documentation": [] + } + ] + } + }, + { + "marker": { + "fileName": "/tests/cases/fourslash/./b.ts", + "position": 215, + "name": "2" + }, + "item": { + "isGlobalCompletion": false, + "isMemberCompletion": false, + "isNewIdentifierLocation": false, + "optionalReplacementSpan": { + "start": 215, + "length": 0 + }, + "entries": [ + { + "name": "json", + "kindModifiers": "", + "kind": "string", + "sortText": "11", + "replacementSpan": { + "start": 215, + "length": 0 + }, + "displayParts": [ + { + "text": "json", + "kind": "text" + } + ] + } + ] + } + }, + { + "marker": { + "fileName": "/tests/cases/fourslash/./b.ts", + "position": 267, + "name": "3" + }, + "item": { + "flags": 0, + "isGlobalCompletion": false, + "isMemberCompletion": false, + "isNewIdentifierLocation": false, + "entries": [ + { + "name": "resolution-mode", + "kind": "property", + "kindModifiers": "declare", + "sortText": "11", + "displayParts": [ + { + "text": "(", + "kind": "punctuation" + }, + { + "text": "property", + "kind": "text" + }, + { + "text": ")", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "ImportAttributes", + "kind": "interfaceName" + }, + { + "text": "[", + "kind": "punctuation" + }, + { + "text": "\"resolution-mode\"", + "kind": "stringLiteral" + }, + { + "text": "]", + "kind": "punctuation" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "\"import\"", + "kind": "stringLiteral" + } + ], + "documentation": [] + } + ] + } + }, + { + "marker": { + "fileName": "/tests/cases/fourslash/./b.ts", + "position": 310, + "name": "4" + }, + "item": { + "flags": 0, + "isGlobalCompletion": false, + "isMemberCompletion": false, + "isNewIdentifierLocation": false, + "entries": [ + { + "name": "\"json\"", + "kind": "string", + "kindModifiers": "", + "sortText": "11", + "displayParts": [ + { + "text": "\"json\"", + "kind": "stringLiteral" + } + ] + }, + { + "name": "resolution-mode", + "kind": "property", + "kindModifiers": "declare", + "sortText": "11", + "displayParts": [ + { + "text": "(", + "kind": "punctuation" + }, + { + "text": "property", + "kind": "text" + }, + { + "text": ")", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "ImportAttributes", + "kind": "interfaceName" + }, + { + "text": "[", + "kind": "punctuation" + }, + { + "text": "\"resolution-mode\"", + "kind": "stringLiteral" + }, + { + "text": "]", + "kind": "punctuation" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "\"import\"", + "kind": "stringLiteral" + } + ], + "documentation": [] + } + ] + } + } +] \ No newline at end of file diff --git a/tests/baselines/reference/completionPropertyFromConstraint.baseline b/tests/baselines/reference/completionPropertyFromConstraint.baseline index 210d913dabee3..a31f3e0646c99 100644 --- a/tests/baselines/reference/completionPropertyFromConstraint.baseline +++ b/tests/baselines/reference/completionPropertyFromConstraint.baseline @@ -17,7 +17,7 @@ // createStyles({ // x: { // '': '' -// +// ^ // | ---------------------------------------------------------------------- // | (property) alignContent?: string // | (property) alignItems?: string diff --git a/tests/baselines/reference/importAssertionNonstring.errors.txt b/tests/baselines/reference/importAssertionNonstring.errors.txt index bb55e2a13bc1d..81a06f278084d 100644 --- a/tests/baselines/reference/importAssertionNonstring.errors.txt +++ b/tests/baselines/reference/importAssertionNonstring.errors.txt @@ -1,13 +1,29 @@ +mod.mts(1,37): error TS2322: Type '{ field: 0; }' is not assignable to type 'ImportAttributes'. + Property 'field' is incompatible with index signature. + Type 'number' is not assignable to type 'string'. mod.mts(1,52): error TS2837: Import assertion values must be string literal expressions. mod.mts(3,52): error TS2837: Import assertion values must be string literal expressions. +mod.mts(5,37): error TS2322: Type '{ field: RegExp; }' is not assignable to type 'ImportAttributes'. + Property 'field' is incompatible with index signature. + Type 'RegExp' is not assignable to type 'string'. mod.mts(5,52): error TS2837: Import assertion values must be string literal expressions. +mod.mts(7,37): error TS2322: Type '{ field: string[]; }' is not assignable to type 'ImportAttributes'. + Property 'field' is incompatible with index signature. + Type 'string[]' is not assignable to type 'string'. mod.mts(7,52): error TS2837: Import assertion values must be string literal expressions. +mod.mts(9,37): error TS2322: Type '{ field: { a: number; }; }' is not assignable to type 'ImportAttributes'. + Property 'field' is incompatible with index signature. + Type '{ a: number; }' is not assignable to type 'string'. mod.mts(9,52): error TS2837: Import assertion values must be string literal expressions. mod.mts(11,66): error TS2837: Import assertion values must be string literal expressions. -==== mod.mts (6 errors) ==== +==== mod.mts (10 errors) ==== import * as thing1 from "./mod.mjs" assert {field: 0}; + ~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type '{ field: 0; }' is not assignable to type 'ImportAttributes'. +!!! error TS2322: Property 'field' is incompatible with index signature. +!!! error TS2322: Type 'number' is not assignable to type 'string'. ~ !!! error TS2837: Import assertion values must be string literal expressions. @@ -16,14 +32,26 @@ mod.mts(11,66): error TS2837: Import assertion values must be string literal exp !!! error TS2837: Import assertion values must be string literal expressions. import * as thing3 from "./mod.mjs" assert {field: /a/g}; + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type '{ field: RegExp; }' is not assignable to type 'ImportAttributes'. +!!! error TS2322: Property 'field' is incompatible with index signature. +!!! error TS2322: Type 'RegExp' is not assignable to type 'string'. ~~~~ !!! error TS2837: Import assertion values must be string literal expressions. import * as thing4 from "./mod.mjs" assert {field: ["a"]}; + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type '{ field: string[]; }' is not assignable to type 'ImportAttributes'. +!!! error TS2322: Property 'field' is incompatible with index signature. +!!! error TS2322: Type 'string[]' is not assignable to type 'string'. ~~~~~ !!! error TS2837: Import assertion values must be string literal expressions. import * as thing5 from "./mod.mjs" assert {field: { a: 0 }}; + ~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type '{ field: { a: number; }; }' is not assignable to type 'ImportAttributes'. +!!! error TS2322: Property 'field' is incompatible with index signature. +!!! error TS2322: Type '{ a: number; }' is not assignable to type 'string'. ~~~~~~~~ !!! error TS2837: Import assertion values must be string literal expressions. diff --git a/tests/baselines/reference/importAttributes6.errors.txt b/tests/baselines/reference/importAttributes6.errors.txt index 18fa0ba6b693d..f2f160a4bd0e1 100644 --- a/tests/baselines/reference/importAttributes6.errors.txt +++ b/tests/baselines/reference/importAttributes6.errors.txt @@ -1,25 +1,53 @@ +mod.mts(1,37): error TS2322: Type '{ field: 0; }' is not assignable to type 'ImportAttributes'. + Property 'field' is incompatible with index signature. + Type 'number' is not assignable to type 'string'. mod.mts(1,51): error TS2858: Import attribute values must be string literal expressions. mod.mts(2,51): error TS2858: Import attribute values must be string literal expressions. +mod.mts(3,37): error TS2322: Type '{ field: RegExp; }' is not assignable to type 'ImportAttributes'. + Property 'field' is incompatible with index signature. + Type 'RegExp' is not assignable to type 'string'. mod.mts(3,51): error TS2858: Import attribute values must be string literal expressions. +mod.mts(4,37): error TS2322: Type '{ field: string[]; }' is not assignable to type 'ImportAttributes'. + Property 'field' is incompatible with index signature. + Type 'string[]' is not assignable to type 'string'. mod.mts(4,51): error TS2858: Import attribute values must be string literal expressions. +mod.mts(5,37): error TS2322: Type '{ field: { a: number; }; }' is not assignable to type 'ImportAttributes'. + Property 'field' is incompatible with index signature. + Type '{ a: number; }' is not assignable to type 'string'. mod.mts(5,51): error TS2858: Import attribute values must be string literal expressions. mod.mts(6,65): error TS2858: Import attribute values must be string literal expressions. -==== mod.mts (6 errors) ==== +==== mod.mts (10 errors) ==== import * as thing1 from "./mod.mjs" with { field: 0 }; + ~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type '{ field: 0; }' is not assignable to type 'ImportAttributes'. +!!! error TS2322: Property 'field' is incompatible with index signature. +!!! error TS2322: Type 'number' is not assignable to type 'string'. ~ !!! error TS2858: Import attribute values must be string literal expressions. import * as thing2 from "./mod.mjs" with { field: `a` }; ~~~ !!! error TS2858: Import attribute values must be string literal expressions. import * as thing3 from "./mod.mjs" with { field: /a/g }; + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type '{ field: RegExp; }' is not assignable to type 'ImportAttributes'. +!!! error TS2322: Property 'field' is incompatible with index signature. +!!! error TS2322: Type 'RegExp' is not assignable to type 'string'. ~~~~ !!! error TS2858: Import attribute values must be string literal expressions. import * as thing4 from "./mod.mjs" with { field: ["a"] }; + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type '{ field: string[]; }' is not assignable to type 'ImportAttributes'. +!!! error TS2322: Property 'field' is incompatible with index signature. +!!! error TS2322: Type 'string[]' is not assignable to type 'string'. ~~~~~ !!! error TS2858: Import attribute values must be string literal expressions. import * as thing5 from "./mod.mjs" with { field: { a: 0 } }; + ~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type '{ field: { a: number; }; }' is not assignable to type 'ImportAttributes'. +!!! error TS2322: Property 'field' is incompatible with index signature. +!!! error TS2322: Type '{ a: number; }' is not assignable to type 'string'. ~~~~~~~~ !!! error TS2858: Import attribute values must be string literal expressions. import * as thing6 from "./mod.mjs" with { type: "json", field: 0..toString() }; diff --git a/tests/baselines/reference/importAttributes9.errors.txt b/tests/baselines/reference/importAttributes9.errors.txt new file mode 100644 index 0000000000000..59006e6b71ed8 --- /dev/null +++ b/tests/baselines/reference/importAttributes9.errors.txt @@ -0,0 +1,41 @@ +b.ts(7,27): error TS2322: Type '{ type: "not-json"; }' is not assignable to type 'ImportAttributes'. + Types of property 'type' are incompatible. + Type '"not-json"' is not assignable to type '"json"'. +b.ts(11,25): error TS2322: Type '{ with: { type: "not-json"; }; }' is not assignable to type 'ImportCallOptions'. + The types of 'with.type' are incompatible between these types. + Type '"not-json"' is not assignable to type '"json"'. + + +==== ./a.ts (0 errors) ==== + export default {}; + +==== ./b.ts (2 errors) ==== + declare global { + interface ImportAttributes { + type: "json" + } + } + + import * as ns from "./a" with { type: "not-json" }; + ~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type '{ type: "not-json"; }' is not assignable to type 'ImportAttributes'. +!!! error TS2322: Types of property 'type' are incompatible. +!!! error TS2322: Type '"not-json"' is not assignable to type '"json"'. + void ns; + + async function f() { + await import("./a", { + ~ + with: { + ~~~~~~~~~~~~~~~ + type: "not-json", + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + }, + ~~~~~~~~~~ + }); + ~~~~~ +!!! error TS2322: Type '{ with: { type: "not-json"; }; }' is not assignable to type 'ImportCallOptions'. +!!! error TS2322: The types of 'with.type' are incompatible between these types. +!!! error TS2322: Type '"not-json"' is not assignable to type '"json"'. + } + \ No newline at end of file diff --git a/tests/baselines/reference/importAttributes9.js b/tests/baselines/reference/importAttributes9.js new file mode 100644 index 0000000000000..10e5230e2b697 --- /dev/null +++ b/tests/baselines/reference/importAttributes9.js @@ -0,0 +1,36 @@ +//// [tests/cases/conformance/importAttributes/importAttributes9.ts] //// + +//// [a.ts] +export default {}; + +//// [b.ts] +declare global { + interface ImportAttributes { + type: "json" + } +} + +import * as ns from "./a" with { type: "not-json" }; +void ns; + +async function f() { + await import("./a", { + with: { + type: "not-json", + }, + }); +} + + +//// [a.js] +export default {}; +//// [b.js] +import * as ns from "./a" with { type: "not-json" }; +void ns; +async function f() { + await import("./a", { + with: { + type: "not-json", + }, + }); +} diff --git a/tests/baselines/reference/importAttributes9.symbols b/tests/baselines/reference/importAttributes9.symbols new file mode 100644 index 0000000000000..bb0975afa8dc0 --- /dev/null +++ b/tests/baselines/reference/importAttributes9.symbols @@ -0,0 +1,40 @@ +//// [tests/cases/conformance/importAttributes/importAttributes9.ts] //// + +=== ./a.ts === + +export default {}; + +=== ./b.ts === +declare global { +>global : Symbol(global, Decl(b.ts, 0, 0)) + + interface ImportAttributes { +>ImportAttributes : Symbol(ImportAttributes, Decl(lib.es5.d.ts, --, --), Decl(b.ts, 0, 16)) + + type: "json" +>type : Symbol(ImportAttributes.type, Decl(b.ts, 1, 33)) + } +} + +import * as ns from "./a" with { type: "not-json" }; +>ns : Symbol(ns, Decl(b.ts, 6, 6)) + +void ns; +>ns : Symbol(ns, Decl(b.ts, 6, 6)) + +async function f() { +>f : Symbol(f, Decl(b.ts, 7, 8)) + + await import("./a", { +>"./a" : Symbol(ns, Decl(a.ts, 0, 0)) + + with: { +>with : Symbol(with, Decl(b.ts, 10, 25)) + + type: "not-json", +>type : Symbol(type, Decl(b.ts, 11, 15)) + + }, + }); +} + diff --git a/tests/baselines/reference/importAttributes9.types b/tests/baselines/reference/importAttributes9.types new file mode 100644 index 0000000000000..c17e4150005ec --- /dev/null +++ b/tests/baselines/reference/importAttributes9.types @@ -0,0 +1,45 @@ +//// [tests/cases/conformance/importAttributes/importAttributes9.ts] //// + +=== ./a.ts === +export default {}; +>{} : {} + +=== ./b.ts === +declare global { +>global : any + + interface ImportAttributes { + type: "json" +>type : "json" + } +} + +import * as ns from "./a" with { type: "not-json" }; +>ns : typeof ns +>type : any + +void ns; +>void ns : undefined +>ns : typeof ns + +async function f() { +>f : () => Promise + + await import("./a", { +>await import("./a", { with: { type: "not-json", }, }) : typeof ns +>import("./a", { with: { type: "not-json", }, }) : Promise +>"./a" : "./a" +>{ with: { type: "not-json", }, } : { with: { type: "not-json"; }; } + + with: { +>with : { type: "not-json"; } +>{ type: "not-json", } : { type: "not-json"; } + + type: "not-json", +>type : "not-json" +>"not-json" : "not-json" + + }, + }); +} + diff --git a/tests/cases/conformance/importAttributes/importAttributes9.ts b/tests/cases/conformance/importAttributes/importAttributes9.ts new file mode 100644 index 0000000000000..9b7138659272b --- /dev/null +++ b/tests/cases/conformance/importAttributes/importAttributes9.ts @@ -0,0 +1,22 @@ +// @module: esnext +// @target: esnext +// @filename: ./a.ts +export default {}; + +// @filename: ./b.ts +declare global { + interface ImportAttributes { + type: "json" + } +} + +import * as ns from "./a" with { type: "not-json" }; +void ns; + +async function f() { + await import("./a", { + with: { + type: "not-json", + }, + }); +} diff --git a/tests/cases/fourslash/completionListForImportAttributes.ts b/tests/cases/fourslash/completionListForImportAttributes.ts new file mode 100644 index 0000000000000..f96c4c9d27f3a --- /dev/null +++ b/tests/cases/fourslash/completionListForImportAttributes.ts @@ -0,0 +1,22 @@ +/// + +// @module: esnext +// @target: esnext +// @filename: ./a.ts +////export default {}; + +// @filename: ./b.ts +////declare global { +//// interface ImportAttributes { +//// type: "json", +//// "resolution-mode": "import" +//// } +////} +////const str = "hello"; +//// +////import * as t1 from "./a" with { /*1*/ }; +////import * as t2 from "./a" with { type: "/*2*/" }; +////import * as t3 from "./a" with { type: "json", /*3*/ }; +////import * as t4 from "./a" with { type: /*4*/ }; + +verify.baselineCompletions(); From 7398b8ed2e8d9643d75a7e0fddec8b2044eceeb5 Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Thu, 11 Jan 2024 06:14:39 +0000 Subject: [PATCH 05/11] Update package-lock.json --- package-lock.json | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4e5578da633f4..53da7df4f8c6c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -638,13 +638,13 @@ } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.13", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", - "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^2.0.1", - "debug": "^4.1.1", + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", "minimatch": "^3.0.5" }, "engines": { @@ -687,9 +687,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", - "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", "dev": true }, "node_modules/@istanbuljs/schema": { @@ -1011,9 +1011,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.10.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.8.tgz", - "integrity": "sha512-f8nQs3cLxbAFc00vEU59yf9UyGUftkPaLGfvbVOIDdx2i1b8epBqj2aNGyP19fiyXWvlmZ7qC1XLjAzw/OKIeA==", + "version": "20.11.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.0.tgz", + "integrity": "sha512-o9bjXmDNcF7GbM4CNQpmi+TutCgap/K3w1JyKgxAjqx41zp9qlIAVFi0IhCNsJcXolEqLWhbFbEeL0PvYm4pcQ==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -4431,13 +4431,13 @@ "dev": true }, "@humanwhocodes/config-array": { - "version": "0.11.13", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", - "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", "dev": true, "requires": { - "@humanwhocodes/object-schema": "^2.0.1", - "debug": "^4.1.1", + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", "minimatch": "^3.0.5" }, "dependencies": { @@ -4469,9 +4469,9 @@ "dev": true }, "@humanwhocodes/object-schema": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", - "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", "dev": true }, "@istanbuljs/schema": { @@ -4736,9 +4736,9 @@ "dev": true }, "@types/node": { - "version": "20.10.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.8.tgz", - "integrity": "sha512-f8nQs3cLxbAFc00vEU59yf9UyGUftkPaLGfvbVOIDdx2i1b8epBqj2aNGyP19fiyXWvlmZ7qC1XLjAzw/OKIeA==", + "version": "20.11.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.0.tgz", + "integrity": "sha512-o9bjXmDNcF7GbM4CNQpmi+TutCgap/K3w1JyKgxAjqx41zp9qlIAVFi0IhCNsJcXolEqLWhbFbEeL0PvYm4pcQ==", "dev": true, "requires": { "undici-types": "~5.26.4" From e76972562dafff8acf04c72bf6c30c938c95b55a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Thu, 11 Jan 2024 19:31:11 +0100 Subject: [PATCH 06/11] Fxied declaration emit for JS files when `module.exports` is assigned a non-alias value and when it has extra type members (#56243) --- src/compiler/checker.ts | 16 +++++++-- ...ssignedFunctionWithExtraTypedefsMembers.js | 35 +++++++++++++++++++ ...edFunctionWithExtraTypedefsMembers.symbols | 18 ++++++++++ ...gnedFunctionWithExtraTypedefsMembers.types | 20 +++++++++++ ...ssignedFunctionWithExtraTypedefsMembers.ts | 16 +++++++++ 5 files changed, 102 insertions(+), 3 deletions(-) create mode 100644 tests/baselines/reference/jsDeclarationEmitExportAssignedFunctionWithExtraTypedefsMembers.js create mode 100644 tests/baselines/reference/jsDeclarationEmitExportAssignedFunctionWithExtraTypedefsMembers.symbols create mode 100644 tests/baselines/reference/jsDeclarationEmitExportAssignedFunctionWithExtraTypedefsMembers.types create mode 100644 tests/cases/compiler/jsDeclarationEmitExportAssignedFunctionWithExtraTypedefsMembers.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5bc244600b953..105765f11b322 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8758,7 +8758,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { }); let addingDeclare = !bundled; const exportEquals = symbolTable.get(InternalSymbolName.ExportEquals); - if (exportEquals && symbolTable.size > 1 && exportEquals.flags & SymbolFlags.Alias) { + if (exportEquals && symbolTable.size > 1 && exportEquals.flags & (SymbolFlags.Alias | SymbolFlags.Module)) { symbolTable = createSymbolTable(); // Remove extraneous elements from root symbol table (they'll be mixed back in when the target of the `export=` is looked up) symbolTable.set(InternalSymbolName.ExportEquals, exportEquals); @@ -9291,8 +9291,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getNamespaceMembersForSerialization(symbol: Symbol) { - const exports = getExportsOfSymbol(symbol); - return !exports ? [] : filter(arrayFrom(exports.values()), m => isNamespaceMember(m) && isIdentifierText(m.escapedName as string, ScriptTarget.ESNext)); + let exports = arrayFrom(getExportsOfSymbol(symbol).values()); + const merged = getMergedSymbol(symbol); + if (merged !== symbol) { + const membersSet = new Set(exports); + for (const exported of getExportsOfSymbol(merged).values()) { + if (!(getSymbolFlags(resolveSymbol(exported)) & SymbolFlags.Value)) { + membersSet.add(exported); + } + } + exports = arrayFrom(membersSet); + } + return filter(exports, m => isNamespaceMember(m) && isIdentifierText(m.escapedName as string, ScriptTarget.ESNext)); } function isTypeOnlyNamespace(symbol: Symbol) { diff --git a/tests/baselines/reference/jsDeclarationEmitExportAssignedFunctionWithExtraTypedefsMembers.js b/tests/baselines/reference/jsDeclarationEmitExportAssignedFunctionWithExtraTypedefsMembers.js new file mode 100644 index 0000000000000..1e02c358656d6 --- /dev/null +++ b/tests/baselines/reference/jsDeclarationEmitExportAssignedFunctionWithExtraTypedefsMembers.js @@ -0,0 +1,35 @@ +//// [tests/cases/compiler/jsDeclarationEmitExportAssignedFunctionWithExtraTypedefsMembers.ts] //// + +//// [index.js] +/** + * @typedef Options + * @property {string} opt + */ + +/** + * @param {Options} options + */ +module.exports = function loader(options) {} + + +//// [index.js] +"use strict"; +/** + * @typedef Options + * @property {string} opt + */ +/** + * @param {Options} options + */ +module.exports = function loader(options) { }; + + +//// [index.d.ts] +declare namespace _exports { + export { Options }; +} +declare function _exports(options: Options): void; +export = _exports; +type Options = { + opt: string; +}; diff --git a/tests/baselines/reference/jsDeclarationEmitExportAssignedFunctionWithExtraTypedefsMembers.symbols b/tests/baselines/reference/jsDeclarationEmitExportAssignedFunctionWithExtraTypedefsMembers.symbols new file mode 100644 index 0000000000000..dc72dbfb0b17d --- /dev/null +++ b/tests/baselines/reference/jsDeclarationEmitExportAssignedFunctionWithExtraTypedefsMembers.symbols @@ -0,0 +1,18 @@ +//// [tests/cases/compiler/jsDeclarationEmitExportAssignedFunctionWithExtraTypedefsMembers.ts] //// + +=== index.js === +/** + * @typedef Options + * @property {string} opt + */ + +/** + * @param {Options} options + */ +module.exports = function loader(options) {} +>module.exports : Symbol(module.exports, Decl(index.js, 0, 0)) +>module : Symbol(export=, Decl(index.js, 0, 0)) +>exports : Symbol(export=, Decl(index.js, 0, 0)) +>loader : Symbol(loader, Decl(index.js, 8, 16)) +>options : Symbol(options, Decl(index.js, 8, 33)) + diff --git a/tests/baselines/reference/jsDeclarationEmitExportAssignedFunctionWithExtraTypedefsMembers.types b/tests/baselines/reference/jsDeclarationEmitExportAssignedFunctionWithExtraTypedefsMembers.types new file mode 100644 index 0000000000000..4343d7b088e5b --- /dev/null +++ b/tests/baselines/reference/jsDeclarationEmitExportAssignedFunctionWithExtraTypedefsMembers.types @@ -0,0 +1,20 @@ +//// [tests/cases/compiler/jsDeclarationEmitExportAssignedFunctionWithExtraTypedefsMembers.ts] //// + +=== index.js === +/** + * @typedef Options + * @property {string} opt + */ + +/** + * @param {Options} options + */ +module.exports = function loader(options) {} +>module.exports = function loader(options) {} : (options: Options) => void +>module.exports : (options: Options) => void +>module : { exports: (options: Options) => void; } +>exports : (options: Options) => void +>function loader(options) {} : (options: Options) => void +>loader : (options: Options) => void +>options : Options + diff --git a/tests/cases/compiler/jsDeclarationEmitExportAssignedFunctionWithExtraTypedefsMembers.ts b/tests/cases/compiler/jsDeclarationEmitExportAssignedFunctionWithExtraTypedefsMembers.ts new file mode 100644 index 0000000000000..2a2a69bd22e70 --- /dev/null +++ b/tests/cases/compiler/jsDeclarationEmitExportAssignedFunctionWithExtraTypedefsMembers.ts @@ -0,0 +1,16 @@ +// @strict: true +// @checkJs: true +// @declaration: true +// @outDir: out + +// @filename: index.js + +/** + * @typedef Options + * @property {string} opt + */ + +/** + * @param {Options} options + */ +module.exports = function loader(options) {} From 9a0c7b1c3bccb4525995a2f241a0b3fae0ddf404 Mon Sep 17 00:00:00 2001 From: Titian Cernicova-Dragomir Date: Thu, 11 Jan 2024 19:08:55 +0000 Subject: [PATCH 07/11] Reduce file system calls during test setup. (#56791) --- src/compiler/sys.ts | 2 ++ src/harness/harnessIO.ts | 51 ++++++++----------------------- src/harness/runnerbase.ts | 5 ++- src/testRunner/compilerRunner.ts | 8 ++--- src/testRunner/fourslashRunner.ts | 3 +- src/testRunner/parallel/host.ts | 3 +- src/testRunner/projectsRunner.ts | 39 +++++++++++++++++------ src/testRunner/runner.ts | 4 +-- 8 files changed, 53 insertions(+), 62 deletions(-) diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index be0d973032edf..32d7af09c03e7 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -1445,6 +1445,7 @@ export interface System { realpath?(path: string): string; /** @internal */ getEnvironmentVariable(name: string): string; /** @internal */ tryEnableSourceMapsForHost?(): void; + /** @internal */ getAccessibleFileSystemEntries?(path: string): FileSystemEntries; /** @internal */ debugMode?: boolean; setTimeout?(callback: (...args: any[]) => void, ms: number, ...args: any[]): any; clearTimeout?(timeoutId: any): void; @@ -1553,6 +1554,7 @@ export let sys: System = (() => { resolvePath: path => _path.resolve(path), fileExists, directoryExists, + getAccessibleFileSystemEntries, createDirectory(directoryName: string) { if (!nodeSystem.directoryExists(directoryName)) { // Wrapped in a try-catch to prevent crashing if we are in a race diff --git a/src/harness/harnessIO.ts b/src/harness/harnessIO.ts index 298d8310161a3..7b7506d30f5bb 100644 --- a/src/harness/harnessIO.ts +++ b/src/harness/harnessIO.ts @@ -25,7 +25,7 @@ export interface IO { fileExists(fileName: string): boolean; directoryExists(path: string): boolean; deleteFile(fileName: string): void; - enumerateTestFiles(runner: RunnerBase): (string | FileBasedTest)[]; + enumerateTestFiles(runner: RunnerBase): string[]; listFiles(path: string, filter?: RegExp, options?: { recursive?: boolean; }): string[]; log(text: string): void; args(): string[]; @@ -84,55 +84,28 @@ function createNodeIO(): IO { return runner.getTestFiles(); } - function listFiles(path: string, spec: RegExp, options: { recursive?: boolean; } = {}) { + function listFiles(path: string, spec: RegExp | undefined, options: { recursive?: boolean; } = {}) { function filesInFolder(folder: string): string[] { + const { files, directories } = ts.sys.getAccessibleFileSystemEntries!(folder); let paths: string[] = []; - - for (const file of fs.readdirSync(folder)) { + for (const file of files) { const pathToFile = pathModule.join(folder, file); - if (!fs.existsSync(pathToFile)) continue; // ignore invalid symlinks - const stat = fs.statSync(pathToFile); - if (options.recursive && stat.isDirectory()) { - paths = paths.concat(filesInFolder(pathToFile)); - } - else if (stat.isFile() && (!spec || file.match(spec))) { + if (!spec || file.match(spec)) { paths.push(pathToFile); } } - + if (options.recursive) { + for (const dir of directories) { + const pathToDir = pathModule.join(folder, dir); + paths = paths.concat(filesInFolder(pathToDir)); + } + } return paths; } return filesInFolder(path); } - function getAccessibleFileSystemEntries(dirname: string): ts.FileSystemEntries { - try { - const entries: string[] = fs.readdirSync(dirname || ".").sort(ts.sys.useCaseSensitiveFileNames ? ts.compareStringsCaseSensitive : ts.compareStringsCaseInsensitive); - const files: string[] = []; - const directories: string[] = []; - for (const entry of entries) { - if (entry === "." || entry === "..") continue; - const name = vpath.combine(dirname, entry); - try { - const stat = fs.statSync(name); - if (!stat) continue; - if (stat.isFile()) { - files.push(entry); - } - else if (stat.isDirectory()) { - directories.push(entry); - } - } - catch { /*ignore*/ } - } - return { files, directories }; - } - catch (e) { - return { files: [], directories: [] }; - } - } - function createDirectory(path: string) { try { fs.mkdirSync(path); @@ -170,7 +143,7 @@ function createNodeIO(): IO { getWorkspaceRoot: () => workspaceRoot, exit: exitCode => ts.sys.exit(exitCode), readDirectory: (path, extension, exclude, include, depth) => ts.sys.readDirectory(path, extension, exclude, include, depth), - getAccessibleFileSystemEntries, + getAccessibleFileSystemEntries: ts.sys.getAccessibleFileSystemEntries!, tryEnableSourceMapsForHost: () => ts.sys.tryEnableSourceMapsForHost && ts.sys.tryEnableSourceMapsForHost(), getMemoryUsage: () => ts.sys.getMemoryUsage && ts.sys.getMemoryUsage(), getEnvironmentVariable: name => ts.sys.getEnvironmentVariable(name), diff --git a/src/harness/runnerbase.ts b/src/harness/runnerbase.ts index 1877d763e9fea..fbe8f32b299f7 100644 --- a/src/harness/runnerbase.ts +++ b/src/harness/runnerbase.ts @@ -1,5 +1,4 @@ import { - FileBasedTest, IO, userSpecifiedRoot, } from "./_namespaces/Harness"; @@ -22,7 +21,7 @@ export function setShardId(id: number) { export abstract class RunnerBase { // contains the tests to run - public tests: (string | FileBasedTest)[] = []; + public tests: string[] = []; /** Add a source file to the runner's list of tests that need to be initialized with initializeTests */ public addTest(fileName: string) { @@ -35,7 +34,7 @@ export abstract class RunnerBase { abstract kind(): TestRunnerKind; - abstract enumerateTestFiles(): (string | FileBasedTest)[]; + abstract enumerateTestFiles(): string[]; getTestFiles(): ReturnType { const all = this.enumerateTestFiles(); diff --git a/src/testRunner/compilerRunner.ts b/src/testRunner/compilerRunner.ts index b3c86f6390ff8..b5d08ca8f2e03 100644 --- a/src/testRunner/compilerRunner.ts +++ b/src/testRunner/compilerRunner.ts @@ -51,9 +51,10 @@ export class CompilerBaselineRunner extends RunnerBase { return this.testSuiteName; } + private testFiles: string[] | undefined; public enumerateTestFiles() { // see also: `enumerateTestFiles` in tests/webTestServer.ts - return this.enumerateFiles(this.basePath, /\.tsx?$/, { recursive: true }).map(CompilerTest.getConfigurations); + return this.testFiles ??= this.enumerateFiles(this.basePath, /\.tsx?$/, { recursive: true }); } public initializeTests() { @@ -64,9 +65,8 @@ export class CompilerBaselineRunner extends RunnerBase { // this will set up a series of describe/it blocks to run between the setup and cleanup phases const files = this.tests.length > 0 ? this.tests : IO.enumerateTestFiles(this); - files.forEach(test => { - const file = typeof test === "string" ? test : test.file; - this.checkTestCodeOutput(vpath.normalizeSeparators(file), typeof test === "string" ? CompilerTest.getConfigurations(test) : test); + files.forEach(file => { + this.checkTestCodeOutput(vpath.normalizeSeparators(file), CompilerTest.getConfigurations(file)); }); }); } diff --git a/src/testRunner/fourslashRunner.ts b/src/testRunner/fourslashRunner.ts index 689cdcceca9f4..6fd61eb0e3b08 100644 --- a/src/testRunner/fourslashRunner.ts +++ b/src/testRunner/fourslashRunner.ts @@ -41,8 +41,7 @@ export class FourSlashRunner extends RunnerBase { } describe(this.testSuiteName + " tests", () => { - this.tests.forEach(test => { - const file = typeof test === "string" ? test : test.file; + this.tests.forEach(file => { describe(file, () => { let fn = ts.normalizeSlashes(file); const justName = fn.replace(/^.*[\\/]/, ""); diff --git a/src/testRunner/parallel/host.ts b/src/testRunner/parallel/host.ts index 126e06cff4e4a..ca8ffb563d355 100644 --- a/src/testRunner/parallel/host.ts +++ b/src/testRunner/parallel/host.ts @@ -217,8 +217,7 @@ export function start() { console.log("Discovering runner-based tests..."); const discoverStart = +(new Date()); for (const runner of runners) { - for (const test of runner.getTestFiles()) { - const file = typeof test === "string" ? test : test.file; + for (const file of runner.getTestFiles()) { let size: number; if (!perfData) { try { diff --git a/src/testRunner/projectsRunner.ts b/src/testRunner/projectsRunner.ts index dd2a2f40f6ead..bedb3343e7c50 100644 --- a/src/testRunner/projectsRunner.ts +++ b/src/testRunner/projectsRunner.ts @@ -54,7 +54,7 @@ export class ProjectRunner extends Harness.RunnerBase { describe("projects tests", () => { const tests = this.tests.length === 0 ? this.enumerateTestFiles() : this.tests; for (const test of tests) { - this.runProjectTestCase(typeof test === "string" ? test : test.file); + this.runProjectTestCase(test); } }); } @@ -202,15 +202,36 @@ class ProjectTestCase { throw assert(false, "Testcase: " + testCaseFileName + " does not contain valid json format: " + e.message); } - const fs = vfs.createFromFileSystem(Harness.IO, /*ignoreCase*/ false); - fs.mountSync(vpath.resolve(Harness.IO.getWorkspaceRoot(), "tests"), vpath.combine(vfs.srcFolder, "tests"), vfs.createResolver(Harness.IO)); - fs.mkdirpSync(vpath.combine(vfs.srcFolder, testCase.projectRoot)); - fs.chdir(vpath.combine(vfs.srcFolder, testCase.projectRoot)); - fs.makeReadonly(); - + function makeFileSystem() { + const fs = vfs.createFromFileSystem(Harness.IO, /*ignoreCase*/ false); + fs.mountSync(vpath.resolve(Harness.IO.getWorkspaceRoot(), "tests"), vpath.combine(vfs.srcFolder, "tests"), vfs.createResolver(Harness.IO)); + fs.mkdirpSync(vpath.combine(vfs.srcFolder, testCase.projectRoot)); + fs.chdir(vpath.combine(vfs.srcFolder, testCase.projectRoot)); + fs.makeReadonly(); + return fs; + } + let fs: vfs.FileSystem | undefined; return [ - { name: `@module: commonjs`, payload: { testCase, moduleKind: ts.ModuleKind.CommonJS, vfs: fs } }, - { name: `@module: amd`, payload: { testCase, moduleKind: ts.ModuleKind.AMD, vfs: fs } }, + { + name: `@module: commonjs`, + payload: { + testCase, + moduleKind: ts.ModuleKind.CommonJS, + get vfs() { + return fs ??= makeFileSystem(); + }, + }, + }, + { + name: `@module: amd`, + payload: { + testCase, + moduleKind: ts.ModuleKind.AMD, + get vfs() { + return fs ??= makeFileSystem(); + }, + }, + }, ]; } diff --git a/src/testRunner/runner.ts b/src/testRunner/runner.ts index d8b7bbed8a501..ecf720996e43e 100644 --- a/src/testRunner/runner.ts +++ b/src/testRunner/runner.ts @@ -27,8 +27,7 @@ function runTests(runners: RunnerBase[]) { const dupes: [string, string][] = []; for (const runner of runners) { if (runner instanceof CompilerBaselineRunner || runner instanceof FourSlashRunner) { - for (const sf of runner.enumerateTestFiles()) { - const full = typeof sf === "string" ? sf : sf.file; + for (const full of runner.enumerateTestFiles()) { const base = vpath.basename(full).toLowerCase(); // allow existing dupes in fourslash/shims and fourslash/server if (seen.has(base) && !/fourslash\/(shim|server)/.test(full)) { @@ -191,7 +190,6 @@ function handleTestConfig() { case "fourslash-generated": runners.push(new GeneratedFourslashRunner(FourSlash.FourSlashTestType.Native)); break; - break; } } } From 1717826b6efdfa945bb9f2cf95bd4c442e77012e Mon Sep 17 00:00:00 2001 From: Sviatoslav Zaytsev Date: Fri, 12 Jan 2024 01:14:03 +0600 Subject: [PATCH 08/11] fix(51225): Go-to-definition on case or default should jump to the containing switch statement if available. (#51236) Co-authored-by: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> --- src/services/findAllReferences.ts | 14 ++++-- src/services/goToDefinition.ts | 47 +++++++++++++++++-- .../goToDefinitionSwitchCase1.baseline.jsonc | 17 +++++++ .../goToDefinitionSwitchCase2.baseline.jsonc | 17 +++++++ .../goToDefinitionSwitchCase3.baseline.jsonc | 45 ++++++++++++++++++ .../goToDefinitionSwitchCase4.baseline.jsonc | 21 +++++++++ .../goToDefinitionSwitchCase5.baseline.jsonc | 16 +++++++ .../goToDefinitionSwitchCase6.baseline.jsonc | 47 +++++++++++++++++++ .../goToDefinitionSwitchCase7.baseline.jsonc | 18 +++++++ .../fourslash/goToDefinitionSwitchCase1.ts | 7 +++ .../fourslash/goToDefinitionSwitchCase2.ts | 7 +++ .../fourslash/goToDefinitionSwitchCase3.ts | 11 +++++ .../fourslash/goToDefinitionSwitchCase4.ts | 11 +++++ .../fourslash/goToDefinitionSwitchCase5.ts | 5 ++ .../fourslash/goToDefinitionSwitchCase6.ts | 7 +++ .../fourslash/goToDefinitionSwitchCase7.ts | 7 +++ 16 files changed, 291 insertions(+), 6 deletions(-) create mode 100644 tests/baselines/reference/goToDefinitionSwitchCase1.baseline.jsonc create mode 100644 tests/baselines/reference/goToDefinitionSwitchCase2.baseline.jsonc create mode 100644 tests/baselines/reference/goToDefinitionSwitchCase3.baseline.jsonc create mode 100644 tests/baselines/reference/goToDefinitionSwitchCase4.baseline.jsonc create mode 100644 tests/baselines/reference/goToDefinitionSwitchCase5.baseline.jsonc create mode 100644 tests/baselines/reference/goToDefinitionSwitchCase6.baseline.jsonc create mode 100644 tests/baselines/reference/goToDefinitionSwitchCase7.baseline.jsonc create mode 100644 tests/cases/fourslash/goToDefinitionSwitchCase1.ts create mode 100644 tests/cases/fourslash/goToDefinitionSwitchCase2.ts create mode 100644 tests/cases/fourslash/goToDefinitionSwitchCase3.ts create mode 100644 tests/cases/fourslash/goToDefinitionSwitchCase4.ts create mode 100644 tests/cases/fourslash/goToDefinitionSwitchCase5.ts create mode 100644 tests/cases/fourslash/goToDefinitionSwitchCase6.ts create mode 100644 tests/cases/fourslash/goToDefinitionSwitchCase7.ts diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 06aea522ce9be..826dfe9eb591b 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -234,6 +234,7 @@ import { StringLiteralLike, stripQuotes, SuperContainer, + SwitchStatement, Symbol, SymbolDisplay, SymbolDisplayPart, @@ -406,7 +407,7 @@ function getContextNodeForNodeEntry(node: Node): ContextNode | undefined { } /** @internal */ -export function getContextNode(node: NamedDeclaration | BinaryExpression | ForInOrOfStatement | undefined): ContextNode | undefined { +export function getContextNode(node: NamedDeclaration | BinaryExpression | ForInOrOfStatement | SwitchStatement | undefined): ContextNode | undefined { if (!node) return undefined; switch (node.kind) { case SyntaxKind.VariableDeclaration: @@ -451,14 +452,18 @@ export function getContextNode(node: NamedDeclaration | BinaryExpression | ForIn findAncestor(node.parent, node => isBinaryExpression(node) || isForInOrOfStatement(node)) as BinaryExpression | ForInOrOfStatement, ) : node; - + case SyntaxKind.SwitchStatement: + return { + start: find(node.getChildren(node.getSourceFile()), node => node.kind === SyntaxKind.SwitchKeyword)!, + end: (node as SwitchStatement).caseBlock, + }; default: return node; } } /** @internal */ -export function toContextSpan(textSpan: TextSpan, sourceFile: SourceFile, context?: ContextNode): { contextSpan: TextSpan; } | undefined { +export function toContextSpan(textSpan: TextSpan, sourceFile: SourceFile, context: ContextNode | undefined): { contextSpan: TextSpan; } | undefined { if (!context) return undefined; const contextSpan = isContextWithStartAndEndNode(context) ? getTextSpan(context.start, sourceFile, context.end) : @@ -874,6 +879,9 @@ function getTextSpan(node: Node, sourceFile: SourceFile, endNode?: Node): TextSp start += 1; end -= 1; } + if (endNode?.kind === SyntaxKind.CaseBlock) { + end = endNode.getFullStart(); + } return createTextSpanFromBounds(start, end); } diff --git a/src/services/goToDefinition.ts b/src/services/goToDefinition.ts index c603c6c7bab3d..79afa66a4d3a6 100644 --- a/src/services/goToDefinition.ts +++ b/src/services/goToDefinition.ts @@ -53,6 +53,7 @@ import { isClassStaticBlockDeclaration, isConstructorDeclaration, isDeclarationFileName, + isDefaultClause, isExternalModuleNameRelative, isFunctionLike, isFunctionLikeDeclaration, @@ -69,6 +70,7 @@ import { isPropertyName, isRightSideOfPropertyAccess, isStaticModifier, + isSwitchStatement, isTypeAliasDeclaration, isTypeReferenceNode, isVariableDeclaration, @@ -91,6 +93,7 @@ import { skipTrivia, some, SourceFile, + SwitchStatement, Symbol, SymbolDisplay, SymbolFlags, @@ -105,6 +108,9 @@ import { TypeReference, unescapeLeadingUnderscores, } from "./_namespaces/ts"; +import { + isContextWithStartAndEndNode, +} from "./_namespaces/ts.FindAllReferences"; /** @internal */ export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile, position: number, searchOtherFilesOnly?: boolean, stopAtAlias?: boolean): readonly DefinitionInfo[] | undefined { @@ -133,9 +139,26 @@ export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile return label ? [createDefinitionInfoFromName(typeChecker, label, ScriptElementKind.label, node.text, /*containerName*/ undefined!)] : undefined; // TODO: GH#18217 } - if (node.kind === SyntaxKind.ReturnKeyword) { - const functionDeclaration = findAncestor(node.parent, n => isClassStaticBlockDeclaration(n) ? "quit" : isFunctionLikeDeclaration(n)) as FunctionLikeDeclaration | undefined; - return functionDeclaration ? [createDefinitionFromSignatureDeclaration(typeChecker, functionDeclaration)] : undefined; + switch (node.kind) { + case SyntaxKind.ReturnKeyword: + const functionDeclaration = findAncestor(node.parent, n => + isClassStaticBlockDeclaration(n) + ? "quit" + : isFunctionLikeDeclaration(n)) as FunctionLikeDeclaration | undefined; + return functionDeclaration + ? [createDefinitionFromSignatureDeclaration(typeChecker, functionDeclaration)] + : undefined; + case SyntaxKind.DefaultKeyword: + if (!isDefaultClause(node.parent)) { + break; + } + // falls through + case SyntaxKind.CaseKeyword: + const switchStatement = findAncestor(node.parent, isSwitchStatement); + if (switchStatement) { + return [createDefinitionInfoFromSwitch(switchStatement, sourceFile)]; + } + break; } if (node.kind === SyntaxKind.AwaitKeyword) { @@ -634,6 +657,24 @@ function createDefinitionInfoFromName(checker: TypeChecker, declaration: Declara }; } +function createDefinitionInfoFromSwitch(statement: SwitchStatement, sourceFile: SourceFile): DefinitionInfo { + const keyword = FindAllReferences.getContextNode(statement)!; + const textSpan = createTextSpanFromNode(isContextWithStartAndEndNode(keyword) ? keyword.start : keyword, sourceFile); + return { + fileName: sourceFile.fileName, + textSpan, + kind: ScriptElementKind.keyword, + name: "switch", + containerKind: undefined!, + containerName: "", + ...FindAllReferences.toContextSpan(textSpan, sourceFile, keyword), + isLocal: true, + isAmbient: false, + unverified: false, + failedAliasResolution: undefined, + }; +} + function isDefinitionVisible(checker: TypeChecker, declaration: Declaration): boolean { if (checker.isDeclarationVisible(declaration)) return true; if (!declaration.parent) return false; diff --git a/tests/baselines/reference/goToDefinitionSwitchCase1.baseline.jsonc b/tests/baselines/reference/goToDefinitionSwitchCase1.baseline.jsonc new file mode 100644 index 0000000000000..c92107111f2a0 --- /dev/null +++ b/tests/baselines/reference/goToDefinitionSwitchCase1.baseline.jsonc @@ -0,0 +1,17 @@ +// === goToDefinition === +// === /tests/cases/fourslash/goToDefinitionSwitchCase1.ts === +// <|[|switch|] (null )|> { +// /*GOTO DEF*/case null: break; +// } + + // === Details === + [ + { + "kind": "keyword", + "name": "switch", + "containerName": "", + "isLocal": true, + "isAmbient": false, + "unverified": false + } + ] \ No newline at end of file diff --git a/tests/baselines/reference/goToDefinitionSwitchCase2.baseline.jsonc b/tests/baselines/reference/goToDefinitionSwitchCase2.baseline.jsonc new file mode 100644 index 0000000000000..318e346d9398f --- /dev/null +++ b/tests/baselines/reference/goToDefinitionSwitchCase2.baseline.jsonc @@ -0,0 +1,17 @@ +// === goToDefinition === +// === /tests/cases/fourslash/goToDefinitionSwitchCase2.ts === +// <|[|switch|] (null)|> { +// /*GOTO DEF*/default: break; +// } + + // === Details === + [ + { + "kind": "keyword", + "name": "switch", + "containerName": "", + "isLocal": true, + "isAmbient": false, + "unverified": false + } + ] \ No newline at end of file diff --git a/tests/baselines/reference/goToDefinitionSwitchCase3.baseline.jsonc b/tests/baselines/reference/goToDefinitionSwitchCase3.baseline.jsonc new file mode 100644 index 0000000000000..022a654b71cdd --- /dev/null +++ b/tests/baselines/reference/goToDefinitionSwitchCase3.baseline.jsonc @@ -0,0 +1,45 @@ +// === goToDefinition === +// === /tests/cases/fourslash/goToDefinitionSwitchCase3.ts === +// <|[|switch|] (null)|> { +// /*GOTO DEF*/default: { +// switch (null) { +// default: break; +// } +// }; +// } + + // === Details === + [ + { + "kind": "keyword", + "name": "switch", + "containerName": "", + "isLocal": true, + "isAmbient": false, + "unverified": false + } + ] + + + +// === goToDefinition === +// === /tests/cases/fourslash/goToDefinitionSwitchCase3.ts === +// switch (null) { +// default: { +// <|[|switch|] (null)|> { +// /*GOTO DEF*/default: break; +// } +// }; +// } + + // === Details === + [ + { + "kind": "keyword", + "name": "switch", + "containerName": "", + "isLocal": true, + "isAmbient": false, + "unverified": false + } + ] \ No newline at end of file diff --git a/tests/baselines/reference/goToDefinitionSwitchCase4.baseline.jsonc b/tests/baselines/reference/goToDefinitionSwitchCase4.baseline.jsonc new file mode 100644 index 0000000000000..12b7b46563064 --- /dev/null +++ b/tests/baselines/reference/goToDefinitionSwitchCase4.baseline.jsonc @@ -0,0 +1,21 @@ +// === goToDefinition === +// === /tests/cases/fourslash/goToDefinitionSwitchCase4.ts === +// switch (null) { +// case null: break; +// } +// +// <|[|switch|] (null)|> { +// /*GOTO DEF*/case null: break; +// } + + // === Details === + [ + { + "kind": "keyword", + "name": "switch", + "containerName": "", + "isLocal": true, + "isAmbient": false, + "unverified": false + } + ] \ No newline at end of file diff --git a/tests/baselines/reference/goToDefinitionSwitchCase5.baseline.jsonc b/tests/baselines/reference/goToDefinitionSwitchCase5.baseline.jsonc new file mode 100644 index 0000000000000..1277d0b5dd945 --- /dev/null +++ b/tests/baselines/reference/goToDefinitionSwitchCase5.baseline.jsonc @@ -0,0 +1,16 @@ +// === goToDefinition === +// === /tests/cases/fourslash/goToDefinitionSwitchCase5.ts === +// [|export /*GOTO DEF*/default {}|] + + // === Details === + [ + { + "kind": "property", + "name": "default", + "containerName": "\"/tests/cases/fourslash/goToDefinitionSwitchCase5\"", + "isLocal": true, + "isAmbient": false, + "unverified": false, + "failedAliasResolution": false + } + ] \ No newline at end of file diff --git a/tests/baselines/reference/goToDefinitionSwitchCase6.baseline.jsonc b/tests/baselines/reference/goToDefinitionSwitchCase6.baseline.jsonc new file mode 100644 index 0000000000000..3f6894203dc69 --- /dev/null +++ b/tests/baselines/reference/goToDefinitionSwitchCase6.baseline.jsonc @@ -0,0 +1,47 @@ +// === goToDefinition === +// === /tests/cases/fourslash/goToDefinitionSwitchCase6.ts === +// export default { /*GOTO DEF*/[|{| textSpan: true |}case|] }; +// default; +// case 42; + + // === Details === + [ + { + "kind": "property", + "name": "case", + "containerName": "__object", + "isLocal": true, + "isAmbient": false, + "unverified": false, + "failedAliasResolution": false + } + ] + + + +// === goToDefinition === +// === /tests/cases/fourslash/goToDefinitionSwitchCase6.ts === +// [|export default { case }; +// /*GOTO DEF*/default; +// case 42;|] + + // === Details === + [ + { + "kind": "module", + "name": "\"/tests/cases/fourslash/goToDefinitionSwitchCase6\"", + "containerName": "", + "isLocal": false, + "isAmbient": false, + "unverified": false, + "failedAliasResolution": false + } + ] + + + +// === goToDefinition === +// === /tests/cases/fourslash/goToDefinitionSwitchCase6.ts === +// export default { case }; +// default; +// /*GOTO DEF*/case 42; \ No newline at end of file diff --git a/tests/baselines/reference/goToDefinitionSwitchCase7.baseline.jsonc b/tests/baselines/reference/goToDefinitionSwitchCase7.baseline.jsonc new file mode 100644 index 0000000000000..bf6c818dc552e --- /dev/null +++ b/tests/baselines/reference/goToDefinitionSwitchCase7.baseline.jsonc @@ -0,0 +1,18 @@ +// === goToDefinition === +// === /tests/cases/fourslash/goToDefinitionSwitchCase7.ts === +// switch (null) { +// case null: +// [|export /*GOTO DEF*/default 123;|] + + // === Details === + [ + { + "kind": "var", + "name": "default", + "containerName": "", + "isLocal": true, + "isAmbient": false, + "unverified": false, + "failedAliasResolution": false + } + ] \ No newline at end of file diff --git a/tests/cases/fourslash/goToDefinitionSwitchCase1.ts b/tests/cases/fourslash/goToDefinitionSwitchCase1.ts new file mode 100644 index 0000000000000..86a695f1ecf3b --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionSwitchCase1.ts @@ -0,0 +1,7 @@ +/// + +////switch (null ) { +//// [|/*start*/case|] null: break; +////} + +verify.baselineGoToDefinition("start"); diff --git a/tests/cases/fourslash/goToDefinitionSwitchCase2.ts b/tests/cases/fourslash/goToDefinitionSwitchCase2.ts new file mode 100644 index 0000000000000..3d480dd198afb --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionSwitchCase2.ts @@ -0,0 +1,7 @@ +/// + +////switch (null) { +//// [|/*start*/default|]: break; +////} + +verify.baselineGoToDefinition("start"); diff --git a/tests/cases/fourslash/goToDefinitionSwitchCase3.ts b/tests/cases/fourslash/goToDefinitionSwitchCase3.ts new file mode 100644 index 0000000000000..0dce0e7c153fc --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionSwitchCase3.ts @@ -0,0 +1,11 @@ +/// + +////switch (null) { +//// [|/*start1*/default|]: { +//// switch (null) { +//// [|/*start2*/default|]: break; +//// } +//// }; +////} + +verify.baselineGoToDefinition("start1", "start2"); diff --git a/tests/cases/fourslash/goToDefinitionSwitchCase4.ts b/tests/cases/fourslash/goToDefinitionSwitchCase4.ts new file mode 100644 index 0000000000000..db4b801415dc2 --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionSwitchCase4.ts @@ -0,0 +1,11 @@ +/// + +//// switch (null) { +//// case null: break; +//// } +//// +//// switch (null) { +//// [|/*start*/case|] null: break; +//// } + +verify.baselineGoToDefinition("start"); diff --git a/tests/cases/fourslash/goToDefinitionSwitchCase5.ts b/tests/cases/fourslash/goToDefinitionSwitchCase5.ts new file mode 100644 index 0000000000000..83e8f28ad0aab --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionSwitchCase5.ts @@ -0,0 +1,5 @@ +/// + +////export [|/*start*/default|] {} + +verify.baselineGoToDefinition("start"); diff --git a/tests/cases/fourslash/goToDefinitionSwitchCase6.ts b/tests/cases/fourslash/goToDefinitionSwitchCase6.ts new file mode 100644 index 0000000000000..b6ac5daf8f5f8 --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionSwitchCase6.ts @@ -0,0 +1,7 @@ +/// + +////export default { [|/*a*/case|] }; +////[|/*b*/default|]; +////[|/*c*/case|] 42; + +verify.baselineGoToDefinition("a", "b", "c"); diff --git a/tests/cases/fourslash/goToDefinitionSwitchCase7.ts b/tests/cases/fourslash/goToDefinitionSwitchCase7.ts new file mode 100644 index 0000000000000..244b4b0b6a726 --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionSwitchCase7.ts @@ -0,0 +1,7 @@ +/// + +////switch (null) { +//// case null: +//// export [|/*start*/default|] 123; + +verify.baselineGoToDefinition("start"); From 67b644e5433c82f14fc53c57bc4aef888d69d2ab Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Thu, 11 Jan 2024 11:15:58 -0800 Subject: [PATCH 09/11] Export internal functions needed by dtsBundler.mjs (#52941) --- src/compiler/checker.ts | 9 ++--- src/compiler/transformers/declarations.ts | 36 +---------------- src/compiler/transformers/es2015.ts | 9 ++--- src/compiler/utilities.ts | 1 - src/compiler/utilitiesPublic.ts | 40 ++++++++++++++++++- src/compiler/visitorPublic.ts | 11 ++--- .../codefixes/annotateWithTypeFromJSDoc.ts | 3 +- src/services/codefixes/helpers.ts | 3 +- src/services/refactors/extractSymbol.ts | 5 +-- src/services/utilities.ts | 3 +- tests/baselines/reference/api/typescript.d.ts | 7 +++- 11 files changed, 64 insertions(+), 63 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 105765f11b322..93f72c5f1890d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -875,7 +875,6 @@ import { NonNullExpression, not, noTruncationMaximumTruncationLength, - nullTransformationContext, NumberLiteralType, NumericLiteral, objectAllocator, @@ -2365,7 +2364,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function markAsSynthetic(node: T): VisitResult { setTextRangePosEnd(node, -1, -1); - return visitEachChild(node, markAsSynthetic, nullTransformationContext); + return visitEachChild(node, markAsSynthetic, /*context*/ undefined); } function getEmitResolver(sourceFile: SourceFile, cancellationToken: CancellationToken) { @@ -7032,7 +7031,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!nodeIsSynthesized(node) && getParseTreeNode(node) === node) { return node; } - return setTextRange(factory.cloneNode(visitEachChild(node, deepCloneOrReuseNode, nullTransformationContext, deepCloneOrReuseNodes)), node); + return setTextRange(factory.cloneNode(visitEachChild(node, deepCloneOrReuseNode, /*context*/ undefined, deepCloneOrReuseNodes)), node); } function deepCloneOrReuseNodes( @@ -7826,7 +7825,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (context.tracker.canTrackSymbol && isComputedPropertyName(node) && isLateBindableName(node)) { trackComputedName(node.expression, context.enclosingDeclaration, context); } - let visited = visitEachChild(node, elideInitializerAndSetEmitFlags, nullTransformationContext, /*nodesVisitor*/ undefined, elideInitializerAndSetEmitFlags)!; + let visited = visitEachChild(node, elideInitializerAndSetEmitFlags, /*context*/ undefined, /*nodesVisitor*/ undefined, elideInitializerAndSetEmitFlags)!; if (isBindingElement(visited)) { visited = factory.updateBindingElement( visited, @@ -8663,7 +8662,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { setEmitFlags(node, EmitFlags.SingleLine); } - return visitEachChild(node, visitExistingNodeTreeSymbols, nullTransformationContext); + return visitEachChild(node, visitExistingNodeTreeSymbols, /*context*/ undefined); function getEffectiveDotDotDotForParameter(p: ParameterDeclaration) { return p.dotDotDotToken || (p.type && isJSDocVariadicType(p.type) ? factory.createToken(SyntaxKind.DotDotDotToken) : undefined); diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 95bcc19820ff0..323ed328f3823 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -14,7 +14,6 @@ import { canHaveModifiers, canProduceDiagnostics, ClassDeclaration, - CommentRange, compact, concatenate, ConditionalTypeNode, @@ -63,8 +62,6 @@ import { getExternalModuleImportEqualsDeclarationExpression, getExternalModuleNameFromDeclaration, getFirstConstructorWithBody, - getLeadingCommentRanges, - getLeadingCommentRangesOfNode, getLineAndCharacterOfPosition, getNameOfDeclaration, getNormalizedAbsolutePath, @@ -80,7 +77,6 @@ import { GetSymbolAccessibilityDiagnostic, getTextOfNode, getThisParameter, - getTrailingCommentRanges, hasDynamicName, hasEffectiveModifier, hasExtension, @@ -126,6 +122,7 @@ import { isImportEqualsDeclaration, isIndexSignatureDeclaration, isInterfaceDeclaration, + isInternalDeclaration, isJsonSourceFile, isLateVisibilityPaintedStatement, isLiteralImportTypeNode, @@ -158,7 +155,6 @@ import { isVariableDeclaration, isVarUsing, JSDocFunctionType, - last, LateBoundDeclaration, LateVisibilityPaintedStatement, length, @@ -202,7 +198,6 @@ import { setParent, setTextRange, SignatureDeclaration, - skipTrivia, some, SourceFile, startsWith, @@ -243,35 +238,6 @@ export function getDeclarationDiagnostics(host: EmitHost, resolver: EmitResolver return result.diagnostics; } -function hasInternalAnnotation(range: CommentRange, currentSourceFile: SourceFile) { - const comment = currentSourceFile.text.substring(range.pos, range.end); - return comment.includes("@internal"); -} - -/** @internal */ -export function isInternalDeclaration(node: Node, currentSourceFile: SourceFile) { - const parseTreeNode = getParseTreeNode(node); - if (parseTreeNode && parseTreeNode.kind === SyntaxKind.Parameter) { - const paramIdx = (parseTreeNode.parent as SignatureDeclaration).parameters.indexOf(parseTreeNode as ParameterDeclaration); - const previousSibling = paramIdx > 0 ? (parseTreeNode.parent as SignatureDeclaration).parameters[paramIdx - 1] : undefined; - const text = currentSourceFile.text; - const commentRanges = previousSibling - ? concatenate( - // to handle - // ... parameters, /** @internal */ - // public param: string - getTrailingCommentRanges(text, skipTrivia(text, previousSibling.end + 1, /*stopAfterLineBreak*/ false, /*stopAtComments*/ true)), - getLeadingCommentRanges(text, node.pos), - ) - : getTrailingCommentRanges(text, skipTrivia(text, node.pos, /*stopAfterLineBreak*/ false, /*stopAtComments*/ true)); - return commentRanges && commentRanges.length && hasInternalAnnotation(last(commentRanges), currentSourceFile); - } - const leadingCommentRanges = parseTreeNode && getLeadingCommentRangesOfNode(parseTreeNode, currentSourceFile); - return !!forEach(leadingCommentRanges, range => { - return hasInternalAnnotation(range, currentSourceFile); - }); -} - const declarationEmitNodeBuilderFlags = NodeBuilderFlags.MultilineObjectLiterals | NodeBuilderFlags.WriteClassExpressionAsTypeLiteral | NodeBuilderFlags.UseTypeOfFunction | diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index e715a2dd815e4..f8849b8cb23f7 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -156,7 +156,6 @@ import { NodeCheckFlags, NodeFlags, nodeIsSynthesized, - nullTransformationContext, NumericLiteral, ObjectLiteralElementLike, ObjectLiteralExpression, @@ -1642,12 +1641,12 @@ export function transformES2015(context: TransformationContext): (x: SourceFile case SyntaxKind.PropertyDeclaration: { const named = node as AccessorDeclaration | MethodDeclaration | PropertyDeclaration; if (isComputedPropertyName(named.name)) { - return factory.replacePropertyName(named, visitEachChild(named.name, elideUnusedThisCaptureWorker, nullTransformationContext)); + return factory.replacePropertyName(named, visitEachChild(named.name, elideUnusedThisCaptureWorker, /*context*/ undefined)); } return node; } } - return visitEachChild(node, elideUnusedThisCaptureWorker, nullTransformationContext); + return visitEachChild(node, elideUnusedThisCaptureWorker, /*context*/ undefined); } /** @@ -1728,12 +1727,12 @@ export function transformES2015(context: TransformationContext): (x: SourceFile case SyntaxKind.PropertyDeclaration: { const named = node as AccessorDeclaration | MethodDeclaration | PropertyDeclaration; if (isComputedPropertyName(named.name)) { - return factory.replacePropertyName(named, visitEachChild(named.name, injectSuperPresenceCheckWorker, nullTransformationContext)); + return factory.replacePropertyName(named, visitEachChild(named.name, injectSuperPresenceCheckWorker, /*context*/ undefined)); } return node; } } - return visitEachChild(node, injectSuperPresenceCheckWorker, nullTransformationContext); + return visitEachChild(node, injectSuperPresenceCheckWorker, /*context*/ undefined); } /** diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index ba51391f71916..e3ef9f744ea11 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2432,7 +2432,6 @@ export const fullTripleSlashAMDReferencePathRegEx = /^(\/\/\/\s*/; const defaultLibReferenceRegEx = /^(\/\/\/\s*/; -/** @internal */ export function isPartOfTypeNode(node: Node): boolean { if (SyntaxKind.FirstTypeNode <= node.kind && node.kind <= SyntaxKind.LastTypeNode) { return true; diff --git a/src/compiler/utilitiesPublic.ts b/src/compiler/utilitiesPublic.ts index 688ef16272039..0a1097326f4af 100644 --- a/src/compiler/utilitiesPublic.ts +++ b/src/compiler/utilitiesPublic.ts @@ -32,8 +32,10 @@ import { ClassLikeDeclaration, ClassStaticBlockDeclaration, combinePaths, + CommentRange, compareDiagnostics, CompilerOptions, + concatenate, ConciseBody, ConstructorDeclaration, ConstructorTypeNode, @@ -62,6 +64,7 @@ import { filter, find, flatMap, + forEach, ForInitializer, ForInOrOfStatement, FunctionBody, @@ -81,6 +84,10 @@ import { getJSDocCommentsAndTags, getJSDocRoot, getJSDocTypeParameterDeclarations, + getLeadingCommentRanges, + getLeadingCommentRangesOfNode, + getSourceFileOfNode, + getTrailingCommentRanges, hasAccessorModifier, HasDecorators, hasDecorators, @@ -204,6 +211,7 @@ import { JsxTagNameExpression, KeywordSyntaxKind, LabeledStatement, + last, lastOrUndefined, LeftHandSideExpression, length, @@ -258,9 +266,11 @@ import { setUILocale, SignatureDeclaration, skipOuterExpressions, + skipTrivia, some, sortAndDeduplicate, SortedReadonlyArray, + SourceFile, Statement, StringLiteral, StringLiteralLike, @@ -2376,7 +2386,6 @@ export function isDeclaration(node: Node): node is NamedDeclaration { return isDeclarationKind(node.kind); } -/** @internal */ export function isDeclarationStatement(node: Node): node is DeclarationStatement { return isDeclarationStatementKind(node.kind); } @@ -2606,3 +2615,32 @@ export function isRestParameter(node: ParameterDeclaration | JSDocParameterTag): const type = isJSDocParameterTag(node) ? (node.typeExpression && node.typeExpression.type) : node.type; return (node as ParameterDeclaration).dotDotDotToken !== undefined || !!type && type.kind === SyntaxKind.JSDocVariadicType; } + +function hasInternalAnnotation(range: CommentRange, sourceFile: SourceFile) { + const comment = sourceFile.text.substring(range.pos, range.end); + return comment.includes("@internal"); +} + +export function isInternalDeclaration(node: Node, sourceFile?: SourceFile) { + sourceFile ??= getSourceFileOfNode(node); + const parseTreeNode = getParseTreeNode(node); + if (parseTreeNode && parseTreeNode.kind === SyntaxKind.Parameter) { + const paramIdx = (parseTreeNode.parent as SignatureDeclaration).parameters.indexOf(parseTreeNode as ParameterDeclaration); + const previousSibling = paramIdx > 0 ? (parseTreeNode.parent as SignatureDeclaration).parameters[paramIdx - 1] : undefined; + const text = sourceFile.text; + const commentRanges = previousSibling + ? concatenate( + // to handle + // ... parameters, /** @internal */ + // public param: string + getTrailingCommentRanges(text, skipTrivia(text, previousSibling.end + 1, /*stopAfterLineBreak*/ false, /*stopAtComments*/ true)), + getLeadingCommentRanges(text, node.pos), + ) + : getTrailingCommentRanges(text, skipTrivia(text, node.pos, /*stopAfterLineBreak*/ false, /*stopAtComments*/ true)); + return some(commentRanges) && hasInternalAnnotation(last(commentRanges), sourceFile); + } + const leadingCommentRanges = parseTreeNode && getLeadingCommentRangesOfNode(parseTreeNode, sourceFile); + return !!forEach(leadingCommentRanges, range => { + return hasInternalAnnotation(range, sourceFile!); + }); +} diff --git a/src/compiler/visitorPublic.ts b/src/compiler/visitorPublic.ts index c5e99d170911c..0a4c746c2e7c6 100644 --- a/src/compiler/visitorPublic.ts +++ b/src/compiler/visitorPublic.ts @@ -90,6 +90,7 @@ import { NodeArray, NodesVisitor, NodeVisitor, + nullTransformationContext, ParameterDeclaration, ScriptTarget, setEmitFlags, @@ -580,9 +581,9 @@ export function visitCommaListElements(elements: NodeArray, visitor: * @param visitor The callback used to visit each child. * @param context A lexical environment context for the visitor. */ -export function visitEachChild(node: T, visitor: Visitor, context: TransformationContext): T; +export function visitEachChild(node: T, visitor: Visitor, context: TransformationContext | undefined): T; /** @internal */ -export function visitEachChild(node: T, visitor: Visitor, context: TransformationContext, nodesVisitor?: NodesVisitor, tokenVisitor?: Visitor, nodeVisitor?: NodeVisitor): T; // eslint-disable-line @typescript-eslint/unified-signatures +export function visitEachChild(node: T, visitor: Visitor, context: TransformationContext | undefined, nodesVisitor?: NodesVisitor, tokenVisitor?: Visitor, nodeVisitor?: NodeVisitor): T; // eslint-disable-line @typescript-eslint/unified-signatures /** * Visits each child of a Node using the supplied visitor, possibly returning a new Node of the same kind in its place. * @@ -590,10 +591,10 @@ export function visitEachChild(node: T, visitor: Visitor, contex * @param visitor The callback used to visit each child. * @param context A lexical environment context for the visitor. */ -export function visitEachChild(node: T | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: typeof visitNodes, tokenVisitor?: Visitor): T | undefined; +export function visitEachChild(node: T | undefined, visitor: Visitor, context: TransformationContext | undefined, nodesVisitor?: typeof visitNodes, tokenVisitor?: Visitor): T | undefined; /** @internal */ -export function visitEachChild(node: T | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: NodesVisitor, tokenVisitor?: Visitor, nodeVisitor?: NodeVisitor): T | undefined; -export function visitEachChild(node: T | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor = visitNodes, tokenVisitor?: Visitor, nodeVisitor: NodeVisitor = visitNode): T | undefined { +export function visitEachChild(node: T | undefined, visitor: Visitor, context: TransformationContext | undefined, nodesVisitor?: NodesVisitor, tokenVisitor?: Visitor, nodeVisitor?: NodeVisitor): T | undefined; +export function visitEachChild(node: T | undefined, visitor: Visitor, context = nullTransformationContext, nodesVisitor = visitNodes, tokenVisitor?: Visitor, nodeVisitor: NodeVisitor = visitNode): T | undefined { if (node === undefined) { return undefined; } diff --git a/src/services/codefixes/annotateWithTypeFromJSDoc.ts b/src/services/codefixes/annotateWithTypeFromJSDoc.ts index f989025b5cc4c..a73a19abffe60 100644 --- a/src/services/codefixes/annotateWithTypeFromJSDoc.ts +++ b/src/services/codefixes/annotateWithTypeFromJSDoc.ts @@ -27,7 +27,6 @@ import { last, map, Node, - nullTransformationContext, ParameterDeclaration, PropertyDeclaration, PropertySignature, @@ -144,7 +143,7 @@ function transformJSDocType(node: Node): Node { case SyntaxKind.JSDocTypeLiteral: return transformJSDocTypeLiteral(node as JSDocTypeLiteral); default: - const visited = visitEachChild(node, transformJSDocType, nullTransformationContext); + const visited = visitEachChild(node, transformJSDocType, /*context*/ undefined); setEmitFlags(visited, EmitFlags.SingleLine); return visited; } diff --git a/src/services/codefixes/helpers.ts b/src/services/codefixes/helpers.ts index 804e87040f48b..5e6dd79755636 100644 --- a/src/services/codefixes/helpers.ts +++ b/src/services/codefixes/helpers.ts @@ -70,7 +70,6 @@ import { NodeArray, NodeBuilderFlags, NodeFlags, - nullTransformationContext, ObjectFlags, ObjectLiteralExpression, ObjectType, @@ -913,7 +912,7 @@ export function tryGetAutoImportableReferenceFromTypeNode(importTypeNode: TypeNo const typeArguments = visitNodes(node.typeArguments, visit, isTypeNode); return factory.createTypeReferenceNode(qualifier, typeArguments); } - return visitEachChild(node, visit, nullTransformationContext); + return visitEachChild(node, visit, /*context*/ undefined); } } diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index f25098e2c060a..e55e4e37f7af5 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -120,7 +120,6 @@ import { Node, NodeBuilderFlags, NodeFlags, - nullTransformationContext, ObjectLiteralElementLike, ParameterDeclaration, positionIsSynthesized, @@ -1648,7 +1647,7 @@ function transformFunctionBody(body: Node, exposedVariableDeclarations: readonly const oldIgnoreReturns = ignoreReturns; ignoreReturns = ignoreReturns || isFunctionLikeDeclaration(node) || isClassLike(node); const substitution = substitutions.get(getNodeId(node).toString()); - const result = substitution ? getSynthesizedDeepClone(substitution) : visitEachChild(node, visitor, nullTransformationContext); + const result = substitution ? getSynthesizedDeepClone(substitution) : visitEachChild(node, visitor, /*context*/ undefined); ignoreReturns = oldIgnoreReturns; return result; } @@ -1662,7 +1661,7 @@ function transformConstantInitializer(initializer: Expression, substitutions: Re function visitor(node: Node): VisitResult { const substitution = substitutions.get(getNodeId(node).toString()); - return substitution ? getSynthesizedDeepClone(substitution) : visitEachChild(node, visitor, nullTransformationContext); + return substitution ? getSynthesizedDeepClone(substitution) : visitEachChild(node, visitor, /*context*/ undefined); } } diff --git a/src/services/utilities.ts b/src/services/utilities.ts index b48367739786d..5005e4e050a32 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -294,7 +294,6 @@ import { normalizePath, NoSubstitutionTemplateLiteral, notImplemented, - nullTransformationContext, NumericLiteral, or, OrganizeImports, @@ -3175,7 +3174,7 @@ function getSynthesizedDeepCloneWorker(node: T, replaceNode?: (n const nodesClone: (ns: NodeArray | undefined) => NodeArray | undefined = replaceNode ? ns => ns && getSynthesizedDeepClonesWithReplacements(ns, /*includeTrivia*/ true, replaceNode) : ns => ns && getSynthesizedDeepClones(ns); - const visited = visitEachChild(node, nodeClone, nullTransformationContext, nodesClone, nodeClone); + const visited = visitEachChild(node, nodeClone, /*context*/ undefined, nodesClone, nodeClone); if (visited === node) { // This only happens for leaf nodes - internal nodes always see their children change. diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 6cd050855d321..1e433e55d63f3 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -9198,6 +9198,7 @@ declare namespace ts { function isForInitializer(node: Node): node is ForInitializer; function isModuleBody(node: Node): node is ModuleBody; function isNamedImportBindings(node: Node): node is NamedImportBindings; + function isDeclarationStatement(node: Node): node is DeclarationStatement; function isStatement(node: Node): node is Statement; function isModuleReference(node: Node): node is ModuleReference; function isJsxTagNameExpression(node: Node): node is JsxTagNameExpression; @@ -9217,11 +9218,13 @@ declare namespace ts { function isJSDocLinkLike(node: Node): node is JSDocLink | JSDocLinkCode | JSDocLinkPlain; function hasRestParameter(s: SignatureDeclaration | JSDocSignature): boolean; function isRestParameter(node: ParameterDeclaration | JSDocParameterTag): boolean; + function isInternalDeclaration(node: Node, sourceFile?: SourceFile): boolean; const unchangedTextChangeRange: TextChangeRange; type ParameterPropertyDeclaration = ParameterDeclaration & { parent: ConstructorDeclaration; name: Identifier; }; + function isPartOfTypeNode(node: Node): boolean; /** * This function checks multiple locations for JSDoc comments that apply to a host node. * At each location, the whole comment may apply to the node, or only a specific tag in @@ -9860,7 +9863,7 @@ declare namespace ts { * @param visitor The callback used to visit each child. * @param context A lexical environment context for the visitor. */ - function visitEachChild(node: T, visitor: Visitor, context: TransformationContext): T; + function visitEachChild(node: T, visitor: Visitor, context: TransformationContext | undefined): T; /** * Visits each child of a Node using the supplied visitor, possibly returning a new Node of the same kind in its place. * @@ -9868,7 +9871,7 @@ declare namespace ts { * @param visitor The callback used to visit each child. * @param context A lexical environment context for the visitor. */ - function visitEachChild(node: T | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: typeof visitNodes, tokenVisitor?: Visitor): T | undefined; + function visitEachChild(node: T | undefined, visitor: Visitor, context: TransformationContext | undefined, nodesVisitor?: typeof visitNodes, tokenVisitor?: Visitor): T | undefined; function getTsBuildInfoEmitOutputFilePath(options: CompilerOptions): string | undefined; function getOutputFileNames(commandLine: ParsedCommandLine, inputFileName: string, ignoreCase: boolean): readonly string[]; function createPrinter(printerOptions?: PrinterOptions, handlers?: PrintHandlers): Printer; From fbf908bd5828238e49cb6e3babb1a891dcc3d5a1 Mon Sep 17 00:00:00 2001 From: Kevin Gibbons Date: Thu, 11 Jan 2024 11:17:54 -0800 Subject: [PATCH 10/11] Add types for Object.groupBy() and Map.groupBy() (#56805) Co-authored-by: Nick McCurdy Co-authored-by: Karl Horky Co-authored-by: Niklas Mollenhauer --- src/compiler/commandLineParser.ts | 3 +- src/lib/esnext.collection.d.ts | 11 +++ src/lib/esnext.d.ts | 2 + src/lib/esnext.object.d.ts | 11 +++ src/lib/libs.json | 2 + .../Parse --lib option with extra comma.js | 2 +- ... --lib option with trailing white-space.js | 2 +- .../Parse invalid option of library flags.js | 2 +- ...array to compiler-options with json api.js | 2 +- ...ompiler-options with jsonSourceFile api.js | 2 +- ... libs to compiler-options with json api.js | 2 +- ...ompiler-options with jsonSourceFile api.js | 2 +- ... libs to compiler-options with json api.js | 2 +- ...ompiler-options with jsonSourceFile api.js | 2 +- ... libs to compiler-options with json api.js | 2 +- ...ompiler-options with jsonSourceFile api.js | 2 +- tests/baselines/reference/mapGroupBy.js | 20 ++++++ tests/baselines/reference/mapGroupBy.symbols | 50 ++++++++++++++ tests/baselines/reference/mapGroupBy.types | 67 +++++++++++++++++++ .../reference/objectGroupBy.errors.txt | 17 +++++ tests/baselines/reference/objectGroupBy.js | 20 ++++++ .../baselines/reference/objectGroupBy.symbols | 50 ++++++++++++++ tests/baselines/reference/objectGroupBy.types | 67 +++++++++++++++++++ ...does-not-add-color-when-NO_COLOR-is-set.js | 2 +- ...-when-host-can't-provide-terminal-width.js | 2 +- ...tatus.DiagnosticsPresent_OutputsSkipped.js | 2 +- .../telemetry/does-not-expose-paths.js | 2 +- .../typesVersions.ambientModules.trace.json | 24 +++++++ .../typesVersions.emptyTypes.trace.json | 26 +++++++ .../typesVersions.justIndex.trace.json | 26 +++++++ .../typesVersions.multiFile.trace.json | 24 +++++++ ...VersionsDeclarationEmit.ambient.trace.json | 24 +++++++ ...rsionsDeclarationEmit.multiFile.trace.json | 24 +++++++ ...it.multiFileBackReferenceToSelf.trace.json | 24 +++++++ ...ultiFileBackReferenceToUnmapped.trace.json | 24 +++++++ tests/cases/compiler/mapGroupBy.ts | 11 +++ tests/cases/compiler/objectGroupBy.ts | 11 +++ 37 files changed, 552 insertions(+), 16 deletions(-) create mode 100644 src/lib/esnext.collection.d.ts create mode 100644 src/lib/esnext.object.d.ts create mode 100644 tests/baselines/reference/mapGroupBy.js create mode 100644 tests/baselines/reference/mapGroupBy.symbols create mode 100644 tests/baselines/reference/mapGroupBy.types create mode 100644 tests/baselines/reference/objectGroupBy.errors.txt create mode 100644 tests/baselines/reference/objectGroupBy.js create mode 100644 tests/baselines/reference/objectGroupBy.symbols create mode 100644 tests/baselines/reference/objectGroupBy.types create mode 100644 tests/cases/compiler/mapGroupBy.ts create mode 100644 tests/cases/compiler/objectGroupBy.ts diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 6d29b82bed704..58c43f7411985 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -218,7 +218,7 @@ const libEntries: [string, string][] = [ ["es2023.array", "lib.es2023.array.d.ts"], ["es2023.collection", "lib.es2023.collection.d.ts"], ["esnext.array", "lib.es2023.array.d.ts"], - ["esnext.collection", "lib.es2023.collection.d.ts"], + ["esnext.collection", "lib.esnext.collection.d.ts"], ["esnext.symbol", "lib.es2019.symbol.d.ts"], ["esnext.asynciterable", "lib.es2018.asynciterable.d.ts"], ["esnext.intl", "lib.esnext.intl.d.ts"], @@ -228,6 +228,7 @@ const libEntries: [string, string][] = [ ["esnext.promise", "lib.esnext.promise.d.ts"], ["esnext.weakref", "lib.es2021.weakref.d.ts"], ["esnext.decorators", "lib.esnext.decorators.d.ts"], + ["esnext.object", "lib.esnext.object.d.ts"], ["decorators", "lib.decorators.d.ts"], ["decorators.legacy", "lib.decorators.legacy.d.ts"], ]; diff --git a/src/lib/esnext.collection.d.ts b/src/lib/esnext.collection.d.ts new file mode 100644 index 0000000000000..7a799f3c494e7 --- /dev/null +++ b/src/lib/esnext.collection.d.ts @@ -0,0 +1,11 @@ +interface MapConstructor { + /** + * Groups members of an iterable according to the return value of the passed callback. + * @param items An iterable. + * @param keySelector A callback which will be invoked for each item in items. + */ + groupBy( + items: Iterable, + keySelector: (item: T, index: number) => K, + ): Map; +} diff --git a/src/lib/esnext.d.ts b/src/lib/esnext.d.ts index 0fd9d10076eea..56d97e566a301 100644 --- a/src/lib/esnext.d.ts +++ b/src/lib/esnext.d.ts @@ -3,3 +3,5 @@ /// /// /// +/// +/// diff --git a/src/lib/esnext.object.d.ts b/src/lib/esnext.object.d.ts new file mode 100644 index 0000000000000..0486ac078139c --- /dev/null +++ b/src/lib/esnext.object.d.ts @@ -0,0 +1,11 @@ +interface ObjectConstructor { + /** + * Groups members of an iterable according to the return value of the passed callback. + * @param items An iterable. + * @param keySelector A callback which will be invoked for each item in items. + */ + groupBy( + items: Iterable, + keySelector: (item: T, index: number) => K, + ): Partial>; +} diff --git a/src/lib/libs.json b/src/lib/libs.json index cde5256e8e573..3258386a2c53e 100644 --- a/src/lib/libs.json +++ b/src/lib/libs.json @@ -74,6 +74,8 @@ "esnext.intl", "esnext.disposable", "esnext.promise", + "esnext.object", + "esnext.collection", "decorators", "decorators.legacy", // Default libraries diff --git a/tests/baselines/reference/config/commandLineParsing/parseCommandLine/Parse --lib option with extra comma.js b/tests/baselines/reference/config/commandLineParsing/parseCommandLine/Parse --lib option with extra comma.js index 68ab2d4176968..cd421cd200b7c 100644 --- a/tests/baselines/reference/config/commandLineParsing/parseCommandLine/Parse --lib option with extra comma.js +++ b/tests/baselines/reference/config/commandLineParsing/parseCommandLine/Parse --lib option with extra comma.js @@ -10,4 +10,4 @@ WatchOptions:: FileNames:: es7,0.ts Errors:: -error TS6046: Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'es2021', 'es2022', 'es2023', 'esnext', 'dom', 'dom.iterable', 'dom.asynciterable', 'webworker', 'webworker.importscripts', 'webworker.iterable', 'webworker.asynciterable', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2016.intl', 'es2017.date', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asyncgenerator', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'es2019.array', 'es2019.object', 'es2019.string', 'es2019.symbol', 'es2019.intl', 'es2020.bigint', 'es2020.date', 'es2020.promise', 'es2020.sharedmemory', 'es2020.string', 'es2020.symbol.wellknown', 'es2020.intl', 'es2020.number', 'es2021.promise', 'es2021.string', 'es2021.weakref', 'es2021.intl', 'es2022.array', 'es2022.error', 'es2022.intl', 'es2022.object', 'es2022.sharedmemory', 'es2022.string', 'es2022.regexp', 'es2023.array', 'es2023.collection', 'esnext.array', 'esnext.collection', 'esnext.symbol', 'esnext.asynciterable', 'esnext.intl', 'esnext.disposable', 'esnext.bigint', 'esnext.string', 'esnext.promise', 'esnext.weakref', 'esnext.decorators', 'decorators', 'decorators.legacy'. +error TS6046: Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'es2021', 'es2022', 'es2023', 'esnext', 'dom', 'dom.iterable', 'dom.asynciterable', 'webworker', 'webworker.importscripts', 'webworker.iterable', 'webworker.asynciterable', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2016.intl', 'es2017.date', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asyncgenerator', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'es2019.array', 'es2019.object', 'es2019.string', 'es2019.symbol', 'es2019.intl', 'es2020.bigint', 'es2020.date', 'es2020.promise', 'es2020.sharedmemory', 'es2020.string', 'es2020.symbol.wellknown', 'es2020.intl', 'es2020.number', 'es2021.promise', 'es2021.string', 'es2021.weakref', 'es2021.intl', 'es2022.array', 'es2022.error', 'es2022.intl', 'es2022.object', 'es2022.sharedmemory', 'es2022.string', 'es2022.regexp', 'es2023.array', 'es2023.collection', 'esnext.array', 'esnext.collection', 'esnext.symbol', 'esnext.asynciterable', 'esnext.intl', 'esnext.disposable', 'esnext.bigint', 'esnext.string', 'esnext.promise', 'esnext.weakref', 'esnext.decorators', 'esnext.object', 'decorators', 'decorators.legacy'. diff --git a/tests/baselines/reference/config/commandLineParsing/parseCommandLine/Parse --lib option with trailing white-space.js b/tests/baselines/reference/config/commandLineParsing/parseCommandLine/Parse --lib option with trailing white-space.js index 0e0b1480091fe..fabeb52959d52 100644 --- a/tests/baselines/reference/config/commandLineParsing/parseCommandLine/Parse --lib option with trailing white-space.js +++ b/tests/baselines/reference/config/commandLineParsing/parseCommandLine/Parse --lib option with trailing white-space.js @@ -10,4 +10,4 @@ WatchOptions:: FileNames:: es7,0.ts Errors:: -error TS6046: Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'es2021', 'es2022', 'es2023', 'esnext', 'dom', 'dom.iterable', 'dom.asynciterable', 'webworker', 'webworker.importscripts', 'webworker.iterable', 'webworker.asynciterable', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2016.intl', 'es2017.date', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asyncgenerator', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'es2019.array', 'es2019.object', 'es2019.string', 'es2019.symbol', 'es2019.intl', 'es2020.bigint', 'es2020.date', 'es2020.promise', 'es2020.sharedmemory', 'es2020.string', 'es2020.symbol.wellknown', 'es2020.intl', 'es2020.number', 'es2021.promise', 'es2021.string', 'es2021.weakref', 'es2021.intl', 'es2022.array', 'es2022.error', 'es2022.intl', 'es2022.object', 'es2022.sharedmemory', 'es2022.string', 'es2022.regexp', 'es2023.array', 'es2023.collection', 'esnext.array', 'esnext.collection', 'esnext.symbol', 'esnext.asynciterable', 'esnext.intl', 'esnext.disposable', 'esnext.bigint', 'esnext.string', 'esnext.promise', 'esnext.weakref', 'esnext.decorators', 'decorators', 'decorators.legacy'. +error TS6046: Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'es2021', 'es2022', 'es2023', 'esnext', 'dom', 'dom.iterable', 'dom.asynciterable', 'webworker', 'webworker.importscripts', 'webworker.iterable', 'webworker.asynciterable', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2016.intl', 'es2017.date', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asyncgenerator', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'es2019.array', 'es2019.object', 'es2019.string', 'es2019.symbol', 'es2019.intl', 'es2020.bigint', 'es2020.date', 'es2020.promise', 'es2020.sharedmemory', 'es2020.string', 'es2020.symbol.wellknown', 'es2020.intl', 'es2020.number', 'es2021.promise', 'es2021.string', 'es2021.weakref', 'es2021.intl', 'es2022.array', 'es2022.error', 'es2022.intl', 'es2022.object', 'es2022.sharedmemory', 'es2022.string', 'es2022.regexp', 'es2023.array', 'es2023.collection', 'esnext.array', 'esnext.collection', 'esnext.symbol', 'esnext.asynciterable', 'esnext.intl', 'esnext.disposable', 'esnext.bigint', 'esnext.string', 'esnext.promise', 'esnext.weakref', 'esnext.decorators', 'esnext.object', 'decorators', 'decorators.legacy'. diff --git a/tests/baselines/reference/config/commandLineParsing/parseCommandLine/Parse invalid option of library flags.js b/tests/baselines/reference/config/commandLineParsing/parseCommandLine/Parse invalid option of library flags.js index 6942908118197..e0e3de1debba3 100644 --- a/tests/baselines/reference/config/commandLineParsing/parseCommandLine/Parse invalid option of library flags.js +++ b/tests/baselines/reference/config/commandLineParsing/parseCommandLine/Parse invalid option of library flags.js @@ -10,4 +10,4 @@ WatchOptions:: FileNames:: 0.ts Errors:: -error TS6046: Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'es2021', 'es2022', 'es2023', 'esnext', 'dom', 'dom.iterable', 'dom.asynciterable', 'webworker', 'webworker.importscripts', 'webworker.iterable', 'webworker.asynciterable', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2016.intl', 'es2017.date', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asyncgenerator', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'es2019.array', 'es2019.object', 'es2019.string', 'es2019.symbol', 'es2019.intl', 'es2020.bigint', 'es2020.date', 'es2020.promise', 'es2020.sharedmemory', 'es2020.string', 'es2020.symbol.wellknown', 'es2020.intl', 'es2020.number', 'es2021.promise', 'es2021.string', 'es2021.weakref', 'es2021.intl', 'es2022.array', 'es2022.error', 'es2022.intl', 'es2022.object', 'es2022.sharedmemory', 'es2022.string', 'es2022.regexp', 'es2023.array', 'es2023.collection', 'esnext.array', 'esnext.collection', 'esnext.symbol', 'esnext.asynciterable', 'esnext.intl', 'esnext.disposable', 'esnext.bigint', 'esnext.string', 'esnext.promise', 'esnext.weakref', 'esnext.decorators', 'decorators', 'decorators.legacy'. +error TS6046: Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'es2021', 'es2022', 'es2023', 'esnext', 'dom', 'dom.iterable', 'dom.asynciterable', 'webworker', 'webworker.importscripts', 'webworker.iterable', 'webworker.asynciterable', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2016.intl', 'es2017.date', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asyncgenerator', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'es2019.array', 'es2019.object', 'es2019.string', 'es2019.symbol', 'es2019.intl', 'es2020.bigint', 'es2020.date', 'es2020.promise', 'es2020.sharedmemory', 'es2020.string', 'es2020.symbol.wellknown', 'es2020.intl', 'es2020.number', 'es2021.promise', 'es2021.string', 'es2021.weakref', 'es2021.intl', 'es2022.array', 'es2022.error', 'es2022.intl', 'es2022.object', 'es2022.sharedmemory', 'es2022.string', 'es2022.regexp', 'es2023.array', 'es2023.collection', 'esnext.array', 'esnext.collection', 'esnext.symbol', 'esnext.asynciterable', 'esnext.intl', 'esnext.disposable', 'esnext.bigint', 'esnext.string', 'esnext.promise', 'esnext.weakref', 'esnext.decorators', 'esnext.object', 'decorators', 'decorators.legacy'. diff --git a/tests/baselines/reference/config/convertCompilerOptionsFromJson/Convert empty string option of libs array to compiler-options with json api.js b/tests/baselines/reference/config/convertCompilerOptionsFromJson/Convert empty string option of libs array to compiler-options with json api.js index a5bb63eac24d9..347aaaaff50d1 100644 --- a/tests/baselines/reference/config/convertCompilerOptionsFromJson/Convert empty string option of libs array to compiler-options with json api.js +++ b/tests/baselines/reference/config/convertCompilerOptionsFromJson/Convert empty string option of libs array to compiler-options with json api.js @@ -30,5 +30,5 @@ CompilerOptions:: "configFilePath": "tsconfig.json" } Errors:: -error TS6046: Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'es2021', 'es2022', 'es2023', 'esnext', 'dom', 'dom.iterable', 'dom.asynciterable', 'webworker', 'webworker.importscripts', 'webworker.iterable', 'webworker.asynciterable', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2016.intl', 'es2017.date', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asyncgenerator', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'es2019.array', 'es2019.object', 'es2019.string', 'es2019.symbol', 'es2019.intl', 'es2020.bigint', 'es2020.date', 'es2020.promise', 'es2020.sharedmemory', 'es2020.string', 'es2020.symbol.wellknown', 'es2020.intl', 'es2020.number', 'es2021.promise', 'es2021.string', 'es2021.weakref', 'es2021.intl', 'es2022.array', 'es2022.error', 'es2022.intl', 'es2022.object', 'es2022.sharedmemory', 'es2022.string', 'es2022.regexp', 'es2023.array', 'es2023.collection', 'esnext.array', 'esnext.collection', 'esnext.symbol', 'esnext.asynciterable', 'esnext.intl', 'esnext.disposable', 'esnext.bigint', 'esnext.string', 'esnext.promise', 'esnext.weakref', 'esnext.decorators', 'decorators', 'decorators.legacy'. +error TS6046: Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'es2021', 'es2022', 'es2023', 'esnext', 'dom', 'dom.iterable', 'dom.asynciterable', 'webworker', 'webworker.importscripts', 'webworker.iterable', 'webworker.asynciterable', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2016.intl', 'es2017.date', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asyncgenerator', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'es2019.array', 'es2019.object', 'es2019.string', 'es2019.symbol', 'es2019.intl', 'es2020.bigint', 'es2020.date', 'es2020.promise', 'es2020.sharedmemory', 'es2020.string', 'es2020.symbol.wellknown', 'es2020.intl', 'es2020.number', 'es2021.promise', 'es2021.string', 'es2021.weakref', 'es2021.intl', 'es2022.array', 'es2022.error', 'es2022.intl', 'es2022.object', 'es2022.sharedmemory', 'es2022.string', 'es2022.regexp', 'es2023.array', 'es2023.collection', 'esnext.array', 'esnext.collection', 'esnext.symbol', 'esnext.asynciterable', 'esnext.intl', 'esnext.disposable', 'esnext.bigint', 'esnext.string', 'esnext.promise', 'esnext.weakref', 'esnext.decorators', 'esnext.object', 'decorators', 'decorators.legacy'. diff --git a/tests/baselines/reference/config/convertCompilerOptionsFromJson/Convert empty string option of libs array to compiler-options with jsonSourceFile api.js b/tests/baselines/reference/config/convertCompilerOptionsFromJson/Convert empty string option of libs array to compiler-options with jsonSourceFile api.js index 18a774c865aa2..2318431048871 100644 --- a/tests/baselines/reference/config/convertCompilerOptionsFromJson/Convert empty string option of libs array to compiler-options with jsonSourceFile api.js +++ b/tests/baselines/reference/config/convertCompilerOptionsFromJson/Convert empty string option of libs array to compiler-options with jsonSourceFile api.js @@ -30,7 +30,7 @@ CompilerOptions:: "configFilePath": "tsconfig.json" } Errors:: -tsconfig.json:8:7 - error TS6046: Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'es2021', 'es2022', 'es2023', 'esnext', 'dom', 'dom.iterable', 'dom.asynciterable', 'webworker', 'webworker.importscripts', 'webworker.iterable', 'webworker.asynciterable', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2016.intl', 'es2017.date', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asyncgenerator', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'es2019.array', 'es2019.object', 'es2019.string', 'es2019.symbol', 'es2019.intl', 'es2020.bigint', 'es2020.date', 'es2020.promise', 'es2020.sharedmemory', 'es2020.string', 'es2020.symbol.wellknown', 'es2020.intl', 'es2020.number', 'es2021.promise', 'es2021.string', 'es2021.weakref', 'es2021.intl', 'es2022.array', 'es2022.error', 'es2022.intl', 'es2022.object', 'es2022.sharedmemory', 'es2022.string', 'es2022.regexp', 'es2023.array', 'es2023.collection', 'esnext.array', 'esnext.collection', 'esnext.symbol', 'esnext.asynciterable', 'esnext.intl', 'esnext.disposable', 'esnext.bigint', 'esnext.string', 'esnext.promise', 'esnext.weakref', 'esnext.decorators', 'decorators', 'decorators.legacy'. +tsconfig.json:8:7 - error TS6046: Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'es2021', 'es2022', 'es2023', 'esnext', 'dom', 'dom.iterable', 'dom.asynciterable', 'webworker', 'webworker.importscripts', 'webworker.iterable', 'webworker.asynciterable', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2016.intl', 'es2017.date', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asyncgenerator', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'es2019.array', 'es2019.object', 'es2019.string', 'es2019.symbol', 'es2019.intl', 'es2020.bigint', 'es2020.date', 'es2020.promise', 'es2020.sharedmemory', 'es2020.string', 'es2020.symbol.wellknown', 'es2020.intl', 'es2020.number', 'es2021.promise', 'es2021.string', 'es2021.weakref', 'es2021.intl', 'es2022.array', 'es2022.error', 'es2022.intl', 'es2022.object', 'es2022.sharedmemory', 'es2022.string', 'es2022.regexp', 'es2023.array', 'es2023.collection', 'esnext.array', 'esnext.collection', 'esnext.symbol', 'esnext.asynciterable', 'esnext.intl', 'esnext.disposable', 'esnext.bigint', 'esnext.string', 'esnext.promise', 'esnext.weakref', 'esnext.decorators', 'esnext.object', 'decorators', 'decorators.legacy'. 8 ""    ~~ diff --git a/tests/baselines/reference/config/convertCompilerOptionsFromJson/Convert empty string option of libs to compiler-options with json api.js b/tests/baselines/reference/config/convertCompilerOptionsFromJson/Convert empty string option of libs to compiler-options with json api.js index 36d03b9fb774b..29e437f45f1f4 100644 --- a/tests/baselines/reference/config/convertCompilerOptionsFromJson/Convert empty string option of libs to compiler-options with json api.js +++ b/tests/baselines/reference/config/convertCompilerOptionsFromJson/Convert empty string option of libs to compiler-options with json api.js @@ -33,5 +33,5 @@ CompilerOptions:: "configFilePath": "tsconfig.json" } Errors:: -error TS6046: Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'es2021', 'es2022', 'es2023', 'esnext', 'dom', 'dom.iterable', 'dom.asynciterable', 'webworker', 'webworker.importscripts', 'webworker.iterable', 'webworker.asynciterable', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2016.intl', 'es2017.date', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asyncgenerator', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'es2019.array', 'es2019.object', 'es2019.string', 'es2019.symbol', 'es2019.intl', 'es2020.bigint', 'es2020.date', 'es2020.promise', 'es2020.sharedmemory', 'es2020.string', 'es2020.symbol.wellknown', 'es2020.intl', 'es2020.number', 'es2021.promise', 'es2021.string', 'es2021.weakref', 'es2021.intl', 'es2022.array', 'es2022.error', 'es2022.intl', 'es2022.object', 'es2022.sharedmemory', 'es2022.string', 'es2022.regexp', 'es2023.array', 'es2023.collection', 'esnext.array', 'esnext.collection', 'esnext.symbol', 'esnext.asynciterable', 'esnext.intl', 'esnext.disposable', 'esnext.bigint', 'esnext.string', 'esnext.promise', 'esnext.weakref', 'esnext.decorators', 'decorators', 'decorators.legacy'. +error TS6046: Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'es2021', 'es2022', 'es2023', 'esnext', 'dom', 'dom.iterable', 'dom.asynciterable', 'webworker', 'webworker.importscripts', 'webworker.iterable', 'webworker.asynciterable', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2016.intl', 'es2017.date', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asyncgenerator', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'es2019.array', 'es2019.object', 'es2019.string', 'es2019.symbol', 'es2019.intl', 'es2020.bigint', 'es2020.date', 'es2020.promise', 'es2020.sharedmemory', 'es2020.string', 'es2020.symbol.wellknown', 'es2020.intl', 'es2020.number', 'es2021.promise', 'es2021.string', 'es2021.weakref', 'es2021.intl', 'es2022.array', 'es2022.error', 'es2022.intl', 'es2022.object', 'es2022.sharedmemory', 'es2022.string', 'es2022.regexp', 'es2023.array', 'es2023.collection', 'esnext.array', 'esnext.collection', 'esnext.symbol', 'esnext.asynciterable', 'esnext.intl', 'esnext.disposable', 'esnext.bigint', 'esnext.string', 'esnext.promise', 'esnext.weakref', 'esnext.decorators', 'esnext.object', 'decorators', 'decorators.legacy'. diff --git a/tests/baselines/reference/config/convertCompilerOptionsFromJson/Convert empty string option of libs to compiler-options with jsonSourceFile api.js b/tests/baselines/reference/config/convertCompilerOptionsFromJson/Convert empty string option of libs to compiler-options with jsonSourceFile api.js index 089cd767e35d0..2576767fca19d 100644 --- a/tests/baselines/reference/config/convertCompilerOptionsFromJson/Convert empty string option of libs to compiler-options with jsonSourceFile api.js +++ b/tests/baselines/reference/config/convertCompilerOptionsFromJson/Convert empty string option of libs to compiler-options with jsonSourceFile api.js @@ -33,7 +33,7 @@ CompilerOptions:: "configFilePath": "tsconfig.json" } Errors:: -tsconfig.json:9:7 - error TS6046: Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'es2021', 'es2022', 'es2023', 'esnext', 'dom', 'dom.iterable', 'dom.asynciterable', 'webworker', 'webworker.importscripts', 'webworker.iterable', 'webworker.asynciterable', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2016.intl', 'es2017.date', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asyncgenerator', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'es2019.array', 'es2019.object', 'es2019.string', 'es2019.symbol', 'es2019.intl', 'es2020.bigint', 'es2020.date', 'es2020.promise', 'es2020.sharedmemory', 'es2020.string', 'es2020.symbol.wellknown', 'es2020.intl', 'es2020.number', 'es2021.promise', 'es2021.string', 'es2021.weakref', 'es2021.intl', 'es2022.array', 'es2022.error', 'es2022.intl', 'es2022.object', 'es2022.sharedmemory', 'es2022.string', 'es2022.regexp', 'es2023.array', 'es2023.collection', 'esnext.array', 'esnext.collection', 'esnext.symbol', 'esnext.asynciterable', 'esnext.intl', 'esnext.disposable', 'esnext.bigint', 'esnext.string', 'esnext.promise', 'esnext.weakref', 'esnext.decorators', 'decorators', 'decorators.legacy'. +tsconfig.json:9:7 - error TS6046: Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'es2021', 'es2022', 'es2023', 'esnext', 'dom', 'dom.iterable', 'dom.asynciterable', 'webworker', 'webworker.importscripts', 'webworker.iterable', 'webworker.asynciterable', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2016.intl', 'es2017.date', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asyncgenerator', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'es2019.array', 'es2019.object', 'es2019.string', 'es2019.symbol', 'es2019.intl', 'es2020.bigint', 'es2020.date', 'es2020.promise', 'es2020.sharedmemory', 'es2020.string', 'es2020.symbol.wellknown', 'es2020.intl', 'es2020.number', 'es2021.promise', 'es2021.string', 'es2021.weakref', 'es2021.intl', 'es2022.array', 'es2022.error', 'es2022.intl', 'es2022.object', 'es2022.sharedmemory', 'es2022.string', 'es2022.regexp', 'es2023.array', 'es2023.collection', 'esnext.array', 'esnext.collection', 'esnext.symbol', 'esnext.asynciterable', 'esnext.intl', 'esnext.disposable', 'esnext.bigint', 'esnext.string', 'esnext.promise', 'esnext.weakref', 'esnext.decorators', 'esnext.object', 'decorators', 'decorators.legacy'. 9 ""    ~~ diff --git a/tests/baselines/reference/config/convertCompilerOptionsFromJson/Convert incorrect option of libs to compiler-options with json api.js b/tests/baselines/reference/config/convertCompilerOptionsFromJson/Convert incorrect option of libs to compiler-options with json api.js index b1087ce9efa20..d416471d82cc8 100644 --- a/tests/baselines/reference/config/convertCompilerOptionsFromJson/Convert incorrect option of libs to compiler-options with json api.js +++ b/tests/baselines/reference/config/convertCompilerOptionsFromJson/Convert incorrect option of libs to compiler-options with json api.js @@ -35,5 +35,5 @@ CompilerOptions:: "configFilePath": "tsconfig.json" } Errors:: -error TS6046: Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'es2021', 'es2022', 'es2023', 'esnext', 'dom', 'dom.iterable', 'dom.asynciterable', 'webworker', 'webworker.importscripts', 'webworker.iterable', 'webworker.asynciterable', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2016.intl', 'es2017.date', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asyncgenerator', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'es2019.array', 'es2019.object', 'es2019.string', 'es2019.symbol', 'es2019.intl', 'es2020.bigint', 'es2020.date', 'es2020.promise', 'es2020.sharedmemory', 'es2020.string', 'es2020.symbol.wellknown', 'es2020.intl', 'es2020.number', 'es2021.promise', 'es2021.string', 'es2021.weakref', 'es2021.intl', 'es2022.array', 'es2022.error', 'es2022.intl', 'es2022.object', 'es2022.sharedmemory', 'es2022.string', 'es2022.regexp', 'es2023.array', 'es2023.collection', 'esnext.array', 'esnext.collection', 'esnext.symbol', 'esnext.asynciterable', 'esnext.intl', 'esnext.disposable', 'esnext.bigint', 'esnext.string', 'esnext.promise', 'esnext.weakref', 'esnext.decorators', 'decorators', 'decorators.legacy'. +error TS6046: Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'es2021', 'es2022', 'es2023', 'esnext', 'dom', 'dom.iterable', 'dom.asynciterable', 'webworker', 'webworker.importscripts', 'webworker.iterable', 'webworker.asynciterable', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2016.intl', 'es2017.date', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asyncgenerator', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'es2019.array', 'es2019.object', 'es2019.string', 'es2019.symbol', 'es2019.intl', 'es2020.bigint', 'es2020.date', 'es2020.promise', 'es2020.sharedmemory', 'es2020.string', 'es2020.symbol.wellknown', 'es2020.intl', 'es2020.number', 'es2021.promise', 'es2021.string', 'es2021.weakref', 'es2021.intl', 'es2022.array', 'es2022.error', 'es2022.intl', 'es2022.object', 'es2022.sharedmemory', 'es2022.string', 'es2022.regexp', 'es2023.array', 'es2023.collection', 'esnext.array', 'esnext.collection', 'esnext.symbol', 'esnext.asynciterable', 'esnext.intl', 'esnext.disposable', 'esnext.bigint', 'esnext.string', 'esnext.promise', 'esnext.weakref', 'esnext.decorators', 'esnext.object', 'decorators', 'decorators.legacy'. diff --git a/tests/baselines/reference/config/convertCompilerOptionsFromJson/Convert incorrect option of libs to compiler-options with jsonSourceFile api.js b/tests/baselines/reference/config/convertCompilerOptionsFromJson/Convert incorrect option of libs to compiler-options with jsonSourceFile api.js index 50369fce5d9ac..751b7b61ae565 100644 --- a/tests/baselines/reference/config/convertCompilerOptionsFromJson/Convert incorrect option of libs to compiler-options with jsonSourceFile api.js +++ b/tests/baselines/reference/config/convertCompilerOptionsFromJson/Convert incorrect option of libs to compiler-options with jsonSourceFile api.js @@ -35,7 +35,7 @@ CompilerOptions:: "configFilePath": "tsconfig.json" } Errors:: -tsconfig.json:10:7 - error TS6046: Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'es2021', 'es2022', 'es2023', 'esnext', 'dom', 'dom.iterable', 'dom.asynciterable', 'webworker', 'webworker.importscripts', 'webworker.iterable', 'webworker.asynciterable', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2016.intl', 'es2017.date', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asyncgenerator', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'es2019.array', 'es2019.object', 'es2019.string', 'es2019.symbol', 'es2019.intl', 'es2020.bigint', 'es2020.date', 'es2020.promise', 'es2020.sharedmemory', 'es2020.string', 'es2020.symbol.wellknown', 'es2020.intl', 'es2020.number', 'es2021.promise', 'es2021.string', 'es2021.weakref', 'es2021.intl', 'es2022.array', 'es2022.error', 'es2022.intl', 'es2022.object', 'es2022.sharedmemory', 'es2022.string', 'es2022.regexp', 'es2023.array', 'es2023.collection', 'esnext.array', 'esnext.collection', 'esnext.symbol', 'esnext.asynciterable', 'esnext.intl', 'esnext.disposable', 'esnext.bigint', 'esnext.string', 'esnext.promise', 'esnext.weakref', 'esnext.decorators', 'decorators', 'decorators.legacy'. +tsconfig.json:10:7 - error TS6046: Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'es2021', 'es2022', 'es2023', 'esnext', 'dom', 'dom.iterable', 'dom.asynciterable', 'webworker', 'webworker.importscripts', 'webworker.iterable', 'webworker.asynciterable', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2016.intl', 'es2017.date', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asyncgenerator', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'es2019.array', 'es2019.object', 'es2019.string', 'es2019.symbol', 'es2019.intl', 'es2020.bigint', 'es2020.date', 'es2020.promise', 'es2020.sharedmemory', 'es2020.string', 'es2020.symbol.wellknown', 'es2020.intl', 'es2020.number', 'es2021.promise', 'es2021.string', 'es2021.weakref', 'es2021.intl', 'es2022.array', 'es2022.error', 'es2022.intl', 'es2022.object', 'es2022.sharedmemory', 'es2022.string', 'es2022.regexp', 'es2023.array', 'es2023.collection', 'esnext.array', 'esnext.collection', 'esnext.symbol', 'esnext.asynciterable', 'esnext.intl', 'esnext.disposable', 'esnext.bigint', 'esnext.string', 'esnext.promise', 'esnext.weakref', 'esnext.decorators', 'esnext.object', 'decorators', 'decorators.legacy'. 10 "incorrectLib"    ~~~~~~~~~~~~~~ diff --git a/tests/baselines/reference/config/convertCompilerOptionsFromJson/Convert trailing-whitespace string option of libs to compiler-options with json api.js b/tests/baselines/reference/config/convertCompilerOptionsFromJson/Convert trailing-whitespace string option of libs to compiler-options with json api.js index 8b7433122f6b7..64fc869bb68ac 100644 --- a/tests/baselines/reference/config/convertCompilerOptionsFromJson/Convert trailing-whitespace string option of libs to compiler-options with json api.js +++ b/tests/baselines/reference/config/convertCompilerOptionsFromJson/Convert trailing-whitespace string option of libs to compiler-options with json api.js @@ -30,5 +30,5 @@ CompilerOptions:: "configFilePath": "tsconfig.json" } Errors:: -error TS6046: Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'es2021', 'es2022', 'es2023', 'esnext', 'dom', 'dom.iterable', 'dom.asynciterable', 'webworker', 'webworker.importscripts', 'webworker.iterable', 'webworker.asynciterable', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2016.intl', 'es2017.date', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asyncgenerator', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'es2019.array', 'es2019.object', 'es2019.string', 'es2019.symbol', 'es2019.intl', 'es2020.bigint', 'es2020.date', 'es2020.promise', 'es2020.sharedmemory', 'es2020.string', 'es2020.symbol.wellknown', 'es2020.intl', 'es2020.number', 'es2021.promise', 'es2021.string', 'es2021.weakref', 'es2021.intl', 'es2022.array', 'es2022.error', 'es2022.intl', 'es2022.object', 'es2022.sharedmemory', 'es2022.string', 'es2022.regexp', 'es2023.array', 'es2023.collection', 'esnext.array', 'esnext.collection', 'esnext.symbol', 'esnext.asynciterable', 'esnext.intl', 'esnext.disposable', 'esnext.bigint', 'esnext.string', 'esnext.promise', 'esnext.weakref', 'esnext.decorators', 'decorators', 'decorators.legacy'. +error TS6046: Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'es2021', 'es2022', 'es2023', 'esnext', 'dom', 'dom.iterable', 'dom.asynciterable', 'webworker', 'webworker.importscripts', 'webworker.iterable', 'webworker.asynciterable', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2016.intl', 'es2017.date', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asyncgenerator', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'es2019.array', 'es2019.object', 'es2019.string', 'es2019.symbol', 'es2019.intl', 'es2020.bigint', 'es2020.date', 'es2020.promise', 'es2020.sharedmemory', 'es2020.string', 'es2020.symbol.wellknown', 'es2020.intl', 'es2020.number', 'es2021.promise', 'es2021.string', 'es2021.weakref', 'es2021.intl', 'es2022.array', 'es2022.error', 'es2022.intl', 'es2022.object', 'es2022.sharedmemory', 'es2022.string', 'es2022.regexp', 'es2023.array', 'es2023.collection', 'esnext.array', 'esnext.collection', 'esnext.symbol', 'esnext.asynciterable', 'esnext.intl', 'esnext.disposable', 'esnext.bigint', 'esnext.string', 'esnext.promise', 'esnext.weakref', 'esnext.decorators', 'esnext.object', 'decorators', 'decorators.legacy'. diff --git a/tests/baselines/reference/config/convertCompilerOptionsFromJson/Convert trailing-whitespace string option of libs to compiler-options with jsonSourceFile api.js b/tests/baselines/reference/config/convertCompilerOptionsFromJson/Convert trailing-whitespace string option of libs to compiler-options with jsonSourceFile api.js index 1d680893a6bbf..833000aa896cf 100644 --- a/tests/baselines/reference/config/convertCompilerOptionsFromJson/Convert trailing-whitespace string option of libs to compiler-options with jsonSourceFile api.js +++ b/tests/baselines/reference/config/convertCompilerOptionsFromJson/Convert trailing-whitespace string option of libs to compiler-options with jsonSourceFile api.js @@ -30,7 +30,7 @@ CompilerOptions:: "configFilePath": "tsconfig.json" } Errors:: -tsconfig.json:8:7 - error TS6046: Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'es2021', 'es2022', 'es2023', 'esnext', 'dom', 'dom.iterable', 'dom.asynciterable', 'webworker', 'webworker.importscripts', 'webworker.iterable', 'webworker.asynciterable', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2016.intl', 'es2017.date', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asyncgenerator', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'es2019.array', 'es2019.object', 'es2019.string', 'es2019.symbol', 'es2019.intl', 'es2020.bigint', 'es2020.date', 'es2020.promise', 'es2020.sharedmemory', 'es2020.string', 'es2020.symbol.wellknown', 'es2020.intl', 'es2020.number', 'es2021.promise', 'es2021.string', 'es2021.weakref', 'es2021.intl', 'es2022.array', 'es2022.error', 'es2022.intl', 'es2022.object', 'es2022.sharedmemory', 'es2022.string', 'es2022.regexp', 'es2023.array', 'es2023.collection', 'esnext.array', 'esnext.collection', 'esnext.symbol', 'esnext.asynciterable', 'esnext.intl', 'esnext.disposable', 'esnext.bigint', 'esnext.string', 'esnext.promise', 'esnext.weakref', 'esnext.decorators', 'decorators', 'decorators.legacy'. +tsconfig.json:8:7 - error TS6046: Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'es2021', 'es2022', 'es2023', 'esnext', 'dom', 'dom.iterable', 'dom.asynciterable', 'webworker', 'webworker.importscripts', 'webworker.iterable', 'webworker.asynciterable', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2016.intl', 'es2017.date', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asyncgenerator', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'es2019.array', 'es2019.object', 'es2019.string', 'es2019.symbol', 'es2019.intl', 'es2020.bigint', 'es2020.date', 'es2020.promise', 'es2020.sharedmemory', 'es2020.string', 'es2020.symbol.wellknown', 'es2020.intl', 'es2020.number', 'es2021.promise', 'es2021.string', 'es2021.weakref', 'es2021.intl', 'es2022.array', 'es2022.error', 'es2022.intl', 'es2022.object', 'es2022.sharedmemory', 'es2022.string', 'es2022.regexp', 'es2023.array', 'es2023.collection', 'esnext.array', 'esnext.collection', 'esnext.symbol', 'esnext.asynciterable', 'esnext.intl', 'esnext.disposable', 'esnext.bigint', 'esnext.string', 'esnext.promise', 'esnext.weakref', 'esnext.decorators', 'esnext.object', 'decorators', 'decorators.legacy'. 8 " "    ~~~~~ diff --git a/tests/baselines/reference/mapGroupBy.js b/tests/baselines/reference/mapGroupBy.js new file mode 100644 index 0000000000000..497f555fd0120 --- /dev/null +++ b/tests/baselines/reference/mapGroupBy.js @@ -0,0 +1,20 @@ +//// [tests/cases/compiler/mapGroupBy.ts] //// + +//// [mapGroupBy.ts] +const basic = Map.groupBy([0, 2, 8], x => x < 5 ? 'small' : 'large'); + +const chars = Map.groupBy('a string', c => c); + +type Employee = { name: string, role: 'ic' | 'manager' } +const employees: Set = new Set(); +const byRole = Map.groupBy(employees, x => x.role); + +const byNonKey = Map.groupBy(employees, x => x); + + +//// [mapGroupBy.js] +const basic = Map.groupBy([0, 2, 8], x => x < 5 ? 'small' : 'large'); +const chars = Map.groupBy('a string', c => c); +const employees = new Set(); +const byRole = Map.groupBy(employees, x => x.role); +const byNonKey = Map.groupBy(employees, x => x); diff --git a/tests/baselines/reference/mapGroupBy.symbols b/tests/baselines/reference/mapGroupBy.symbols new file mode 100644 index 0000000000000..4905d158fc9d8 --- /dev/null +++ b/tests/baselines/reference/mapGroupBy.symbols @@ -0,0 +1,50 @@ +//// [tests/cases/compiler/mapGroupBy.ts] //// + +=== mapGroupBy.ts === +const basic = Map.groupBy([0, 2, 8], x => x < 5 ? 'small' : 'large'); +>basic : Symbol(basic, Decl(mapGroupBy.ts, 0, 5)) +>Map.groupBy : Symbol(MapConstructor.groupBy, Decl(lib.esnext.collection.d.ts, --, --)) +>Map : Symbol(Map, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>groupBy : Symbol(MapConstructor.groupBy, Decl(lib.esnext.collection.d.ts, --, --)) +>x : Symbol(x, Decl(mapGroupBy.ts, 0, 36)) +>x : Symbol(x, Decl(mapGroupBy.ts, 0, 36)) + +const chars = Map.groupBy('a string', c => c); +>chars : Symbol(chars, Decl(mapGroupBy.ts, 2, 5)) +>Map.groupBy : Symbol(MapConstructor.groupBy, Decl(lib.esnext.collection.d.ts, --, --)) +>Map : Symbol(Map, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>groupBy : Symbol(MapConstructor.groupBy, Decl(lib.esnext.collection.d.ts, --, --)) +>c : Symbol(c, Decl(mapGroupBy.ts, 2, 37)) +>c : Symbol(c, Decl(mapGroupBy.ts, 2, 37)) + +type Employee = { name: string, role: 'ic' | 'manager' } +>Employee : Symbol(Employee, Decl(mapGroupBy.ts, 2, 46)) +>name : Symbol(name, Decl(mapGroupBy.ts, 4, 17)) +>role : Symbol(role, Decl(mapGroupBy.ts, 4, 31)) + +const employees: Set = new Set(); +>employees : Symbol(employees, Decl(mapGroupBy.ts, 5, 5)) +>Set : Symbol(Set, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Employee : Symbol(Employee, Decl(mapGroupBy.ts, 2, 46)) +>Set : Symbol(Set, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + +const byRole = Map.groupBy(employees, x => x.role); +>byRole : Symbol(byRole, Decl(mapGroupBy.ts, 6, 5)) +>Map.groupBy : Symbol(MapConstructor.groupBy, Decl(lib.esnext.collection.d.ts, --, --)) +>Map : Symbol(Map, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>groupBy : Symbol(MapConstructor.groupBy, Decl(lib.esnext.collection.d.ts, --, --)) +>employees : Symbol(employees, Decl(mapGroupBy.ts, 5, 5)) +>x : Symbol(x, Decl(mapGroupBy.ts, 6, 37)) +>x.role : Symbol(role, Decl(mapGroupBy.ts, 4, 31)) +>x : Symbol(x, Decl(mapGroupBy.ts, 6, 37)) +>role : Symbol(role, Decl(mapGroupBy.ts, 4, 31)) + +const byNonKey = Map.groupBy(employees, x => x); +>byNonKey : Symbol(byNonKey, Decl(mapGroupBy.ts, 8, 5)) +>Map.groupBy : Symbol(MapConstructor.groupBy, Decl(lib.esnext.collection.d.ts, --, --)) +>Map : Symbol(Map, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>groupBy : Symbol(MapConstructor.groupBy, Decl(lib.esnext.collection.d.ts, --, --)) +>employees : Symbol(employees, Decl(mapGroupBy.ts, 5, 5)) +>x : Symbol(x, Decl(mapGroupBy.ts, 8, 39)) +>x : Symbol(x, Decl(mapGroupBy.ts, 8, 39)) + diff --git a/tests/baselines/reference/mapGroupBy.types b/tests/baselines/reference/mapGroupBy.types new file mode 100644 index 0000000000000..998b2254156f1 --- /dev/null +++ b/tests/baselines/reference/mapGroupBy.types @@ -0,0 +1,67 @@ +//// [tests/cases/compiler/mapGroupBy.ts] //// + +=== mapGroupBy.ts === +const basic = Map.groupBy([0, 2, 8], x => x < 5 ? 'small' : 'large'); +>basic : Map<"small" | "large", number[]> +>Map.groupBy([0, 2, 8], x => x < 5 ? 'small' : 'large') : Map<"small" | "large", number[]> +>Map.groupBy : (items: Iterable, keySelector: (item: T, index: number) => K) => Map +>Map : MapConstructor +>groupBy : (items: Iterable, keySelector: (item: T, index: number) => K) => Map +>[0, 2, 8] : number[] +>0 : 0 +>2 : 2 +>8 : 8 +>x => x < 5 ? 'small' : 'large' : (x: number) => "small" | "large" +>x : number +>x < 5 ? 'small' : 'large' : "small" | "large" +>x < 5 : boolean +>x : number +>5 : 5 +>'small' : "small" +>'large' : "large" + +const chars = Map.groupBy('a string', c => c); +>chars : Map +>Map.groupBy('a string', c => c) : Map +>Map.groupBy : (items: Iterable, keySelector: (item: T, index: number) => K) => Map +>Map : MapConstructor +>groupBy : (items: Iterable, keySelector: (item: T, index: number) => K) => Map +>'a string' : "a string" +>c => c : (c: string) => string +>c : string +>c : string + +type Employee = { name: string, role: 'ic' | 'manager' } +>Employee : { name: string; role: 'ic' | 'manager'; } +>name : string +>role : "ic" | "manager" + +const employees: Set = new Set(); +>employees : Set +>new Set() : Set +>Set : SetConstructor + +const byRole = Map.groupBy(employees, x => x.role); +>byRole : Map<"ic" | "manager", Employee[]> +>Map.groupBy(employees, x => x.role) : Map<"ic" | "manager", Employee[]> +>Map.groupBy : (items: Iterable, keySelector: (item: T, index: number) => K) => Map +>Map : MapConstructor +>groupBy : (items: Iterable, keySelector: (item: T, index: number) => K) => Map +>employees : Set +>x => x.role : (x: Employee) => "ic" | "manager" +>x : Employee +>x.role : "ic" | "manager" +>x : Employee +>role : "ic" | "manager" + +const byNonKey = Map.groupBy(employees, x => x); +>byNonKey : Map +>Map.groupBy(employees, x => x) : Map +>Map.groupBy : (items: Iterable, keySelector: (item: T, index: number) => K) => Map +>Map : MapConstructor +>groupBy : (items: Iterable, keySelector: (item: T, index: number) => K) => Map +>employees : Set +>x => x : (x: Employee) => Employee +>x : Employee +>x : Employee + diff --git a/tests/baselines/reference/objectGroupBy.errors.txt b/tests/baselines/reference/objectGroupBy.errors.txt new file mode 100644 index 0000000000000..b748dc72da416 --- /dev/null +++ b/tests/baselines/reference/objectGroupBy.errors.txt @@ -0,0 +1,17 @@ +objectGroupBy.ts(9,49): error TS2322: Type 'Employee' is not assignable to type 'PropertyKey'. + + +==== objectGroupBy.ts (1 errors) ==== + const basic = Object.groupBy([0, 2, 8], x => x < 5 ? 'small' : 'large'); + + const chars = Object.groupBy('a string', c => c); + + type Employee = { name: string, role: 'ic' | 'manager' } + const employees: Set = new Set(); + const byRole = Object.groupBy(employees, x => x.role); + + const byNonKey = Object.groupBy(employees, x => x); + ~ +!!! error TS2322: Type 'Employee' is not assignable to type 'PropertyKey'. +!!! related TS6502 lib.esnext.object.d.ts:--:--: The expected type comes from the return type of this signature. + \ No newline at end of file diff --git a/tests/baselines/reference/objectGroupBy.js b/tests/baselines/reference/objectGroupBy.js new file mode 100644 index 0000000000000..320475a1a427c --- /dev/null +++ b/tests/baselines/reference/objectGroupBy.js @@ -0,0 +1,20 @@ +//// [tests/cases/compiler/objectGroupBy.ts] //// + +//// [objectGroupBy.ts] +const basic = Object.groupBy([0, 2, 8], x => x < 5 ? 'small' : 'large'); + +const chars = Object.groupBy('a string', c => c); + +type Employee = { name: string, role: 'ic' | 'manager' } +const employees: Set = new Set(); +const byRole = Object.groupBy(employees, x => x.role); + +const byNonKey = Object.groupBy(employees, x => x); + + +//// [objectGroupBy.js] +const basic = Object.groupBy([0, 2, 8], x => x < 5 ? 'small' : 'large'); +const chars = Object.groupBy('a string', c => c); +const employees = new Set(); +const byRole = Object.groupBy(employees, x => x.role); +const byNonKey = Object.groupBy(employees, x => x); diff --git a/tests/baselines/reference/objectGroupBy.symbols b/tests/baselines/reference/objectGroupBy.symbols new file mode 100644 index 0000000000000..df5e44fbf3c16 --- /dev/null +++ b/tests/baselines/reference/objectGroupBy.symbols @@ -0,0 +1,50 @@ +//// [tests/cases/compiler/objectGroupBy.ts] //// + +=== objectGroupBy.ts === +const basic = Object.groupBy([0, 2, 8], x => x < 5 ? 'small' : 'large'); +>basic : Symbol(basic, Decl(objectGroupBy.ts, 0, 5)) +>Object.groupBy : Symbol(ObjectConstructor.groupBy, Decl(lib.esnext.object.d.ts, --, --)) +>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>groupBy : Symbol(ObjectConstructor.groupBy, Decl(lib.esnext.object.d.ts, --, --)) +>x : Symbol(x, Decl(objectGroupBy.ts, 0, 39)) +>x : Symbol(x, Decl(objectGroupBy.ts, 0, 39)) + +const chars = Object.groupBy('a string', c => c); +>chars : Symbol(chars, Decl(objectGroupBy.ts, 2, 5)) +>Object.groupBy : Symbol(ObjectConstructor.groupBy, Decl(lib.esnext.object.d.ts, --, --)) +>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>groupBy : Symbol(ObjectConstructor.groupBy, Decl(lib.esnext.object.d.ts, --, --)) +>c : Symbol(c, Decl(objectGroupBy.ts, 2, 40)) +>c : Symbol(c, Decl(objectGroupBy.ts, 2, 40)) + +type Employee = { name: string, role: 'ic' | 'manager' } +>Employee : Symbol(Employee, Decl(objectGroupBy.ts, 2, 49)) +>name : Symbol(name, Decl(objectGroupBy.ts, 4, 17)) +>role : Symbol(role, Decl(objectGroupBy.ts, 4, 31)) + +const employees: Set = new Set(); +>employees : Symbol(employees, Decl(objectGroupBy.ts, 5, 5)) +>Set : Symbol(Set, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Employee : Symbol(Employee, Decl(objectGroupBy.ts, 2, 49)) +>Set : Symbol(Set, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + +const byRole = Object.groupBy(employees, x => x.role); +>byRole : Symbol(byRole, Decl(objectGroupBy.ts, 6, 5)) +>Object.groupBy : Symbol(ObjectConstructor.groupBy, Decl(lib.esnext.object.d.ts, --, --)) +>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>groupBy : Symbol(ObjectConstructor.groupBy, Decl(lib.esnext.object.d.ts, --, --)) +>employees : Symbol(employees, Decl(objectGroupBy.ts, 5, 5)) +>x : Symbol(x, Decl(objectGroupBy.ts, 6, 40)) +>x.role : Symbol(role, Decl(objectGroupBy.ts, 4, 31)) +>x : Symbol(x, Decl(objectGroupBy.ts, 6, 40)) +>role : Symbol(role, Decl(objectGroupBy.ts, 4, 31)) + +const byNonKey = Object.groupBy(employees, x => x); +>byNonKey : Symbol(byNonKey, Decl(objectGroupBy.ts, 8, 5)) +>Object.groupBy : Symbol(ObjectConstructor.groupBy, Decl(lib.esnext.object.d.ts, --, --)) +>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>groupBy : Symbol(ObjectConstructor.groupBy, Decl(lib.esnext.object.d.ts, --, --)) +>employees : Symbol(employees, Decl(objectGroupBy.ts, 5, 5)) +>x : Symbol(x, Decl(objectGroupBy.ts, 8, 42)) +>x : Symbol(x, Decl(objectGroupBy.ts, 8, 42)) + diff --git a/tests/baselines/reference/objectGroupBy.types b/tests/baselines/reference/objectGroupBy.types new file mode 100644 index 0000000000000..1fb901e8edb83 --- /dev/null +++ b/tests/baselines/reference/objectGroupBy.types @@ -0,0 +1,67 @@ +//// [tests/cases/compiler/objectGroupBy.ts] //// + +=== objectGroupBy.ts === +const basic = Object.groupBy([0, 2, 8], x => x < 5 ? 'small' : 'large'); +>basic : Partial> +>Object.groupBy([0, 2, 8], x => x < 5 ? 'small' : 'large') : Partial> +>Object.groupBy : (items: Iterable, keySelector: (item: T, index: number) => K) => Partial> +>Object : ObjectConstructor +>groupBy : (items: Iterable, keySelector: (item: T, index: number) => K) => Partial> +>[0, 2, 8] : number[] +>0 : 0 +>2 : 2 +>8 : 8 +>x => x < 5 ? 'small' : 'large' : (x: number) => "small" | "large" +>x : number +>x < 5 ? 'small' : 'large' : "small" | "large" +>x < 5 : boolean +>x : number +>5 : 5 +>'small' : "small" +>'large' : "large" + +const chars = Object.groupBy('a string', c => c); +>chars : Partial> +>Object.groupBy('a string', c => c) : Partial> +>Object.groupBy : (items: Iterable, keySelector: (item: T, index: number) => K) => Partial> +>Object : ObjectConstructor +>groupBy : (items: Iterable, keySelector: (item: T, index: number) => K) => Partial> +>'a string' : "a string" +>c => c : (c: string) => string +>c : string +>c : string + +type Employee = { name: string, role: 'ic' | 'manager' } +>Employee : { name: string; role: 'ic' | 'manager'; } +>name : string +>role : "ic" | "manager" + +const employees: Set = new Set(); +>employees : Set +>new Set() : Set +>Set : SetConstructor + +const byRole = Object.groupBy(employees, x => x.role); +>byRole : Partial> +>Object.groupBy(employees, x => x.role) : Partial> +>Object.groupBy : (items: Iterable, keySelector: (item: T, index: number) => K) => Partial> +>Object : ObjectConstructor +>groupBy : (items: Iterable, keySelector: (item: T, index: number) => K) => Partial> +>employees : Set +>x => x.role : (x: Employee) => "ic" | "manager" +>x : Employee +>x.role : "ic" | "manager" +>x : Employee +>role : "ic" | "manager" + +const byNonKey = Object.groupBy(employees, x => x); +>byNonKey : Partial> +>Object.groupBy(employees, x => x) : Partial> +>Object.groupBy : (items: Iterable, keySelector: (item: T, index: number) => K) => Partial> +>Object : ObjectConstructor +>groupBy : (items: Iterable, keySelector: (item: T, index: number) => K) => Partial> +>employees : Set +>x => x : (x: Employee) => Employee +>x : Employee +>x : Employee + diff --git a/tests/baselines/reference/tsc/runWithoutArgs/does-not-add-color-when-NO_COLOR-is-set.js b/tests/baselines/reference/tsc/runWithoutArgs/does-not-add-color-when-NO_COLOR-is-set.js index a589fbabc4de9..d93b62dedeee6 100644 --- a/tests/baselines/reference/tsc/runWithoutArgs/does-not-add-color-when-NO_COLOR-is-set.js +++ b/tests/baselines/reference/tsc/runWithoutArgs/does-not-add-color-when-NO_COLOR-is-set.js @@ -111,7 +111,7 @@ default: undefined --lib Specify a set of bundled library declaration files that describe the target runtime environment. -one or more: es5, es6/es2015, es7/es2016, es2017, es2018, es2019, es2020, es2021, es2022, es2023, esnext, dom, dom.iterable, dom.asynciterable, webworker, webworker.importscripts, webworker.iterable, webworker.asynciterable, scripthost, es2015.core, es2015.collection, es2015.generator, es2015.iterable, es2015.promise, es2015.proxy, es2015.reflect, es2015.symbol, es2015.symbol.wellknown, es2016.array.include, es2016.intl, es2017.date, es2017.object, es2017.sharedmemory, es2017.string, es2017.intl, es2017.typedarrays, es2018.asyncgenerator, es2018.asynciterable/esnext.asynciterable, es2018.intl, es2018.promise, es2018.regexp, es2019.array, es2019.object, es2019.string, es2019.symbol/esnext.symbol, es2019.intl, es2020.bigint/esnext.bigint, es2020.date, es2020.promise, es2020.sharedmemory, es2020.string, es2020.symbol.wellknown, es2020.intl, es2020.number, es2021.promise, es2021.string, es2021.weakref/esnext.weakref, es2021.intl, es2022.array, es2022.error, es2022.intl, es2022.object, es2022.sharedmemory, es2022.string/esnext.string, es2022.regexp, es2023.array/esnext.array, es2023.collection/esnext.collection, esnext.intl, esnext.disposable, esnext.promise, esnext.decorators, decorators, decorators.legacy +one or more: es5, es6/es2015, es7/es2016, es2017, es2018, es2019, es2020, es2021, es2022, es2023, esnext, dom, dom.iterable, dom.asynciterable, webworker, webworker.importscripts, webworker.iterable, webworker.asynciterable, scripthost, es2015.core, es2015.collection, es2015.generator, es2015.iterable, es2015.promise, es2015.proxy, es2015.reflect, es2015.symbol, es2015.symbol.wellknown, es2016.array.include, es2016.intl, es2017.date, es2017.object, es2017.sharedmemory, es2017.string, es2017.intl, es2017.typedarrays, es2018.asyncgenerator, es2018.asynciterable/esnext.asynciterable, es2018.intl, es2018.promise, es2018.regexp, es2019.array, es2019.object, es2019.string, es2019.symbol/esnext.symbol, es2019.intl, es2020.bigint/esnext.bigint, es2020.date, es2020.promise, es2020.sharedmemory, es2020.string, es2020.symbol.wellknown, es2020.intl, es2020.number, es2021.promise, es2021.string, es2021.weakref/esnext.weakref, es2021.intl, es2022.array, es2022.error, es2022.intl, es2022.object, es2022.sharedmemory, es2022.string/esnext.string, es2022.regexp, es2023.array/esnext.array, es2023.collection, esnext.collection, esnext.intl, esnext.disposable, esnext.promise, esnext.decorators, esnext.object, decorators, decorators.legacy default: undefined --allowJs diff --git a/tests/baselines/reference/tsc/runWithoutArgs/show-help-with-ExitStatus.DiagnosticsPresent_OutputsSkipped-when-host-can't-provide-terminal-width.js b/tests/baselines/reference/tsc/runWithoutArgs/show-help-with-ExitStatus.DiagnosticsPresent_OutputsSkipped-when-host-can't-provide-terminal-width.js index b738987321d96..37a11b54fb930 100644 --- a/tests/baselines/reference/tsc/runWithoutArgs/show-help-with-ExitStatus.DiagnosticsPresent_OutputsSkipped-when-host-can't-provide-terminal-width.js +++ b/tests/baselines/reference/tsc/runWithoutArgs/show-help-with-ExitStatus.DiagnosticsPresent_OutputsSkipped-when-host-can't-provide-terminal-width.js @@ -111,7 +111,7 @@ default: undefined --lib Specify a set of bundled library declaration files that describe the target runtime environment. -one or more: es5, es6/es2015, es7/es2016, es2017, es2018, es2019, es2020, es2021, es2022, es2023, esnext, dom, dom.iterable, dom.asynciterable, webworker, webworker.importscripts, webworker.iterable, webworker.asynciterable, scripthost, es2015.core, es2015.collection, es2015.generator, es2015.iterable, es2015.promise, es2015.proxy, es2015.reflect, es2015.symbol, es2015.symbol.wellknown, es2016.array.include, es2016.intl, es2017.date, es2017.object, es2017.sharedmemory, es2017.string, es2017.intl, es2017.typedarrays, es2018.asyncgenerator, es2018.asynciterable/esnext.asynciterable, es2018.intl, es2018.promise, es2018.regexp, es2019.array, es2019.object, es2019.string, es2019.symbol/esnext.symbol, es2019.intl, es2020.bigint/esnext.bigint, es2020.date, es2020.promise, es2020.sharedmemory, es2020.string, es2020.symbol.wellknown, es2020.intl, es2020.number, es2021.promise, es2021.string, es2021.weakref/esnext.weakref, es2021.intl, es2022.array, es2022.error, es2022.intl, es2022.object, es2022.sharedmemory, es2022.string/esnext.string, es2022.regexp, es2023.array/esnext.array, es2023.collection/esnext.collection, esnext.intl, esnext.disposable, esnext.promise, esnext.decorators, decorators, decorators.legacy +one or more: es5, es6/es2015, es7/es2016, es2017, es2018, es2019, es2020, es2021, es2022, es2023, esnext, dom, dom.iterable, dom.asynciterable, webworker, webworker.importscripts, webworker.iterable, webworker.asynciterable, scripthost, es2015.core, es2015.collection, es2015.generator, es2015.iterable, es2015.promise, es2015.proxy, es2015.reflect, es2015.symbol, es2015.symbol.wellknown, es2016.array.include, es2016.intl, es2017.date, es2017.object, es2017.sharedmemory, es2017.string, es2017.intl, es2017.typedarrays, es2018.asyncgenerator, es2018.asynciterable/esnext.asynciterable, es2018.intl, es2018.promise, es2018.regexp, es2019.array, es2019.object, es2019.string, es2019.symbol/esnext.symbol, es2019.intl, es2020.bigint/esnext.bigint, es2020.date, es2020.promise, es2020.sharedmemory, es2020.string, es2020.symbol.wellknown, es2020.intl, es2020.number, es2021.promise, es2021.string, es2021.weakref/esnext.weakref, es2021.intl, es2022.array, es2022.error, es2022.intl, es2022.object, es2022.sharedmemory, es2022.string/esnext.string, es2022.regexp, es2023.array/esnext.array, es2023.collection, esnext.collection, esnext.intl, esnext.disposable, esnext.promise, esnext.decorators, esnext.object, decorators, decorators.legacy default: undefined --allowJs diff --git a/tests/baselines/reference/tsc/runWithoutArgs/show-help-with-ExitStatus.DiagnosticsPresent_OutputsSkipped.js b/tests/baselines/reference/tsc/runWithoutArgs/show-help-with-ExitStatus.DiagnosticsPresent_OutputsSkipped.js index b738987321d96..37a11b54fb930 100644 --- a/tests/baselines/reference/tsc/runWithoutArgs/show-help-with-ExitStatus.DiagnosticsPresent_OutputsSkipped.js +++ b/tests/baselines/reference/tsc/runWithoutArgs/show-help-with-ExitStatus.DiagnosticsPresent_OutputsSkipped.js @@ -111,7 +111,7 @@ default: undefined --lib Specify a set of bundled library declaration files that describe the target runtime environment. -one or more: es5, es6/es2015, es7/es2016, es2017, es2018, es2019, es2020, es2021, es2022, es2023, esnext, dom, dom.iterable, dom.asynciterable, webworker, webworker.importscripts, webworker.iterable, webworker.asynciterable, scripthost, es2015.core, es2015.collection, es2015.generator, es2015.iterable, es2015.promise, es2015.proxy, es2015.reflect, es2015.symbol, es2015.symbol.wellknown, es2016.array.include, es2016.intl, es2017.date, es2017.object, es2017.sharedmemory, es2017.string, es2017.intl, es2017.typedarrays, es2018.asyncgenerator, es2018.asynciterable/esnext.asynciterable, es2018.intl, es2018.promise, es2018.regexp, es2019.array, es2019.object, es2019.string, es2019.symbol/esnext.symbol, es2019.intl, es2020.bigint/esnext.bigint, es2020.date, es2020.promise, es2020.sharedmemory, es2020.string, es2020.symbol.wellknown, es2020.intl, es2020.number, es2021.promise, es2021.string, es2021.weakref/esnext.weakref, es2021.intl, es2022.array, es2022.error, es2022.intl, es2022.object, es2022.sharedmemory, es2022.string/esnext.string, es2022.regexp, es2023.array/esnext.array, es2023.collection/esnext.collection, esnext.intl, esnext.disposable, esnext.promise, esnext.decorators, decorators, decorators.legacy +one or more: es5, es6/es2015, es7/es2016, es2017, es2018, es2019, es2020, es2021, es2022, es2023, esnext, dom, dom.iterable, dom.asynciterable, webworker, webworker.importscripts, webworker.iterable, webworker.asynciterable, scripthost, es2015.core, es2015.collection, es2015.generator, es2015.iterable, es2015.promise, es2015.proxy, es2015.reflect, es2015.symbol, es2015.symbol.wellknown, es2016.array.include, es2016.intl, es2017.date, es2017.object, es2017.sharedmemory, es2017.string, es2017.intl, es2017.typedarrays, es2018.asyncgenerator, es2018.asynciterable/esnext.asynciterable, es2018.intl, es2018.promise, es2018.regexp, es2019.array, es2019.object, es2019.string, es2019.symbol/esnext.symbol, es2019.intl, es2020.bigint/esnext.bigint, es2020.date, es2020.promise, es2020.sharedmemory, es2020.string, es2020.symbol.wellknown, es2020.intl, es2020.number, es2021.promise, es2021.string, es2021.weakref/esnext.weakref, es2021.intl, es2022.array, es2022.error, es2022.intl, es2022.object, es2022.sharedmemory, es2022.string/esnext.string, es2022.regexp, es2023.array/esnext.array, es2023.collection, esnext.collection, esnext.intl, esnext.disposable, esnext.promise, esnext.decorators, esnext.object, decorators, decorators.legacy default: undefined --allowJs diff --git a/tests/baselines/reference/tsserver/telemetry/does-not-expose-paths.js b/tests/baselines/reference/tsserver/telemetry/does-not-expose-paths.js index 4c29185d5827e..9813d58b44a80 100644 --- a/tests/baselines/reference/tsserver/telemetry/does-not-expose-paths.js +++ b/tests/baselines/reference/tsserver/telemetry/does-not-expose-paths.js @@ -471,7 +471,7 @@ Info seq [hh:mm:ss:mss] event: "line": 34, "offset": 16 }, - "text": "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'es2021', 'es2022', 'es2023', 'esnext', 'dom', 'dom.iterable', 'dom.asynciterable', 'webworker', 'webworker.importscripts', 'webworker.iterable', 'webworker.asynciterable', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2016.intl', 'es2017.date', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asyncgenerator', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'es2019.array', 'es2019.object', 'es2019.string', 'es2019.symbol', 'es2019.intl', 'es2020.bigint', 'es2020.date', 'es2020.promise', 'es2020.sharedmemory', 'es2020.string', 'es2020.symbol.wellknown', 'es2020.intl', 'es2020.number', 'es2021.promise', 'es2021.string', 'es2021.weakref', 'es2021.intl', 'es2022.array', 'es2022.error', 'es2022.intl', 'es2022.object', 'es2022.sharedmemory', 'es2022.string', 'es2022.regexp', 'es2023.array', 'es2023.collection', 'esnext.array', 'esnext.collection', 'esnext.symbol', 'esnext.asynciterable', 'esnext.intl', 'esnext.disposable', 'esnext.bigint', 'esnext.string', 'esnext.promise', 'esnext.weakref', 'esnext.decorators', 'decorators', 'decorators.legacy'.", + "text": "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'es2021', 'es2022', 'es2023', 'esnext', 'dom', 'dom.iterable', 'dom.asynciterable', 'webworker', 'webworker.importscripts', 'webworker.iterable', 'webworker.asynciterable', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2016.intl', 'es2017.date', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asyncgenerator', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'es2019.array', 'es2019.object', 'es2019.string', 'es2019.symbol', 'es2019.intl', 'es2020.bigint', 'es2020.date', 'es2020.promise', 'es2020.sharedmemory', 'es2020.string', 'es2020.symbol.wellknown', 'es2020.intl', 'es2020.number', 'es2021.promise', 'es2021.string', 'es2021.weakref', 'es2021.intl', 'es2022.array', 'es2022.error', 'es2022.intl', 'es2022.object', 'es2022.sharedmemory', 'es2022.string', 'es2022.regexp', 'es2023.array', 'es2023.collection', 'esnext.array', 'esnext.collection', 'esnext.symbol', 'esnext.asynciterable', 'esnext.intl', 'esnext.disposable', 'esnext.bigint', 'esnext.string', 'esnext.promise', 'esnext.weakref', 'esnext.decorators', 'esnext.object', 'decorators', 'decorators.legacy'.", "code": 6046, "category": "error", "fileName": "/tsconfig.json" diff --git a/tests/baselines/reference/typesVersions.ambientModules.trace.json b/tests/baselines/reference/typesVersions.ambientModules.trace.json index 637af04734a94..cc715e4c5f7b1 100644 --- a/tests/baselines/reference/typesVersions.ambientModules.trace.json +++ b/tests/baselines/reference/typesVersions.ambientModules.trace.json @@ -834,6 +834,30 @@ "Searching all ancestor node_modules directories for fallback extensions: JavaScript.", "Directory '/node_modules' does not exist, skipping all lookups in it.", "======== Module name '@typescript/lib-esnext/promise' was not resolved. ========", + "======== Resolving module '@typescript/lib-esnext/object' from '/.src/__lib_node_modules_lookup_lib.esnext.object.d.ts__.ts'. ========", + "Explicitly specified module resolution kind: 'Node10'.", + "Loading module '@typescript/lib-esnext/object' from 'node_modules' folder, target file types: TypeScript, Declaration.", + "Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.", + "Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-esnext/object'", + "Directory '/node_modules' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-esnext/object'", + "Loading module '@typescript/lib-esnext/object' from 'node_modules' folder, target file types: JavaScript.", + "Searching all ancestor node_modules directories for fallback extensions: JavaScript.", + "Directory '/node_modules' does not exist, skipping all lookups in it.", + "======== Module name '@typescript/lib-esnext/object' was not resolved. ========", + "======== Resolving module '@typescript/lib-esnext/collection' from '/.src/__lib_node_modules_lookup_lib.esnext.collection.d.ts__.ts'. ========", + "Explicitly specified module resolution kind: 'Node10'.", + "Loading module '@typescript/lib-esnext/collection' from 'node_modules' folder, target file types: TypeScript, Declaration.", + "Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.", + "Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-esnext/collection'", + "Directory '/node_modules' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-esnext/collection'", + "Loading module '@typescript/lib-esnext/collection' from 'node_modules' folder, target file types: JavaScript.", + "Searching all ancestor node_modules directories for fallback extensions: JavaScript.", + "Directory '/node_modules' does not exist, skipping all lookups in it.", + "======== Module name '@typescript/lib-esnext/collection' was not resolved. ========", "======== Resolving module '@typescript/lib-dom' from '/.src/__lib_node_modules_lookup_lib.dom.d.ts__.ts'. ========", "Explicitly specified module resolution kind: 'Node10'.", "Loading module '@typescript/lib-dom' from 'node_modules' folder, target file types: TypeScript, Declaration.", diff --git a/tests/baselines/reference/typesVersions.emptyTypes.trace.json b/tests/baselines/reference/typesVersions.emptyTypes.trace.json index 51284d259e6a9..1860a9288d301 100644 --- a/tests/baselines/reference/typesVersions.emptyTypes.trace.json +++ b/tests/baselines/reference/typesVersions.emptyTypes.trace.json @@ -866,6 +866,32 @@ "Directory '/.src/node_modules' does not exist, skipping all lookups in it.", "Directory '/node_modules' does not exist, skipping all lookups in it.", "======== Module name '@typescript/lib-esnext/promise' was not resolved. ========", + "======== Resolving module '@typescript/lib-esnext/object' from '/.src/__lib_node_modules_lookup_lib.esnext.object.d.ts__.ts'. ========", + "Explicitly specified module resolution kind: 'Node10'.", + "Loading module '@typescript/lib-esnext/object' from 'node_modules' folder, target file types: TypeScript, Declaration.", + "Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.", + "Directory '/.src/node_modules' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-esnext/object'", + "Directory '/node_modules' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-esnext/object'", + "Loading module '@typescript/lib-esnext/object' from 'node_modules' folder, target file types: JavaScript.", + "Searching all ancestor node_modules directories for fallback extensions: JavaScript.", + "Directory '/.src/node_modules' does not exist, skipping all lookups in it.", + "Directory '/node_modules' does not exist, skipping all lookups in it.", + "======== Module name '@typescript/lib-esnext/object' was not resolved. ========", + "======== Resolving module '@typescript/lib-esnext/collection' from '/.src/__lib_node_modules_lookup_lib.esnext.collection.d.ts__.ts'. ========", + "Explicitly specified module resolution kind: 'Node10'.", + "Loading module '@typescript/lib-esnext/collection' from 'node_modules' folder, target file types: TypeScript, Declaration.", + "Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.", + "Directory '/.src/node_modules' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-esnext/collection'", + "Directory '/node_modules' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-esnext/collection'", + "Loading module '@typescript/lib-esnext/collection' from 'node_modules' folder, target file types: JavaScript.", + "Searching all ancestor node_modules directories for fallback extensions: JavaScript.", + "Directory '/.src/node_modules' does not exist, skipping all lookups in it.", + "Directory '/node_modules' does not exist, skipping all lookups in it.", + "======== Module name '@typescript/lib-esnext/collection' was not resolved. ========", "======== Resolving module '@typescript/lib-dom' from '/.src/__lib_node_modules_lookup_lib.dom.d.ts__.ts'. ========", "Explicitly specified module resolution kind: 'Node10'.", "Loading module '@typescript/lib-dom' from 'node_modules' folder, target file types: TypeScript, Declaration.", diff --git a/tests/baselines/reference/typesVersions.justIndex.trace.json b/tests/baselines/reference/typesVersions.justIndex.trace.json index 567aedf61205d..c027d7ee5f121 100644 --- a/tests/baselines/reference/typesVersions.justIndex.trace.json +++ b/tests/baselines/reference/typesVersions.justIndex.trace.json @@ -866,6 +866,32 @@ "Directory '/.src/node_modules' does not exist, skipping all lookups in it.", "Directory '/node_modules' does not exist, skipping all lookups in it.", "======== Module name '@typescript/lib-esnext/promise' was not resolved. ========", + "======== Resolving module '@typescript/lib-esnext/object' from '/.src/__lib_node_modules_lookup_lib.esnext.object.d.ts__.ts'. ========", + "Explicitly specified module resolution kind: 'Node10'.", + "Loading module '@typescript/lib-esnext/object' from 'node_modules' folder, target file types: TypeScript, Declaration.", + "Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.", + "Directory '/.src/node_modules' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-esnext/object'", + "Directory '/node_modules' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-esnext/object'", + "Loading module '@typescript/lib-esnext/object' from 'node_modules' folder, target file types: JavaScript.", + "Searching all ancestor node_modules directories for fallback extensions: JavaScript.", + "Directory '/.src/node_modules' does not exist, skipping all lookups in it.", + "Directory '/node_modules' does not exist, skipping all lookups in it.", + "======== Module name '@typescript/lib-esnext/object' was not resolved. ========", + "======== Resolving module '@typescript/lib-esnext/collection' from '/.src/__lib_node_modules_lookup_lib.esnext.collection.d.ts__.ts'. ========", + "Explicitly specified module resolution kind: 'Node10'.", + "Loading module '@typescript/lib-esnext/collection' from 'node_modules' folder, target file types: TypeScript, Declaration.", + "Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.", + "Directory '/.src/node_modules' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-esnext/collection'", + "Directory '/node_modules' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-esnext/collection'", + "Loading module '@typescript/lib-esnext/collection' from 'node_modules' folder, target file types: JavaScript.", + "Searching all ancestor node_modules directories for fallback extensions: JavaScript.", + "Directory '/.src/node_modules' does not exist, skipping all lookups in it.", + "Directory '/node_modules' does not exist, skipping all lookups in it.", + "======== Module name '@typescript/lib-esnext/collection' was not resolved. ========", "======== Resolving module '@typescript/lib-dom' from '/.src/__lib_node_modules_lookup_lib.dom.d.ts__.ts'. ========", "Explicitly specified module resolution kind: 'Node10'.", "Loading module '@typescript/lib-dom' from 'node_modules' folder, target file types: TypeScript, Declaration.", diff --git a/tests/baselines/reference/typesVersions.multiFile.trace.json b/tests/baselines/reference/typesVersions.multiFile.trace.json index 7f5aaf3d3ebc9..533725ea68f2d 100644 --- a/tests/baselines/reference/typesVersions.multiFile.trace.json +++ b/tests/baselines/reference/typesVersions.multiFile.trace.json @@ -813,6 +813,30 @@ "Searching all ancestor node_modules directories for fallback extensions: JavaScript.", "Directory '/node_modules' does not exist, skipping all lookups in it.", "======== Module name '@typescript/lib-esnext/promise' was not resolved. ========", + "======== Resolving module '@typescript/lib-esnext/object' from '/.src/__lib_node_modules_lookup_lib.esnext.object.d.ts__.ts'. ========", + "Explicitly specified module resolution kind: 'Node10'.", + "Loading module '@typescript/lib-esnext/object' from 'node_modules' folder, target file types: TypeScript, Declaration.", + "Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.", + "Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-esnext/object'", + "Directory '/node_modules' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-esnext/object'", + "Loading module '@typescript/lib-esnext/object' from 'node_modules' folder, target file types: JavaScript.", + "Searching all ancestor node_modules directories for fallback extensions: JavaScript.", + "Directory '/node_modules' does not exist, skipping all lookups in it.", + "======== Module name '@typescript/lib-esnext/object' was not resolved. ========", + "======== Resolving module '@typescript/lib-esnext/collection' from '/.src/__lib_node_modules_lookup_lib.esnext.collection.d.ts__.ts'. ========", + "Explicitly specified module resolution kind: 'Node10'.", + "Loading module '@typescript/lib-esnext/collection' from 'node_modules' folder, target file types: TypeScript, Declaration.", + "Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.", + "Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-esnext/collection'", + "Directory '/node_modules' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-esnext/collection'", + "Loading module '@typescript/lib-esnext/collection' from 'node_modules' folder, target file types: JavaScript.", + "Searching all ancestor node_modules directories for fallback extensions: JavaScript.", + "Directory '/node_modules' does not exist, skipping all lookups in it.", + "======== Module name '@typescript/lib-esnext/collection' was not resolved. ========", "======== Resolving module '@typescript/lib-dom' from '/.src/__lib_node_modules_lookup_lib.dom.d.ts__.ts'. ========", "Explicitly specified module resolution kind: 'Node10'.", "Loading module '@typescript/lib-dom' from 'node_modules' folder, target file types: TypeScript, Declaration.", diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.trace.json b/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.trace.json index 637af04734a94..cc715e4c5f7b1 100644 --- a/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.trace.json +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.trace.json @@ -834,6 +834,30 @@ "Searching all ancestor node_modules directories for fallback extensions: JavaScript.", "Directory '/node_modules' does not exist, skipping all lookups in it.", "======== Module name '@typescript/lib-esnext/promise' was not resolved. ========", + "======== Resolving module '@typescript/lib-esnext/object' from '/.src/__lib_node_modules_lookup_lib.esnext.object.d.ts__.ts'. ========", + "Explicitly specified module resolution kind: 'Node10'.", + "Loading module '@typescript/lib-esnext/object' from 'node_modules' folder, target file types: TypeScript, Declaration.", + "Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.", + "Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-esnext/object'", + "Directory '/node_modules' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-esnext/object'", + "Loading module '@typescript/lib-esnext/object' from 'node_modules' folder, target file types: JavaScript.", + "Searching all ancestor node_modules directories for fallback extensions: JavaScript.", + "Directory '/node_modules' does not exist, skipping all lookups in it.", + "======== Module name '@typescript/lib-esnext/object' was not resolved. ========", + "======== Resolving module '@typescript/lib-esnext/collection' from '/.src/__lib_node_modules_lookup_lib.esnext.collection.d.ts__.ts'. ========", + "Explicitly specified module resolution kind: 'Node10'.", + "Loading module '@typescript/lib-esnext/collection' from 'node_modules' folder, target file types: TypeScript, Declaration.", + "Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.", + "Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-esnext/collection'", + "Directory '/node_modules' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-esnext/collection'", + "Loading module '@typescript/lib-esnext/collection' from 'node_modules' folder, target file types: JavaScript.", + "Searching all ancestor node_modules directories for fallback extensions: JavaScript.", + "Directory '/node_modules' does not exist, skipping all lookups in it.", + "======== Module name '@typescript/lib-esnext/collection' was not resolved. ========", "======== Resolving module '@typescript/lib-dom' from '/.src/__lib_node_modules_lookup_lib.dom.d.ts__.ts'. ========", "Explicitly specified module resolution kind: 'Node10'.", "Loading module '@typescript/lib-dom' from 'node_modules' folder, target file types: TypeScript, Declaration.", diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.trace.json b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.trace.json index 7f5aaf3d3ebc9..533725ea68f2d 100644 --- a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.trace.json +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.trace.json @@ -813,6 +813,30 @@ "Searching all ancestor node_modules directories for fallback extensions: JavaScript.", "Directory '/node_modules' does not exist, skipping all lookups in it.", "======== Module name '@typescript/lib-esnext/promise' was not resolved. ========", + "======== Resolving module '@typescript/lib-esnext/object' from '/.src/__lib_node_modules_lookup_lib.esnext.object.d.ts__.ts'. ========", + "Explicitly specified module resolution kind: 'Node10'.", + "Loading module '@typescript/lib-esnext/object' from 'node_modules' folder, target file types: TypeScript, Declaration.", + "Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.", + "Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-esnext/object'", + "Directory '/node_modules' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-esnext/object'", + "Loading module '@typescript/lib-esnext/object' from 'node_modules' folder, target file types: JavaScript.", + "Searching all ancestor node_modules directories for fallback extensions: JavaScript.", + "Directory '/node_modules' does not exist, skipping all lookups in it.", + "======== Module name '@typescript/lib-esnext/object' was not resolved. ========", + "======== Resolving module '@typescript/lib-esnext/collection' from '/.src/__lib_node_modules_lookup_lib.esnext.collection.d.ts__.ts'. ========", + "Explicitly specified module resolution kind: 'Node10'.", + "Loading module '@typescript/lib-esnext/collection' from 'node_modules' folder, target file types: TypeScript, Declaration.", + "Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.", + "Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-esnext/collection'", + "Directory '/node_modules' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-esnext/collection'", + "Loading module '@typescript/lib-esnext/collection' from 'node_modules' folder, target file types: JavaScript.", + "Searching all ancestor node_modules directories for fallback extensions: JavaScript.", + "Directory '/node_modules' does not exist, skipping all lookups in it.", + "======== Module name '@typescript/lib-esnext/collection' was not resolved. ========", "======== Resolving module '@typescript/lib-dom' from '/.src/__lib_node_modules_lookup_lib.dom.d.ts__.ts'. ========", "Explicitly specified module resolution kind: 'Node10'.", "Loading module '@typescript/lib-dom' from 'node_modules' folder, target file types: TypeScript, Declaration.", diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.trace.json b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.trace.json index 5598b74ec8099..a84c6cc085223 100644 --- a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.trace.json +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.trace.json @@ -836,6 +836,30 @@ "Searching all ancestor node_modules directories for fallback extensions: JavaScript.", "Directory '/node_modules' does not exist, skipping all lookups in it.", "======== Module name '@typescript/lib-esnext/promise' was not resolved. ========", + "======== Resolving module '@typescript/lib-esnext/object' from '/.src/__lib_node_modules_lookup_lib.esnext.object.d.ts__.ts'. ========", + "Explicitly specified module resolution kind: 'Node10'.", + "Loading module '@typescript/lib-esnext/object' from 'node_modules' folder, target file types: TypeScript, Declaration.", + "Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.", + "Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-esnext/object'", + "Directory '/node_modules' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-esnext/object'", + "Loading module '@typescript/lib-esnext/object' from 'node_modules' folder, target file types: JavaScript.", + "Searching all ancestor node_modules directories for fallback extensions: JavaScript.", + "Directory '/node_modules' does not exist, skipping all lookups in it.", + "======== Module name '@typescript/lib-esnext/object' was not resolved. ========", + "======== Resolving module '@typescript/lib-esnext/collection' from '/.src/__lib_node_modules_lookup_lib.esnext.collection.d.ts__.ts'. ========", + "Explicitly specified module resolution kind: 'Node10'.", + "Loading module '@typescript/lib-esnext/collection' from 'node_modules' folder, target file types: TypeScript, Declaration.", + "Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.", + "Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-esnext/collection'", + "Directory '/node_modules' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-esnext/collection'", + "Loading module '@typescript/lib-esnext/collection' from 'node_modules' folder, target file types: JavaScript.", + "Searching all ancestor node_modules directories for fallback extensions: JavaScript.", + "Directory '/node_modules' does not exist, skipping all lookups in it.", + "======== Module name '@typescript/lib-esnext/collection' was not resolved. ========", "======== Resolving module '@typescript/lib-dom' from '/.src/__lib_node_modules_lookup_lib.dom.d.ts__.ts'. ========", "Explicitly specified module resolution kind: 'Node10'.", "Loading module '@typescript/lib-dom' from 'node_modules' folder, target file types: TypeScript, Declaration.", diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.trace.json b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.trace.json index ded85860a42e3..50d0ecbeb1d53 100644 --- a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.trace.json +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.trace.json @@ -819,6 +819,30 @@ "Searching all ancestor node_modules directories for fallback extensions: JavaScript.", "Directory '/node_modules' does not exist, skipping all lookups in it.", "======== Module name '@typescript/lib-esnext/promise' was not resolved. ========", + "======== Resolving module '@typescript/lib-esnext/object' from '/.src/__lib_node_modules_lookup_lib.esnext.object.d.ts__.ts'. ========", + "Explicitly specified module resolution kind: 'Node10'.", + "Loading module '@typescript/lib-esnext/object' from 'node_modules' folder, target file types: TypeScript, Declaration.", + "Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.", + "Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-esnext/object'", + "Directory '/node_modules' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-esnext/object'", + "Loading module '@typescript/lib-esnext/object' from 'node_modules' folder, target file types: JavaScript.", + "Searching all ancestor node_modules directories for fallback extensions: JavaScript.", + "Directory '/node_modules' does not exist, skipping all lookups in it.", + "======== Module name '@typescript/lib-esnext/object' was not resolved. ========", + "======== Resolving module '@typescript/lib-esnext/collection' from '/.src/__lib_node_modules_lookup_lib.esnext.collection.d.ts__.ts'. ========", + "Explicitly specified module resolution kind: 'Node10'.", + "Loading module '@typescript/lib-esnext/collection' from 'node_modules' folder, target file types: TypeScript, Declaration.", + "Searching all ancestor node_modules directories for preferred extensions: TypeScript, Declaration.", + "Directory '/.src/node_modules/@types' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-esnext/collection'", + "Directory '/node_modules' does not exist, skipping all lookups in it.", + "Scoped package detected, looking in 'typescript__lib-esnext/collection'", + "Loading module '@typescript/lib-esnext/collection' from 'node_modules' folder, target file types: JavaScript.", + "Searching all ancestor node_modules directories for fallback extensions: JavaScript.", + "Directory '/node_modules' does not exist, skipping all lookups in it.", + "======== Module name '@typescript/lib-esnext/collection' was not resolved. ========", "======== Resolving module '@typescript/lib-dom' from '/.src/__lib_node_modules_lookup_lib.dom.d.ts__.ts'. ========", "Explicitly specified module resolution kind: 'Node10'.", "Loading module '@typescript/lib-dom' from 'node_modules' folder, target file types: TypeScript, Declaration.", diff --git a/tests/cases/compiler/mapGroupBy.ts b/tests/cases/compiler/mapGroupBy.ts new file mode 100644 index 0000000000000..a9fbbe9247020 --- /dev/null +++ b/tests/cases/compiler/mapGroupBy.ts @@ -0,0 +1,11 @@ +// @target: esnext + +const basic = Map.groupBy([0, 2, 8], x => x < 5 ? 'small' : 'large'); + +const chars = Map.groupBy('a string', c => c); + +type Employee = { name: string, role: 'ic' | 'manager' } +const employees: Set = new Set(); +const byRole = Map.groupBy(employees, x => x.role); + +const byNonKey = Map.groupBy(employees, x => x); diff --git a/tests/cases/compiler/objectGroupBy.ts b/tests/cases/compiler/objectGroupBy.ts new file mode 100644 index 0000000000000..5dd93542493f1 --- /dev/null +++ b/tests/cases/compiler/objectGroupBy.ts @@ -0,0 +1,11 @@ +// @target: esnext + +const basic = Object.groupBy([0, 2, 8], x => x < 5 ? 'small' : 'large'); + +const chars = Object.groupBy('a string', c => c); + +type Employee = { name: string, role: 'ic' | 'manager' } +const employees: Set = new Set(); +const byRole = Object.groupBy(employees, x => x.role); + +const byNonKey = Object.groupBy(employees, x => x); From ea9aed8d996a5a9a71204de6d247524cff587c59 Mon Sep 17 00:00:00 2001 From: Titian Cernicova-Dragomir Date: Thu, 11 Jan 2024 21:11:53 +0000 Subject: [PATCH 11/11] Reduce buffer to string conversions. (#56961) --- src/harness/vfsUtil.ts | 59 ++++++++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 19 deletions(-) diff --git a/src/harness/vfsUtil.ts b/src/harness/vfsUtil.ts index 5d34d0bf15fb5..1d387f0c16c3f 100644 --- a/src/harness/vfsUtil.ts +++ b/src/harness/vfsUtil.ts @@ -656,8 +656,8 @@ export class FileSystem { if (isDirectory(node)) throw createIOError("EISDIR"); if (!isFile(node)) throw createIOError("EBADF"); - const buffer = this._getBuffer(node).slice(); - return encoding ? buffer.toString(encoding) : buffer; + const fileBuffer = this._getBuffer(node, encoding ?? undefined); + return !fileBuffer.encoding ? fileBuffer.data.slice() : fileBuffer.data; } /** @@ -681,8 +681,11 @@ export class FileSystem { if (isDirectory(node)) throw createIOError("EISDIR"); if (!isFile(node)) throw createIOError("EBADF"); - node.buffer = Buffer.isBuffer(data) ? data.slice() : ts.sys.bufferFrom!("" + data, encoding || "utf8") as Buffer; - node.size = node.buffer.byteLength; + node.buffer = Buffer.isBuffer(data) ? + { encoding: undefined, data: data.slice() } : + { encoding: (encoding ?? "utf8") as BufferEncoding, data }; + // Updated the size if it's easy to get, otherwise set to undefined. _getSize will compute the correct size + node.size = !node.buffer.encoding ? node.buffer.data.byteLength : undefined; node.mtimeMs = time; node.ctimeMs = time; } @@ -700,6 +703,7 @@ export class FileSystem { return hasDifferences ? differences : undefined; } + public static defaultEncoding: BufferEncoding | undefined = "utf8"; /** * Generates a `FileSet` patch containing all the entries in `changed` that are not in `base`. */ @@ -800,24 +804,28 @@ export class FileSystem { baseNode.resolver === changedNode.resolver && baseNode.source === changedNode.source ) return false; - const changedBuffer = changed._getBuffer(changedNode); - const baseBuffer = base._getBuffer(baseNode); + const encoding = changedNode.buffer?.encoding ?? baseNode.buffer?.encoding ?? FileSystem.defaultEncoding; + const changedBuffer = changed._getBuffer(changedNode, encoding); + const baseBuffer = base._getBuffer(baseNode, encoding); // no difference if both buffers are the same reference if (changedBuffer === baseBuffer) { if (!options.includeChangedFileWithSameContent || changedNode.mtimeMs === baseNode.mtimeMs) return false; - container[basename] = new SameFileWithModifiedTime(changedBuffer); + container[basename] = new SameFileWithModifiedTime(changedBuffer.data, { encoding: changedBuffer.encoding }); return true; } // no difference if both buffers are identical - if (Buffer.compare(changedBuffer, baseBuffer) === 0) { + if ( + !changedBuffer.encoding && !baseBuffer.encoding && Buffer.compare(changedBuffer.data, baseBuffer.data) === 0 // same buffer content + || changedBuffer.encoding === baseBuffer.encoding && changedBuffer.data === baseBuffer.data // same string content + ) { if (!options.includeChangedFileWithSameContent) return false; - container[basename] = new SameFileContentFile(changedBuffer); + container[basename] = new SameFileContentFile(changedBuffer.data, { encoding: changedBuffer.encoding }); return true; } - container[basename] = new File(changedBuffer); + container[basename] = new File(changedBuffer.data, { encoding: changedBuffer.encoding }); return true; } @@ -838,7 +846,8 @@ export class FileSystem { container[basename] = new Symlink(node.symlink); } else { - container[basename] = new File(changed._getBuffer(node)); + const buffer = changed._getBuffer(node, FileSystem.defaultEncoding); + container[basename] = new File(buffer.data, { encoding: buffer.encoding ?? undefined }); } return true; } @@ -984,14 +993,14 @@ export class FileSystem { } private _getSize(node: FileInode): number { - if (node.buffer) return node.buffer.byteLength; + if (node.buffer) return Buffer.byteLength(node.buffer.data); if (node.size !== undefined) return node.size; if (node.source && node.resolver) return node.size = node.resolver.statSync(node.source).size; if (this._shadowRoot && node.shadowRoot) return node.size = this._shadowRoot._getSize(node.shadowRoot); return 0; } - private _getBuffer(node: FileInode): Buffer { + private _getBuffer(node: FileInode, encoding: BufferEncoding | undefined): FileDataBuffer { if (!node.buffer) { const { source, resolver } = node; if (source && resolver) { @@ -1001,12 +1010,13 @@ export class FileSystem { node.buffer = resolver.readFileSync(source); } else if (this._shadowRoot && node.shadowRoot) { - node.buffer = this._shadowRoot._getBuffer(node.shadowRoot); + node.buffer = this._shadowRoot._getBuffer(node.shadowRoot, encoding); } else { - node.buffer = Buffer.allocUnsafe(0); + node.buffer = { encoding: undefined, data: Buffer.allocUnsafe(0) }; } } + ensureBufferEncoding(node.buffer, encoding); return node.buffer; } @@ -1189,7 +1199,7 @@ export interface Traversal { export interface FileSystemResolver { statSync(path: string): { mode: number; size: number; }; readdirSync(path: string): string[]; - readFileSync(path: string): Buffer; + readFileSync(path: string): FileDataBuffer; } export interface FileSystemResolverHost { @@ -1219,8 +1229,8 @@ export function createResolver(host: FileSystemResolverHost): FileSystemResolver throw new Error("ENOENT: path does not exist"); } }, - readFileSync(path: string): Buffer { - return ts.sys.bufferFrom!(host.readFile(path)!, "utf8") as Buffer; // TODO: GH#18217 + readFileSync(path: string): FileDataBuffer { + return { encoding: "utf8", data: host.readFile(path)! }; }, }; } @@ -1444,6 +1454,17 @@ export class Mount { // a generic POSIX inode type Inode = FileInode | DirectoryInode | SymlinkInode; +type FileDataBuffer = { encoding?: undefined; data: Buffer; } | { encoding: BufferEncoding; data: string; }; + +function ensureBufferEncoding(fileBuffer: FileDataBuffer, encoding: BufferEncoding | undefined) { + if (fileBuffer.encoding === encoding) return; + + const buffer = !fileBuffer.encoding ? fileBuffer.data : ts.sys.bufferFrom!(fileBuffer.data, fileBuffer.encoding); + + fileBuffer.encoding = encoding; + fileBuffer.data = !encoding ? buffer as Buffer : buffer.toString(encoding); +} + interface FileInode { dev: number; // device id ino: number; // inode id @@ -1454,7 +1475,7 @@ interface FileInode { birthtimeMs: number; // creation time nlink: number; // number of hard links size?: number; - buffer?: Buffer; + buffer?: FileDataBuffer; source?: string; resolver?: FileSystemResolver; shadowRoot?: FileInode;