From afee8bf9682dfb3ed927fdc7756d96a19851b811 Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Wed, 2 Feb 2022 06:06:01 +0000 Subject: [PATCH 01/55] Update package-lock.json --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index faefba0ed189a..33402e194a068 100644 --- a/package-lock.json +++ b/package-lock.json @@ -687,9 +687,9 @@ "dev": true }, "@types/node": { - "version": "17.0.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.13.tgz", - "integrity": "sha512-Y86MAxASe25hNzlDbsviXl8jQHb0RDvKt4c40ZJQ1Don0AAL0STLZSs4N+6gLEO55pedy7r2cLwS+ZDxPm/2Bw==", + "version": "17.0.14", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.14.tgz", + "integrity": "sha512-SbjLmERksKOGzWzPNuW7fJM7fk3YXVTFiZWB/Hs99gwhk+/dnrQRPBQjPW9aO+fi1tAffi9PrwFvsmOKmDTyng==", "dev": true }, "@types/node-fetch": { From 854cec7387292d5385d6d02527f6693cf6e61b17 Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Wed, 2 Feb 2022 20:45:18 +0200 Subject: [PATCH 02/55] fix(47670): remove import alias that uses the same name (#47676) --- src/services/organizeImports.ts | 19 +++++++++++++++++-- tests/cases/fourslash/organizeImports8.ts | 9 +++++++++ tests/cases/fourslash/organizeImports9.ts | 9 +++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 tests/cases/fourslash/organizeImports8.ts create mode 100644 tests/cases/fourslash/organizeImports9.ts diff --git a/src/services/organizeImports.ts b/src/services/organizeImports.ts index 5463cf00585d4..77fba1707b0e8 100644 --- a/src/services/organizeImports.ts +++ b/src/services/organizeImports.ts @@ -236,10 +236,9 @@ namespace ts.OrganizeImports { } } - newImportSpecifiers.push(...flatMap(namedImports, i => (i.importClause!.namedBindings as NamedImports).elements)); // TODO: GH#18217 + newImportSpecifiers.push(...getNewImportSpecifiers(namedImports)); const sortedImportSpecifiers = sortSpecifiers(newImportSpecifiers); - const importDecl = defaultImports.length > 0 ? defaultImports[0] : namedImports[0]; @@ -492,4 +491,20 @@ namespace ts.OrganizeImports { return 6; } } + + function getNewImportSpecifiers(namedImports: ImportDeclaration[]) { + return flatMap(namedImports, namedImport => + map(tryGetNamedBindingElements(namedImport), importSpecifier => + importSpecifier.name && importSpecifier.propertyName && importSpecifier.name.escapedText === importSpecifier.propertyName.escapedText + ? factory.updateImportSpecifier(importSpecifier, importSpecifier.isTypeOnly, /*propertyName*/ undefined, importSpecifier.name) + : importSpecifier + ) + ); + } + + function tryGetNamedBindingElements(namedImport: ImportDeclaration) { + return namedImport.importClause?.namedBindings && isNamedImports(namedImport.importClause.namedBindings) + ? namedImport.importClause.namedBindings.elements + : undefined; + } } diff --git a/tests/cases/fourslash/organizeImports8.ts b/tests/cases/fourslash/organizeImports8.ts new file mode 100644 index 0000000000000..e2eecae7672f2 --- /dev/null +++ b/tests/cases/fourslash/organizeImports8.ts @@ -0,0 +1,9 @@ +/// + +////import { foo as foo } from "foo"; +////foo; + +verify.organizeImports( +`import { foo } from "foo"; +foo;` +); diff --git a/tests/cases/fourslash/organizeImports9.ts b/tests/cases/fourslash/organizeImports9.ts new file mode 100644 index 0000000000000..af1010b564904 --- /dev/null +++ b/tests/cases/fourslash/organizeImports9.ts @@ -0,0 +1,9 @@ +/// + +////import { a as a, b, c, d as d, e as e } from "foo"; +////a(b, d); + +verify.organizeImports( +`import { a, b, d } from "foo"; +a(b, d);` +); From c4fd0028f5b79aef118f360429f1930ba6c72e97 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 2 Feb 2022 14:00:08 -0800 Subject: [PATCH 03/55] Fix @link https:// formatting (#47705) * Fix @link https:// formatting Also improve .d.ts formatting of `@link`,`@linkcode`,`@linkplain`. Fixes #46734 1. Previously, `@link` incorrectly put a space between "https" and "://" when formatting jsdoc for editors. Now it does not. 2. When fixing the same output for .d.ts, I discovered that all `@link` tags were formatted as `@link`, even if they were `@linkcode` or `@linkplain`. I fixed that too. * semicolon lint --- src/compiler/utilitiesPublic.ts | 13 +- src/services/utilities.ts | 2 +- tests/baselines/reference/linkTagEmit1.js | 14 ++ .../baselines/reference/linkTagEmit1.symbols | 6 + tests/baselines/reference/linkTagEmit1.types | 7 + ...foForJSDocWithUnresolvedHttpLinks.baseline | 126 ++++++++++++++++++ tests/cases/conformance/jsdoc/linkTagEmit1.ts | 5 + ...uickInfoForJSDocWithUnresolvedHttpLinks.ts | 12 ++ 8 files changed, 181 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/quickInfoForJSDocWithUnresolvedHttpLinks.baseline create mode 100644 tests/cases/fourslash/quickInfoForJSDocWithUnresolvedHttpLinks.ts diff --git a/src/compiler/utilitiesPublic.ts b/src/compiler/utilitiesPublic.ts index 8f834e5e45971..24f812476cdeb 100644 --- a/src/compiler/utilitiesPublic.ts +++ b/src/compiler/utilitiesPublic.ts @@ -905,9 +905,16 @@ namespace ts { /** Gets the text of a jsdoc comment, flattening links to their text. */ export function getTextOfJSDocComment(comment?: string | NodeArray) { return typeof comment === "string" ? comment - : comment?.map(c => - // TODO: Other kinds here - c.kind === SyntaxKind.JSDocText ? c.text : `{@link ${c.name ? entityNameToString(c.name) + " " : ""}${c.text}}`).join(""); + : comment?.map(c => c.kind === SyntaxKind.JSDocText ? c.text : formatJSDocLink(c)).join(""); + } + + function formatJSDocLink(link: JSDocLink | JSDocLinkCode | JSDocLinkPlain) { + const kind = link.kind === SyntaxKind.JSDocLink ? "link" + : link.kind === SyntaxKind.JSDocLinkCode ? "linkcode" + : "linkplain"; + const name = link.name ? entityNameToString(link.name) : ""; + const space = link.name && link.text.startsWith("://") ? "" : " "; + return `{@${kind} ${name}${space}${link.text}}`; } /** diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 98ac7627e32d7..f36346a14d46d 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -2320,7 +2320,7 @@ namespace ts { if (text) parts.push(linkTextPart(text)); } else { - parts.push(linkTextPart(name + (suffix ? "" : " ") + text)); + parts.push(linkTextPart(name + (suffix || text.indexOf("://") === 0 ? "" : " ") + text)); } } parts.push(linkPart("}")); diff --git a/tests/baselines/reference/linkTagEmit1.js b/tests/baselines/reference/linkTagEmit1.js index 377fa211381c8..0fe024f665afa 100644 --- a/tests/baselines/reference/linkTagEmit1.js +++ b/tests/baselines/reference/linkTagEmit1.js @@ -20,6 +20,11 @@ declare namespace NS { function computeCommonSourceDirectoryOfFilenames(integer) { return integer + 1 // pls pls pls } + +/** {@link https://hvad} */ +var see3 = true + +/** @typedef {number} Attempt {@link https://wat} {@linkcode I think lingcod is better} {@linkplain or lutefisk}*/ //// [linkTagEmit1.js] @@ -36,6 +41,9 @@ function computeCommonSourceDirectoryOfFilenames(integer) { function computeCommonSourceDirectoryOfFilenames(integer) { return integer + 1; // pls pls pls } +/** {@link https://hvad} */ +var see3 = true; +/** @typedef {number} Attempt {@link https://wat} {@linkcode I think lingcod is better} {@linkplain or lutefisk}*/ //// [linkTagEmit1.d.ts] @@ -50,6 +58,8 @@ function computeCommonSourceDirectoryOfFilenames(integer) { * @param {number} integer {@link Z} */ declare function computeCommonSourceDirectoryOfFilenames(integer: number): number; +/** {@link https://hvad} */ +declare var see3: boolean; type N = number; type D1 = { /** @@ -62,3 +72,7 @@ type D1 = { m: 1; }; type Z = number; +/** + * {@link https://wat} {@linkcode I think lingcod is better} {@linkplain or lutefisk} + */ +type Attempt = number; diff --git a/tests/baselines/reference/linkTagEmit1.symbols b/tests/baselines/reference/linkTagEmit1.symbols index 30b7ab681f89b..047da5804156c 100644 --- a/tests/baselines/reference/linkTagEmit1.symbols +++ b/tests/baselines/reference/linkTagEmit1.symbols @@ -26,3 +26,9 @@ function computeCommonSourceDirectoryOfFilenames(integer) { >integer : Symbol(integer, Decl(linkTagEmit1.js, 12, 49)) } +/** {@link https://hvad} */ +var see3 = true +>see3 : Symbol(see3, Decl(linkTagEmit1.js, 17, 3)) + +/** @typedef {number} Attempt {@link https://wat} {@linkcode I think lingcod is better} {@linkplain or lutefisk}*/ + diff --git a/tests/baselines/reference/linkTagEmit1.types b/tests/baselines/reference/linkTagEmit1.types index a5456e3877f0b..17bdfb38f6268 100644 --- a/tests/baselines/reference/linkTagEmit1.types +++ b/tests/baselines/reference/linkTagEmit1.types @@ -26,3 +26,10 @@ function computeCommonSourceDirectoryOfFilenames(integer) { >1 : 1 } +/** {@link https://hvad} */ +var see3 = true +>see3 : boolean +>true : true + +/** @typedef {number} Attempt {@link https://wat} {@linkcode I think lingcod is better} {@linkplain or lutefisk}*/ + diff --git a/tests/baselines/reference/quickInfoForJSDocWithUnresolvedHttpLinks.baseline b/tests/baselines/reference/quickInfoForJSDocWithUnresolvedHttpLinks.baseline new file mode 100644 index 0000000000000..7700b2b908f78 --- /dev/null +++ b/tests/baselines/reference/quickInfoForJSDocWithUnresolvedHttpLinks.baseline @@ -0,0 +1,126 @@ +[ + { + "marker": { + "fileName": "/tests/cases/fourslash/quickInfoForJSDocWithHttpLinks.js", + "position": 36, + "name": "5" + }, + "quickInfo": { + "kind": "var", + "kindModifiers": "", + "textSpan": { + "start": 36, + "length": 4 + }, + "displayParts": [ + { + "text": "var", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "see2", + "kind": "localName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "boolean", + "kind": "keyword" + } + ], + "documentation": [], + "tags": [ + { + "name": "see", + "text": [ + { + "text": "", + "kind": "text" + }, + { + "text": "{@link ", + "kind": "link" + }, + { + "text": "https://hva", + "kind": "linkText" + }, + { + "text": "}", + "kind": "link" + } + ] + } + ] + } + }, + { + "marker": { + "fileName": "/tests/cases/fourslash/quickInfoForJSDocWithHttpLinks.js", + "position": 81, + "name": "6" + }, + "quickInfo": { + "kind": "var", + "kindModifiers": "", + "textSpan": { + "start": 81, + "length": 4 + }, + "displayParts": [ + { + "text": "var", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "see3", + "kind": "localName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "boolean", + "kind": "keyword" + } + ], + "documentation": [ + { + "text": "", + "kind": "text" + }, + { + "text": "{@link ", + "kind": "link" + }, + { + "text": "https://hvaD", + "kind": "linkText" + }, + { + "text": "}", + "kind": "link" + } + ] + } + } +] \ No newline at end of file diff --git a/tests/cases/conformance/jsdoc/linkTagEmit1.ts b/tests/cases/conformance/jsdoc/linkTagEmit1.ts index 3c35376414618..e53e45c3d4ea1 100644 --- a/tests/cases/conformance/jsdoc/linkTagEmit1.ts +++ b/tests/cases/conformance/jsdoc/linkTagEmit1.ts @@ -21,3 +21,8 @@ declare namespace NS { function computeCommonSourceDirectoryOfFilenames(integer) { return integer + 1 // pls pls pls } + +/** {@link https://hvad} */ +var see3 = true + +/** @typedef {number} Attempt {@link https://wat} {@linkcode I think lingcod is better} {@linkplain or lutefisk}*/ diff --git a/tests/cases/fourslash/quickInfoForJSDocWithUnresolvedHttpLinks.ts b/tests/cases/fourslash/quickInfoForJSDocWithUnresolvedHttpLinks.ts new file mode 100644 index 0000000000000..eb892b9ce1945 --- /dev/null +++ b/tests/cases/fourslash/quickInfoForJSDocWithUnresolvedHttpLinks.ts @@ -0,0 +1,12 @@ +/// +// @checkJs: true +// @filename: quickInfoForJSDocWithHttpLinks.js +// #46734 + +//// /** @see {@link https://hva} */ +//// var /*5*/see2 = true +//// +//// /** {@link https://hvaD} */ +//// var /*6*/see3 = true + +verify.baselineQuickInfo(); From 9b0f01a13f3d9272d1d71cf9151d7617581e4853 Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Thu, 3 Feb 2022 06:06:30 +0000 Subject: [PATCH 04/55] Update package-lock.json --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 33402e194a068..3501b7ef0090b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5124,9 +5124,9 @@ } }, "loupe": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.1.tgz", - "integrity": "sha512-EN1D3jyVmaX4tnajVlfbREU4axL647hLec1h/PXAb8CPDMJiYitcWF2UeLVNttRqaIqQs4x+mRvXf+d+TlDrCA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.2.tgz", + "integrity": "sha512-QgVamnvj0jX1LMPlCAq0MK6hATORFtGqHoUKXTkwNe13BqlN6aePQCKnnTcFvdDYEEITcJ+gBl4mTW7YJtJbyQ==", "dev": true, "requires": { "get-func-name": "^2.0.0" From b7d011777e5d492eedeabd7cc7fddbe1324d4b62 Mon Sep 17 00:00:00 2001 From: Oliver Joseph Ash Date: Thu, 3 Feb 2022 18:13:05 +0000 Subject: [PATCH 05/55] "Convert parameters to destructured object": enable for functions with just one parameter (#46945) * "Convert parameters to destructured object": enable for functions with just one parameter Fixes https://github.com/microsoft/TypeScript/issues/41753 * Add test --- .../refactors/convertParamsToDestructuredObject.ts | 2 +- ...cturedObject_arrowFunctionWithSingleParameter.ts | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 tests/cases/fourslash/refactorConvertParamsToDestructuredObject_arrowFunctionWithSingleParameter.ts diff --git a/src/services/refactors/convertParamsToDestructuredObject.ts b/src/services/refactors/convertParamsToDestructuredObject.ts index 784cefda23b49..5fcd96a801870 100644 --- a/src/services/refactors/convertParamsToDestructuredObject.ts +++ b/src/services/refactors/convertParamsToDestructuredObject.ts @@ -1,7 +1,7 @@ /* @internal */ namespace ts.refactor.convertParamsToDestructuredObject { const refactorName = "Convert parameters to destructured object"; - const minimumParameterLength = 2; + const minimumParameterLength = 1; const refactorDescription = getLocaleSpecificMessage(Diagnostics.Convert_parameters_to_destructured_object); const toDestructuredAction = { diff --git a/tests/cases/fourslash/refactorConvertParamsToDestructuredObject_arrowFunctionWithSingleParameter.ts b/tests/cases/fourslash/refactorConvertParamsToDestructuredObject_arrowFunctionWithSingleParameter.ts new file mode 100644 index 0000000000000..5c130b3b0e9da --- /dev/null +++ b/tests/cases/fourslash/refactorConvertParamsToDestructuredObject_arrowFunctionWithSingleParameter.ts @@ -0,0 +1,13 @@ +/// + +////const foo = /*a*/(a: number)/*b*/ => { }; +////foo(1); + +goTo.select("a", "b"); +edit.applyRefactor({ + refactorName: "Convert parameters to destructured object", + actionName: "Convert parameters to destructured object", + actionDescription: "Convert parameters to destructured object", + newContent: `const foo = ({ a }: { a: number; }) => { }; +foo({ a: 1 });`, +}); From 8d47ea0064a35bb0cc19a5464298c814d6536888 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Feb 2022 11:22:54 -0800 Subject: [PATCH 06/55] Bump node-fetch from 2.6.1 to 2.6.7 (#47564) Bumps [node-fetch](https://github.com/node-fetch/node-fetch) from 2.6.1 to 2.6.7. - [Release notes](https://github.com/node-fetch/node-fetch/releases) - [Changelog](https://github.com/node-fetch/node-fetch/blob/main/docs/CHANGELOG.md) - [Commits](https://github.com/node-fetch/node-fetch/compare/v2.6.1...v2.6.7) --- updated-dependencies: - dependency-name: node-fetch dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3501b7ef0090b..0a737e94eb56d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5848,10 +5848,13 @@ "dev": true }, "node-fetch": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", - "dev": true + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "requires": { + "whatwg-url": "^5.0.0" + } }, "normalize-package-data": { "version": "2.5.0", From 46d1cb11e2af58d53929eb957fa8966fca4bbc7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=A8=E6=98=93=E4=BB=80=E4=B9=88=E6=9D=A5=E7=9D=80?= <38951157+mysmlz@users.noreply.github.com> Date: Fri, 4 Feb 2022 03:23:36 +0800 Subject: [PATCH 07/55] i18n:Inappropriate localization (#46924) The previous version of the file incorrectly translated the keywords of some document comments into Chinese, which would be misleading --- lib/zh-cn/diagnosticMessages.generated.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/zh-cn/diagnosticMessages.generated.json b/lib/zh-cn/diagnosticMessages.generated.json index 9c79f7feb06f7..824ee7b5c06fd 100644 --- a/lib/zh-cn/diagnosticMessages.generated.json +++ b/lib/zh-cn/diagnosticMessages.generated.json @@ -130,7 +130,7 @@ "Add_await_to_initializer_for_0_95084": "将 \"await\" 添加到 \"{0}\" 的初始值设定项", "Add_await_to_initializers_95089": "将 \"await\" 添加到初始值设定项", "Add_braces_to_arrow_function_95059": "向箭头函数添加大括号", - "Add_class_tag_95102": "添加“@类”标记", + "Add_class_tag_95102": "添加“@class”标记", "Add_const_to_all_unresolved_variables_95082": "将 \"const\" 添加到所有未解析变量", "Add_const_to_unresolved_variable_95081": "将 \"const\" 添加到未解析的变量", "Add_default_import_0_to_existing_import_declaration_from_1_90033": "将默认导入 \"{0}\" 从 \"{1}\" 添加到现有导入声明。", @@ -154,7 +154,7 @@ "Add_parameter_name_90034": "添加参数名称", "Add_qualifier_to_all_unresolved_variables_matching_a_member_name_95037": "将限定符添加到匹配成员名称的所有未解析变量", "Add_this_parameter_95104": "添加“此”参数。", - "Add_this_tag_95103": "添加“@此”标记", + "Add_this_tag_95103": "添加“@this”标记", "Add_to_all_uncalled_decorators_95044": "将 \"()\" 添加到所有未调用的修饰器", "Add_ts_ignore_to_all_error_messages_95042": "将 \"@ts-ignore\" 添加到所有错误消息", "Add_undefined_to_a_type_when_accessed_using_an_index_6674": "使用索引访问时,将 “undefined” 添加到类型。", @@ -1784,4 +1784,4 @@ "with_statements_are_not_allowed_in_strict_mode_1101": "严格模式下不允许使用 \"with\" 语句。", "yield_expression_implicitly_results_in_an_any_type_because_its_containing_generator_lacks_a_return_t_7057": "\"yield\" 表达式隐式导致 \"any\" 类型,因为它的包含生成器缺少返回类型批注。", "yield_expressions_cannot_be_used_in_a_parameter_initializer_2523": "不能在参数初始化表达式中使用 \"yield\" 表达式。" -} \ No newline at end of file +} From 0d5abd8a15fb8bbb97e8f53cdf4d28299516ff8c Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Thu, 3 Feb 2022 21:27:40 +0200 Subject: [PATCH 08/55] feat(27601): include JSDoc comments for destructuring arguments (#46886) --- src/services/symbolDisplay.ts | 13 ++ ...InfoForObjectBindingElementName03.baseline | 57 +++++++ ...InfoForObjectBindingElementName04.baseline | 148 ++++++++++++++++++ ...InfoForObjectBindingElementName05.baseline | 73 +++++++++ .../quickInfoForObjectBindingElementName03.ts | 14 ++ .../quickInfoForObjectBindingElementName04.ts | 20 +++ .../quickInfoForObjectBindingElementName05.ts | 17 ++ 7 files changed, 342 insertions(+) create mode 100644 tests/baselines/reference/quickInfoForObjectBindingElementName03.baseline create mode 100644 tests/baselines/reference/quickInfoForObjectBindingElementName04.baseline create mode 100644 tests/baselines/reference/quickInfoForObjectBindingElementName05.baseline create mode 100644 tests/cases/fourslash/quickInfoForObjectBindingElementName03.ts create mode 100644 tests/cases/fourslash/quickInfoForObjectBindingElementName04.ts create mode 100644 tests/cases/fourslash/quickInfoForObjectBindingElementName05.ts diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts index 15325ea9e4f91..973e28476b6a5 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -584,6 +584,19 @@ namespace ts.SymbolDisplay { } } + if (documentation.length === 0 && isIdentifier(location) && symbol.valueDeclaration && isBindingElement(symbol.valueDeclaration)) { + const declaration = symbol.valueDeclaration; + const parent = declaration.parent; + if (isIdentifier(declaration.name) && isObjectBindingPattern(parent)) { + const name = getTextOfIdentifierOrLiteral(declaration.name); + const objectType = typeChecker.getTypeAtLocation(parent); + documentation = firstDefined(objectType.isUnion() ? objectType.types : [objectType], t => { + const prop = t.getProperty(name); + return prop ? prop.getDocumentationComment(typeChecker) : undefined; + }) || emptyArray; + } + } + if (tags.length === 0 && !hasMultipleSignatures) { tags = symbol.getContextualJsDocTags(enclosingDeclaration, typeChecker); } diff --git a/tests/baselines/reference/quickInfoForObjectBindingElementName03.baseline b/tests/baselines/reference/quickInfoForObjectBindingElementName03.baseline new file mode 100644 index 0000000000000..4e311ef906f73 --- /dev/null +++ b/tests/baselines/reference/quickInfoForObjectBindingElementName03.baseline @@ -0,0 +1,57 @@ +[ + { + "marker": { + "fileName": "/tests/cases/fourslash/quickInfoForObjectBindingElementName03.ts", + "position": 122, + "name": "1" + }, + "quickInfo": { + "kind": "parameter", + "kindModifiers": "", + "textSpan": { + "start": 119, + "length": 3 + }, + "displayParts": [ + { + "text": "(", + "kind": "punctuation" + }, + { + "text": "parameter", + "kind": "text" + }, + { + "text": ")", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "foo", + "kind": "parameterName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "string", + "kind": "keyword" + } + ], + "documentation": [ + { + "text": "A description of foo", + "kind": "text" + } + ] + } + } +] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoForObjectBindingElementName04.baseline b/tests/baselines/reference/quickInfoForObjectBindingElementName04.baseline new file mode 100644 index 0000000000000..0370d38cdb46b --- /dev/null +++ b/tests/baselines/reference/quickInfoForObjectBindingElementName04.baseline @@ -0,0 +1,148 @@ +[ + { + "marker": { + "fileName": "/tests/cases/fourslash/quickInfoForObjectBindingElementName04.ts", + "position": 193, + "name": "1" + }, + "quickInfo": { + "kind": "parameter", + "kindModifiers": "", + "textSpan": { + "start": 192, + "length": 1 + }, + "displayParts": [ + { + "text": "(", + "kind": "punctuation" + }, + { + "text": "parameter", + "kind": "text" + }, + { + "text": ")", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "a", + "kind": "parameterName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "{", + "kind": "punctuation" + }, + { + "text": "\n", + "kind": "lineBreak" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "b", + "kind": "propertyName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "string", + "kind": "keyword" + }, + { + "text": ";", + "kind": "punctuation" + }, + { + "text": "\n", + "kind": "lineBreak" + }, + { + "text": "}", + "kind": "punctuation" + } + ], + "documentation": [ + { + "text": "A description of 'a'", + "kind": "text" + } + ] + } + }, + { + "marker": { + "fileName": "/tests/cases/fourslash/quickInfoForObjectBindingElementName04.ts", + "position": 200, + "name": "2" + }, + "quickInfo": { + "kind": "parameter", + "kindModifiers": "", + "textSpan": { + "start": 199, + "length": 1 + }, + "displayParts": [ + { + "text": "(", + "kind": "punctuation" + }, + { + "text": "parameter", + "kind": "text" + }, + { + "text": ")", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "b", + "kind": "parameterName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "string", + "kind": "keyword" + } + ], + "documentation": [ + { + "text": "A description of 'b'", + "kind": "text" + } + ] + } + } +] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoForObjectBindingElementName05.baseline b/tests/baselines/reference/quickInfoForObjectBindingElementName05.baseline new file mode 100644 index 0000000000000..9790245d186ee --- /dev/null +++ b/tests/baselines/reference/quickInfoForObjectBindingElementName05.baseline @@ -0,0 +1,73 @@ +[ + { + "marker": { + "fileName": "/tests/cases/fourslash/quickInfoForObjectBindingElementName05.ts", + "position": 137, + "name": "" + }, + "quickInfo": { + "kind": "parameter", + "kindModifiers": "", + "textSpan": { + "start": 136, + "length": 1 + }, + "displayParts": [ + { + "text": "(", + "kind": "punctuation" + }, + { + "text": "parameter", + "kind": "text" + }, + { + "text": ")", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "a", + "kind": "parameterName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "string", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "|", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "number", + "kind": "keyword" + } + ], + "documentation": [ + { + "text": "A description of a", + "kind": "text" + } + ] + } + } +] \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoForObjectBindingElementName03.ts b/tests/cases/fourslash/quickInfoForObjectBindingElementName03.ts new file mode 100644 index 0000000000000..4ead56c90ed39 --- /dev/null +++ b/tests/cases/fourslash/quickInfoForObjectBindingElementName03.ts @@ -0,0 +1,14 @@ +/// + +////interface Options { +//// /** +//// * A description of foo +//// */ +//// foo: string; +////} +//// +////function f({ foo }: Options) { +//// foo/*1*/; +////} + +verify.baselineQuickInfo(); diff --git a/tests/cases/fourslash/quickInfoForObjectBindingElementName04.ts b/tests/cases/fourslash/quickInfoForObjectBindingElementName04.ts new file mode 100644 index 0000000000000..c9844cb13ef32 --- /dev/null +++ b/tests/cases/fourslash/quickInfoForObjectBindingElementName04.ts @@ -0,0 +1,20 @@ +/// + +////interface Options { +//// /** +//// * A description of 'a' +//// */ +//// a: { +//// /** +//// * A description of 'b' +//// */ +//// b: string; +//// } +////} +//// +////function f({ a, a: { b } }: Options) { +//// a/*1*/; +//// b/*2*/; +////} + +verify.baselineQuickInfo(); diff --git a/tests/cases/fourslash/quickInfoForObjectBindingElementName05.ts b/tests/cases/fourslash/quickInfoForObjectBindingElementName05.ts new file mode 100644 index 0000000000000..defde63601945 --- /dev/null +++ b/tests/cases/fourslash/quickInfoForObjectBindingElementName05.ts @@ -0,0 +1,17 @@ +/// + +////interface A { +//// /** +//// * A description of a +//// */ +//// a: number; +////} +////interface B { +//// a: string; +////} +//// +////function f({ a }: A | B) { +//// a/**/; +////} + +verify.baselineQuickInfo(); From 69d06cb359cd1c9c6125d0b61e75de1759dcc741 Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Fri, 4 Feb 2022 06:07:01 +0000 Subject: [PATCH 09/55] Update package-lock.json --- package-lock.json | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0a737e94eb56d..3b49b5bd7d51e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -367,17 +367,6 @@ "is-plain-object": "^5.0.0", "node-fetch": "^2.6.7", "universal-user-agent": "^6.0.0" - }, - "dependencies": { - "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dev": true, - "requires": { - "whatwg-url": "^5.0.0" - } - } } }, "@octokit/request-error": { From 300a53c333895ff545e94354be3fc9fd9c01611d Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Fri, 4 Feb 2022 09:17:55 -0800 Subject: [PATCH 10/55] Auto-import perf: Do symbol name/flags filtering before cache rehydration (#47678) * Do symbol name filtering before cache rehydration * Fix typo Co-authored-by: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> * Update test * Fix variable clobbered in merge conflict Co-authored-by: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> --- src/services/completions.ts | 35 ++++++++++------- src/services/exportInfoMap.ts | 38 +++++++++---------- src/services/utilities.ts | 25 +++++++++++- .../unittests/tsserver/exportMapCache.ts | 8 ++-- 4 files changed, 66 insertions(+), 40 deletions(-) diff --git a/src/services/completions.ts b/src/services/completions.ts index e3417b9e652eb..0ec8a5d71758f 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -2495,19 +2495,26 @@ namespace ts.Completions { preferences, !!importCompletionNode, context => { - exportInfo.forEach(sourceFile.path, (info, getSymbolName, isFromAmbientModule, exportMapKey) => { - const symbolName = getSymbolName(/*preferCapitalized*/ isRightOfOpenTag); - if (!isIdentifierText(symbolName, getEmitScriptTarget(host.getCompilationSettings()))) return; - if (!detailsEntryId && isStringANonContextualKeyword(symbolName)) return; - // `targetFlags` should be the same for each `info` - if (!isTypeOnlyLocation && !importCompletionNode && !(info[0].targetFlags & SymbolFlags.Value)) return; - if (isTypeOnlyLocation && !(info[0].targetFlags & (SymbolFlags.Module | SymbolFlags.Type))) return; - // Do not try to auto-import something with a lowercase first letter for a JSX tag - const firstChar = symbolName.charCodeAt(0); - if (isRightOfOpenTag && (firstChar < CharacterCodes.A || firstChar > CharacterCodes.Z)) return; - - const isCompletionDetailsMatch = detailsEntryId && some(info, i => detailsEntryId.source === stripQuotes(i.moduleSymbol.name)); - if (isCompletionDetailsMatch || !detailsEntryId && charactersFuzzyMatchInString(symbolName, lowerCaseTokenText)) { + exportInfo.search( + sourceFile.path, + /*preferCapitalized*/ isRightOfOpenTag, + (symbolName, targetFlags) => { + if (!isIdentifierText(symbolName, getEmitScriptTarget(host.getCompilationSettings()))) return false; + if (!detailsEntryId && isStringANonContextualKeyword(symbolName)) return false; + if (!isTypeOnlyLocation && !importCompletionNode && !(targetFlags & SymbolFlags.Value)) return false; + if (isTypeOnlyLocation && !(targetFlags & (SymbolFlags.Module | SymbolFlags.Type))) return false; + // Do not try to auto-import something with a lowercase first letter for a JSX tag + const firstChar = symbolName.charCodeAt(0); + if (isRightOfOpenTag && (firstChar < CharacterCodes.A || firstChar > CharacterCodes.Z)) return false; + + if (detailsEntryId) return true; + return charactersFuzzyMatchInString(symbolName, lowerCaseTokenText); + }, + (info, symbolName, isFromAmbientModule, exportMapKey) => { + if (detailsEntryId && !some(info, i => detailsEntryId.source === stripQuotes(i.moduleSymbol.name))) { + return; + } + const defaultExportInfo = find(info, isImportableExportInfo); if (!defaultExportInfo) { return; @@ -2531,7 +2538,7 @@ namespace ts.Completions { isFromPackageJson: exportInfo.isFromPackageJson, }); } - }); + ); hasUnresolvedAutoImports = context.resolutionLimitExceeded(); } diff --git a/src/services/exportInfoMap.ts b/src/services/exportInfoMap.ts index a234e7376fa7d..adb1f97e91c09 100644 --- a/src/services/exportInfoMap.ts +++ b/src/services/exportInfoMap.ts @@ -29,6 +29,7 @@ namespace ts { // Used to rehydrate `symbol` and `moduleSymbol` when transient id: number; symbolName: string; + capitalizedSymbolName: string | undefined; symbolTableKey: __String; moduleName: string; moduleFile: SourceFile | undefined; @@ -48,7 +49,7 @@ namespace ts { clear(): void; add(importingFile: Path, symbol: Symbol, key: __String, moduleSymbol: Symbol, moduleFile: SourceFile | undefined, exportKind: ExportKind, isFromPackageJson: boolean, checker: TypeChecker): void; get(importingFile: Path, key: string): readonly SymbolExportInfo[] | undefined; - forEach(importingFile: Path, action: (info: readonly SymbolExportInfo[], getSymbolName: (preferCapitalized?: boolean) => string, isFromAmbientModule: boolean, key: string) => void): void; + search(importingFile: Path, preferCapitalized: boolean, matches: (name: string, targetFlags: SymbolFlags) => boolean, action: (info: readonly SymbolExportInfo[], symbolName: string, isFromAmbientModule: boolean, key: string) => void): void; releaseSymbols(): void; isEmpty(): boolean; /** @returns Whether the change resulted in the cache being cleared */ @@ -121,9 +122,12 @@ namespace ts { // 3. Otherwise, we have a default/namespace import that can be imported by any name, and // `symbolTableKey` will be something undesirable like `export=` or `default`, so we try to // get a better name. - const importedName = exportKind === ExportKind.Named || isExternalModuleSymbol(namedSymbol) + const names = exportKind === ExportKind.Named || isExternalModuleSymbol(namedSymbol) ? unescapeLeadingUnderscores(symbolTableKey) - : getNameForExportedSymbol(namedSymbol, /*scriptTarget*/ undefined); + : getNamesForExportedSymbol(namedSymbol, /*scriptTarget*/ undefined); + + const symbolName = typeof names === "string" ? names : names[0]; + const capitalizedSymbolName = typeof names === "string" ? undefined : names[1]; const moduleName = stripQuotes(moduleSymbol.name); const id = exportInfoId++; @@ -132,10 +136,11 @@ namespace ts { const storedModuleSymbol = moduleSymbol.flags & SymbolFlags.Transient ? undefined : moduleSymbol; if (!storedSymbol || !storedModuleSymbol) symbols.set(id, [symbol, moduleSymbol]); - exportInfo.add(key(importedName, symbol, isExternalModuleNameRelative(moduleName) ? undefined : moduleName, checker), { + exportInfo.add(key(symbolName, symbol, isExternalModuleNameRelative(moduleName) ? undefined : moduleName, checker), { id, symbolTableKey, - symbolName: importedName, + symbolName, + capitalizedSymbolName, moduleName, moduleFile, moduleFileName: moduleFile?.fileName, @@ -152,24 +157,17 @@ namespace ts { const result = exportInfo.get(key); return result?.map(rehydrateCachedInfo); }, - forEach: (importingFile, action) => { + search: (importingFile, preferCapitalized, matches, action) => { if (importingFile !== usableByFileName) return; exportInfo.forEach((info, key) => { const { symbolName, ambientModuleName } = parseKey(key); - const rehydrated = info.map(rehydrateCachedInfo); - const filtered = rehydrated.filter((r, i) => isNotShadowedByDeeperNodeModulesPackage(r, info[i].packageName)); - if (filtered.length) { - action( - filtered, - preferCapitalized => { - const { symbol, exportKind } = rehydrated[0]; - const namedSymbol = exportKind === ExportKind.Default && getLocalSymbolForExportDefault(symbol) || symbol; - return preferCapitalized - ? getNameForExportedSymbol(namedSymbol, /*scriptTarget*/ undefined, /*preferCapitalized*/ true) - : symbolName; - }, - !!ambientModuleName, - key); + const name = preferCapitalized && info[0].capitalizedSymbolName || symbolName; + if (matches(name, info[0].targetFlags)) { + const rehydrated = info.map(rehydrateCachedInfo); + const filtered = rehydrated.filter((r, i) => isNotShadowedByDeeperNodeModulesPackage(r, info[i].packageName)); + if (filtered.length) { + action(filtered, name, !!ambientModuleName, key); + } } }); }, diff --git a/src/services/utilities.ts b/src/services/utilities.ts index f36346a14d46d..016eb35227eda 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -3210,13 +3210,34 @@ namespace ts { return isArray(valueOrArray) ? first(valueOrArray) : valueOrArray; } + export function getNamesForExportedSymbol(symbol: Symbol, scriptTarget: ScriptTarget | undefined): string | [lowercase: string, capitalized: string] { + if (needsNameFromDeclaration(symbol)) { + const fromDeclaration = getDefaultLikeExportNameFromDeclaration(symbol); + if (fromDeclaration) return fromDeclaration; + const fileNameCase = codefix.moduleSymbolToValidIdentifier(getSymbolParentOrFail(symbol), scriptTarget, /*preferCapitalized*/ false); + const capitalized = codefix.moduleSymbolToValidIdentifier(getSymbolParentOrFail(symbol), scriptTarget, /*preferCapitalized*/ true); + if (fileNameCase === capitalized) return fileNameCase; + return [fileNameCase, capitalized]; + } + return symbol.name; + } + export function getNameForExportedSymbol(symbol: Symbol, scriptTarget: ScriptTarget | undefined, preferCapitalized?: boolean) { - if (!(symbol.flags & SymbolFlags.Transient) && (symbol.escapedName === InternalSymbolName.ExportEquals || symbol.escapedName === InternalSymbolName.Default)) { + if (needsNameFromDeclaration(symbol)) { // Name of "export default foo;" is "foo". Name of "export default 0" is the filename converted to camelCase. - return firstDefined(symbol.declarations, d => isExportAssignment(d) ? tryCast(skipOuterExpressions(d.expression), isIdentifier)?.text : undefined) + return getDefaultLikeExportNameFromDeclaration(symbol) || codefix.moduleSymbolToValidIdentifier(getSymbolParentOrFail(symbol), scriptTarget, !!preferCapitalized); } return symbol.name; + + } + + function needsNameFromDeclaration(symbol: Symbol) { + return !(symbol.flags & SymbolFlags.Transient) && (symbol.escapedName === InternalSymbolName.ExportEquals || symbol.escapedName === InternalSymbolName.Default); + } + + function getDefaultLikeExportNameFromDeclaration(symbol: Symbol) { + return firstDefined(symbol.declarations, d => isExportAssignment(d) ? tryCast(skipOuterExpressions(d.expression), isIdentifier)?.text : undefined); } function getSymbolParentOrFail(symbol: Symbol) { diff --git a/src/testRunner/unittests/tsserver/exportMapCache.ts b/src/testRunner/unittests/tsserver/exportMapCache.ts index b082c7f803e40..184200c07cbe4 100644 --- a/src/testRunner/unittests/tsserver/exportMapCache.ts +++ b/src/testRunner/unittests/tsserver/exportMapCache.ts @@ -87,8 +87,8 @@ namespace ts.projectSystem { // transient symbols are recreated with every new checker. const programBefore = project.getCurrentProgram()!; let sigintPropBefore: readonly SymbolExportInfo[] | undefined; - exportMapCache.forEach(bTs.path as Path, (info, getSymbolName) => { - if (getSymbolName() === "SIGINT") sigintPropBefore = info; + exportMapCache.search(bTs.path as Path, /*preferCapitalized*/ false, returnTrue, (info, symbolName) => { + if (symbolName === "SIGINT") sigintPropBefore = info; }); assert.ok(sigintPropBefore); assert.ok(sigintPropBefore![0].symbol.flags & SymbolFlags.Transient); @@ -113,8 +113,8 @@ namespace ts.projectSystem { // Get same info from cache again let sigintPropAfter: readonly SymbolExportInfo[] | undefined; - exportMapCache.forEach(bTs.path as Path, (info, getSymbolName) => { - if (getSymbolName() === "SIGINT") sigintPropAfter = info; + exportMapCache.search(bTs.path as Path, /*preferCapitalized*/ false, returnTrue, (info, symbolName) => { + if (symbolName === "SIGINT") sigintPropAfter = info; }); assert.ok(sigintPropAfter); assert.notEqual(symbolIdBefore, getSymbolId(sigintPropAfter![0].symbol)); From ceee97505262b43d7d3b7d725963ca6b325cc138 Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Fri, 4 Feb 2022 22:15:02 +0200 Subject: [PATCH 11/55] fix(45917): show completions in string literal followed by a comma (#46970) --- src/services/signatureHelp.ts | 19 +++++++++--------- .../fourslash/completionForStringLiteral16.ts | 20 +++++++++++++++++++ 2 files changed, 29 insertions(+), 10 deletions(-) create mode 100644 tests/cases/fourslash/completionForStringLiteral16.ts diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts index ea72661a8687c..e26b0f49425b8 100644 --- a/src/services/signatureHelp.ts +++ b/src/services/signatureHelp.ts @@ -169,12 +169,12 @@ namespace ts.SignatureHelp { : { invocation: info.invocation.node, argumentCount: info.argumentCount, argumentIndex: info.argumentIndex }; } - function getArgumentOrParameterListInfo(node: Node, sourceFile: SourceFile): { readonly list: Node, readonly argumentIndex: number, readonly argumentCount: number, readonly argumentsSpan: TextSpan } | undefined { + function getArgumentOrParameterListInfo(node: Node, position: number, sourceFile: SourceFile): { readonly list: Node, readonly argumentIndex: number, readonly argumentCount: number, readonly argumentsSpan: TextSpan } | undefined { const info = getArgumentOrParameterListAndIndex(node, sourceFile); if (!info) return undefined; const { list, argumentIndex } = info; - const argumentCount = getArgumentCount(list); + const argumentCount = getArgumentCount(list, /*ignoreTrailingComma*/ isInString(sourceFile, position, node)); if (argumentIndex !== 0) { Debug.assertLessThan(argumentIndex, argumentCount); } @@ -222,7 +222,7 @@ namespace ts.SignatureHelp { // Case 3: // foo(a#, #b#) -> The token is buried inside a list, and should give signature help // Find out if 'node' is an argument, a type argument, or neither - const info = getArgumentOrParameterListInfo(node, sourceFile); + const info = getArgumentOrParameterListInfo(node, position, sourceFile); if (!info) return undefined; const { list, argumentIndex, argumentCount, argumentsSpan } = info; const isTypeParameterList = !!parent.typeArguments && parent.typeArguments.pos === list.pos; @@ -299,8 +299,8 @@ namespace ts.SignatureHelp { return isBinaryExpression(b.left) ? countBinaryExpressionParameters(b.left) + 1 : 2; } - function tryGetParameterInfo(startingToken: Node, _position: number, sourceFile: SourceFile, checker: TypeChecker): ArgumentListInfo | undefined { - const info = getContextualSignatureLocationInfo(startingToken, sourceFile, checker); + function tryGetParameterInfo(startingToken: Node, position: number, sourceFile: SourceFile, checker: TypeChecker): ArgumentListInfo | undefined { + const info = getContextualSignatureLocationInfo(startingToken, sourceFile, position, checker); if (!info) return undefined; const { contextualType, argumentIndex, argumentCount, argumentsSpan } = info; @@ -315,7 +315,7 @@ namespace ts.SignatureHelp { } interface ContextualSignatureLocationInfo { readonly contextualType: Type; readonly argumentIndex: number; readonly argumentCount: number; readonly argumentsSpan: TextSpan; } - function getContextualSignatureLocationInfo(startingToken: Node, sourceFile: SourceFile, checker: TypeChecker): ContextualSignatureLocationInfo | undefined { + function getContextualSignatureLocationInfo(startingToken: Node, sourceFile: SourceFile, position: number, checker: TypeChecker): ContextualSignatureLocationInfo | undefined { if (startingToken.kind !== SyntaxKind.OpenParenToken && startingToken.kind !== SyntaxKind.CommaToken) return undefined; const { parent } = startingToken; switch (parent.kind) { @@ -323,7 +323,7 @@ namespace ts.SignatureHelp { case SyntaxKind.MethodDeclaration: case SyntaxKind.FunctionExpression: case SyntaxKind.ArrowFunction: - const info = getArgumentOrParameterListInfo(startingToken, sourceFile); + const info = getArgumentOrParameterListInfo(startingToken, position, sourceFile); if (!info) return undefined; const { argumentIndex, argumentCount, argumentsSpan } = info; const contextualType = isMethodDeclaration(parent) ? checker.getContextualTypeForObjectLiteralElement(parent) : checker.getContextualType(parent as ParenthesizedExpression | FunctionExpression | ArrowFunction); @@ -372,7 +372,7 @@ namespace ts.SignatureHelp { return argumentIndex; } - function getArgumentCount(argumentsList: Node) { + function getArgumentCount(argumentsList: Node, ignoreTrailingComma: boolean) { // The argument count for a list is normally the number of non-comma children it has. // For example, if you have "Foo(a,b)" then there will be three children of the arg // list 'a' '' 'b'. So, in this case the arg count will be 2. However, there @@ -387,10 +387,9 @@ namespace ts.SignatureHelp { const listChildren = argumentsList.getChildren(); let argumentCount = countWhere(listChildren, arg => arg.kind !== SyntaxKind.CommaToken); - if (listChildren.length > 0 && last(listChildren).kind === SyntaxKind.CommaToken) { + if (!ignoreTrailingComma && listChildren.length > 0 && last(listChildren).kind === SyntaxKind.CommaToken) { argumentCount++; } - return argumentCount; } diff --git a/tests/cases/fourslash/completionForStringLiteral16.ts b/tests/cases/fourslash/completionForStringLiteral16.ts new file mode 100644 index 0000000000000..4f482053d6880 --- /dev/null +++ b/tests/cases/fourslash/completionForStringLiteral16.ts @@ -0,0 +1,20 @@ +/// + +////interface Foo { +//// a: string; +//// b: number; +//// c: string; +////} +//// +////declare function f1(key: keyof T): T; +////declare function f2(a: keyof T, b: keyof T): T; +//// +////f1("/*1*/",); +////f1("/*2*/"); +////f1("/*3*/",,,); + +////f2("/*4*/", "/*5*/",); +////f2("/*6*/", "/*7*/"); +////f2("/*8*/", "/*9*/",,,); + +verify.completions({ marker: test.markers(), exact: ["a", "b", "c"] }); From 3328feb7991f358e245088d48b64ad9da8f015e2 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Fri, 4 Feb 2022 12:34:29 -0800 Subject: [PATCH 12/55] Use 'static {}' for static fields when available and useDefineForClassFields is false (#47707) --- src/compiler/checker.ts | 27 +--- src/compiler/diagnosticMessages.json | 8 - src/compiler/transformers/classFields.ts | 98 +++++++++--- .../reference/computedPropertyName.js | 2 +- ...ClassFieldsInEsNext(target=es2020).symbols | 126 --------------- ...orClassFieldsInEsNext(target=es2020).types | 150 ------------------ ...ssFieldsInEsNext(target=esnext).errors.txt | 74 --------- ...ClassFieldsInEsNext(target=esnext).symbols | 126 --------------- ...orClassFieldsInEsNext(target=esnext).types | 150 ------------------ .../privateNameFieldsESNext(target=es2022).js | 3 +- ...NameFieldsESNext(target=esnext).errors.txt | 5 +- .../privateNameFieldsESNext(target=esnext).js | 3 +- ...ressionTransform(target=esnext).errors.txt | 5 +- ...aticAndStaticInitializer(target=es2022).js | 6 +- ...taticInitializer(target=esnext).errors.txt | 15 -- ...aticAndStaticInitializer(target=esnext).js | 6 +- ...FieldDestructuredBinding(target=es2022).js | 3 +- ...tructuredBinding(target=esnext).errors.txt | 30 ---- ...FieldDestructuredBinding(target=esnext).js | 3 +- ...meStaticFieldInitializer(target=es2022).js | 3 +- ...FieldInitializer(target=esnext).errors.txt | 11 -- ...meStaticFieldInitializer(target=esnext).js | 3 +- ...eForClassFieldsInEsNext(target=es2020).js} | 76 ++++----- ...ClassFieldsInEsNext(target=es2020).symbols | 126 +++++++++++++++ ...orClassFieldsInEsNext(target=es2020).types | 150 ++++++++++++++++++ ...eForClassFieldsInEsNext(target=esnext).js} | 80 +++++----- ...ClassFieldsInEsNext(target=esnext).symbols | 126 +++++++++++++++ ...orClassFieldsInEsNext(target=esnext).types | 150 ++++++++++++++++++ ...AndSuperInStaticMembers2(target=es2022).js | 52 +++--- ...AndSuperInStaticMembers2(target=esnext).js | 52 +++--- ...rectly.rewrittenNamespaceFollowingClass.js | 2 +- ...eOfThisInStaticMembers10(target=es2022).js | 33 ++-- ...eOfThisInStaticMembers10(target=esnext).js | 33 ++-- ...eOfThisInStaticMembers12(target=es2022).js | 19 +-- ...eOfThisInStaticMembers12(target=esnext).js | 19 +-- ...peOfThisInStaticMembers3(target=es2022).js | 15 +- ...peOfThisInStaticMembers3(target=esnext).js | 15 +- tests/baselines/reference/uniqueSymbols.js | 20 +-- .../reference/uniqueSymbolsDeclarations.js | 20 +-- .../uniqueSymbolsDeclarationsInJs.js | 20 +-- .../reference/unusedPrivateStaticMembers.js | 6 +- ...WhenNotUseDefineForClassFieldsInEsNext.ts} | 38 ++--- 42 files changed, 882 insertions(+), 1027 deletions(-) delete mode 100644 tests/baselines/reference/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext(target=es2020).symbols delete mode 100644 tests/baselines/reference/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext(target=es2020).types delete mode 100644 tests/baselines/reference/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext(target=esnext).errors.txt delete mode 100644 tests/baselines/reference/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext(target=esnext).symbols delete mode 100644 tests/baselines/reference/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext(target=esnext).types delete mode 100644 tests/baselines/reference/privateNameStaticAndStaticInitializer(target=esnext).errors.txt delete mode 100644 tests/baselines/reference/privateNameStaticFieldDestructuredBinding(target=esnext).errors.txt delete mode 100644 tests/baselines/reference/privateNameStaticFieldInitializer(target=esnext).errors.txt rename tests/baselines/reference/{privateNameErrorsOnNotUseDefineForClassFieldsInEsNext(target=es2020).js => privateNameWhenNotUseDefineForClassFieldsInEsNext(target=es2020).js} (55%) create mode 100644 tests/baselines/reference/privateNameWhenNotUseDefineForClassFieldsInEsNext(target=es2020).symbols create mode 100644 tests/baselines/reference/privateNameWhenNotUseDefineForClassFieldsInEsNext(target=es2020).types rename tests/baselines/reference/{privateNameErrorsOnNotUseDefineForClassFieldsInEsNext(target=esnext).js => privateNameWhenNotUseDefineForClassFieldsInEsNext(target=esnext).js} (52%) create mode 100644 tests/baselines/reference/privateNameWhenNotUseDefineForClassFieldsInEsNext(target=esnext).symbols create mode 100644 tests/baselines/reference/privateNameWhenNotUseDefineForClassFieldsInEsNext(target=esnext).types rename tests/cases/conformance/classes/members/privateNames/{privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts => privateNameWhenNotUseDefineForClassFieldsInEsNext.ts} (52%) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4140f49f9a6f4..840aa5e827b61 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -28425,29 +28425,6 @@ namespace ts { grammarErrorOnNode(right, Diagnostics.Cannot_assign_to_private_method_0_Private_methods_are_not_writable, idText(right)); } - if (lexicallyScopedSymbol?.valueDeclaration && (getEmitScriptTarget(compilerOptions) === ScriptTarget.ESNext && !useDefineForClassFields)) { - const lexicalClass = getContainingClass(lexicallyScopedSymbol.valueDeclaration); - const parentStaticFieldInitializer = findAncestor(node, (n) => { - if (n === lexicalClass) return "quit"; - if (isPropertyDeclaration(n.parent) && hasStaticModifier(n.parent) && n.parent.initializer === n && n.parent.parent === lexicalClass) { - return true; - } - return false; - }); - if (parentStaticFieldInitializer) { - const parentStaticFieldInitializerSymbol = getSymbolOfNode(parentStaticFieldInitializer.parent); - Debug.assert(parentStaticFieldInitializerSymbol, "Initializer without declaration symbol"); - const diagnostic = error(node, - Diagnostics.Property_0_may_not_be_used_in_a_static_property_s_initializer_in_the_same_class_when_target_is_esnext_and_useDefineForClassFields_is_false, - symbolName(lexicallyScopedSymbol)); - addRelatedInfo(diagnostic, - createDiagnosticForNode(parentStaticFieldInitializer.parent, - Diagnostics.Initializer_for_property_0, - symbolName(parentStaticFieldInitializerSymbol)) - ); - } - } - if (isAnyLike) { if (lexicallyScopedSymbol) { return isErrorType(apparentType) ? errorType : apparentType; @@ -34656,9 +34633,7 @@ namespace ts { checkVariableLikeDeclaration(node); setNodeLinksForPrivateIdentifierScope(node); - if (isPrivateIdentifier(node.name) && hasStaticModifier(node) && node.initializer && languageVersion === ScriptTarget.ESNext && !compilerOptions.useDefineForClassFields) { - error(node.initializer, Diagnostics.Static_fields_with_private_names_can_t_have_initializers_when_the_useDefineForClassFields_flag_is_not_specified_with_a_target_of_esnext_Consider_adding_the_useDefineForClassFields_flag); - } + // property signatures already report "initializer not allowed in ambient context" elsewhere if (hasSyntacticModifier(node, ModifierFlags.Abstract) && node.kind === SyntaxKind.PropertyDeclaration && node.initializer) { error(node, Diagnostics.Property_0_cannot_have_an_initializer_because_it_is_marked_abstract, declarationNameToString(node.name)); diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index f00183c8ec8cb..4523f5c4ed3b8 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3281,10 +3281,6 @@ "category": "Error", "code": 2804 }, - "Static fields with private names can't have initializers when the '--useDefineForClassFields' flag is not specified with a '--target' of 'esnext'. Consider adding the '--useDefineForClassFields' flag.": { - "category": "Error", - "code": 2805 - }, "Private accessor was defined without a getter.": { "category": "Error", "code": 2806 @@ -3301,10 +3297,6 @@ "category": "Error", "code": 2809 }, - "Property '{0}' may not be used in a static property's initializer in the same class when 'target' is 'esnext' and 'useDefineForClassFields' is 'false'.": { - "category": "Error", - "code": 2810 - }, "Initializer for property '{0}'": { "category": "Error", "code": 2811 diff --git a/src/compiler/transformers/classFields.ts b/src/compiler/transformers/classFields.ts index 0d4cb46a04c2c..3ac842e8abab5 100644 --- a/src/compiler/transformers/classFields.ts +++ b/src/compiler/transformers/classFields.ts @@ -135,10 +135,13 @@ namespace ts { const shouldTransformPrivateElementsOrClassStaticBlocks = languageVersion < ScriptTarget.ES2022; + // We need to transform `this` in a static initializer into a reference to the class + // when targeting < ES2022 since the assignment will be moved outside of the class body. + const shouldTransformThisInStaticInitializers = languageVersion < ScriptTarget.ES2022; + // We don't need to transform `super` property access when targeting ES5, ES3 because // the es2015 transformation handles those. - const shouldTransformSuperInStaticInitializers = (languageVersion <= ScriptTarget.ES2021 || !useDefineForClassFields) && languageVersion >= ScriptTarget.ES2015; - const shouldTransformThisInStaticInitializers = languageVersion <= ScriptTarget.ES2021 || !useDefineForClassFields; + const shouldTransformSuperInStaticInitializers = shouldTransformThisInStaticInitializers && languageVersion >= ScriptTarget.ES2015; const previousOnSubstituteNode = context.onSubstituteNode; context.onSubstituteNode = onSubstituteNode; @@ -422,6 +425,11 @@ namespace ts { if (isPrivateIdentifier(node.name)) { if (!shouldTransformPrivateElementsOrClassStaticBlocks) { + if (isStatic(node)) { + // static fields are left as is + return visitEachChild(node, visitor, context); + } + // Initializer is elided as the field is initialized in transformConstructor. return factory.updatePropertyDeclaration( node, @@ -448,6 +456,28 @@ namespace ts { if (expr && !isSimpleInlineableExpression(expr)) { getPendingExpressions().push(expr); } + + if (isStatic(node) && !shouldTransformPrivateElementsOrClassStaticBlocks && !useDefineForClassFields) { + const initializerStatement = transformPropertyOrClassStaticBlock(node, factory.createThis()); + if (initializerStatement) { + const staticBlock = factory.createClassStaticBlockDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, + factory.createBlock([initializerStatement]) + ); + + setOriginalNode(staticBlock, node); + setCommentRange(staticBlock, node); + + // Set the comment range for the statement to an empty synthetic range + // and drop synthetic comments from the statement to avoid printing them twice. + setCommentRange(initializerStatement, { pos: -1, end: -1 }); + setSyntheticLeadingComments(initializerStatement, undefined); + setSyntheticTrailingComments(initializerStatement, undefined); + return staticBlock; + } + } + return undefined; } @@ -1006,8 +1036,6 @@ namespace ts { enableSubstitutionForClassStaticThisOrSuperReference(); } - const staticProperties = getStaticPropertiesAndClassStaticBlock(node); - // If a class has private static fields, or a static field has a `this` or `super` reference, // then we need to allocate a temp variable to hold on to that reference. let pendingClassReferenceAssignment: BinaryExpression | undefined; @@ -1047,6 +1075,7 @@ namespace ts { // HasLexicalDeclaration (N) : Determines if the argument identifier has a binding in this environment record that was created using // a lexical declaration such as a LexicalDeclaration or a ClassDeclaration. + const staticProperties = getStaticPropertiesAndClassStaticBlock(node); if (some(staticProperties)) { addPropertyOrClassStaticBlockStatements(statements, staticProperties, factory.getInternalName(node)); } @@ -1102,7 +1131,7 @@ namespace ts { transformClassMembers(node, isDerivedClass) ); - const hasTransformableStatics = some(staticPropertiesOrClassStaticBlocks, p => isClassStaticBlockDeclaration(p) || !!p.initializer || (shouldTransformPrivateElementsOrClassStaticBlocks && isPrivateIdentifier(p.name))); + const hasTransformableStatics = shouldTransformPrivateElementsOrClassStaticBlocks && some(staticPropertiesOrClassStaticBlocks, p => isClassStaticBlockDeclaration(p) || !!p.initializer || isPrivateIdentifier(p.name)); if (hasTransformableStatics || some(pendingExpressions)) { if (isDecoratedClassDeclaration) { Debug.assertIsDefined(pendingStatements, "Decorated classes transformed by TypeScript are expected to be within a variable declaration."); @@ -1156,6 +1185,7 @@ namespace ts { } function transformClassMembers(node: ClassDeclaration | ClassExpression, isDerivedClass: boolean) { + const members: ClassElement[] = []; if (shouldTransformPrivateElementsOrClassStaticBlocks) { // Declare private names. for (const member of node.members) { @@ -1169,12 +1199,26 @@ namespace ts { } } - const members: ClassElement[] = []; const constructor = transformConstructor(node, isDerivedClass); + const visitedMembers = visitNodes(node.members, classElementVisitor, isClassElement); + if (constructor) { members.push(constructor); } - addRange(members, visitNodes(node.members, classElementVisitor, isClassElement)); + + if (!shouldTransformPrivateElementsOrClassStaticBlocks && some(pendingExpressions)) { + members.push(factory.createClassStaticBlockDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, + factory.createBlock([ + factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions)) + ]) + )); + pendingExpressions = undefined; + } + + addRange(members, visitedMembers); + return setTextRange(factory.createNodeArray(members), /*location*/ node.members); } @@ -1374,27 +1418,41 @@ namespace ts { */ function addPropertyOrClassStaticBlockStatements(statements: Statement[], properties: readonly (PropertyDeclaration | ClassStaticBlockDeclaration)[], receiver: LeftHandSideExpression) { for (const property of properties) { - const expression = isClassStaticBlockDeclaration(property) ? - transformClassStaticBlockDeclaration(property) : - transformProperty(property, receiver); - if (!expression) { + if (isStatic(property) && !shouldTransformPrivateElementsOrClassStaticBlocks && !useDefineForClassFields) { continue; } - const statement = factory.createExpressionStatement(expression); - setSourceMapRange(statement, moveRangePastModifiers(property)); - setCommentRange(statement, property); - setOriginalNode(statement, property); - // `setOriginalNode` *copies* the `emitNode` from `property`, so now both - // `statement` and `expression` have a copy of the synthesized comments. - // Drop the comments from expression to avoid printing them twice. - setSyntheticLeadingComments(expression, undefined); - setSyntheticTrailingComments(expression, undefined); + const statement = transformPropertyOrClassStaticBlock(property, receiver); + if (!statement) { + continue; + } statements.push(statement); } } + function transformPropertyOrClassStaticBlock(property: PropertyDeclaration | ClassStaticBlockDeclaration, receiver: LeftHandSideExpression) { + const expression = isClassStaticBlockDeclaration(property) ? + transformClassStaticBlockDeclaration(property) : + transformProperty(property, receiver); + if (!expression) { + return undefined; + } + + const statement = factory.createExpressionStatement(expression); + setSourceMapRange(statement, moveRangePastModifiers(property)); + setCommentRange(statement, property); + setOriginalNode(statement, property); + + // `setOriginalNode` *copies* the `emitNode` from `property`, so now both + // `statement` and `expression` have a copy of the synthesized comments. + // Drop the comments from expression to avoid printing them twice. + setSyntheticLeadingComments(expression, undefined); + setSyntheticTrailingComments(expression, undefined); + + return statement; + } + /** * Generates assignment expressions for property initializers. * diff --git a/tests/baselines/reference/computedPropertyName.js b/tests/baselines/reference/computedPropertyName.js index 27adbb6113886..d1e2e359311ae 100644 --- a/tests/baselines/reference/computedPropertyName.js +++ b/tests/baselines/reference/computedPropertyName.js @@ -56,8 +56,8 @@ class D { constructor() { this[_a] = 0; // Error } + static { _a = onInit; } } -_a = onInit; class E { [onInit]() { } // Error } diff --git a/tests/baselines/reference/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext(target=es2020).symbols b/tests/baselines/reference/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext(target=es2020).symbols deleted file mode 100644 index 58c405de0ac8a..0000000000000 --- a/tests/baselines/reference/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext(target=es2020).symbols +++ /dev/null @@ -1,126 +0,0 @@ -=== tests/cases/conformance/classes/members/privateNames/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts === -class TestWithErrors { ->TestWithErrors : Symbol(TestWithErrors, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 0, 0)) - - #prop = 0 ->#prop : Symbol(TestWithErrors.#prop, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 0, 22)) - - static dd = new TestWithErrors().#prop; // Err ->dd : Symbol(TestWithErrors.dd, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 1, 13)) ->new TestWithErrors().#prop : Symbol(TestWithErrors.#prop, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 0, 22)) ->TestWithErrors : Symbol(TestWithErrors, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 0, 0)) - - static ["X_ z_ zz"] = class Inner { ->["X_ z_ zz"] : Symbol(TestWithErrors["X_ z_ zz"], Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 2, 43)) ->"X_ z_ zz" : Symbol(TestWithErrors["X_ z_ zz"], Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 2, 43)) ->Inner : Symbol(Inner, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 3, 25)) - - #foo = 10 ->#foo : Symbol(Inner.#foo, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 3, 39)) - - m() { ->m : Symbol(Inner.m, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 4, 18)) - - new TestWithErrors().#prop // Err ->new TestWithErrors().#prop : Symbol(TestWithErrors.#prop, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 0, 22)) ->TestWithErrors : Symbol(TestWithErrors, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 0, 0)) - } - static C = class InnerInner { ->C : Symbol(Inner.C, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 7, 9)) ->InnerInner : Symbol(InnerInner, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 8, 18)) - - m() { ->m : Symbol(InnerInner.m, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 8, 37)) - - new TestWithErrors().#prop // Err ->new TestWithErrors().#prop : Symbol(TestWithErrors.#prop, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 0, 22)) ->TestWithErrors : Symbol(TestWithErrors, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 0, 0)) - - new Inner().#foo; // Err ->new Inner().#foo : Symbol(Inner.#foo, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 3, 39)) ->Inner : Symbol(Inner, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 3, 25)) - } - } - - static M(){ ->M : Symbol(Inner.M, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 13, 9)) - - return class { - m() { ->m : Symbol((Anonymous class).m, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 16, 26)) - - new TestWithErrors().#prop // Err ->new TestWithErrors().#prop : Symbol(TestWithErrors.#prop, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 0, 22)) ->TestWithErrors : Symbol(TestWithErrors, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 0, 0)) - - new Inner().#foo; // OK ->new Inner().#foo : Symbol(Inner.#foo, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 3, 39)) ->Inner : Symbol(Inner, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 3, 25)) - } - } - } - } -} - -class TestNoErrors { ->TestNoErrors : Symbol(TestNoErrors, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 24, 1)) - - #prop = 0 ->#prop : Symbol(TestNoErrors.#prop, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 26, 20)) - - dd = new TestNoErrors().#prop; // OK ->dd : Symbol(TestNoErrors.dd, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 27, 13)) ->new TestNoErrors().#prop : Symbol(TestNoErrors.#prop, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 26, 20)) ->TestNoErrors : Symbol(TestNoErrors, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 24, 1)) - - ["X_ z_ zz"] = class Inner { ->["X_ z_ zz"] : Symbol(TestNoErrors["X_ z_ zz"], Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 28, 34)) ->"X_ z_ zz" : Symbol(TestNoErrors["X_ z_ zz"], Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 28, 34)) ->Inner : Symbol(Inner, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 29, 18)) - - #foo = 10 ->#foo : Symbol(Inner.#foo, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 29, 32)) - - m() { ->m : Symbol(Inner.m, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 30, 18)) - - new TestNoErrors().#prop // Ok ->new TestNoErrors().#prop : Symbol(TestNoErrors.#prop, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 26, 20)) ->TestNoErrors : Symbol(TestNoErrors, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 24, 1)) - } - C = class InnerInner { ->C : Symbol(Inner.C, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 33, 9)) ->InnerInner : Symbol(InnerInner, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 34, 11)) - - m() { ->m : Symbol(InnerInner.m, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 34, 30)) - - new TestNoErrors().#prop // Ok ->new TestNoErrors().#prop : Symbol(TestNoErrors.#prop, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 26, 20)) ->TestNoErrors : Symbol(TestNoErrors, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 24, 1)) - - new Inner().#foo; // Ok ->new Inner().#foo : Symbol(Inner.#foo, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 29, 32)) ->Inner : Symbol(Inner, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 29, 18)) - } - } - - static M(){ ->M : Symbol(Inner.M, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 39, 9)) - - return class { - m() { ->m : Symbol((Anonymous class).m, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 42, 26)) - - new TestNoErrors().#prop // OK ->new TestNoErrors().#prop : Symbol(TestNoErrors.#prop, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 26, 20)) ->TestNoErrors : Symbol(TestNoErrors, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 24, 1)) - - new Inner().#foo; // OK ->new Inner().#foo : Symbol(Inner.#foo, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 29, 32)) ->Inner : Symbol(Inner, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 29, 18)) - } - } - } - } - } diff --git a/tests/baselines/reference/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext(target=es2020).types b/tests/baselines/reference/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext(target=es2020).types deleted file mode 100644 index 274a774c65e80..0000000000000 --- a/tests/baselines/reference/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext(target=es2020).types +++ /dev/null @@ -1,150 +0,0 @@ -=== tests/cases/conformance/classes/members/privateNames/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts === -class TestWithErrors { ->TestWithErrors : TestWithErrors - - #prop = 0 ->#prop : number ->0 : 0 - - static dd = new TestWithErrors().#prop; // Err ->dd : number ->new TestWithErrors().#prop : number ->new TestWithErrors() : TestWithErrors ->TestWithErrors : typeof TestWithErrors - - static ["X_ z_ zz"] = class Inner { ->["X_ z_ zz"] : typeof Inner ->"X_ z_ zz" : "X_ z_ zz" ->class Inner { #foo = 10 m() { new TestWithErrors().#prop // Err } static C = class InnerInner { m() { new TestWithErrors().#prop // Err new Inner().#foo; // Err } } static M(){ return class { m() { new TestWithErrors().#prop // Err new Inner().#foo; // OK } } } } : typeof Inner ->Inner : typeof Inner - - #foo = 10 ->#foo : number ->10 : 10 - - m() { ->m : () => void - - new TestWithErrors().#prop // Err ->new TestWithErrors().#prop : number ->new TestWithErrors() : TestWithErrors ->TestWithErrors : typeof TestWithErrors - } - static C = class InnerInner { ->C : typeof InnerInner ->class InnerInner { m() { new TestWithErrors().#prop // Err new Inner().#foo; // Err } } : typeof InnerInner ->InnerInner : typeof InnerInner - - m() { ->m : () => void - - new TestWithErrors().#prop // Err ->new TestWithErrors().#prop : number ->new TestWithErrors() : TestWithErrors ->TestWithErrors : typeof TestWithErrors - - new Inner().#foo; // Err ->new Inner().#foo : number ->new Inner() : Inner ->Inner : typeof Inner - } - } - - static M(){ ->M : () => typeof (Anonymous class) - - return class { ->class { m() { new TestWithErrors().#prop // Err new Inner().#foo; // OK } } : typeof (Anonymous class) - - m() { ->m : () => void - - new TestWithErrors().#prop // Err ->new TestWithErrors().#prop : number ->new TestWithErrors() : TestWithErrors ->TestWithErrors : typeof TestWithErrors - - new Inner().#foo; // OK ->new Inner().#foo : number ->new Inner() : Inner ->Inner : typeof Inner - } - } - } - } -} - -class TestNoErrors { ->TestNoErrors : TestNoErrors - - #prop = 0 ->#prop : number ->0 : 0 - - dd = new TestNoErrors().#prop; // OK ->dd : number ->new TestNoErrors().#prop : number ->new TestNoErrors() : TestNoErrors ->TestNoErrors : typeof TestNoErrors - - ["X_ z_ zz"] = class Inner { ->["X_ z_ zz"] : typeof Inner ->"X_ z_ zz" : "X_ z_ zz" ->class Inner { #foo = 10 m() { new TestNoErrors().#prop // Ok } C = class InnerInner { m() { new TestNoErrors().#prop // Ok new Inner().#foo; // Ok } } static M(){ return class { m() { new TestNoErrors().#prop // OK new Inner().#foo; // OK } } } } : typeof Inner ->Inner : typeof Inner - - #foo = 10 ->#foo : number ->10 : 10 - - m() { ->m : () => void - - new TestNoErrors().#prop // Ok ->new TestNoErrors().#prop : number ->new TestNoErrors() : TestNoErrors ->TestNoErrors : typeof TestNoErrors - } - C = class InnerInner { ->C : typeof InnerInner ->class InnerInner { m() { new TestNoErrors().#prop // Ok new Inner().#foo; // Ok } } : typeof InnerInner ->InnerInner : typeof InnerInner - - m() { ->m : () => void - - new TestNoErrors().#prop // Ok ->new TestNoErrors().#prop : number ->new TestNoErrors() : TestNoErrors ->TestNoErrors : typeof TestNoErrors - - new Inner().#foo; // Ok ->new Inner().#foo : number ->new Inner() : Inner ->Inner : typeof Inner - } - } - - static M(){ ->M : () => typeof (Anonymous class) - - return class { ->class { m() { new TestNoErrors().#prop // OK new Inner().#foo; // OK } } : typeof (Anonymous class) - - m() { ->m : () => void - - new TestNoErrors().#prop // OK ->new TestNoErrors().#prop : number ->new TestNoErrors() : TestNoErrors ->TestNoErrors : typeof TestNoErrors - - new Inner().#foo; // OK ->new Inner().#foo : number ->new Inner() : Inner ->Inner : typeof Inner - } - } - } - } - } diff --git a/tests/baselines/reference/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext(target=esnext).errors.txt b/tests/baselines/reference/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext(target=esnext).errors.txt deleted file mode 100644 index 030a6c5883b44..0000000000000 --- a/tests/baselines/reference/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext(target=esnext).errors.txt +++ /dev/null @@ -1,74 +0,0 @@ -tests/cases/conformance/classes/members/privateNames/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts(3,17): error TS2810: Property '#prop' may not be used in a static property's initializer in the same class when 'target' is 'esnext' and 'useDefineForClassFields' is 'false'. -tests/cases/conformance/classes/members/privateNames/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts(7,13): error TS2810: Property '#prop' may not be used in a static property's initializer in the same class when 'target' is 'esnext' and 'useDefineForClassFields' is 'false'. -tests/cases/conformance/classes/members/privateNames/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts(11,17): error TS2810: Property '#prop' may not be used in a static property's initializer in the same class when 'target' is 'esnext' and 'useDefineForClassFields' is 'false'. -tests/cases/conformance/classes/members/privateNames/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts(12,17): error TS2810: Property '#foo' may not be used in a static property's initializer in the same class when 'target' is 'esnext' and 'useDefineForClassFields' is 'false'. -tests/cases/conformance/classes/members/privateNames/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts(19,21): error TS2810: Property '#prop' may not be used in a static property's initializer in the same class when 'target' is 'esnext' and 'useDefineForClassFields' is 'false'. - - -==== tests/cases/conformance/classes/members/privateNames/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts (5 errors) ==== - class TestWithErrors { - #prop = 0 - static dd = new TestWithErrors().#prop; // Err - ~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2810: Property '#prop' may not be used in a static property's initializer in the same class when 'target' is 'esnext' and 'useDefineForClassFields' is 'false'. -!!! related TS2811 tests/cases/conformance/classes/members/privateNames/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts:3:12: Initializer for property 'dd' - static ["X_ z_ zz"] = class Inner { - #foo = 10 - m() { - new TestWithErrors().#prop // Err - ~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2810: Property '#prop' may not be used in a static property's initializer in the same class when 'target' is 'esnext' and 'useDefineForClassFields' is 'false'. -!!! related TS2811 tests/cases/conformance/classes/members/privateNames/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts:4:12: Initializer for property 'X_ z_ zz' - } - static C = class InnerInner { - m() { - new TestWithErrors().#prop // Err - ~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2810: Property '#prop' may not be used in a static property's initializer in the same class when 'target' is 'esnext' and 'useDefineForClassFields' is 'false'. -!!! related TS2811 tests/cases/conformance/classes/members/privateNames/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts:4:12: Initializer for property 'X_ z_ zz' - new Inner().#foo; // Err - ~~~~~~~~~~~~~~~~ -!!! error TS2810: Property '#foo' may not be used in a static property's initializer in the same class when 'target' is 'esnext' and 'useDefineForClassFields' is 'false'. -!!! related TS2811 tests/cases/conformance/classes/members/privateNames/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts:9:16: Initializer for property 'C' - } - } - - static M(){ - return class { - m() { - new TestWithErrors().#prop // Err - ~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2810: Property '#prop' may not be used in a static property's initializer in the same class when 'target' is 'esnext' and 'useDefineForClassFields' is 'false'. -!!! related TS2811 tests/cases/conformance/classes/members/privateNames/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts:4:12: Initializer for property 'X_ z_ zz' - new Inner().#foo; // OK - } - } - } - } - } - - class TestNoErrors { - #prop = 0 - dd = new TestNoErrors().#prop; // OK - ["X_ z_ zz"] = class Inner { - #foo = 10 - m() { - new TestNoErrors().#prop // Ok - } - C = class InnerInner { - m() { - new TestNoErrors().#prop // Ok - new Inner().#foo; // Ok - } - } - - static M(){ - return class { - m() { - new TestNoErrors().#prop // OK - new Inner().#foo; // OK - } - } - } - } - } \ No newline at end of file diff --git a/tests/baselines/reference/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext(target=esnext).symbols b/tests/baselines/reference/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext(target=esnext).symbols deleted file mode 100644 index 58c405de0ac8a..0000000000000 --- a/tests/baselines/reference/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext(target=esnext).symbols +++ /dev/null @@ -1,126 +0,0 @@ -=== tests/cases/conformance/classes/members/privateNames/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts === -class TestWithErrors { ->TestWithErrors : Symbol(TestWithErrors, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 0, 0)) - - #prop = 0 ->#prop : Symbol(TestWithErrors.#prop, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 0, 22)) - - static dd = new TestWithErrors().#prop; // Err ->dd : Symbol(TestWithErrors.dd, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 1, 13)) ->new TestWithErrors().#prop : Symbol(TestWithErrors.#prop, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 0, 22)) ->TestWithErrors : Symbol(TestWithErrors, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 0, 0)) - - static ["X_ z_ zz"] = class Inner { ->["X_ z_ zz"] : Symbol(TestWithErrors["X_ z_ zz"], Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 2, 43)) ->"X_ z_ zz" : Symbol(TestWithErrors["X_ z_ zz"], Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 2, 43)) ->Inner : Symbol(Inner, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 3, 25)) - - #foo = 10 ->#foo : Symbol(Inner.#foo, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 3, 39)) - - m() { ->m : Symbol(Inner.m, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 4, 18)) - - new TestWithErrors().#prop // Err ->new TestWithErrors().#prop : Symbol(TestWithErrors.#prop, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 0, 22)) ->TestWithErrors : Symbol(TestWithErrors, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 0, 0)) - } - static C = class InnerInner { ->C : Symbol(Inner.C, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 7, 9)) ->InnerInner : Symbol(InnerInner, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 8, 18)) - - m() { ->m : Symbol(InnerInner.m, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 8, 37)) - - new TestWithErrors().#prop // Err ->new TestWithErrors().#prop : Symbol(TestWithErrors.#prop, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 0, 22)) ->TestWithErrors : Symbol(TestWithErrors, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 0, 0)) - - new Inner().#foo; // Err ->new Inner().#foo : Symbol(Inner.#foo, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 3, 39)) ->Inner : Symbol(Inner, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 3, 25)) - } - } - - static M(){ ->M : Symbol(Inner.M, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 13, 9)) - - return class { - m() { ->m : Symbol((Anonymous class).m, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 16, 26)) - - new TestWithErrors().#prop // Err ->new TestWithErrors().#prop : Symbol(TestWithErrors.#prop, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 0, 22)) ->TestWithErrors : Symbol(TestWithErrors, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 0, 0)) - - new Inner().#foo; // OK ->new Inner().#foo : Symbol(Inner.#foo, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 3, 39)) ->Inner : Symbol(Inner, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 3, 25)) - } - } - } - } -} - -class TestNoErrors { ->TestNoErrors : Symbol(TestNoErrors, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 24, 1)) - - #prop = 0 ->#prop : Symbol(TestNoErrors.#prop, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 26, 20)) - - dd = new TestNoErrors().#prop; // OK ->dd : Symbol(TestNoErrors.dd, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 27, 13)) ->new TestNoErrors().#prop : Symbol(TestNoErrors.#prop, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 26, 20)) ->TestNoErrors : Symbol(TestNoErrors, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 24, 1)) - - ["X_ z_ zz"] = class Inner { ->["X_ z_ zz"] : Symbol(TestNoErrors["X_ z_ zz"], Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 28, 34)) ->"X_ z_ zz" : Symbol(TestNoErrors["X_ z_ zz"], Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 28, 34)) ->Inner : Symbol(Inner, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 29, 18)) - - #foo = 10 ->#foo : Symbol(Inner.#foo, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 29, 32)) - - m() { ->m : Symbol(Inner.m, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 30, 18)) - - new TestNoErrors().#prop // Ok ->new TestNoErrors().#prop : Symbol(TestNoErrors.#prop, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 26, 20)) ->TestNoErrors : Symbol(TestNoErrors, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 24, 1)) - } - C = class InnerInner { ->C : Symbol(Inner.C, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 33, 9)) ->InnerInner : Symbol(InnerInner, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 34, 11)) - - m() { ->m : Symbol(InnerInner.m, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 34, 30)) - - new TestNoErrors().#prop // Ok ->new TestNoErrors().#prop : Symbol(TestNoErrors.#prop, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 26, 20)) ->TestNoErrors : Symbol(TestNoErrors, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 24, 1)) - - new Inner().#foo; // Ok ->new Inner().#foo : Symbol(Inner.#foo, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 29, 32)) ->Inner : Symbol(Inner, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 29, 18)) - } - } - - static M(){ ->M : Symbol(Inner.M, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 39, 9)) - - return class { - m() { ->m : Symbol((Anonymous class).m, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 42, 26)) - - new TestNoErrors().#prop // OK ->new TestNoErrors().#prop : Symbol(TestNoErrors.#prop, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 26, 20)) ->TestNoErrors : Symbol(TestNoErrors, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 24, 1)) - - new Inner().#foo; // OK ->new Inner().#foo : Symbol(Inner.#foo, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 29, 32)) ->Inner : Symbol(Inner, Decl(privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts, 29, 18)) - } - } - } - } - } diff --git a/tests/baselines/reference/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext(target=esnext).types b/tests/baselines/reference/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext(target=esnext).types deleted file mode 100644 index 274a774c65e80..0000000000000 --- a/tests/baselines/reference/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext(target=esnext).types +++ /dev/null @@ -1,150 +0,0 @@ -=== tests/cases/conformance/classes/members/privateNames/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts === -class TestWithErrors { ->TestWithErrors : TestWithErrors - - #prop = 0 ->#prop : number ->0 : 0 - - static dd = new TestWithErrors().#prop; // Err ->dd : number ->new TestWithErrors().#prop : number ->new TestWithErrors() : TestWithErrors ->TestWithErrors : typeof TestWithErrors - - static ["X_ z_ zz"] = class Inner { ->["X_ z_ zz"] : typeof Inner ->"X_ z_ zz" : "X_ z_ zz" ->class Inner { #foo = 10 m() { new TestWithErrors().#prop // Err } static C = class InnerInner { m() { new TestWithErrors().#prop // Err new Inner().#foo; // Err } } static M(){ return class { m() { new TestWithErrors().#prop // Err new Inner().#foo; // OK } } } } : typeof Inner ->Inner : typeof Inner - - #foo = 10 ->#foo : number ->10 : 10 - - m() { ->m : () => void - - new TestWithErrors().#prop // Err ->new TestWithErrors().#prop : number ->new TestWithErrors() : TestWithErrors ->TestWithErrors : typeof TestWithErrors - } - static C = class InnerInner { ->C : typeof InnerInner ->class InnerInner { m() { new TestWithErrors().#prop // Err new Inner().#foo; // Err } } : typeof InnerInner ->InnerInner : typeof InnerInner - - m() { ->m : () => void - - new TestWithErrors().#prop // Err ->new TestWithErrors().#prop : number ->new TestWithErrors() : TestWithErrors ->TestWithErrors : typeof TestWithErrors - - new Inner().#foo; // Err ->new Inner().#foo : number ->new Inner() : Inner ->Inner : typeof Inner - } - } - - static M(){ ->M : () => typeof (Anonymous class) - - return class { ->class { m() { new TestWithErrors().#prop // Err new Inner().#foo; // OK } } : typeof (Anonymous class) - - m() { ->m : () => void - - new TestWithErrors().#prop // Err ->new TestWithErrors().#prop : number ->new TestWithErrors() : TestWithErrors ->TestWithErrors : typeof TestWithErrors - - new Inner().#foo; // OK ->new Inner().#foo : number ->new Inner() : Inner ->Inner : typeof Inner - } - } - } - } -} - -class TestNoErrors { ->TestNoErrors : TestNoErrors - - #prop = 0 ->#prop : number ->0 : 0 - - dd = new TestNoErrors().#prop; // OK ->dd : number ->new TestNoErrors().#prop : number ->new TestNoErrors() : TestNoErrors ->TestNoErrors : typeof TestNoErrors - - ["X_ z_ zz"] = class Inner { ->["X_ z_ zz"] : typeof Inner ->"X_ z_ zz" : "X_ z_ zz" ->class Inner { #foo = 10 m() { new TestNoErrors().#prop // Ok } C = class InnerInner { m() { new TestNoErrors().#prop // Ok new Inner().#foo; // Ok } } static M(){ return class { m() { new TestNoErrors().#prop // OK new Inner().#foo; // OK } } } } : typeof Inner ->Inner : typeof Inner - - #foo = 10 ->#foo : number ->10 : 10 - - m() { ->m : () => void - - new TestNoErrors().#prop // Ok ->new TestNoErrors().#prop : number ->new TestNoErrors() : TestNoErrors ->TestNoErrors : typeof TestNoErrors - } - C = class InnerInner { ->C : typeof InnerInner ->class InnerInner { m() { new TestNoErrors().#prop // Ok new Inner().#foo; // Ok } } : typeof InnerInner ->InnerInner : typeof InnerInner - - m() { ->m : () => void - - new TestNoErrors().#prop // Ok ->new TestNoErrors().#prop : number ->new TestNoErrors() : TestNoErrors ->TestNoErrors : typeof TestNoErrors - - new Inner().#foo; // Ok ->new Inner().#foo : number ->new Inner() : Inner ->Inner : typeof Inner - } - } - - static M(){ ->M : () => typeof (Anonymous class) - - return class { ->class { m() { new TestNoErrors().#prop // OK new Inner().#foo; // OK } } : typeof (Anonymous class) - - m() { ->m : () => void - - new TestNoErrors().#prop // OK ->new TestNoErrors().#prop : number ->new TestNoErrors() : TestNoErrors ->TestNoErrors : typeof TestNoErrors - - new Inner().#foo; // OK ->new Inner().#foo : number ->new Inner() : Inner ->Inner : typeof Inner - } - } - } - } - } diff --git a/tests/baselines/reference/privateNameFieldsESNext(target=es2022).js b/tests/baselines/reference/privateNameFieldsESNext(target=es2022).js index acc37caa3cc8f..99abdeb482a20 100644 --- a/tests/baselines/reference/privateNameFieldsESNext(target=es2022).js +++ b/tests/baselines/reference/privateNameFieldsESNext(target=es2022).js @@ -35,7 +35,7 @@ class C { this.#a = "hello"; console.log(this.#b); } - static #m; + static #m = "test"; static #x; static test() { console.log(this.#m); @@ -43,4 +43,3 @@ class C { } #something; } -C.#m = "test"; diff --git a/tests/baselines/reference/privateNameFieldsESNext(target=esnext).errors.txt b/tests/baselines/reference/privateNameFieldsESNext(target=esnext).errors.txt index 10288bc30085d..28f283e66a817 100644 --- a/tests/baselines/reference/privateNameFieldsESNext(target=esnext).errors.txt +++ b/tests/baselines/reference/privateNameFieldsESNext(target=esnext).errors.txt @@ -1,8 +1,7 @@ tests/cases/conformance/classes/members/privateNames/privateNameFieldsESNext.ts(8,9): error TS2322: Type 'string' is not assignable to type 'number'. -tests/cases/conformance/classes/members/privateNames/privateNameFieldsESNext.ts(11,17): error TS2805: Static fields with private names can't have initializers when the '--useDefineForClassFields' flag is not specified with a '--target' of 'esnext'. Consider adding the '--useDefineForClassFields' flag. -==== tests/cases/conformance/classes/members/privateNames/privateNameFieldsESNext.ts (2 errors) ==== +==== tests/cases/conformance/classes/members/privateNames/privateNameFieldsESNext.ts (1 errors) ==== class C { a = 123; #a = 10; @@ -16,8 +15,6 @@ tests/cases/conformance/classes/members/privateNames/privateNameFieldsESNext.ts( console.log(this.#b); } static #m = "test"; - ~~~~~~ -!!! error TS2805: Static fields with private names can't have initializers when the '--useDefineForClassFields' flag is not specified with a '--target' of 'esnext'. Consider adding the '--useDefineForClassFields' flag. static #x; static test() { console.log(this.#m); diff --git a/tests/baselines/reference/privateNameFieldsESNext(target=esnext).js b/tests/baselines/reference/privateNameFieldsESNext(target=esnext).js index acc37caa3cc8f..99abdeb482a20 100644 --- a/tests/baselines/reference/privateNameFieldsESNext(target=esnext).js +++ b/tests/baselines/reference/privateNameFieldsESNext(target=esnext).js @@ -35,7 +35,7 @@ class C { this.#a = "hello"; console.log(this.#b); } - static #m; + static #m = "test"; static #x; static test() { console.log(this.#m); @@ -43,4 +43,3 @@ class C { } #something; } -C.#m = "test"; diff --git a/tests/baselines/reference/privateNameInInExpressionTransform(target=esnext).errors.txt b/tests/baselines/reference/privateNameInInExpressionTransform(target=esnext).errors.txt index b48e2ac7889ef..1d00c96fac064 100644 --- a/tests/baselines/reference/privateNameInInExpressionTransform(target=esnext).errors.txt +++ b/tests/baselines/reference/privateNameInInExpressionTransform(target=esnext).errors.txt @@ -1,17 +1,14 @@ -tests/cases/conformance/classes/members/privateNames/privateNameInInExpressionTransform.ts(4,26): error TS2805: Static fields with private names can't have initializers when the '--useDefineForClassFields' flag is not specified with a '--target' of 'esnext'. Consider adding the '--useDefineForClassFields' flag. tests/cases/conformance/classes/members/privateNames/privateNameInInExpressionTransform.ts(20,24): error TS2361: The right-hand side of an 'in' expression must not be a primitive. tests/cases/conformance/classes/members/privateNames/privateNameInInExpressionTransform.ts(24,14): error TS2360: The left-hand side of an 'in' expression must be a private identifier or of type 'any', 'string', 'number', or 'symbol'. tests/cases/conformance/classes/members/privateNames/privateNameInInExpressionTransform.ts(29,21): error TS1005: ';' expected. tests/cases/conformance/classes/members/privateNames/privateNameInInExpressionTransform.ts(30,21): error TS1005: ';' expected. -==== tests/cases/conformance/classes/members/privateNames/privateNameInInExpressionTransform.ts (5 errors) ==== +==== tests/cases/conformance/classes/members/privateNames/privateNameInInExpressionTransform.ts (4 errors) ==== class Foo { #field = 1; #method() {} static #staticField= 2; - ~ -!!! error TS2805: Static fields with private names can't have initializers when the '--useDefineForClassFields' flag is not specified with a '--target' of 'esnext'. Consider adding the '--useDefineForClassFields' flag. static #staticMethod() {} check(v: any) { diff --git a/tests/baselines/reference/privateNameStaticAndStaticInitializer(target=es2022).js b/tests/baselines/reference/privateNameStaticAndStaticInitializer(target=es2022).js index 2e3d168e42004..ccd7fec0c66bc 100644 --- a/tests/baselines/reference/privateNameStaticAndStaticInitializer(target=es2022).js +++ b/tests/baselines/reference/privateNameStaticAndStaticInitializer(target=es2022).js @@ -8,8 +8,6 @@ class A { //// [privateNameStaticAndStaticInitializer.js] class A { - static #foo; - static #prop; + static #foo = 1; + static #prop = 2; } -A.#foo = 1; -A.#prop = 2; diff --git a/tests/baselines/reference/privateNameStaticAndStaticInitializer(target=esnext).errors.txt b/tests/baselines/reference/privateNameStaticAndStaticInitializer(target=esnext).errors.txt deleted file mode 100644 index ae43b5335e8f9..0000000000000 --- a/tests/baselines/reference/privateNameStaticAndStaticInitializer(target=esnext).errors.txt +++ /dev/null @@ -1,15 +0,0 @@ -tests/cases/conformance/classes/members/privateNames/privateNameStaticAndStaticInitializer.ts(2,17): error TS2805: Static fields with private names can't have initializers when the '--useDefineForClassFields' flag is not specified with a '--target' of 'esnext'. Consider adding the '--useDefineForClassFields' flag. -tests/cases/conformance/classes/members/privateNames/privateNameStaticAndStaticInitializer.ts(3,18): error TS2805: Static fields with private names can't have initializers when the '--useDefineForClassFields' flag is not specified with a '--target' of 'esnext'. Consider adding the '--useDefineForClassFields' flag. - - -==== tests/cases/conformance/classes/members/privateNames/privateNameStaticAndStaticInitializer.ts (2 errors) ==== - class A { - static #foo = 1; - ~ -!!! error TS2805: Static fields with private names can't have initializers when the '--useDefineForClassFields' flag is not specified with a '--target' of 'esnext'. Consider adding the '--useDefineForClassFields' flag. - static #prop = 2; - ~ -!!! error TS2805: Static fields with private names can't have initializers when the '--useDefineForClassFields' flag is not specified with a '--target' of 'esnext'. Consider adding the '--useDefineForClassFields' flag. - } - - \ No newline at end of file diff --git a/tests/baselines/reference/privateNameStaticAndStaticInitializer(target=esnext).js b/tests/baselines/reference/privateNameStaticAndStaticInitializer(target=esnext).js index 2e3d168e42004..ccd7fec0c66bc 100644 --- a/tests/baselines/reference/privateNameStaticAndStaticInitializer(target=esnext).js +++ b/tests/baselines/reference/privateNameStaticAndStaticInitializer(target=esnext).js @@ -8,8 +8,6 @@ class A { //// [privateNameStaticAndStaticInitializer.js] class A { - static #foo; - static #prop; + static #foo = 1; + static #prop = 2; } -A.#foo = 1; -A.#prop = 2; diff --git a/tests/baselines/reference/privateNameStaticFieldDestructuredBinding(target=es2022).js b/tests/baselines/reference/privateNameStaticFieldDestructuredBinding(target=es2022).js index bbaf5cd7601ab..69b4fff34e2bf 100644 --- a/tests/baselines/reference/privateNameStaticFieldDestructuredBinding(target=es2022).js +++ b/tests/baselines/reference/privateNameStaticFieldDestructuredBinding(target=es2022).js @@ -37,7 +37,7 @@ class A { [A.#field = 2] = []; [this.otherClass.#field = 2] = []; } - static #field; + static #field = 1; testObject() { return { x: 10, y: 6 }; } @@ -48,4 +48,3 @@ class A { [_a.#field] = [2]; } } -A.#field = 1; diff --git a/tests/baselines/reference/privateNameStaticFieldDestructuredBinding(target=esnext).errors.txt b/tests/baselines/reference/privateNameStaticFieldDestructuredBinding(target=esnext).errors.txt deleted file mode 100644 index f0932d7ba51aa..0000000000000 --- a/tests/baselines/reference/privateNameStaticFieldDestructuredBinding(target=esnext).errors.txt +++ /dev/null @@ -1,30 +0,0 @@ -tests/cases/conformance/classes/members/privateNames/privateNameStaticFieldDestructuredBinding.ts(2,21): error TS2805: Static fields with private names can't have initializers when the '--useDefineForClassFields' flag is not specified with a '--target' of 'esnext'. Consider adding the '--useDefineForClassFields' flag. - - -==== tests/cases/conformance/classes/members/privateNames/privateNameStaticFieldDestructuredBinding.ts (1 errors) ==== - class A { - static #field = 1; - ~ -!!! error TS2805: Static fields with private names can't have initializers when the '--useDefineForClassFields' flag is not specified with a '--target' of 'esnext'. Consider adding the '--useDefineForClassFields' flag. - otherClass = A; - testObject() { - return { x: 10, y: 6 }; - } - testArray() { - return [10, 11]; - } - constructor() { - let y: number; - ({ x: A.#field, y } = this.testObject()); - ([A.#field, y] = this.testArray()); - ({ a: A.#field, b: [A.#field] } = { a: 1, b: [2] }); - [A.#field, [A.#field]] = [1, [2]]; - ({ a: A.#field = 1, b: [A.#field = 1] } = { b: [] }); - [A.#field = 2] = []; - [this.otherClass.#field = 2] = []; - } - static test(_a: typeof A) { - [_a.#field] = [2]; - } - } - \ No newline at end of file diff --git a/tests/baselines/reference/privateNameStaticFieldDestructuredBinding(target=esnext).js b/tests/baselines/reference/privateNameStaticFieldDestructuredBinding(target=esnext).js index bbaf5cd7601ab..69b4fff34e2bf 100644 --- a/tests/baselines/reference/privateNameStaticFieldDestructuredBinding(target=esnext).js +++ b/tests/baselines/reference/privateNameStaticFieldDestructuredBinding(target=esnext).js @@ -37,7 +37,7 @@ class A { [A.#field = 2] = []; [this.otherClass.#field = 2] = []; } - static #field; + static #field = 1; testObject() { return { x: 10, y: 6 }; } @@ -48,4 +48,3 @@ class A { [_a.#field] = [2]; } } -A.#field = 1; diff --git a/tests/baselines/reference/privateNameStaticFieldInitializer(target=es2022).js b/tests/baselines/reference/privateNameStaticFieldInitializer(target=es2022).js index fddf56e1754c5..f52e29bf027e5 100644 --- a/tests/baselines/reference/privateNameStaticFieldInitializer(target=es2022).js +++ b/tests/baselines/reference/privateNameStaticFieldInitializer(target=es2022).js @@ -7,7 +7,6 @@ class A { //// [privateNameStaticFieldInitializer.js] class A { - static #field; + static #field = 10; static #uninitialized; } -A.#field = 10; diff --git a/tests/baselines/reference/privateNameStaticFieldInitializer(target=esnext).errors.txt b/tests/baselines/reference/privateNameStaticFieldInitializer(target=esnext).errors.txt deleted file mode 100644 index 13dc546e2dd96..0000000000000 --- a/tests/baselines/reference/privateNameStaticFieldInitializer(target=esnext).errors.txt +++ /dev/null @@ -1,11 +0,0 @@ -tests/cases/conformance/classes/members/privateNames/privateNameStaticFieldInitializer.ts(2,21): error TS2805: Static fields with private names can't have initializers when the '--useDefineForClassFields' flag is not specified with a '--target' of 'esnext'. Consider adding the '--useDefineForClassFields' flag. - - -==== tests/cases/conformance/classes/members/privateNames/privateNameStaticFieldInitializer.ts (1 errors) ==== - class A { - static #field = 10; - ~~ -!!! error TS2805: Static fields with private names can't have initializers when the '--useDefineForClassFields' flag is not specified with a '--target' of 'esnext'. Consider adding the '--useDefineForClassFields' flag. - static #uninitialized; - } - \ No newline at end of file diff --git a/tests/baselines/reference/privateNameStaticFieldInitializer(target=esnext).js b/tests/baselines/reference/privateNameStaticFieldInitializer(target=esnext).js index fddf56e1754c5..f52e29bf027e5 100644 --- a/tests/baselines/reference/privateNameStaticFieldInitializer(target=esnext).js +++ b/tests/baselines/reference/privateNameStaticFieldInitializer(target=esnext).js @@ -7,7 +7,6 @@ class A { //// [privateNameStaticFieldInitializer.js] class A { - static #field; + static #field = 10; static #uninitialized; } -A.#field = 10; diff --git a/tests/baselines/reference/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext(target=es2020).js b/tests/baselines/reference/privateNameWhenNotUseDefineForClassFieldsInEsNext(target=es2020).js similarity index 55% rename from tests/baselines/reference/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext(target=es2020).js rename to tests/baselines/reference/privateNameWhenNotUseDefineForClassFieldsInEsNext(target=es2020).js index 6b91145aa061e..656f556ed4859 100644 --- a/tests/baselines/reference/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext(target=es2020).js +++ b/tests/baselines/reference/privateNameWhenNotUseDefineForClassFieldsInEsNext(target=es2020).js @@ -1,82 +1,82 @@ -//// [privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts] -class TestWithErrors { - #prop = 0 - static dd = new TestWithErrors().#prop; // Err +//// [privateNameWhenNotUseDefineForClassFieldsInEsNext.ts] +class TestWithStatics { + #prop = 0 + static dd = new TestWithStatics().#prop; // OK static ["X_ z_ zz"] = class Inner { - #foo = 10 + #foo = 10 m() { - new TestWithErrors().#prop // Err + new TestWithStatics().#prop // OK } static C = class InnerInner { m() { - new TestWithErrors().#prop // Err - new Inner().#foo; // Err + new TestWithStatics().#prop // OK + new Inner().#foo; // OK } } static M(){ return class { m() { - new TestWithErrors().#prop // Err + new TestWithStatics().#prop // OK new Inner().#foo; // OK } } - } + } } } -class TestNoErrors { - #prop = 0 - dd = new TestNoErrors().#prop; // OK +class TestNonStatics { + #prop = 0 + dd = new TestNonStatics().#prop; // OK ["X_ z_ zz"] = class Inner { - #foo = 10 + #foo = 10 m() { - new TestNoErrors().#prop // Ok + new TestNonStatics().#prop // Ok } C = class InnerInner { m() { - new TestNoErrors().#prop // Ok + new TestNonStatics().#prop // Ok new Inner().#foo; // Ok } } - + static M(){ return class { m() { - new TestNoErrors().#prop // OK + new TestNonStatics().#prop // OK new Inner().#foo; // OK } } - } + } } - } +} -//// [privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.js] +//// [privateNameWhenNotUseDefineForClassFieldsInEsNext.js] "use strict"; var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; -var _TestWithErrors_prop, _Inner_foo, _a, _TestNoErrors_prop; -class TestWithErrors { +var _TestWithStatics_prop, _Inner_foo, _a, _TestNonStatics_prop; +class TestWithStatics { constructor() { - _TestWithErrors_prop.set(this, 0); + _TestWithStatics_prop.set(this, 0); } } -_TestWithErrors_prop = new WeakMap(); -TestWithErrors.dd = __classPrivateFieldGet(new TestWithErrors(), _TestWithErrors_prop, "f"); // Err -TestWithErrors["X_ z_ zz"] = (_a = class Inner { +_TestWithStatics_prop = new WeakMap(); +TestWithStatics.dd = __classPrivateFieldGet(new TestWithStatics(), _TestWithStatics_prop, "f"); // OK +TestWithStatics["X_ z_ zz"] = (_a = class Inner { constructor() { _Inner_foo.set(this, 10); } m() { - __classPrivateFieldGet(new TestWithErrors(), _TestWithErrors_prop, "f"); // Err + __classPrivateFieldGet(new TestWithStatics(), _TestWithStatics_prop, "f"); // OK } static M() { return class { m() { - __classPrivateFieldGet(new TestWithErrors(), _TestWithErrors_prop, "f"); // Err + __classPrivateFieldGet(new TestWithStatics(), _TestWithStatics_prop, "f"); // OK __classPrivateFieldGet(new Inner(), _Inner_foo, "f"); // OK } }; @@ -85,33 +85,33 @@ TestWithErrors["X_ z_ zz"] = (_a = class Inner { _Inner_foo = new WeakMap(), _a.C = class InnerInner { m() { - __classPrivateFieldGet(new TestWithErrors(), _TestWithErrors_prop, "f"); // Err - __classPrivateFieldGet(new _a(), _Inner_foo, "f"); // Err + __classPrivateFieldGet(new TestWithStatics(), _TestWithStatics_prop, "f"); // OK + __classPrivateFieldGet(new _a(), _Inner_foo, "f"); // OK } }, _a); -class TestNoErrors { +class TestNonStatics { constructor() { var _Inner_foo_1, _b; - _TestNoErrors_prop.set(this, 0); - this.dd = __classPrivateFieldGet(new TestNoErrors(), _TestNoErrors_prop, "f"); // OK + _TestNonStatics_prop.set(this, 0); + this.dd = __classPrivateFieldGet(new TestNonStatics(), _TestNonStatics_prop, "f"); // OK this["X_ z_ zz"] = (_b = class Inner { constructor() { _Inner_foo_1.set(this, 10); this.C = class InnerInner { m() { - __classPrivateFieldGet(new TestNoErrors(), _TestNoErrors_prop, "f"); // Ok + __classPrivateFieldGet(new TestNonStatics(), _TestNonStatics_prop, "f"); // Ok __classPrivateFieldGet(new Inner(), _Inner_foo_1, "f"); // Ok } }; } m() { - __classPrivateFieldGet(new TestNoErrors(), _TestNoErrors_prop, "f"); // Ok + __classPrivateFieldGet(new TestNonStatics(), _TestNonStatics_prop, "f"); // Ok } static M() { return class { m() { - __classPrivateFieldGet(new TestNoErrors(), _TestNoErrors_prop, "f"); // OK + __classPrivateFieldGet(new TestNonStatics(), _TestNonStatics_prop, "f"); // OK __classPrivateFieldGet(new Inner(), _Inner_foo_1, "f"); // OK } }; @@ -121,4 +121,4 @@ class TestNoErrors { _b); } } -_TestNoErrors_prop = new WeakMap(); +_TestNonStatics_prop = new WeakMap(); diff --git a/tests/baselines/reference/privateNameWhenNotUseDefineForClassFieldsInEsNext(target=es2020).symbols b/tests/baselines/reference/privateNameWhenNotUseDefineForClassFieldsInEsNext(target=es2020).symbols new file mode 100644 index 0000000000000..ff4ef05554888 --- /dev/null +++ b/tests/baselines/reference/privateNameWhenNotUseDefineForClassFieldsInEsNext(target=es2020).symbols @@ -0,0 +1,126 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameWhenNotUseDefineForClassFieldsInEsNext.ts === +class TestWithStatics { +>TestWithStatics : Symbol(TestWithStatics, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 0, 0)) + + #prop = 0 +>#prop : Symbol(TestWithStatics.#prop, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 0, 23)) + + static dd = new TestWithStatics().#prop; // OK +>dd : Symbol(TestWithStatics.dd, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 1, 13)) +>new TestWithStatics().#prop : Symbol(TestWithStatics.#prop, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 0, 23)) +>TestWithStatics : Symbol(TestWithStatics, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 0, 0)) + + static ["X_ z_ zz"] = class Inner { +>["X_ z_ zz"] : Symbol(TestWithStatics["X_ z_ zz"], Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 2, 44)) +>"X_ z_ zz" : Symbol(TestWithStatics["X_ z_ zz"], Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 2, 44)) +>Inner : Symbol(Inner, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 3, 25)) + + #foo = 10 +>#foo : Symbol(Inner.#foo, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 3, 39)) + + m() { +>m : Symbol(Inner.m, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 4, 18)) + + new TestWithStatics().#prop // OK +>new TestWithStatics().#prop : Symbol(TestWithStatics.#prop, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 0, 23)) +>TestWithStatics : Symbol(TestWithStatics, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 0, 0)) + } + static C = class InnerInner { +>C : Symbol(Inner.C, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 7, 9)) +>InnerInner : Symbol(InnerInner, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 8, 18)) + + m() { +>m : Symbol(InnerInner.m, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 8, 37)) + + new TestWithStatics().#prop // OK +>new TestWithStatics().#prop : Symbol(TestWithStatics.#prop, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 0, 23)) +>TestWithStatics : Symbol(TestWithStatics, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 0, 0)) + + new Inner().#foo; // OK +>new Inner().#foo : Symbol(Inner.#foo, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 3, 39)) +>Inner : Symbol(Inner, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 3, 25)) + } + } + + static M(){ +>M : Symbol(Inner.M, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 13, 9)) + + return class { + m() { +>m : Symbol((Anonymous class).m, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 16, 26)) + + new TestWithStatics().#prop // OK +>new TestWithStatics().#prop : Symbol(TestWithStatics.#prop, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 0, 23)) +>TestWithStatics : Symbol(TestWithStatics, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 0, 0)) + + new Inner().#foo; // OK +>new Inner().#foo : Symbol(Inner.#foo, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 3, 39)) +>Inner : Symbol(Inner, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 3, 25)) + } + } + } + } +} + +class TestNonStatics { +>TestNonStatics : Symbol(TestNonStatics, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 24, 1)) + + #prop = 0 +>#prop : Symbol(TestNonStatics.#prop, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 26, 22)) + + dd = new TestNonStatics().#prop; // OK +>dd : Symbol(TestNonStatics.dd, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 27, 13)) +>new TestNonStatics().#prop : Symbol(TestNonStatics.#prop, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 26, 22)) +>TestNonStatics : Symbol(TestNonStatics, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 24, 1)) + + ["X_ z_ zz"] = class Inner { +>["X_ z_ zz"] : Symbol(TestNonStatics["X_ z_ zz"], Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 28, 36)) +>"X_ z_ zz" : Symbol(TestNonStatics["X_ z_ zz"], Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 28, 36)) +>Inner : Symbol(Inner, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 29, 18)) + + #foo = 10 +>#foo : Symbol(Inner.#foo, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 29, 32)) + + m() { +>m : Symbol(Inner.m, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 30, 18)) + + new TestNonStatics().#prop // Ok +>new TestNonStatics().#prop : Symbol(TestNonStatics.#prop, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 26, 22)) +>TestNonStatics : Symbol(TestNonStatics, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 24, 1)) + } + C = class InnerInner { +>C : Symbol(Inner.C, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 33, 9)) +>InnerInner : Symbol(InnerInner, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 34, 11)) + + m() { +>m : Symbol(InnerInner.m, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 34, 30)) + + new TestNonStatics().#prop // Ok +>new TestNonStatics().#prop : Symbol(TestNonStatics.#prop, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 26, 22)) +>TestNonStatics : Symbol(TestNonStatics, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 24, 1)) + + new Inner().#foo; // Ok +>new Inner().#foo : Symbol(Inner.#foo, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 29, 32)) +>Inner : Symbol(Inner, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 29, 18)) + } + } + + static M(){ +>M : Symbol(Inner.M, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 39, 9)) + + return class { + m() { +>m : Symbol((Anonymous class).m, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 42, 26)) + + new TestNonStatics().#prop // OK +>new TestNonStatics().#prop : Symbol(TestNonStatics.#prop, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 26, 22)) +>TestNonStatics : Symbol(TestNonStatics, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 24, 1)) + + new Inner().#foo; // OK +>new Inner().#foo : Symbol(Inner.#foo, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 29, 32)) +>Inner : Symbol(Inner, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 29, 18)) + } + } + } + } +} diff --git a/tests/baselines/reference/privateNameWhenNotUseDefineForClassFieldsInEsNext(target=es2020).types b/tests/baselines/reference/privateNameWhenNotUseDefineForClassFieldsInEsNext(target=es2020).types new file mode 100644 index 0000000000000..198a1f8f2c070 --- /dev/null +++ b/tests/baselines/reference/privateNameWhenNotUseDefineForClassFieldsInEsNext(target=es2020).types @@ -0,0 +1,150 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameWhenNotUseDefineForClassFieldsInEsNext.ts === +class TestWithStatics { +>TestWithStatics : TestWithStatics + + #prop = 0 +>#prop : number +>0 : 0 + + static dd = new TestWithStatics().#prop; // OK +>dd : number +>new TestWithStatics().#prop : number +>new TestWithStatics() : TestWithStatics +>TestWithStatics : typeof TestWithStatics + + static ["X_ z_ zz"] = class Inner { +>["X_ z_ zz"] : typeof Inner +>"X_ z_ zz" : "X_ z_ zz" +>class Inner { #foo = 10 m() { new TestWithStatics().#prop // OK } static C = class InnerInner { m() { new TestWithStatics().#prop // OK new Inner().#foo; // OK } } static M(){ return class { m() { new TestWithStatics().#prop // OK new Inner().#foo; // OK } } } } : typeof Inner +>Inner : typeof Inner + + #foo = 10 +>#foo : number +>10 : 10 + + m() { +>m : () => void + + new TestWithStatics().#prop // OK +>new TestWithStatics().#prop : number +>new TestWithStatics() : TestWithStatics +>TestWithStatics : typeof TestWithStatics + } + static C = class InnerInner { +>C : typeof InnerInner +>class InnerInner { m() { new TestWithStatics().#prop // OK new Inner().#foo; // OK } } : typeof InnerInner +>InnerInner : typeof InnerInner + + m() { +>m : () => void + + new TestWithStatics().#prop // OK +>new TestWithStatics().#prop : number +>new TestWithStatics() : TestWithStatics +>TestWithStatics : typeof TestWithStatics + + new Inner().#foo; // OK +>new Inner().#foo : number +>new Inner() : Inner +>Inner : typeof Inner + } + } + + static M(){ +>M : () => typeof (Anonymous class) + + return class { +>class { m() { new TestWithStatics().#prop // OK new Inner().#foo; // OK } } : typeof (Anonymous class) + + m() { +>m : () => void + + new TestWithStatics().#prop // OK +>new TestWithStatics().#prop : number +>new TestWithStatics() : TestWithStatics +>TestWithStatics : typeof TestWithStatics + + new Inner().#foo; // OK +>new Inner().#foo : number +>new Inner() : Inner +>Inner : typeof Inner + } + } + } + } +} + +class TestNonStatics { +>TestNonStatics : TestNonStatics + + #prop = 0 +>#prop : number +>0 : 0 + + dd = new TestNonStatics().#prop; // OK +>dd : number +>new TestNonStatics().#prop : number +>new TestNonStatics() : TestNonStatics +>TestNonStatics : typeof TestNonStatics + + ["X_ z_ zz"] = class Inner { +>["X_ z_ zz"] : typeof Inner +>"X_ z_ zz" : "X_ z_ zz" +>class Inner { #foo = 10 m() { new TestNonStatics().#prop // Ok } C = class InnerInner { m() { new TestNonStatics().#prop // Ok new Inner().#foo; // Ok } } static M(){ return class { m() { new TestNonStatics().#prop // OK new Inner().#foo; // OK } } } } : typeof Inner +>Inner : typeof Inner + + #foo = 10 +>#foo : number +>10 : 10 + + m() { +>m : () => void + + new TestNonStatics().#prop // Ok +>new TestNonStatics().#prop : number +>new TestNonStatics() : TestNonStatics +>TestNonStatics : typeof TestNonStatics + } + C = class InnerInner { +>C : typeof InnerInner +>class InnerInner { m() { new TestNonStatics().#prop // Ok new Inner().#foo; // Ok } } : typeof InnerInner +>InnerInner : typeof InnerInner + + m() { +>m : () => void + + new TestNonStatics().#prop // Ok +>new TestNonStatics().#prop : number +>new TestNonStatics() : TestNonStatics +>TestNonStatics : typeof TestNonStatics + + new Inner().#foo; // Ok +>new Inner().#foo : number +>new Inner() : Inner +>Inner : typeof Inner + } + } + + static M(){ +>M : () => typeof (Anonymous class) + + return class { +>class { m() { new TestNonStatics().#prop // OK new Inner().#foo; // OK } } : typeof (Anonymous class) + + m() { +>m : () => void + + new TestNonStatics().#prop // OK +>new TestNonStatics().#prop : number +>new TestNonStatics() : TestNonStatics +>TestNonStatics : typeof TestNonStatics + + new Inner().#foo; // OK +>new Inner().#foo : number +>new Inner() : Inner +>Inner : typeof Inner + } + } + } + } +} diff --git a/tests/baselines/reference/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext(target=esnext).js b/tests/baselines/reference/privateNameWhenNotUseDefineForClassFieldsInEsNext(target=esnext).js similarity index 52% rename from tests/baselines/reference/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext(target=esnext).js rename to tests/baselines/reference/privateNameWhenNotUseDefineForClassFieldsInEsNext(target=esnext).js index 8c3b1cff1f3fe..e0ce069f349ec 100644 --- a/tests/baselines/reference/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext(target=esnext).js +++ b/tests/baselines/reference/privateNameWhenNotUseDefineForClassFieldsInEsNext(target=esnext).js @@ -1,112 +1,110 @@ -//// [privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts] -class TestWithErrors { - #prop = 0 - static dd = new TestWithErrors().#prop; // Err +//// [privateNameWhenNotUseDefineForClassFieldsInEsNext.ts] +class TestWithStatics { + #prop = 0 + static dd = new TestWithStatics().#prop; // OK static ["X_ z_ zz"] = class Inner { - #foo = 10 + #foo = 10 m() { - new TestWithErrors().#prop // Err + new TestWithStatics().#prop // OK } static C = class InnerInner { m() { - new TestWithErrors().#prop // Err - new Inner().#foo; // Err + new TestWithStatics().#prop // OK + new Inner().#foo; // OK } } static M(){ return class { m() { - new TestWithErrors().#prop // Err + new TestWithStatics().#prop // OK new Inner().#foo; // OK } } - } + } } } -class TestNoErrors { - #prop = 0 - dd = new TestNoErrors().#prop; // OK +class TestNonStatics { + #prop = 0 + dd = new TestNonStatics().#prop; // OK ["X_ z_ zz"] = class Inner { - #foo = 10 + #foo = 10 m() { - new TestNoErrors().#prop // Ok + new TestNonStatics().#prop // Ok } C = class InnerInner { m() { - new TestNoErrors().#prop // Ok + new TestNonStatics().#prop // Ok new Inner().#foo; // Ok } } - + static M(){ return class { m() { - new TestNoErrors().#prop // OK + new TestNonStatics().#prop // OK new Inner().#foo; // OK } } - } + } } - } +} -//// [privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.js] +//// [privateNameWhenNotUseDefineForClassFieldsInEsNext.js] "use strict"; -var _a; -class TestWithErrors { +class TestWithStatics { constructor() { this.#prop = 0; } #prop; -} -TestWithErrors.dd = new TestWithErrors().#prop; // Err -TestWithErrors["X_ z_ zz"] = (_a = class Inner { + static { this.dd = new TestWithStatics().#prop; } // OK + static { this["X_ z_ zz"] = class Inner { constructor() { this.#foo = 10; } #foo; m() { - new TestWithErrors().#prop; // Err + new TestWithStatics().#prop; // OK } + static { this.C = class InnerInner { + m() { + new TestWithStatics().#prop; // OK + new Inner().#foo; // OK + } + }; } static M() { return class { m() { - new TestWithErrors().#prop; // Err + new TestWithStatics().#prop; // OK new Inner().#foo; // OK } }; } - }, - _a.C = class InnerInner { - m() { - new TestWithErrors().#prop; // Err - new _a().#foo; // Err - } - }, - _a); -class TestNoErrors { + }; } +} +class TestNonStatics { constructor() { this.#prop = 0; - this.dd = new TestNoErrors().#prop; // OK + this.dd = new TestNonStatics().#prop; // OK this["X_ z_ zz"] = class Inner { constructor() { this.#foo = 10; this.C = class InnerInner { m() { - new TestNoErrors().#prop; // Ok + new TestNonStatics().#prop; // Ok new Inner().#foo; // Ok } }; } #foo; m() { - new TestNoErrors().#prop; // Ok + new TestNonStatics().#prop; // Ok } static M() { return class { m() { - new TestNoErrors().#prop; // OK + new TestNonStatics().#prop; // OK new Inner().#foo; // OK } }; diff --git a/tests/baselines/reference/privateNameWhenNotUseDefineForClassFieldsInEsNext(target=esnext).symbols b/tests/baselines/reference/privateNameWhenNotUseDefineForClassFieldsInEsNext(target=esnext).symbols new file mode 100644 index 0000000000000..ff4ef05554888 --- /dev/null +++ b/tests/baselines/reference/privateNameWhenNotUseDefineForClassFieldsInEsNext(target=esnext).symbols @@ -0,0 +1,126 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameWhenNotUseDefineForClassFieldsInEsNext.ts === +class TestWithStatics { +>TestWithStatics : Symbol(TestWithStatics, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 0, 0)) + + #prop = 0 +>#prop : Symbol(TestWithStatics.#prop, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 0, 23)) + + static dd = new TestWithStatics().#prop; // OK +>dd : Symbol(TestWithStatics.dd, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 1, 13)) +>new TestWithStatics().#prop : Symbol(TestWithStatics.#prop, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 0, 23)) +>TestWithStatics : Symbol(TestWithStatics, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 0, 0)) + + static ["X_ z_ zz"] = class Inner { +>["X_ z_ zz"] : Symbol(TestWithStatics["X_ z_ zz"], Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 2, 44)) +>"X_ z_ zz" : Symbol(TestWithStatics["X_ z_ zz"], Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 2, 44)) +>Inner : Symbol(Inner, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 3, 25)) + + #foo = 10 +>#foo : Symbol(Inner.#foo, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 3, 39)) + + m() { +>m : Symbol(Inner.m, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 4, 18)) + + new TestWithStatics().#prop // OK +>new TestWithStatics().#prop : Symbol(TestWithStatics.#prop, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 0, 23)) +>TestWithStatics : Symbol(TestWithStatics, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 0, 0)) + } + static C = class InnerInner { +>C : Symbol(Inner.C, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 7, 9)) +>InnerInner : Symbol(InnerInner, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 8, 18)) + + m() { +>m : Symbol(InnerInner.m, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 8, 37)) + + new TestWithStatics().#prop // OK +>new TestWithStatics().#prop : Symbol(TestWithStatics.#prop, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 0, 23)) +>TestWithStatics : Symbol(TestWithStatics, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 0, 0)) + + new Inner().#foo; // OK +>new Inner().#foo : Symbol(Inner.#foo, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 3, 39)) +>Inner : Symbol(Inner, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 3, 25)) + } + } + + static M(){ +>M : Symbol(Inner.M, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 13, 9)) + + return class { + m() { +>m : Symbol((Anonymous class).m, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 16, 26)) + + new TestWithStatics().#prop // OK +>new TestWithStatics().#prop : Symbol(TestWithStatics.#prop, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 0, 23)) +>TestWithStatics : Symbol(TestWithStatics, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 0, 0)) + + new Inner().#foo; // OK +>new Inner().#foo : Symbol(Inner.#foo, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 3, 39)) +>Inner : Symbol(Inner, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 3, 25)) + } + } + } + } +} + +class TestNonStatics { +>TestNonStatics : Symbol(TestNonStatics, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 24, 1)) + + #prop = 0 +>#prop : Symbol(TestNonStatics.#prop, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 26, 22)) + + dd = new TestNonStatics().#prop; // OK +>dd : Symbol(TestNonStatics.dd, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 27, 13)) +>new TestNonStatics().#prop : Symbol(TestNonStatics.#prop, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 26, 22)) +>TestNonStatics : Symbol(TestNonStatics, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 24, 1)) + + ["X_ z_ zz"] = class Inner { +>["X_ z_ zz"] : Symbol(TestNonStatics["X_ z_ zz"], Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 28, 36)) +>"X_ z_ zz" : Symbol(TestNonStatics["X_ z_ zz"], Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 28, 36)) +>Inner : Symbol(Inner, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 29, 18)) + + #foo = 10 +>#foo : Symbol(Inner.#foo, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 29, 32)) + + m() { +>m : Symbol(Inner.m, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 30, 18)) + + new TestNonStatics().#prop // Ok +>new TestNonStatics().#prop : Symbol(TestNonStatics.#prop, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 26, 22)) +>TestNonStatics : Symbol(TestNonStatics, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 24, 1)) + } + C = class InnerInner { +>C : Symbol(Inner.C, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 33, 9)) +>InnerInner : Symbol(InnerInner, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 34, 11)) + + m() { +>m : Symbol(InnerInner.m, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 34, 30)) + + new TestNonStatics().#prop // Ok +>new TestNonStatics().#prop : Symbol(TestNonStatics.#prop, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 26, 22)) +>TestNonStatics : Symbol(TestNonStatics, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 24, 1)) + + new Inner().#foo; // Ok +>new Inner().#foo : Symbol(Inner.#foo, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 29, 32)) +>Inner : Symbol(Inner, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 29, 18)) + } + } + + static M(){ +>M : Symbol(Inner.M, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 39, 9)) + + return class { + m() { +>m : Symbol((Anonymous class).m, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 42, 26)) + + new TestNonStatics().#prop // OK +>new TestNonStatics().#prop : Symbol(TestNonStatics.#prop, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 26, 22)) +>TestNonStatics : Symbol(TestNonStatics, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 24, 1)) + + new Inner().#foo; // OK +>new Inner().#foo : Symbol(Inner.#foo, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 29, 32)) +>Inner : Symbol(Inner, Decl(privateNameWhenNotUseDefineForClassFieldsInEsNext.ts, 29, 18)) + } + } + } + } +} diff --git a/tests/baselines/reference/privateNameWhenNotUseDefineForClassFieldsInEsNext(target=esnext).types b/tests/baselines/reference/privateNameWhenNotUseDefineForClassFieldsInEsNext(target=esnext).types new file mode 100644 index 0000000000000..198a1f8f2c070 --- /dev/null +++ b/tests/baselines/reference/privateNameWhenNotUseDefineForClassFieldsInEsNext(target=esnext).types @@ -0,0 +1,150 @@ +=== tests/cases/conformance/classes/members/privateNames/privateNameWhenNotUseDefineForClassFieldsInEsNext.ts === +class TestWithStatics { +>TestWithStatics : TestWithStatics + + #prop = 0 +>#prop : number +>0 : 0 + + static dd = new TestWithStatics().#prop; // OK +>dd : number +>new TestWithStatics().#prop : number +>new TestWithStatics() : TestWithStatics +>TestWithStatics : typeof TestWithStatics + + static ["X_ z_ zz"] = class Inner { +>["X_ z_ zz"] : typeof Inner +>"X_ z_ zz" : "X_ z_ zz" +>class Inner { #foo = 10 m() { new TestWithStatics().#prop // OK } static C = class InnerInner { m() { new TestWithStatics().#prop // OK new Inner().#foo; // OK } } static M(){ return class { m() { new TestWithStatics().#prop // OK new Inner().#foo; // OK } } } } : typeof Inner +>Inner : typeof Inner + + #foo = 10 +>#foo : number +>10 : 10 + + m() { +>m : () => void + + new TestWithStatics().#prop // OK +>new TestWithStatics().#prop : number +>new TestWithStatics() : TestWithStatics +>TestWithStatics : typeof TestWithStatics + } + static C = class InnerInner { +>C : typeof InnerInner +>class InnerInner { m() { new TestWithStatics().#prop // OK new Inner().#foo; // OK } } : typeof InnerInner +>InnerInner : typeof InnerInner + + m() { +>m : () => void + + new TestWithStatics().#prop // OK +>new TestWithStatics().#prop : number +>new TestWithStatics() : TestWithStatics +>TestWithStatics : typeof TestWithStatics + + new Inner().#foo; // OK +>new Inner().#foo : number +>new Inner() : Inner +>Inner : typeof Inner + } + } + + static M(){ +>M : () => typeof (Anonymous class) + + return class { +>class { m() { new TestWithStatics().#prop // OK new Inner().#foo; // OK } } : typeof (Anonymous class) + + m() { +>m : () => void + + new TestWithStatics().#prop // OK +>new TestWithStatics().#prop : number +>new TestWithStatics() : TestWithStatics +>TestWithStatics : typeof TestWithStatics + + new Inner().#foo; // OK +>new Inner().#foo : number +>new Inner() : Inner +>Inner : typeof Inner + } + } + } + } +} + +class TestNonStatics { +>TestNonStatics : TestNonStatics + + #prop = 0 +>#prop : number +>0 : 0 + + dd = new TestNonStatics().#prop; // OK +>dd : number +>new TestNonStatics().#prop : number +>new TestNonStatics() : TestNonStatics +>TestNonStatics : typeof TestNonStatics + + ["X_ z_ zz"] = class Inner { +>["X_ z_ zz"] : typeof Inner +>"X_ z_ zz" : "X_ z_ zz" +>class Inner { #foo = 10 m() { new TestNonStatics().#prop // Ok } C = class InnerInner { m() { new TestNonStatics().#prop // Ok new Inner().#foo; // Ok } } static M(){ return class { m() { new TestNonStatics().#prop // OK new Inner().#foo; // OK } } } } : typeof Inner +>Inner : typeof Inner + + #foo = 10 +>#foo : number +>10 : 10 + + m() { +>m : () => void + + new TestNonStatics().#prop // Ok +>new TestNonStatics().#prop : number +>new TestNonStatics() : TestNonStatics +>TestNonStatics : typeof TestNonStatics + } + C = class InnerInner { +>C : typeof InnerInner +>class InnerInner { m() { new TestNonStatics().#prop // Ok new Inner().#foo; // Ok } } : typeof InnerInner +>InnerInner : typeof InnerInner + + m() { +>m : () => void + + new TestNonStatics().#prop // Ok +>new TestNonStatics().#prop : number +>new TestNonStatics() : TestNonStatics +>TestNonStatics : typeof TestNonStatics + + new Inner().#foo; // Ok +>new Inner().#foo : number +>new Inner() : Inner +>Inner : typeof Inner + } + } + + static M(){ +>M : () => typeof (Anonymous class) + + return class { +>class { m() { new TestNonStatics().#prop // OK new Inner().#foo; // OK } } : typeof (Anonymous class) + + m() { +>m : () => void + + new TestNonStatics().#prop // OK +>new TestNonStatics().#prop : number +>new TestNonStatics() : TestNonStatics +>TestNonStatics : typeof TestNonStatics + + new Inner().#foo; // OK +>new Inner().#foo : number +>new Inner() : Inner +>Inner : typeof Inner + } + } + } + } +} diff --git a/tests/baselines/reference/thisAndSuperInStaticMembers2(target=es2022).js b/tests/baselines/reference/thisAndSuperInStaticMembers2(target=es2022).js index 742fa6b656a60..852c1b8a4b1ac 100644 --- a/tests/baselines/reference/thisAndSuperInStaticMembers2(target=es2022).js +++ b/tests/baselines/reference/thisAndSuperInStaticMembers2(target=es2022).js @@ -40,8 +40,7 @@ class C extends B { //// [thisAndSuperInStaticMembers2.js] -var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o; -class C extends (_b = B) { +class C extends B { constructor() { super(...arguments); // these should be unaffected @@ -49,29 +48,28 @@ class C extends (_b = B) { this.y = this.x; this.z = super.f(); } + static { this.x = undefined; } + static { this.y1 = this.x; } + static { this.y2 = this.x(); } + static { this.y3 = this?.x(); } + static { this.y4 = this[("x")](); } + static { this.y5 = this?.[("x")](); } + static { this.z1 = super.a; } + static { this.z2 = super["a"]; } + static { this.z3 = super.f(); } + static { this.z4 = super["f"](); } + static { this.z5 = super.a = 0; } + static { this.z6 = super.a += 1; } + static { this.z7 = (() => { super.a = 0; })(); } + static { this.z8 = [super.a] = [0]; } + static { this.z9 = [super.a = 0] = [0]; } + static { this.z10 = [...super.a] = [0]; } + static { this.z11 = { x: super.a } = { x: 0 }; } + static { this.z12 = { x: super.a = 0 } = { x: 0 }; } + static { this.z13 = { ...super.a } = { x: 0 }; } + static { this.z14 = ++super.a; } + static { this.z15 = --super.a; } + static { this.z16 = ++super[("a")]; } + static { this.z17 = super.a++; } + static { this.z18 = super.a ``; } } -_a = C; -C.x = undefined; -C.y1 = _a.x; -C.y2 = _a.x(); -C.y3 = _a?.x(); -C.y4 = _a[("x")](); -C.y5 = _a?.[("x")](); -C.z1 = Reflect.get(_b, "a", _a); -C.z2 = Reflect.get(_b, "a", _a); -C.z3 = Reflect.get(_b, "f", _a).call(_a); -C.z4 = Reflect.get(_b, "f", _a).call(_a); -C.z5 = (Reflect.set(_b, "a", _c = 0, _a), _c); -C.z6 = (Reflect.set(_b, "a", _d = Reflect.get(_b, "a", _a) + 1, _a), _d); -C.z7 = (() => { Reflect.set(_b, "a", 0, _a); })(); -C.z8 = [({ set value(_c) { Reflect.set(_b, "a", _c, _a); } }).value] = [0]; -C.z9 = [({ set value(_c) { Reflect.set(_b, "a", _c, _a); } }).value = 0] = [0]; -C.z10 = [...({ set value(_c) { Reflect.set(_b, "a", _c, _a); } }).value] = [0]; -C.z11 = { x: ({ set value(_c) { Reflect.set(_b, "a", _c, _a); } }).value } = { x: 0 }; -C.z12 = { x: ({ set value(_c) { Reflect.set(_b, "a", _c, _a); } }).value = 0 } = { x: 0 }; -C.z13 = { ...({ set value(_c) { Reflect.set(_b, "a", _c, _a); } }).value } = { x: 0 }; -C.z14 = (Reflect.set(_b, "a", (_f = Reflect.get(_b, "a", _a), _e = ++_f), _a), _e); -C.z15 = (Reflect.set(_b, "a", (_h = Reflect.get(_b, "a", _a), _g = --_h), _a), _g); -C.z16 = (Reflect.set(_b, _j = ("a"), (_l = Reflect.get(_b, _j, _a), _k = ++_l), _a), _k); -C.z17 = (Reflect.set(_b, "a", (_o = Reflect.get(_b, "a", _a), _m = _o++, _o), _a), _m); -C.z18 = Reflect.get(_b, "a", _a).bind(_a) ``; diff --git a/tests/baselines/reference/thisAndSuperInStaticMembers2(target=esnext).js b/tests/baselines/reference/thisAndSuperInStaticMembers2(target=esnext).js index 742fa6b656a60..852c1b8a4b1ac 100644 --- a/tests/baselines/reference/thisAndSuperInStaticMembers2(target=esnext).js +++ b/tests/baselines/reference/thisAndSuperInStaticMembers2(target=esnext).js @@ -40,8 +40,7 @@ class C extends B { //// [thisAndSuperInStaticMembers2.js] -var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o; -class C extends (_b = B) { +class C extends B { constructor() { super(...arguments); // these should be unaffected @@ -49,29 +48,28 @@ class C extends (_b = B) { this.y = this.x; this.z = super.f(); } + static { this.x = undefined; } + static { this.y1 = this.x; } + static { this.y2 = this.x(); } + static { this.y3 = this?.x(); } + static { this.y4 = this[("x")](); } + static { this.y5 = this?.[("x")](); } + static { this.z1 = super.a; } + static { this.z2 = super["a"]; } + static { this.z3 = super.f(); } + static { this.z4 = super["f"](); } + static { this.z5 = super.a = 0; } + static { this.z6 = super.a += 1; } + static { this.z7 = (() => { super.a = 0; })(); } + static { this.z8 = [super.a] = [0]; } + static { this.z9 = [super.a = 0] = [0]; } + static { this.z10 = [...super.a] = [0]; } + static { this.z11 = { x: super.a } = { x: 0 }; } + static { this.z12 = { x: super.a = 0 } = { x: 0 }; } + static { this.z13 = { ...super.a } = { x: 0 }; } + static { this.z14 = ++super.a; } + static { this.z15 = --super.a; } + static { this.z16 = ++super[("a")]; } + static { this.z17 = super.a++; } + static { this.z18 = super.a ``; } } -_a = C; -C.x = undefined; -C.y1 = _a.x; -C.y2 = _a.x(); -C.y3 = _a?.x(); -C.y4 = _a[("x")](); -C.y5 = _a?.[("x")](); -C.z1 = Reflect.get(_b, "a", _a); -C.z2 = Reflect.get(_b, "a", _a); -C.z3 = Reflect.get(_b, "f", _a).call(_a); -C.z4 = Reflect.get(_b, "f", _a).call(_a); -C.z5 = (Reflect.set(_b, "a", _c = 0, _a), _c); -C.z6 = (Reflect.set(_b, "a", _d = Reflect.get(_b, "a", _a) + 1, _a), _d); -C.z7 = (() => { Reflect.set(_b, "a", 0, _a); })(); -C.z8 = [({ set value(_c) { Reflect.set(_b, "a", _c, _a); } }).value] = [0]; -C.z9 = [({ set value(_c) { Reflect.set(_b, "a", _c, _a); } }).value = 0] = [0]; -C.z10 = [...({ set value(_c) { Reflect.set(_b, "a", _c, _a); } }).value] = [0]; -C.z11 = { x: ({ set value(_c) { Reflect.set(_b, "a", _c, _a); } }).value } = { x: 0 }; -C.z12 = { x: ({ set value(_c) { Reflect.set(_b, "a", _c, _a); } }).value = 0 } = { x: 0 }; -C.z13 = { ...({ set value(_c) { Reflect.set(_b, "a", _c, _a); } }).value } = { x: 0 }; -C.z14 = (Reflect.set(_b, "a", (_f = Reflect.get(_b, "a", _a), _e = ++_f), _a), _e); -C.z15 = (Reflect.set(_b, "a", (_h = Reflect.get(_b, "a", _a), _g = --_h), _a), _g); -C.z16 = (Reflect.set(_b, _j = ("a"), (_l = Reflect.get(_b, _j, _a), _k = ++_l), _a), _k); -C.z17 = (Reflect.set(_b, "a", (_o = Reflect.get(_b, "a", _a), _m = _o++, _o), _a), _m); -C.z18 = Reflect.get(_b, "a", _a).bind(_a) ``; diff --git a/tests/baselines/reference/transformApi/transformsCorrectly.rewrittenNamespaceFollowingClass.js b/tests/baselines/reference/transformApi/transformsCorrectly.rewrittenNamespaceFollowingClass.js index 3f2dd6cdb56fb..7aa448bfa0b38 100644 --- a/tests/baselines/reference/transformApi/transformsCorrectly.rewrittenNamespaceFollowingClass.js +++ b/tests/baselines/reference/transformApi/transformsCorrectly.rewrittenNamespaceFollowingClass.js @@ -2,8 +2,8 @@ class C { constructor() { this.foo = 10; } + static { this.bar = 20; } } -C.bar = 20; (function (C) { C.x = 10; })(C || (C = {})); diff --git a/tests/baselines/reference/typeOfThisInStaticMembers10(target=es2022).js b/tests/baselines/reference/typeOfThisInStaticMembers10(target=es2022).js index a45a5c9915488..bdd2e337cf9e9 100644 --- a/tests/baselines/reference/typeOfThisInStaticMembers10(target=es2022).js +++ b/tests/baselines/reference/typeOfThisInStaticMembers10(target=es2022).js @@ -55,15 +55,19 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; -var _a, _b, _c; let C = class C { + static { this.a = 1; } + static { this.b = this.a + 1; } }; -C.a = 1; -C.b = (void 0).a + 1; C = __decorate([ foo ], C); let D = class D extends C { + static { this.c = 2; } + static { this.d = this.c + 1; } + static { this.e = super.a + this.c + 1; } + static { this.f = () => this.c + 1; } + static { this.ff = function () { this.c + 1; }; } static foo() { return this.c + 1; } @@ -74,20 +78,19 @@ let D = class D extends C { this.c = v + 1; } }; -D.c = 2; -D.d = (void 0).c + 1; -D.e = (void 0).a + (void 0).c + 1; -D.f = () => (void 0).c + 1; -D.ff = function () { this.c + 1; }; D = __decorate([ foo ], D); class CC { + static { this.a = 1; } + static { this.b = this.a + 1; } } -_a = CC; -CC.a = 1; -CC.b = _a.a + 1; -class DD extends (_c = CC) { +class DD extends CC { + static { this.c = 2; } + static { this.d = this.c + 1; } + static { this.e = super.a + this.c + 1; } + static { this.f = () => this.c + 1; } + static { this.ff = function () { this.c + 1; }; } static foo() { return this.c + 1; } @@ -98,9 +101,3 @@ class DD extends (_c = CC) { this.c = v + 1; } } -_b = DD; -DD.c = 2; -DD.d = _b.c + 1; -DD.e = Reflect.get(_c, "a", _b) + _b.c + 1; -DD.f = () => _b.c + 1; -DD.ff = function () { this.c + 1; }; diff --git a/tests/baselines/reference/typeOfThisInStaticMembers10(target=esnext).js b/tests/baselines/reference/typeOfThisInStaticMembers10(target=esnext).js index a45a5c9915488..bdd2e337cf9e9 100644 --- a/tests/baselines/reference/typeOfThisInStaticMembers10(target=esnext).js +++ b/tests/baselines/reference/typeOfThisInStaticMembers10(target=esnext).js @@ -55,15 +55,19 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; -var _a, _b, _c; let C = class C { + static { this.a = 1; } + static { this.b = this.a + 1; } }; -C.a = 1; -C.b = (void 0).a + 1; C = __decorate([ foo ], C); let D = class D extends C { + static { this.c = 2; } + static { this.d = this.c + 1; } + static { this.e = super.a + this.c + 1; } + static { this.f = () => this.c + 1; } + static { this.ff = function () { this.c + 1; }; } static foo() { return this.c + 1; } @@ -74,20 +78,19 @@ let D = class D extends C { this.c = v + 1; } }; -D.c = 2; -D.d = (void 0).c + 1; -D.e = (void 0).a + (void 0).c + 1; -D.f = () => (void 0).c + 1; -D.ff = function () { this.c + 1; }; D = __decorate([ foo ], D); class CC { + static { this.a = 1; } + static { this.b = this.a + 1; } } -_a = CC; -CC.a = 1; -CC.b = _a.a + 1; -class DD extends (_c = CC) { +class DD extends CC { + static { this.c = 2; } + static { this.d = this.c + 1; } + static { this.e = super.a + this.c + 1; } + static { this.f = () => this.c + 1; } + static { this.ff = function () { this.c + 1; }; } static foo() { return this.c + 1; } @@ -98,9 +101,3 @@ class DD extends (_c = CC) { this.c = v + 1; } } -_b = DD; -DD.c = 2; -DD.d = _b.c + 1; -DD.e = Reflect.get(_c, "a", _b) + _b.c + 1; -DD.f = () => _b.c + 1; -DD.ff = function () { this.c + 1; }; diff --git a/tests/baselines/reference/typeOfThisInStaticMembers12(target=es2022).js b/tests/baselines/reference/typeOfThisInStaticMembers12(target=es2022).js index 59ce5132646d1..4072197b7007d 100644 --- a/tests/baselines/reference/typeOfThisInStaticMembers12(target=es2022).js +++ b/tests/baselines/reference/typeOfThisInStaticMembers12(target=es2022).js @@ -9,17 +9,14 @@ class C { //// [typeOfThisInStaticMembers12.js] -var _a, _b, _c, _d; +var _a, _b; class C { -} -_a = C; -C.c = "foo"; -C.bar = (_b = class Inner { + static { this.c = "foo"; } + static { this.bar = class Inner { constructor() { - this[_d] = 123; + this[_b] = 123; } - }, - _c = _a.c, - _d = _a.c, - _b[_c] = 123, - _b); + static { _a = this.c, _b = this.c; } + static { this[_a] = 123; } + }; } +} diff --git a/tests/baselines/reference/typeOfThisInStaticMembers12(target=esnext).js b/tests/baselines/reference/typeOfThisInStaticMembers12(target=esnext).js index 59ce5132646d1..4072197b7007d 100644 --- a/tests/baselines/reference/typeOfThisInStaticMembers12(target=esnext).js +++ b/tests/baselines/reference/typeOfThisInStaticMembers12(target=esnext).js @@ -9,17 +9,14 @@ class C { //// [typeOfThisInStaticMembers12.js] -var _a, _b, _c, _d; +var _a, _b; class C { -} -_a = C; -C.c = "foo"; -C.bar = (_b = class Inner { + static { this.c = "foo"; } + static { this.bar = class Inner { constructor() { - this[_d] = 123; + this[_b] = 123; } - }, - _c = _a.c, - _d = _a.c, - _b[_c] = 123, - _b); + static { _a = this.c, _b = this.c; } + static { this[_a] = 123; } + }; } +} diff --git a/tests/baselines/reference/typeOfThisInStaticMembers3(target=es2022).js b/tests/baselines/reference/typeOfThisInStaticMembers3(target=es2022).js index ac5018106c0f7..0364cfcf3cd0f 100644 --- a/tests/baselines/reference/typeOfThisInStaticMembers3(target=es2022).js +++ b/tests/baselines/reference/typeOfThisInStaticMembers3(target=es2022).js @@ -12,15 +12,12 @@ class D extends C { //// [typeOfThisInStaticMembers3.js] -var _a, _b, _c; class C { + static { this.a = 1; } + static { this.b = this.a + 1; } } -_a = C; -C.a = 1; -C.b = _a.a + 1; -class D extends (_c = C) { +class D extends C { + static { this.c = 2; } + static { this.d = this.c + 1; } + static { this.e = super.a + this.c + 1; } } -_b = D; -D.c = 2; -D.d = _b.c + 1; -D.e = Reflect.get(_c, "a", _b) + _b.c + 1; diff --git a/tests/baselines/reference/typeOfThisInStaticMembers3(target=esnext).js b/tests/baselines/reference/typeOfThisInStaticMembers3(target=esnext).js index ac5018106c0f7..0364cfcf3cd0f 100644 --- a/tests/baselines/reference/typeOfThisInStaticMembers3(target=esnext).js +++ b/tests/baselines/reference/typeOfThisInStaticMembers3(target=esnext).js @@ -12,15 +12,12 @@ class D extends C { //// [typeOfThisInStaticMembers3.js] -var _a, _b, _c; class C { + static { this.a = 1; } + static { this.b = this.a + 1; } } -_a = C; -C.a = 1; -C.b = _a.a + 1; -class D extends (_c = C) { +class D extends C { + static { this.c = 2; } + static { this.d = this.c + 1; } + static { this.e = super.a + this.c + 1; } } -_b = D; -D.c = 2; -D.d = _b.c + 1; -D.e = Reflect.get(_c, "a", _b) + _b.c + 1; diff --git a/tests/baselines/reference/uniqueSymbols.js b/tests/baselines/reference/uniqueSymbols.js index 54f59e8e217b6..6d1c9308f9f90 100644 --- a/tests/baselines/reference/uniqueSymbols.js +++ b/tests/baselines/reference/uniqueSymbols.js @@ -319,10 +319,10 @@ class C { this.readonlyCall = Symbol(); this.readwriteCall = Symbol(); } + static { this.readonlyStaticCall = Symbol(); } + static { this.readonlyStaticTypeAndCall = Symbol(); } + static { this.readwriteStaticCall = Symbol(); } } -C.readonlyStaticCall = Symbol(); -C.readonlyStaticTypeAndCall = Symbol(); -C.readwriteStaticCall = Symbol(); const constInitToCReadonlyStaticCall = C.readonlyStaticCall; const constInitToCReadonlyStaticType = C.readonlyStaticType; const constInitToCReadonlyStaticTypeAndCall = C.readonlyStaticTypeAndCall; @@ -379,18 +379,18 @@ class C0 { this.e = N.s; this.f = N["s"]; } + static { this.a = s; } + static { this.b = N.s; } + static { this.c = N["s"]; } + static { this.d = s; } + static { this.e = N.s; } + static { this.f = N["s"]; } method1() { return s; } async method2() { return s; } async *method3() { yield s; } *method4() { yield s; } method5(p = s) { return p; } } -C0.a = s; -C0.b = N.s; -C0.c = N["s"]; -C0.d = s; -C0.e = N.s; -C0.f = N["s"]; // non-widening positions // element access o[s]; @@ -417,8 +417,8 @@ Math.random() * 2 ? N["s"] : "a"; [N.s]: "b", }); class C1 { + static { N.s, N.s; } } -N.s, N.s; const o3 = { method1() { return s; // return type should not widen due to contextual type diff --git a/tests/baselines/reference/uniqueSymbolsDeclarations.js b/tests/baselines/reference/uniqueSymbolsDeclarations.js index 15342a0bd97fc..c70a2163e3dcc 100644 --- a/tests/baselines/reference/uniqueSymbolsDeclarations.js +++ b/tests/baselines/reference/uniqueSymbolsDeclarations.js @@ -287,10 +287,10 @@ class C { this.readonlyCall = Symbol(); this.readwriteCall = Symbol(); } + static { this.readonlyStaticCall = Symbol(); } + static { this.readonlyStaticTypeAndCall = Symbol(); } + static { this.readwriteStaticCall = Symbol(); } } -C.readonlyStaticCall = Symbol(); -C.readonlyStaticTypeAndCall = Symbol(); -C.readwriteStaticCall = Symbol(); const constInitToCReadonlyStaticCall = C.readonlyStaticCall; const constInitToCReadonlyStaticType = C.readonlyStaticType; const constInitToCReadonlyStaticTypeAndCall = C.readonlyStaticTypeAndCall; @@ -347,18 +347,18 @@ class C0 { this.e = N.s; this.f = N["s"]; } + static { this.a = s; } + static { this.b = N.s; } + static { this.c = N["s"]; } + static { this.d = s; } + static { this.e = N.s; } + static { this.f = N["s"]; } method1() { return s; } async method2() { return s; } async *method3() { yield s; } *method4() { yield s; } method5(p = s) { return p; } } -C0.a = s; -C0.b = N.s; -C0.c = N["s"]; -C0.d = s; -C0.e = N.s; -C0.f = N["s"]; // non-widening positions // element access o[s]; @@ -385,8 +385,8 @@ Math.random() * 2 ? N["s"] : "a"; [N.s]: "b", }); class C1 { + static { N.s, N.s; } } -N.s, N.s; const o4 = { method1() { return s; // return type should not widen due to contextual type diff --git a/tests/baselines/reference/uniqueSymbolsDeclarationsInJs.js b/tests/baselines/reference/uniqueSymbolsDeclarationsInJs.js index 88d29c6a68430..3d0a68bbd3ad3 100644 --- a/tests/baselines/reference/uniqueSymbolsDeclarationsInJs.js +++ b/tests/baselines/reference/uniqueSymbolsDeclarationsInJs.js @@ -35,17 +35,17 @@ class C { this.readonlyCall = Symbol(); this.readwriteCall = Symbol(); } + /** + * @readonly + */ + static { this.readonlyStaticCall = Symbol(); } + /** + * @type {unique symbol} + * @readonly + */ + static { this.readonlyStaticTypeAndCall = Symbol(); } + static { this.readwriteStaticCall = Symbol(); } } -/** - * @readonly - */ -C.readonlyStaticCall = Symbol(); -/** - * @type {unique symbol} - * @readonly - */ -C.readonlyStaticTypeAndCall = Symbol(); -C.readwriteStaticCall = Symbol(); //// [uniqueSymbolsDeclarationsInJs-out.d.ts] diff --git a/tests/baselines/reference/unusedPrivateStaticMembers.js b/tests/baselines/reference/unusedPrivateStaticMembers.js index 8fda032e8bd1f..b4284e6d09012 100644 --- a/tests/baselines/reference/unusedPrivateStaticMembers.js +++ b/tests/baselines/reference/unusedPrivateStaticMembers.js @@ -51,15 +51,15 @@ class Test1 { } } class Test2 { + static { this.p1 = 0; } static test() { Test2.p1; } } -Test2.p1 = 0; class Test3 { + static { this.p1 = 0; } static m1() { } } -Test3.p1 = 0; class Test4 { static m1(n) { return (n === 0) ? 1 : (n * Test4.m1(n - 1)); @@ -75,8 +75,8 @@ class Test5 { } } class Test6 { + static { this.p1 = 0; } static test() { Test6["p1"]; } } -Test6.p1 = 0; diff --git a/tests/cases/conformance/classes/members/privateNames/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts b/tests/cases/conformance/classes/members/privateNames/privateNameWhenNotUseDefineForClassFieldsInEsNext.ts similarity index 52% rename from tests/cases/conformance/classes/members/privateNames/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts rename to tests/cases/conformance/classes/members/privateNames/privateNameWhenNotUseDefineForClassFieldsInEsNext.ts index 0da07902fc137..b9a2b2d1d65c7 100644 --- a/tests/cases/conformance/classes/members/privateNames/privateNameErrorsOnNotUseDefineForClassFieldsInEsNext.ts +++ b/tests/cases/conformance/classes/members/privateNames/privateNameWhenNotUseDefineForClassFieldsInEsNext.ts @@ -2,54 +2,54 @@ // @target: esNext,es2020 // @useDefineForClassFields: false -class TestWithErrors { - #prop = 0 - static dd = new TestWithErrors().#prop; // Err +class TestWithStatics { + #prop = 0 + static dd = new TestWithStatics().#prop; // OK static ["X_ z_ zz"] = class Inner { - #foo = 10 + #foo = 10 m() { - new TestWithErrors().#prop // Err + new TestWithStatics().#prop // OK } static C = class InnerInner { m() { - new TestWithErrors().#prop // Err - new Inner().#foo; // Err + new TestWithStatics().#prop // OK + new Inner().#foo; // OK } } static M(){ return class { m() { - new TestWithErrors().#prop // Err + new TestWithStatics().#prop // OK new Inner().#foo; // OK } } - } + } } } -class TestNoErrors { - #prop = 0 - dd = new TestNoErrors().#prop; // OK +class TestNonStatics { + #prop = 0 + dd = new TestNonStatics().#prop; // OK ["X_ z_ zz"] = class Inner { - #foo = 10 + #foo = 10 m() { - new TestNoErrors().#prop // Ok + new TestNonStatics().#prop // Ok } C = class InnerInner { m() { - new TestNoErrors().#prop // Ok + new TestNonStatics().#prop // Ok new Inner().#foo; // Ok } } - + static M(){ return class { m() { - new TestNoErrors().#prop // OK + new TestNonStatics().#prop // OK new Inner().#foo; // OK } } - } + } } - } \ No newline at end of file +} \ No newline at end of file From 8ddead50ebc27f95cc4430341adeb96f5536fceb Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Sat, 5 Feb 2022 02:12:23 +0200 Subject: [PATCH 13/55] fix(32941): include Template tag constraint to QuickInfo response (#47567) --- src/services/jsDoc.ts | 22 +- .../reference/jsdocReturnsTag.baseline | 2 +- .../reference/quickInfoJsDocTags10.baseline | 177 ++++++++++++++ .../reference/quickInfoJsDocTags11.baseline | 230 ++++++++++++++++++ .../reference/quickInfoJsDocTags7.baseline | 100 ++++++++ .../reference/quickInfoJsDocTags8.baseline | 108 ++++++++ .../reference/quickInfoJsDocTags9.baseline | 116 +++++++++ .../signatureHelpTypeArguments2.baseline | 64 ++++- tests/cases/fourslash/quickInfoJsDocTags10.ts | 14 ++ tests/cases/fourslash/quickInfoJsDocTags11.ts | 15 ++ tests/cases/fourslash/quickInfoJsDocTags7.ts | 17 ++ tests/cases/fourslash/quickInfoJsDocTags8.ts | 17 ++ tests/cases/fourslash/quickInfoJsDocTags9.ts | 17 ++ 13 files changed, 889 insertions(+), 10 deletions(-) create mode 100644 tests/baselines/reference/quickInfoJsDocTags10.baseline create mode 100644 tests/baselines/reference/quickInfoJsDocTags11.baseline create mode 100644 tests/baselines/reference/quickInfoJsDocTags7.baseline create mode 100644 tests/baselines/reference/quickInfoJsDocTags8.baseline create mode 100644 tests/baselines/reference/quickInfoJsDocTags9.baseline create mode 100644 tests/cases/fourslash/quickInfoJsDocTags10.ts create mode 100644 tests/cases/fourslash/quickInfoJsDocTags11.ts create mode 100644 tests/cases/fourslash/quickInfoJsDocTags7.ts create mode 100644 tests/cases/fourslash/quickInfoJsDocTags8.ts create mode 100644 tests/cases/fourslash/quickInfoJsDocTags9.ts diff --git a/src/services/jsDoc.ts b/src/services/jsDoc.ts index 2e2bc61136a3f..43600422a5c84 100644 --- a/src/services/jsDoc.ts +++ b/src/services/jsDoc.ts @@ -169,7 +169,27 @@ namespace ts.JsDoc { case SyntaxKind.JSDocAugmentsTag: return withNode((tag as JSDocAugmentsTag).class); case SyntaxKind.JSDocTemplateTag: - return addComment((tag as JSDocTemplateTag).typeParameters.map(tp => tp.getText()).join(", ")); + const templateTag = tag as JSDocTemplateTag; + const displayParts: SymbolDisplayPart[] = []; + if (templateTag.constraint) { + displayParts.push(textPart(templateTag.constraint.getText())); + } + if (length(templateTag.typeParameters)) { + if (length(displayParts)) { + displayParts.push(spacePart()); + } + const lastTypeParameter = templateTag.typeParameters[templateTag.typeParameters.length - 1]; + forEach(templateTag.typeParameters, tp => { + displayParts.push(namePart(tp.getText())); + if (lastTypeParameter !== tp) { + displayParts.push(...[punctuationPart(SyntaxKind.CommaToken), spacePart()]); + } + }); + } + if (comment) { + displayParts.push(...[spacePart(), ...getDisplayPartsFromComment(comment, checker)]); + } + return displayParts; case SyntaxKind.JSDocTypeTag: return withNode((tag as JSDocTypeTag).typeExpression); case SyntaxKind.JSDocTypedefTag: diff --git a/tests/baselines/reference/jsdocReturnsTag.baseline b/tests/baselines/reference/jsdocReturnsTag.baseline index 1ab8b6a24399b..9ee6f61706e63 100644 --- a/tests/baselines/reference/jsdocReturnsTag.baseline +++ b/tests/baselines/reference/jsdocReturnsTag.baseline @@ -117,7 +117,7 @@ "text": [ { "text": "T", - "kind": "text" + "kind": "typeParameterName" } ] }, diff --git a/tests/baselines/reference/quickInfoJsDocTags10.baseline b/tests/baselines/reference/quickInfoJsDocTags10.baseline new file mode 100644 index 0000000000000..e4e616652aaf2 --- /dev/null +++ b/tests/baselines/reference/quickInfoJsDocTags10.baseline @@ -0,0 +1,177 @@ +[ + { + "marker": { + "fileName": "/tests/cases/fourslash/quickInfoJsDocTags10.js", + "position": 80, + "name": "" + }, + "quickInfo": { + "kind": "const", + "kindModifiers": "", + "textSpan": { + "start": 80, + "length": 3 + }, + "displayParts": [ + { + "text": "const", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "foo", + "kind": "localName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "<", + "kind": "punctuation" + }, + { + "text": "T1", + "kind": "typeParameterName" + }, + { + "text": ",", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "T2", + "kind": "typeParameterName" + }, + { + "text": ">", + "kind": "punctuation" + }, + { + "text": "(", + "kind": "punctuation" + }, + { + "text": "a", + "kind": "parameterName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "T1", + "kind": "typeParameterName" + }, + { + "text": ",", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "b", + "kind": "parameterName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "any", + "kind": "keyword" + }, + { + "text": ")", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "=>", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "void", + "kind": "keyword" + } + ], + "documentation": [], + "tags": [ + { + "name": "param", + "text": [ + { + "text": "a", + "kind": "text" + } + ] + }, + { + "name": "param", + "text": [ + { + "text": "a", + "kind": "text" + } + ] + }, + { + "name": "template", + "text": [ + { + "text": "T1", + "kind": "typeParameterName" + }, + { + "text": ",", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "T2", + "kind": "typeParameterName" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "Comment Text", + "kind": "text" + } + ] + } + ] + } + } +] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoJsDocTags11.baseline b/tests/baselines/reference/quickInfoJsDocTags11.baseline new file mode 100644 index 0000000000000..86d49f8089e0f --- /dev/null +++ b/tests/baselines/reference/quickInfoJsDocTags11.baseline @@ -0,0 +1,230 @@ +[ + { + "marker": { + "fileName": "/tests/cases/fourslash/quickInfoJsDocTags11.js", + "position": 120, + "name": "" + }, + "quickInfo": { + "kind": "const", + "kindModifiers": "", + "textSpan": { + "start": 120, + "length": 3 + }, + "displayParts": [ + { + "text": "const", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "foo", + "kind": "localName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "<", + "kind": "punctuation" + }, + { + "text": "T1", + "kind": "typeParameterName" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "extends", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "number", + "kind": "keyword" + }, + { + "text": ",", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "T2", + "kind": "typeParameterName" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "extends", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "number", + "kind": "keyword" + }, + { + "text": ">", + "kind": "punctuation" + }, + { + "text": "(", + "kind": "punctuation" + }, + { + "text": "a", + "kind": "parameterName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "T1", + "kind": "typeParameterName" + }, + { + "text": ",", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "b", + "kind": "parameterName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "T2", + "kind": "typeParameterName" + }, + { + "text": ")", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "=>", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "void", + "kind": "keyword" + } + ], + "documentation": [], + "tags": [ + { + "name": "param", + "text": [ + { + "text": "a", + "kind": "text" + } + ] + }, + { + "name": "param", + "text": [ + { + "text": "b", + "kind": "text" + } + ] + }, + { + "name": "template", + "text": [ + { + "text": "{number}", + "kind": "text" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "T1", + "kind": "typeParameterName" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "Comment T1", + "kind": "text" + } + ] + }, + { + "name": "template", + "text": [ + { + "text": "{number}", + "kind": "text" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "T2", + "kind": "typeParameterName" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "Comment T2", + "kind": "text" + } + ] + } + ] + } + } +] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoJsDocTags7.baseline b/tests/baselines/reference/quickInfoJsDocTags7.baseline new file mode 100644 index 0000000000000..4b5d48a290117 --- /dev/null +++ b/tests/baselines/reference/quickInfoJsDocTags7.baseline @@ -0,0 +1,100 @@ +[ + { + "marker": { + "fileName": "/tests/cases/fourslash/quickInfoJsDocTags7.js", + "position": 116, + "name": "" + }, + "quickInfo": { + "kind": "const", + "kindModifiers": "", + "textSpan": { + "start": 116, + "length": 3 + }, + "displayParts": [ + { + "text": "const", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "foo", + "kind": "localName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "(", + "kind": "punctuation" + }, + { + "text": "t", + "kind": "parameterName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "T", + "kind": "typeParameterName" + }, + { + "text": ")", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "=>", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "number", + "kind": "keyword" + } + ], + "documentation": [], + "tags": [ + { + "name": "type", + "text": [ + { + "text": "{(t: T) => number}", + "kind": "text" + } + ] + }, + { + "name": "template", + "text": [ + { + "text": "T", + "kind": "typeParameterName" + } + ] + } + ] + } + } +] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoJsDocTags8.baseline b/tests/baselines/reference/quickInfoJsDocTags8.baseline new file mode 100644 index 0000000000000..def6b90bcf85d --- /dev/null +++ b/tests/baselines/reference/quickInfoJsDocTags8.baseline @@ -0,0 +1,108 @@ +[ + { + "marker": { + "fileName": "/tests/cases/fourslash/quickInfoJsDocTags8.js", + "position": 122, + "name": "" + }, + "quickInfo": { + "kind": "const", + "kindModifiers": "", + "textSpan": { + "start": 122, + "length": 3 + }, + "displayParts": [ + { + "text": "const", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "foo", + "kind": "localName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "(", + "kind": "punctuation" + }, + { + "text": "t", + "kind": "parameterName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "T", + "kind": "typeParameterName" + }, + { + "text": ")", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "=>", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "number", + "kind": "keyword" + } + ], + "documentation": [], + "tags": [ + { + "name": "type", + "text": [ + { + "text": "{(t: T) => number}", + "kind": "text" + } + ] + }, + { + "name": "template", + "text": [ + { + "text": "{Foo}", + "kind": "text" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "T", + "kind": "typeParameterName" + } + ] + } + ] + } + } +] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoJsDocTags9.baseline b/tests/baselines/reference/quickInfoJsDocTags9.baseline new file mode 100644 index 0000000000000..248a657146b6b --- /dev/null +++ b/tests/baselines/reference/quickInfoJsDocTags9.baseline @@ -0,0 +1,116 @@ +[ + { + "marker": { + "fileName": "/tests/cases/fourslash/quickInfoJsDocTags9.js", + "position": 135, + "name": "" + }, + "quickInfo": { + "kind": "const", + "kindModifiers": "", + "textSpan": { + "start": 135, + "length": 3 + }, + "displayParts": [ + { + "text": "const", + "kind": "keyword" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "foo", + "kind": "localName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "(", + "kind": "punctuation" + }, + { + "text": "t", + "kind": "parameterName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "T", + "kind": "typeParameterName" + }, + { + "text": ")", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "=>", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "number", + "kind": "keyword" + } + ], + "documentation": [], + "tags": [ + { + "name": "type", + "text": [ + { + "text": "{(t: T) => number}", + "kind": "text" + } + ] + }, + { + "name": "template", + "text": [ + { + "text": "{Foo}", + "kind": "text" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "T", + "kind": "typeParameterName" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "Comment Text", + "kind": "text" + } + ] + } + ] + } + } +] \ No newline at end of file diff --git a/tests/baselines/reference/signatureHelpTypeArguments2.baseline b/tests/baselines/reference/signatureHelpTypeArguments2.baseline index 75971fa59ce64..7e70e96ada6a5 100644 --- a/tests/baselines/reference/signatureHelpTypeArguments2.baseline +++ b/tests/baselines/reference/signatureHelpTypeArguments2.baseline @@ -213,7 +213,7 @@ "text": [ { "text": "W", - "kind": "text" + "kind": "typeParameterName" } ] }, @@ -221,7 +221,19 @@ "name": "template", "text": [ { - "text": "U, V", + "text": "U", + "kind": "typeParameterName" + }, + { + "text": ",", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "V", "kind": "typeParameterName" }, { @@ -494,7 +506,7 @@ "text": [ { "text": "W", - "kind": "text" + "kind": "typeParameterName" } ] }, @@ -502,7 +514,19 @@ "name": "template", "text": [ { - "text": "U, V", + "text": "U", + "kind": "typeParameterName" + }, + { + "text": ",", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "V", "kind": "typeParameterName" }, { @@ -775,7 +799,7 @@ "text": [ { "text": "W", - "kind": "text" + "kind": "typeParameterName" } ] }, @@ -783,7 +807,19 @@ "name": "template", "text": [ { - "text": "U, V", + "text": "U", + "kind": "typeParameterName" + }, + { + "text": ",", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "V", "kind": "typeParameterName" }, { @@ -1056,7 +1092,7 @@ "text": [ { "text": "W", - "kind": "text" + "kind": "typeParameterName" } ] }, @@ -1064,7 +1100,19 @@ "name": "template", "text": [ { - "text": "U, V", + "text": "U", + "kind": "typeParameterName" + }, + { + "text": ",", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "V", "kind": "typeParameterName" }, { diff --git a/tests/cases/fourslash/quickInfoJsDocTags10.ts b/tests/cases/fourslash/quickInfoJsDocTags10.ts new file mode 100644 index 0000000000000..f635da3ee5709 --- /dev/null +++ b/tests/cases/fourslash/quickInfoJsDocTags10.ts @@ -0,0 +1,14 @@ +/// + +// @noEmit: true +// @allowJs: true + +// @Filename: quickInfoJsDocTags10.js +/////** +//// * @param {T1} a +//// * @param {T2} a +//// * @template T1,T2 Comment Text +//// */ +////const /**/foo = (a, b) => {}; + +verify.baselineQuickInfo(); diff --git a/tests/cases/fourslash/quickInfoJsDocTags11.ts b/tests/cases/fourslash/quickInfoJsDocTags11.ts new file mode 100644 index 0000000000000..348940ba09159 --- /dev/null +++ b/tests/cases/fourslash/quickInfoJsDocTags11.ts @@ -0,0 +1,15 @@ +/// + +// @noEmit: true +// @allowJs: true + +// @Filename: quickInfoJsDocTags11.js +/////** +//// * @param {T1} a +//// * @param {T2} b +//// * @template {number} T1 Comment T1 +//// * @template {number} T2 Comment T2 +//// */ +////const /**/foo = (a, b) => {}; + +verify.baselineQuickInfo(); diff --git a/tests/cases/fourslash/quickInfoJsDocTags7.ts b/tests/cases/fourslash/quickInfoJsDocTags7.ts new file mode 100644 index 0000000000000..3cc00ad803b73 --- /dev/null +++ b/tests/cases/fourslash/quickInfoJsDocTags7.ts @@ -0,0 +1,17 @@ +/// + +// @noEmit: true +// @allowJs: true + +// @Filename: quickInfoJsDocTags7.js +/////** +//// * @typedef {{ [x: string]: any, y: number }} Foo +//// */ +//// +/////** +//// * @type {(t: T) => number} +//// * @template T +//// */ +////const /**/foo = t => t.y; + +verify.baselineQuickInfo(); diff --git a/tests/cases/fourslash/quickInfoJsDocTags8.ts b/tests/cases/fourslash/quickInfoJsDocTags8.ts new file mode 100644 index 0000000000000..cc9c5aa160606 --- /dev/null +++ b/tests/cases/fourslash/quickInfoJsDocTags8.ts @@ -0,0 +1,17 @@ +/// + +// @noEmit: true +// @allowJs: true + +// @Filename: quickInfoJsDocTags8.js +/////** +//// * @typedef {{ [x: string]: any, y: number }} Foo +//// */ +//// +/////** +//// * @type {(t: T) => number} +//// * @template {Foo} T +//// */ +////const /**/foo = t => t.y; + +verify.baselineQuickInfo(); diff --git a/tests/cases/fourslash/quickInfoJsDocTags9.ts b/tests/cases/fourslash/quickInfoJsDocTags9.ts new file mode 100644 index 0000000000000..0558786a9ba55 --- /dev/null +++ b/tests/cases/fourslash/quickInfoJsDocTags9.ts @@ -0,0 +1,17 @@ +/// + +// @noEmit: true +// @allowJs: true + +// @Filename: quickInfoJsDocTags9.js +/////** +//// * @typedef {{ [x: string]: any, y: number }} Foo +//// */ +//// +/////** +//// * @type {(t: T) => number} +//// * @template {Foo} T Comment Text +//// */ +////const /**/foo = t => t.y; + +verify.baselineQuickInfo(); From 9c3b41d3cc6fd46656dfcade11d6c1da034a3116 Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Fri, 4 Feb 2022 17:11:25 -0800 Subject: [PATCH 14/55] Refactor named imports to default instead of namespace when esModuleInterop is on and module is an export= (#47744) --- src/compiler/core.ts | 8 +- src/compiler/diagnosticMessages.json | 4 + src/services/refactors/convertImport.ts | 89 ++++++++++++------- .../refactorConvertImport_namedToDefault1.ts | 50 +++++++++++ 4 files changed, 115 insertions(+), 36 deletions(-) create mode 100644 tests/cases/fourslash/refactorConvertImport_namedToDefault1.ts diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 6bc89ae25eae5..cceaa2abd50b3 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1252,11 +1252,11 @@ namespace ts { return result; } - export function getOwnValues(sparseArray: T[]): T[] { + export function getOwnValues(collection: MapLike | T[]): T[] { const values: T[] = []; - for (const key in sparseArray) { - if (hasOwnProperty.call(sparseArray, key)) { - values.push(sparseArray[key]); + for (const key in collection) { + if (hasOwnProperty.call(collection, key)) { + values.push((collection as MapLike)[key]); } } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 4523f5c4ed3b8..34685f0ef7b28 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -7123,6 +7123,10 @@ "category": "Message", "code": 95169 }, + "Convert named imports to default import": { + "category": "Message", + "code": 95170 + }, "No value exists in scope for the shorthand property '{0}'. Either declare one or provide an initializer.": { "category": "Error", diff --git a/src/services/refactors/convertImport.ts b/src/services/refactors/convertImport.ts index fedeb986eddd8..3589e3006c1bf 100644 --- a/src/services/refactors/convertImport.ts +++ b/src/services/refactors/convertImport.ts @@ -2,46 +2,48 @@ namespace ts.refactor { const refactorName = "Convert import"; - const namespaceToNamedAction = { - name: "Convert namespace import to named imports", - description: Diagnostics.Convert_namespace_import_to_named_imports.message, - kind: "refactor.rewrite.import.named", - }; - const namedToNamespaceAction = { - name: "Convert named imports to namespace import", - description: Diagnostics.Convert_named_imports_to_namespace_import.message, - kind: "refactor.rewrite.import.namespace", + const actions = { + [ImportKind.Named]: { + name: "Convert namespace import to named imports", + description: Diagnostics.Convert_namespace_import_to_named_imports.message, + kind: "refactor.rewrite.import.named", + }, + [ImportKind.Namespace]: { + name: "Convert named imports to namespace import", + description: Diagnostics.Convert_named_imports_to_namespace_import.message, + kind: "refactor.rewrite.import.namespace", + }, + [ImportKind.Default]: { + name: "Convert named imports to default import", + description: Diagnostics.Convert_named_imports_to_default_import.message, + kind: "refactor.rewrite.import.default", + }, }; registerRefactor(refactorName, { - kinds: [ - namespaceToNamedAction.kind, - namedToNamespaceAction.kind - ], + kinds: getOwnValues(actions).map(a => a.kind), getAvailableActions: function getRefactorActionsToConvertBetweenNamedAndNamespacedImports(context): readonly ApplicableRefactorInfo[] { - const info = getImportToConvert(context, context.triggerReason === "invoked"); + const info = getImportConversionInfo(context, context.triggerReason === "invoked"); if (!info) return emptyArray; if (!isRefactorErrorInfo(info)) { - const namespaceImport = info.kind === SyntaxKind.NamespaceImport; - const action = namespaceImport ? namespaceToNamedAction : namedToNamespaceAction; + const action = actions[info.convertTo]; return [{ name: refactorName, description: action.description, actions: [action] }]; } if (context.preferences.provideRefactorNotApplicableReason) { - return [ - { name: refactorName, description: namespaceToNamedAction.description, - actions: [{ ...namespaceToNamedAction, notApplicableReason: info.error }] }, - { name: refactorName, description: namedToNamespaceAction.description, - actions: [{ ...namedToNamespaceAction, notApplicableReason: info.error }] } - ]; + return getOwnValues(actions).map(action => ({ + name: refactorName, + description: action.description, + actions: [{ ...action, notApplicableReason: info.error }] + })); } return emptyArray; }, getEditsForAction: function getRefactorEditsToConvertBetweenNamedAndNamespacedImports(context, actionName): RefactorEditInfo { - Debug.assert(actionName === namespaceToNamedAction.name || actionName === namedToNamespaceAction.name, "Unexpected action name"); - const info = getImportToConvert(context); + Debug.assert(some(getOwnValues(actions), action => action.name === actionName), "Unexpected action name"); + const info = getImportConversionInfo(context); Debug.assert(info && !isRefactorErrorInfo(info), "Expected applicable refactor info"); const edits = textChanges.ChangeTracker.with(context, t => doChange(context.file, context.program, t, info)); return { edits, renameFilename: undefined, renameLocation: undefined }; @@ -49,7 +51,12 @@ namespace ts.refactor { }); // Can convert imports of the form `import * as m from "m";` or `import d, { x, y } from "m";`. - function getImportToConvert(context: RefactorContext, considerPartialSpans = true): NamedImportBindings | RefactorErrorInfo | undefined { + type ImportConversionInfo = + | { convertTo: ImportKind.Default, import: NamedImports } + | { convertTo: ImportKind.Namespace, import: NamedImports } + | { convertTo: ImportKind.Named, import: NamespaceImport }; + + function getImportConversionInfo(context: RefactorContext, considerPartialSpans = true): ImportConversionInfo | RefactorErrorInfo | undefined { const { file } = context; const span = getRefactorContextSpan(context); const token = getTokenAtPosition(file, span.start); @@ -69,16 +76,25 @@ namespace ts.refactor { return { error: getLocaleSpecificMessage(Diagnostics.Could_not_find_namespace_import_or_named_imports) }; } - return importClause.namedBindings; + if (importClause.namedBindings.kind === SyntaxKind.NamespaceImport) { + return { convertTo: ImportKind.Named, import: importClause.namedBindings }; + } + const compilerOptions = context.program.getCompilerOptions(); + const shouldUseDefault = getAllowSyntheticDefaultImports(compilerOptions) + && isExportEqualsModule(importClause.parent.moduleSpecifier, context.program.getTypeChecker()); + + return shouldUseDefault + ? { convertTo: ImportKind.Default, import: importClause.namedBindings } + : { convertTo: ImportKind.Namespace, import: importClause.namedBindings }; } - function doChange(sourceFile: SourceFile, program: Program, changes: textChanges.ChangeTracker, toConvert: NamedImportBindings): void { + function doChange(sourceFile: SourceFile, program: Program, changes: textChanges.ChangeTracker, info: ImportConversionInfo): void { const checker = program.getTypeChecker(); - if (toConvert.kind === SyntaxKind.NamespaceImport) { - doChangeNamespaceToNamed(sourceFile, checker, changes, toConvert, getAllowSyntheticDefaultImports(program.getCompilerOptions())); + if (info.convertTo === ImportKind.Named) { + doChangeNamespaceToNamed(sourceFile, checker, changes, info.import, getAllowSyntheticDefaultImports(program.getCompilerOptions())); } else { - doChangeNamedToNamespace(sourceFile, checker, changes, toConvert); + doChangeNamedToNamespaceOrDefault(sourceFile, checker, changes, info.import, info.convertTo === ImportKind.Default); } } @@ -137,7 +153,7 @@ namespace ts.refactor { return isPropertyAccessExpression(propertyAccessOrQualifiedName) ? propertyAccessOrQualifiedName.expression : propertyAccessOrQualifiedName.left; } - function doChangeNamedToNamespace(sourceFile: SourceFile, checker: TypeChecker, changes: textChanges.ChangeTracker, toConvert: NamedImports): void { + function doChangeNamedToNamespaceOrDefault(sourceFile: SourceFile, checker: TypeChecker, changes: textChanges.ChangeTracker, toConvert: NamedImports, shouldUseDefault: boolean) { const importDecl = toConvert.parent.parent; const { moduleSpecifier } = importDecl; @@ -188,7 +204,9 @@ namespace ts.refactor { }); } - changes.replaceNode(sourceFile, toConvert, factory.createNamespaceImport(factory.createIdentifier(namespaceImportName))); + changes.replaceNode(sourceFile, toConvert, shouldUseDefault + ? factory.createIdentifier(namespaceImportName) + : factory.createNamespaceImport(factory.createIdentifier(namespaceImportName))); if (neededNamedImports.size) { const newNamedImports: ImportSpecifier[] = arrayFrom(neededNamedImports.values()).map(element => factory.createImportSpecifier(element.isTypeOnly, element.propertyName && factory.createIdentifier(element.propertyName.text), factory.createIdentifier(element.name.text))); @@ -196,6 +214,13 @@ namespace ts.refactor { } } + function isExportEqualsModule(moduleSpecifier: Expression, checker: TypeChecker) { + const externalModule = checker.resolveExternalModuleName(moduleSpecifier); + if (!externalModule) return false; + const exportEquals = checker.resolveExternalModuleSymbol(externalModule); + return externalModule !== exportEquals; + } + function updateImport(old: ImportDeclaration, defaultImportName: Identifier | undefined, elements: readonly ImportSpecifier[] | undefined): ImportDeclaration { return factory.createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, factory.createImportClause(/*isTypeOnly*/ false, defaultImportName, elements && elements.length ? factory.createNamedImports(elements) : undefined), old.moduleSpecifier, /*assertClause*/ undefined); diff --git a/tests/cases/fourslash/refactorConvertImport_namedToDefault1.ts b/tests/cases/fourslash/refactorConvertImport_namedToDefault1.ts new file mode 100644 index 0000000000000..ecc259c374566 --- /dev/null +++ b/tests/cases/fourslash/refactorConvertImport_namedToDefault1.ts @@ -0,0 +1,50 @@ +/// + +// @esModuleInterop: true + +// @Filename: /process.d.ts +//// declare module "process" { +//// interface Process { +//// pid: number; +//// addListener(event: string, listener: (...args: any[]) => void): void; +//// } +//// var process: Process; +//// export = process; +//// } + +// @Filename: /url.d.ts +//// declare module "url" { +//// export function parse(urlStr: string): any; +//// } + +// @Filename: /index.ts +//// [|import { pid, addListener } from "process";|] +//// addListener("message", (m) => { +//// console.log(pid); +//// }); + +// @Filename: /a.ts +//// [|import { parse } from "url";|] +//// parse("https://www.typescriptlang.org"); + +goTo.selectRange(test.ranges()[0]); +edit.applyRefactor({ + refactorName: "Convert import", + actionName: "Convert named imports to default import", + actionDescription: "Convert named imports to default import", + newContent: `import process from "process"; +process.addListener("message", (m) => { + console.log(process.pid); +});`, +}); +verify.not.refactorAvailable("Convert import", "Convert named imports to namespace import"); + +goTo.selectRange(test.ranges()[1]); +edit.applyRefactor({ + refactorName: "Convert import", + actionName: "Convert named imports to namespace import", + actionDescription: "Convert named imports to namespace import", + newContent: `import * as url from "url"; +url.parse("https://www.typescriptlang.org");`, +}); +verify.not.refactorAvailable("Convert import", "Convert named imports to default import"); \ No newline at end of file From e1532a18ac035a91f9d6b4168745f9c81a8836a3 Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Sat, 5 Feb 2022 06:07:35 +0000 Subject: [PATCH 15/55] Update package-lock.json --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3b49b5bd7d51e..5855a18367a0d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -676,9 +676,9 @@ "dev": true }, "@types/node": { - "version": "17.0.14", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.14.tgz", - "integrity": "sha512-SbjLmERksKOGzWzPNuW7fJM7fk3YXVTFiZWB/Hs99gwhk+/dnrQRPBQjPW9aO+fi1tAffi9PrwFvsmOKmDTyng==", + "version": "17.0.15", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.15.tgz", + "integrity": "sha512-zWt4SDDv1S9WRBNxLFxFRHxdD9tvH8f5/kg5/IaLFdnSNXsDY4eL3Q3XXN+VxUnWIhyVFDwcsmAprvwXoM/ClA==", "dev": true }, "@types/node-fetch": { From 163fef9f5d3b7e4aed2fc08c1770123e8eca8564 Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Sun, 6 Feb 2022 06:06:05 +0000 Subject: [PATCH 16/55] Update package-lock.json --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5855a18367a0d..739daaa36cd76 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5113,9 +5113,9 @@ } }, "loupe": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.2.tgz", - "integrity": "sha512-QgVamnvj0jX1LMPlCAq0MK6hATORFtGqHoUKXTkwNe13BqlN6aePQCKnnTcFvdDYEEITcJ+gBl4mTW7YJtJbyQ==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.3.tgz", + "integrity": "sha512-krIV4Cf1BIGIx2t1e6tucThhrBemUnIUjMtD2vN4mrMxnxpBvrcosBSpooqunBqP/hOEEV1w/Cr1YskGtqw5Jg==", "dev": true, "requires": { "get-func-name": "^2.0.0" From 14feed97a04e29ab8fdeb6c3671a1f4473a7c0b2 Mon Sep 17 00:00:00 2001 From: csigs Date: Mon, 7 Feb 2022 02:50:24 -0800 Subject: [PATCH 17/55] LEGO: Merge pull request 47761 LEGO: Merge pull request 47761 --- .../diagnosticMessages.generated.json.lcl | 27 +++++++------------ .../diagnosticMessages.generated.json.lcl | 27 +++++++------------ .../diagnosticMessages.generated.json.lcl | 27 +++++++------------ 3 files changed, 27 insertions(+), 54 deletions(-) diff --git a/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl index ed4206c96c4d6..09f67fd366c2a 100644 --- a/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -4041,6 +4041,15 @@ + + + + + + + + + @@ -10296,15 +10305,6 @@ - - - - - - - - - @@ -12192,15 +12192,6 @@ - - - - - - - - - diff --git a/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl index ff954ba1bfebc..7617eab686352 100644 --- a/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -4038,6 +4038,15 @@ + + + + + + + + + @@ -10290,15 +10299,6 @@ - - - - - - - - - @@ -12186,15 +12186,6 @@ - - - - - - - - - diff --git a/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl index f893e9be3d3f8..d0bda41a2ecef 100644 --- a/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -4040,6 +4040,15 @@ + + + + + + + + + @@ -10295,15 +10304,6 @@ - - - - - - - - - @@ -12191,15 +12191,6 @@ - - - - - - - - - From afeacf41bd85f3cddb13cbece45e3a33c4cd18e6 Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Mon, 7 Feb 2022 23:26:39 +0200 Subject: [PATCH 18/55] fix(47782): forbid super() extraction outside this container (#47784) --- src/services/refactors/extractSymbol.ts | 4 ++-- tests/cases/fourslash/extractSuperOutsideClass.ts | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 tests/cases/fourslash/extractSuperOutsideClass.ts diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index 5b0032e6f0168..0120f81cb02a9 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -486,8 +486,8 @@ namespace ts.refactor.extractSymbol { // but a super *method call* simply implies a 'this' reference if (node.parent.kind === SyntaxKind.CallExpression) { // Super constructor call - const containingClass = getContainingClass(node)!; // TODO:GH#18217 - if (containingClass.pos < span.start || containingClass.end >= (span.start + span.length)) { + const containingClass = getContainingClass(node); + if (containingClass === undefined || containingClass.pos < span.start || containingClass.end >= (span.start + span.length)) { (errors ||= []).push(createDiagnosticForNode(node, Messages.cannotExtractSuper)); return true; } diff --git a/tests/cases/fourslash/extractSuperOutsideClass.ts b/tests/cases/fourslash/extractSuperOutsideClass.ts new file mode 100644 index 0000000000000..26fd2becd6a61 --- /dev/null +++ b/tests/cases/fourslash/extractSuperOutsideClass.ts @@ -0,0 +1,6 @@ +/// + +/////*a*/super()/*b*/ + +goTo.select("a", "b"); +verify.not.refactorAvailable("Extract Symbol"); From 867470ca26acb9437c5527a9049a382beafc9cd8 Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Tue, 8 Feb 2022 00:08:35 +0200 Subject: [PATCH 19/55] fix(47783): show globals completion in case keyword outside of switch statement (#47786) --- src/services/completions.ts | 3 ++- tests/cases/fourslash/completionAtCaseClause.ts | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 tests/cases/fourslash/completionAtCaseClause.ts diff --git a/src/services/completions.ts b/src/services/completions.ts index 0ec8a5d71758f..ea8a976fa8540 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -1680,7 +1680,8 @@ namespace ts.Completions { case SyntaxKind.NewKeyword: return checker.getContextualType(parent as Expression); case SyntaxKind.CaseKeyword: - return getSwitchedType(cast(parent, isCaseClause), checker); + const caseClause = tryCast(parent, isCaseClause); + return caseClause ? getSwitchedType(caseClause, checker) : undefined; case SyntaxKind.OpenBraceToken: return isJsxExpression(parent) && !isJsxElement(parent.parent) && !isJsxFragment(parent.parent) ? checker.getContextualTypeForJsxAttribute(parent.parent) : undefined; default: diff --git a/tests/cases/fourslash/completionAtCaseClause.ts b/tests/cases/fourslash/completionAtCaseClause.ts new file mode 100644 index 0000000000000..48c5a1c465856 --- /dev/null +++ b/tests/cases/fourslash/completionAtCaseClause.ts @@ -0,0 +1,6 @@ +/// + +////case /**/ + +verify.completions({ marker: "", exact: completion.globals }); + From d8ac54bfb14d4033a32967907d4e4f9a64c8a8f9 Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Mon, 7 Feb 2022 15:53:13 -0800 Subject: [PATCH 20/55] Fix substitution types of indexed access types of substitution types (#47791) * Fix substitution types of indexed access types of substitution types * Add tests * Fix accidental unindentation --- src/compiler/checker.ts | 2 +- .../substitutionTypeForIndexedAccessType1.js | 8 +++++ ...stitutionTypeForIndexedAccessType1.symbols | 18 ++++++++++ ...ubstitutionTypeForIndexedAccessType1.types | 8 +++++ .../substitutionTypeForIndexedAccessType2.js | 18 ++++++++++ ...stitutionTypeForIndexedAccessType2.symbols | 33 +++++++++++++++++++ ...ubstitutionTypeForIndexedAccessType2.types | 20 +++++++++++ .../substitutionTypeForIndexedAccessType1.ts | 5 +++ .../substitutionTypeForIndexedAccessType2.ts | 15 +++++++++ 9 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/substitutionTypeForIndexedAccessType1.js create mode 100644 tests/baselines/reference/substitutionTypeForIndexedAccessType1.symbols create mode 100644 tests/baselines/reference/substitutionTypeForIndexedAccessType1.types create mode 100644 tests/baselines/reference/substitutionTypeForIndexedAccessType2.js create mode 100644 tests/baselines/reference/substitutionTypeForIndexedAccessType2.symbols create mode 100644 tests/baselines/reference/substitutionTypeForIndexedAccessType2.types create mode 100644 tests/cases/compiler/substitutionTypeForIndexedAccessType1.ts create mode 100644 tests/cases/compiler/substitutionTypeForIndexedAccessType2.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 840aa5e827b61..ecac36fafdc29 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13506,7 +13506,7 @@ namespace ts { function getImpliedConstraint(type: Type, checkNode: TypeNode, extendsNode: TypeNode): Type | undefined { return isUnaryTupleTypeNode(checkNode) && isUnaryTupleTypeNode(extendsNode) ? getImpliedConstraint(type, (checkNode as TupleTypeNode).elements[0], (extendsNode as TupleTypeNode).elements[0]) : - getActualTypeVariable(getTypeFromTypeNode(checkNode)) === type ? getTypeFromTypeNode(extendsNode) : + getActualTypeVariable(getTypeFromTypeNode(checkNode)) === getActualTypeVariable(type) ? getTypeFromTypeNode(extendsNode) : undefined; } diff --git a/tests/baselines/reference/substitutionTypeForIndexedAccessType1.js b/tests/baselines/reference/substitutionTypeForIndexedAccessType1.js new file mode 100644 index 0000000000000..21e18fc1e079d --- /dev/null +++ b/tests/baselines/reference/substitutionTypeForIndexedAccessType1.js @@ -0,0 +1,8 @@ +//// [substitutionTypeForIndexedAccessType1.ts] +type AddPropToObject = Prop extends keyof Obj + ? Obj[Prop] extends unknown[] + ? [...Obj[Prop]] + : never + : never + +//// [substitutionTypeForIndexedAccessType1.js] diff --git a/tests/baselines/reference/substitutionTypeForIndexedAccessType1.symbols b/tests/baselines/reference/substitutionTypeForIndexedAccessType1.symbols new file mode 100644 index 0000000000000..6b46ff33c16c1 --- /dev/null +++ b/tests/baselines/reference/substitutionTypeForIndexedAccessType1.symbols @@ -0,0 +1,18 @@ +=== tests/cases/compiler/substitutionTypeForIndexedAccessType1.ts === +type AddPropToObject = Prop extends keyof Obj +>AddPropToObject : Symbol(AddPropToObject, Decl(substitutionTypeForIndexedAccessType1.ts, 0, 0)) +>Obj : Symbol(Obj, Decl(substitutionTypeForIndexedAccessType1.ts, 0, 21)) +>Prop : Symbol(Prop, Decl(substitutionTypeForIndexedAccessType1.ts, 0, 40)) +>Prop : Symbol(Prop, Decl(substitutionTypeForIndexedAccessType1.ts, 0, 40)) +>Obj : Symbol(Obj, Decl(substitutionTypeForIndexedAccessType1.ts, 0, 21)) + + ? Obj[Prop] extends unknown[] +>Obj : Symbol(Obj, Decl(substitutionTypeForIndexedAccessType1.ts, 0, 21)) +>Prop : Symbol(Prop, Decl(substitutionTypeForIndexedAccessType1.ts, 0, 40)) + + ? [...Obj[Prop]] +>Obj : Symbol(Obj, Decl(substitutionTypeForIndexedAccessType1.ts, 0, 21)) +>Prop : Symbol(Prop, Decl(substitutionTypeForIndexedAccessType1.ts, 0, 40)) + + : never + : never diff --git a/tests/baselines/reference/substitutionTypeForIndexedAccessType1.types b/tests/baselines/reference/substitutionTypeForIndexedAccessType1.types new file mode 100644 index 0000000000000..8b9a2ef6ba3db --- /dev/null +++ b/tests/baselines/reference/substitutionTypeForIndexedAccessType1.types @@ -0,0 +1,8 @@ +=== tests/cases/compiler/substitutionTypeForIndexedAccessType1.ts === +type AddPropToObject = Prop extends keyof Obj +>AddPropToObject : AddPropToObject + + ? Obj[Prop] extends unknown[] + ? [...Obj[Prop]] + : never + : never diff --git a/tests/baselines/reference/substitutionTypeForIndexedAccessType2.js b/tests/baselines/reference/substitutionTypeForIndexedAccessType2.js new file mode 100644 index 0000000000000..9cad42066541b --- /dev/null +++ b/tests/baselines/reference/substitutionTypeForIndexedAccessType2.js @@ -0,0 +1,18 @@ +//// [substitutionTypeForIndexedAccessType2.ts] +interface Foo { + foo: string|undefined +} + +type Str = T + +type Bar = + T extends Foo + ? T['foo'] extends string + // Type 'T["foo"]' does not satisfy the constraint 'string'. + // Type 'string | undefined' is not assignable to type 'string'. + // Type 'undefined' is not assignable to type 'string'.(2344) + ? Str + : never + : never + +//// [substitutionTypeForIndexedAccessType2.js] diff --git a/tests/baselines/reference/substitutionTypeForIndexedAccessType2.symbols b/tests/baselines/reference/substitutionTypeForIndexedAccessType2.symbols new file mode 100644 index 0000000000000..db31bbe9c55c4 --- /dev/null +++ b/tests/baselines/reference/substitutionTypeForIndexedAccessType2.symbols @@ -0,0 +1,33 @@ +=== tests/cases/compiler/substitutionTypeForIndexedAccessType2.ts === +interface Foo { +>Foo : Symbol(Foo, Decl(substitutionTypeForIndexedAccessType2.ts, 0, 0)) + + foo: string|undefined +>foo : Symbol(Foo.foo, Decl(substitutionTypeForIndexedAccessType2.ts, 0, 15)) +} + +type Str = T +>Str : Symbol(Str, Decl(substitutionTypeForIndexedAccessType2.ts, 2, 1)) +>T : Symbol(T, Decl(substitutionTypeForIndexedAccessType2.ts, 4, 9)) +>T : Symbol(T, Decl(substitutionTypeForIndexedAccessType2.ts, 4, 9)) + +type Bar = +>Bar : Symbol(Bar, Decl(substitutionTypeForIndexedAccessType2.ts, 4, 30)) +>T : Symbol(T, Decl(substitutionTypeForIndexedAccessType2.ts, 6, 9)) + + T extends Foo +>T : Symbol(T, Decl(substitutionTypeForIndexedAccessType2.ts, 6, 9)) +>Foo : Symbol(Foo, Decl(substitutionTypeForIndexedAccessType2.ts, 0, 0)) + + ? T['foo'] extends string +>T : Symbol(T, Decl(substitutionTypeForIndexedAccessType2.ts, 6, 9)) + + // Type 'T["foo"]' does not satisfy the constraint 'string'. + // Type 'string | undefined' is not assignable to type 'string'. + // Type 'undefined' is not assignable to type 'string'.(2344) + ? Str +>Str : Symbol(Str, Decl(substitutionTypeForIndexedAccessType2.ts, 2, 1)) +>T : Symbol(T, Decl(substitutionTypeForIndexedAccessType2.ts, 6, 9)) + + : never + : never diff --git a/tests/baselines/reference/substitutionTypeForIndexedAccessType2.types b/tests/baselines/reference/substitutionTypeForIndexedAccessType2.types new file mode 100644 index 0000000000000..2ded8fe41a4ef --- /dev/null +++ b/tests/baselines/reference/substitutionTypeForIndexedAccessType2.types @@ -0,0 +1,20 @@ +=== tests/cases/compiler/substitutionTypeForIndexedAccessType2.ts === +interface Foo { + foo: string|undefined +>foo : string +} + +type Str = T +>Str : T + +type Bar = +>Bar : Bar + + T extends Foo + ? T['foo'] extends string + // Type 'T["foo"]' does not satisfy the constraint 'string'. + // Type 'string | undefined' is not assignable to type 'string'. + // Type 'undefined' is not assignable to type 'string'.(2344) + ? Str + : never + : never diff --git a/tests/cases/compiler/substitutionTypeForIndexedAccessType1.ts b/tests/cases/compiler/substitutionTypeForIndexedAccessType1.ts new file mode 100644 index 0000000000000..4c665d768544c --- /dev/null +++ b/tests/cases/compiler/substitutionTypeForIndexedAccessType1.ts @@ -0,0 +1,5 @@ +type AddPropToObject = Prop extends keyof Obj + ? Obj[Prop] extends unknown[] + ? [...Obj[Prop]] + : never + : never \ No newline at end of file diff --git a/tests/cases/compiler/substitutionTypeForIndexedAccessType2.ts b/tests/cases/compiler/substitutionTypeForIndexedAccessType2.ts new file mode 100644 index 0000000000000..c687879efd463 --- /dev/null +++ b/tests/cases/compiler/substitutionTypeForIndexedAccessType2.ts @@ -0,0 +1,15 @@ +interface Foo { + foo: string|undefined +} + +type Str = T + +type Bar = + T extends Foo + ? T['foo'] extends string + // Type 'T["foo"]' does not satisfy the constraint 'string'. + // Type 'string | undefined' is not assignable to type 'string'. + // Type 'undefined' is not assignable to type 'string'.(2344) + ? Str + : never + : never \ No newline at end of file From 1b6fb99efe37f239221e3a3ee6141934f9bf55e8 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Mon, 7 Feb 2022 16:10:01 -0800 Subject: [PATCH 21/55] Log per-project FAR and update baselines (#47781) --- src/server/session.ts | 5 ++++- ...edirects-are-disabled-and-a-decl-map-is-missing.js | 1 + ...edirects-are-disabled-and-a-decl-map-is-present.js | 2 ++ ...redirects-are-enabled-and-a-decl-map-is-missing.js | 2 ++ ...redirects-are-enabled-and-a-decl-map-is-present.js | 2 ++ ...edirects-are-disabled-and-a-decl-map-is-missing.js | 1 + ...edirects-are-disabled-and-a-decl-map-is-present.js | 2 ++ ...redirects-are-enabled-and-a-decl-map-is-missing.js | 2 ++ ...redirects-are-enabled-and-a-decl-map-is-present.js | 2 ++ ...edirects-are-disabled-and-a-decl-map-is-missing.js | 1 + ...edirects-are-disabled-and-a-decl-map-is-present.js | 1 + ...redirects-are-enabled-and-a-decl-map-is-missing.js | 1 + ...redirects-are-enabled-and-a-decl-map-is-present.js | 1 + ...edirects-are-disabled-and-a-decl-map-is-missing.js | 1 + ...edirects-are-disabled-and-a-decl-map-is-present.js | 2 ++ ...redirects-are-enabled-and-a-decl-map-is-missing.js | 2 ++ ...redirects-are-enabled-and-a-decl-map-is-present.js | 2 ++ .../sibling-projects.js | 3 +++ .../project-is-directly-referenced-by-solution.js | 3 +++ .../project-is-indirectly-referenced-by-solution.js | 7 +++++++ ...m-referenced-project-and-using-declaration-maps.js | 2 ++ .../root-file-is-file-from-referenced-project.js | 2 ++ ...-references-open-file-through-project-reference.js | 6 ++++++ ...nd-project-is-indirectly-referenced-by-solution.js | 11 +++++++++++ ...arrow-function-as-object-literal-property-types.js | 3 +++ ...using-arrow-function-as-object-literal-property.js | 2 ++ ...-localness-when-using-arrow-function-assignment.js | 3 +++ ...localness-when-using-method-of-class-expression.js | 3 +++ ...of-localness-when-using-object-literal-property.js | 3 +++ ...wo-projects-are-open-and-one-project-references.js | 1 + ...nSearching-solution-and-siblings-are-not-loaded.js | 1 + 31 files changed, 79 insertions(+), 1 deletion(-) diff --git a/src/server/session.ts b/src/server/session.ts index b0bb42dade1ca..25d9a6fe83b59 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -370,7 +370,8 @@ namespace ts.server { function combineProjectOutputForReferences( projects: Projects, defaultProject: Project, - initialLocation: DocumentPosition + initialLocation: DocumentPosition, + logger: Logger, ): readonly ReferencedSymbol[] { const outputs: ReferencedSymbol[] = []; @@ -379,6 +380,7 @@ namespace ts.server { defaultProject, initialLocation, (project, location, getMappedLocation) => { + logger.info(`Finding references to ${location.fileName} position ${location.pos} in project ${project.getProjectName()}`); for (const outputReferencedSymbol of project.getLanguageService().findReferences(location.fileName, location.pos) || emptyArray) { const mappedDefinitionFile = getMappedLocation(project, documentSpanLocation(outputReferencedSymbol.definition)); const definition: ReferencedSymbolDefinitionInfo = mappedDefinitionFile === undefined ? @@ -1588,6 +1590,7 @@ namespace ts.server { projects, this.getDefaultProject(args), { fileName: args.file, pos: position }, + this.logger, ); if (!simplifiedResult) return references; diff --git a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-missing.js b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-missing.js index 97452f09da4bd..e4a796ad6a22c 100644 --- a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-missing.js +++ b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-missing.js @@ -118,5 +118,6 @@ Open files: Projects: /user/username/projects/myproject/b/tsconfig.json response:{"responseRequired":false} request:{"command":"references","arguments":{"file":"/user/username/projects/myproject/a/index.ts","line":3,"offset":10},"seq":1,"type":"request"} +Finding references to /user/username/projects/myproject/a/index.ts position 40 in project /user/username/projects/myproject/a/tsconfig.json FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b/lib/index.d.ts.map 2000 undefined WatchType: Missing source map file response:{"response":{"refs":[{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":1,"offset":10},"end":{"line":1,"offset":11},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":30},"lineText":"import { B } from \"../b/lib\";","isWriteAccess":true,"isDefinition":true},{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":3,"offset":10},"end":{"line":3,"offset":11},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":3,"offset":18},"end":{"line":3,"offset":19},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/b/lib/index.d.ts","start":{"line":1,"offset":22},"end":{"line":1,"offset":23},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":3,"offset":2},"lineText":"export declare class B {","isWriteAccess":true,"isDefinition":false}],"symbolName":"B","symbolStartOffset":10,"symbolDisplayString":"(alias) class B\nimport B"},"responseRequired":true} \ No newline at end of file diff --git a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-present.js b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-present.js index 14506aa873cf1..de2955e6e7be2 100644 --- a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-present.js +++ b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-present.js @@ -118,9 +118,11 @@ Open files: Projects: /user/username/projects/myproject/b/tsconfig.json response:{"responseRequired":false} request:{"command":"references","arguments":{"file":"/user/username/projects/myproject/a/index.ts","line":3,"offset":10},"seq":1,"type":"request"} +Finding references to /user/username/projects/myproject/a/index.ts position 40 in project /user/username/projects/myproject/a/tsconfig.json FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b/lib/index.d.ts.map 500 undefined WatchType: Closed Script info Search path: /user/username/projects/myproject/b For info: /user/username/projects/myproject/b/index.ts :: Config file name: /user/username/projects/myproject/b/tsconfig.json Search path: /user/username/projects/myproject/b For info: /user/username/projects/myproject/b/index.ts :: Config file name: /user/username/projects/myproject/b/tsconfig.json +Finding references to /user/username/projects/myproject/b/index.ts position 13 in project /user/username/projects/myproject/b/tsconfig.json response:{"response":{"refs":[{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":1,"offset":10},"end":{"line":1,"offset":11},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":30},"lineText":"import { B } from \"../b/lib\";","isWriteAccess":true,"isDefinition":true},{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":3,"offset":10},"end":{"line":3,"offset":11},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":3,"offset":18},"end":{"line":3,"offset":19},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/b/index.ts","start":{"line":1,"offset":14},"end":{"line":1,"offset":15},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":3,"offset":2},"lineText":"export class B {","isWriteAccess":true,"isDefinition":true},{"file":"/user/username/projects/myproject/b/helper.ts","start":{"line":1,"offset":10},"end":{"line":1,"offset":11},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":23},"lineText":"import { B } from \".\";","isWriteAccess":true,"isDefinition":false},{"file":"/user/username/projects/myproject/b/helper.ts","start":{"line":3,"offset":10},"end":{"line":3,"offset":11},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/b/helper.ts","start":{"line":3,"offset":18},"end":{"line":3,"offset":19},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false}],"symbolName":"B","symbolStartOffset":10,"symbolDisplayString":"(alias) class B\nimport B"},"responseRequired":true} \ No newline at end of file diff --git a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-missing.js b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-missing.js index 9675f9aceb516..b1df27518b1b0 100644 --- a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-missing.js +++ b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-missing.js @@ -117,8 +117,10 @@ Open files: Projects: /user/username/projects/myproject/b/tsconfig.json response:{"responseRequired":false} request:{"command":"references","arguments":{"file":"/user/username/projects/myproject/a/index.ts","line":3,"offset":10},"seq":1,"type":"request"} +Finding references to /user/username/projects/myproject/a/index.ts position 40 in project /user/username/projects/myproject/a/tsconfig.json Search path: /user/username/projects/myproject/b For info: /user/username/projects/myproject/b/index.ts :: Config file name: /user/username/projects/myproject/b/tsconfig.json Search path: /user/username/projects/myproject/b For info: /user/username/projects/myproject/b/index.ts :: Config file name: /user/username/projects/myproject/b/tsconfig.json +Finding references to /user/username/projects/myproject/b/index.ts position 13 in project /user/username/projects/myproject/b/tsconfig.json response:{"response":{"refs":[{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":1,"offset":10},"end":{"line":1,"offset":11},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":30},"lineText":"import { B } from \"../b/lib\";","isWriteAccess":true,"isDefinition":true},{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":3,"offset":10},"end":{"line":3,"offset":11},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":3,"offset":18},"end":{"line":3,"offset":19},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/b/index.ts","start":{"line":1,"offset":14},"end":{"line":1,"offset":15},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":3,"offset":2},"lineText":"export class B {","isWriteAccess":true,"isDefinition":false},{"file":"/user/username/projects/myproject/b/helper.ts","start":{"line":1,"offset":10},"end":{"line":1,"offset":11},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":23},"lineText":"import { B } from \".\";","isWriteAccess":true,"isDefinition":false},{"file":"/user/username/projects/myproject/b/helper.ts","start":{"line":3,"offset":10},"end":{"line":3,"offset":11},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/b/helper.ts","start":{"line":3,"offset":18},"end":{"line":3,"offset":19},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false}],"symbolName":"B","symbolStartOffset":10,"symbolDisplayString":"(alias) class B\nimport B"},"responseRequired":true} \ No newline at end of file diff --git a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-present.js b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-present.js index 9675f9aceb516..b1df27518b1b0 100644 --- a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-present.js +++ b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-present.js @@ -117,8 +117,10 @@ Open files: Projects: /user/username/projects/myproject/b/tsconfig.json response:{"responseRequired":false} request:{"command":"references","arguments":{"file":"/user/username/projects/myproject/a/index.ts","line":3,"offset":10},"seq":1,"type":"request"} +Finding references to /user/username/projects/myproject/a/index.ts position 40 in project /user/username/projects/myproject/a/tsconfig.json Search path: /user/username/projects/myproject/b For info: /user/username/projects/myproject/b/index.ts :: Config file name: /user/username/projects/myproject/b/tsconfig.json Search path: /user/username/projects/myproject/b For info: /user/username/projects/myproject/b/index.ts :: Config file name: /user/username/projects/myproject/b/tsconfig.json +Finding references to /user/username/projects/myproject/b/index.ts position 13 in project /user/username/projects/myproject/b/tsconfig.json response:{"response":{"refs":[{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":1,"offset":10},"end":{"line":1,"offset":11},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":30},"lineText":"import { B } from \"../b/lib\";","isWriteAccess":true,"isDefinition":true},{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":3,"offset":10},"end":{"line":3,"offset":11},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":3,"offset":18},"end":{"line":3,"offset":19},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/b/index.ts","start":{"line":1,"offset":14},"end":{"line":1,"offset":15},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":3,"offset":2},"lineText":"export class B {","isWriteAccess":true,"isDefinition":false},{"file":"/user/username/projects/myproject/b/helper.ts","start":{"line":1,"offset":10},"end":{"line":1,"offset":11},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":23},"lineText":"import { B } from \".\";","isWriteAccess":true,"isDefinition":false},{"file":"/user/username/projects/myproject/b/helper.ts","start":{"line":3,"offset":10},"end":{"line":3,"offset":11},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/b/helper.ts","start":{"line":3,"offset":18},"end":{"line":3,"offset":19},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false}],"symbolName":"B","symbolStartOffset":10,"symbolDisplayString":"(alias) class B\nimport B"},"responseRequired":true} \ No newline at end of file diff --git a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-missing.js b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-missing.js index d240cf5f50f5b..67cd7b768598a 100644 --- a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-missing.js +++ b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-missing.js @@ -118,5 +118,6 @@ Open files: Projects: /user/username/projects/myproject/b/tsconfig.json response:{"responseRequired":false} request:{"command":"references","arguments":{"file":"/user/username/projects/myproject/a/index.ts","line":3,"offset":10},"seq":1,"type":"request"} +Finding references to /user/username/projects/myproject/a/index.ts position 40 in project /user/username/projects/myproject/a/tsconfig.json FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b/lib/index.d.ts.map 2000 undefined WatchType: Missing source map file response:{"response":{"refs":[{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":1,"offset":10},"end":{"line":1,"offset":11},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":30},"lineText":"import { B } from \"../b/lib\";","isWriteAccess":true,"isDefinition":true},{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":3,"offset":10},"end":{"line":3,"offset":11},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":3,"offset":18},"end":{"line":3,"offset":19},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/b/lib/index.d.ts","start":{"line":1,"offset":22},"end":{"line":1,"offset":23},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":3,"offset":2},"lineText":"export declare class B {","isWriteAccess":true,"isDefinition":false}],"symbolName":"B","symbolStartOffset":10,"symbolDisplayString":"(alias) class B\nimport B"},"responseRequired":true} \ No newline at end of file diff --git a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-present.js b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-present.js index 86197a4a62841..e647f2e2f5c68 100644 --- a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-present.js +++ b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-present.js @@ -118,9 +118,11 @@ Open files: Projects: /user/username/projects/myproject/b/tsconfig.json response:{"responseRequired":false} request:{"command":"references","arguments":{"file":"/user/username/projects/myproject/a/index.ts","line":3,"offset":10},"seq":1,"type":"request"} +Finding references to /user/username/projects/myproject/a/index.ts position 40 in project /user/username/projects/myproject/a/tsconfig.json FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b/lib/index.d.ts.map 500 undefined WatchType: Closed Script info Search path: /user/username/projects/myproject/b For info: /user/username/projects/myproject/b/index.ts :: Config file name: /user/username/projects/myproject/b/tsconfig.json Search path: /user/username/projects/myproject/b For info: /user/username/projects/myproject/b/index.ts :: Config file name: /user/username/projects/myproject/b/tsconfig.json +Finding references to /user/username/projects/myproject/b/index.ts position 13 in project /user/username/projects/myproject/b/tsconfig.json response:{"response":{"refs":[{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":1,"offset":10},"end":{"line":1,"offset":11},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":30},"lineText":"import { B } from \"../b/lib\";","isWriteAccess":true,"isDefinition":true},{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":3,"offset":10},"end":{"line":3,"offset":11},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":3,"offset":18},"end":{"line":3,"offset":19},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/b/index.ts","start":{"line":1,"offset":14},"end":{"line":1,"offset":15},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":3,"offset":2},"lineText":"export class B {","isWriteAccess":true,"isDefinition":true},{"file":"/user/username/projects/myproject/b/helper.ts","start":{"line":1,"offset":10},"end":{"line":1,"offset":11},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":23},"lineText":"import { B } from \".\";","isWriteAccess":true,"isDefinition":false},{"file":"/user/username/projects/myproject/b/helper.ts","start":{"line":3,"offset":10},"end":{"line":3,"offset":11},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/b/helper.ts","start":{"line":3,"offset":18},"end":{"line":3,"offset":19},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false}],"symbolName":"B","symbolStartOffset":10,"symbolDisplayString":"(alias) class B\nimport B"},"responseRequired":true} \ No newline at end of file diff --git a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-missing.js b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-missing.js index 7dfe811088ca2..74ca1adfc4a5f 100644 --- a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-missing.js +++ b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-missing.js @@ -117,8 +117,10 @@ Open files: Projects: /user/username/projects/myproject/b/tsconfig.json response:{"responseRequired":false} request:{"command":"references","arguments":{"file":"/user/username/projects/myproject/a/index.ts","line":3,"offset":10},"seq":1,"type":"request"} +Finding references to /user/username/projects/myproject/a/index.ts position 40 in project /user/username/projects/myproject/a/tsconfig.json Search path: /user/username/projects/myproject/b For info: /user/username/projects/myproject/b/index.ts :: Config file name: /user/username/projects/myproject/b/tsconfig.json Search path: /user/username/projects/myproject/b For info: /user/username/projects/myproject/b/index.ts :: Config file name: /user/username/projects/myproject/b/tsconfig.json +Finding references to /user/username/projects/myproject/b/index.ts position 13 in project /user/username/projects/myproject/b/tsconfig.json response:{"response":{"refs":[{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":1,"offset":10},"end":{"line":1,"offset":11},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":30},"lineText":"import { B } from \"../b/lib\";","isWriteAccess":true,"isDefinition":true},{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":3,"offset":10},"end":{"line":3,"offset":11},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":3,"offset":18},"end":{"line":3,"offset":19},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/b/index.ts","start":{"line":1,"offset":14},"end":{"line":1,"offset":15},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":3,"offset":2},"lineText":"export class B {","isWriteAccess":true,"isDefinition":false},{"file":"/user/username/projects/myproject/b/helper.ts","start":{"line":1,"offset":10},"end":{"line":1,"offset":11},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":23},"lineText":"import { B } from \".\";","isWriteAccess":true,"isDefinition":false},{"file":"/user/username/projects/myproject/b/helper.ts","start":{"line":3,"offset":10},"end":{"line":3,"offset":11},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/b/helper.ts","start":{"line":3,"offset":18},"end":{"line":3,"offset":19},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false}],"symbolName":"B","symbolStartOffset":10,"symbolDisplayString":"(alias) class B\nimport B"},"responseRequired":true} \ No newline at end of file diff --git a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-present.js b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-present.js index 7dfe811088ca2..74ca1adfc4a5f 100644 --- a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-present.js +++ b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-present.js @@ -117,8 +117,10 @@ Open files: Projects: /user/username/projects/myproject/b/tsconfig.json response:{"responseRequired":false} request:{"command":"references","arguments":{"file":"/user/username/projects/myproject/a/index.ts","line":3,"offset":10},"seq":1,"type":"request"} +Finding references to /user/username/projects/myproject/a/index.ts position 40 in project /user/username/projects/myproject/a/tsconfig.json Search path: /user/username/projects/myproject/b For info: /user/username/projects/myproject/b/index.ts :: Config file name: /user/username/projects/myproject/b/tsconfig.json Search path: /user/username/projects/myproject/b For info: /user/username/projects/myproject/b/index.ts :: Config file name: /user/username/projects/myproject/b/tsconfig.json +Finding references to /user/username/projects/myproject/b/index.ts position 13 in project /user/username/projects/myproject/b/tsconfig.json response:{"response":{"refs":[{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":1,"offset":10},"end":{"line":1,"offset":11},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":30},"lineText":"import { B } from \"../b/lib\";","isWriteAccess":true,"isDefinition":true},{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":3,"offset":10},"end":{"line":3,"offset":11},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":3,"offset":18},"end":{"line":3,"offset":19},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/b/index.ts","start":{"line":1,"offset":14},"end":{"line":1,"offset":15},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":3,"offset":2},"lineText":"export class B {","isWriteAccess":true,"isDefinition":false},{"file":"/user/username/projects/myproject/b/helper.ts","start":{"line":1,"offset":10},"end":{"line":1,"offset":11},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":23},"lineText":"import { B } from \".\";","isWriteAccess":true,"isDefinition":false},{"file":"/user/username/projects/myproject/b/helper.ts","start":{"line":3,"offset":10},"end":{"line":3,"offset":11},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/b/helper.ts","start":{"line":3,"offset":18},"end":{"line":3,"offset":19},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false}],"symbolName":"B","symbolStartOffset":10,"symbolDisplayString":"(alias) class B\nimport B"},"responseRequired":true} \ No newline at end of file diff --git a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-missing.js b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-missing.js index 9802936b4f05e..632f7b1324eaf 100644 --- a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-missing.js +++ b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-missing.js @@ -72,5 +72,6 @@ Open files: Projects: /user/username/projects/myproject/a/tsconfig.json response:{"responseRequired":false} request:{"command":"references","arguments":{"file":"/user/username/projects/myproject/a/index.ts","line":3,"offset":10},"seq":1,"type":"request"} +Finding references to /user/username/projects/myproject/a/index.ts position 40 in project /user/username/projects/myproject/a/tsconfig.json FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b/lib/index.d.ts.map 2000 undefined WatchType: Missing source map file response:{"response":{"refs":[{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":1,"offset":10},"end":{"line":1,"offset":11},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":30},"lineText":"import { B } from \"../b/lib\";","isWriteAccess":true,"isDefinition":true},{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":3,"offset":10},"end":{"line":3,"offset":11},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":3,"offset":18},"end":{"line":3,"offset":19},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/b/lib/index.d.ts","start":{"line":1,"offset":22},"end":{"line":1,"offset":23},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":3,"offset":2},"lineText":"export declare class B {","isWriteAccess":true,"isDefinition":false}],"symbolName":"B","symbolStartOffset":10,"symbolDisplayString":"(alias) class B\nimport B"},"responseRequired":true} \ No newline at end of file diff --git a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-present.js b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-present.js index 0a3f5852f993a..1903f0af5e95c 100644 --- a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-present.js +++ b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-present.js @@ -72,6 +72,7 @@ Open files: Projects: /user/username/projects/myproject/a/tsconfig.json response:{"responseRequired":false} request:{"command":"references","arguments":{"file":"/user/username/projects/myproject/a/index.ts","line":3,"offset":10},"seq":1,"type":"request"} +Finding references to /user/username/projects/myproject/a/index.ts position 40 in project /user/username/projects/myproject/a/tsconfig.json FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b/lib/index.d.ts.map 500 undefined WatchType: Closed Script info FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b/index.ts 500 undefined WatchType: Closed Script info Search path: /user/username/projects/myproject/b diff --git a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-missing.js b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-missing.js index 9ded214384a27..472fa5d8a5b48 100644 --- a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-missing.js +++ b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-missing.js @@ -72,6 +72,7 @@ Open files: Projects: /user/username/projects/myproject/a/tsconfig.json response:{"responseRequired":false} request:{"command":"references","arguments":{"file":"/user/username/projects/myproject/a/index.ts","line":3,"offset":10},"seq":1,"type":"request"} +Finding references to /user/username/projects/myproject/a/index.ts position 40 in project /user/username/projects/myproject/a/tsconfig.json Search path: /user/username/projects/myproject/b For info: /user/username/projects/myproject/b/index.ts :: Config file name: /user/username/projects/myproject/b/tsconfig.json Search path: /user/username/projects/myproject/b diff --git a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-present.js b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-present.js index 9ded214384a27..472fa5d8a5b48 100644 --- a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-present.js +++ b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-present.js @@ -72,6 +72,7 @@ Open files: Projects: /user/username/projects/myproject/a/tsconfig.json response:{"responseRequired":false} request:{"command":"references","arguments":{"file":"/user/username/projects/myproject/a/index.ts","line":3,"offset":10},"seq":1,"type":"request"} +Finding references to /user/username/projects/myproject/a/index.ts position 40 in project /user/username/projects/myproject/a/tsconfig.json Search path: /user/username/projects/myproject/b For info: /user/username/projects/myproject/b/index.ts :: Config file name: /user/username/projects/myproject/b/tsconfig.json Search path: /user/username/projects/myproject/b diff --git a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-missing.js b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-missing.js index e0558ac23e961..6fb984c8aca64 100644 --- a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-missing.js +++ b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-missing.js @@ -72,5 +72,6 @@ Open files: Projects: /user/username/projects/myproject/a/tsconfig.json response:{"responseRequired":false} request:{"command":"references","arguments":{"file":"/user/username/projects/myproject/a/index.ts","line":3,"offset":10},"seq":1,"type":"request"} +Finding references to /user/username/projects/myproject/a/index.ts position 40 in project /user/username/projects/myproject/a/tsconfig.json FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b/lib/index.d.ts.map 2000 undefined WatchType: Missing source map file response:{"response":{"refs":[{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":1,"offset":10},"end":{"line":1,"offset":11},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":30},"lineText":"import { B } from \"../b/lib\";","isWriteAccess":true,"isDefinition":true},{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":3,"offset":10},"end":{"line":3,"offset":11},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":3,"offset":18},"end":{"line":3,"offset":19},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/b/lib/index.d.ts","start":{"line":1,"offset":22},"end":{"line":1,"offset":23},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":3,"offset":2},"lineText":"export declare class B {","isWriteAccess":true,"isDefinition":false}],"symbolName":"B","symbolStartOffset":10,"symbolDisplayString":"(alias) class B\nimport B"},"responseRequired":true} \ No newline at end of file diff --git a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-present.js b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-present.js index 518b4d0347f4f..73acf6730c022 100644 --- a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-present.js +++ b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-present.js @@ -72,6 +72,7 @@ Open files: Projects: /user/username/projects/myproject/a/tsconfig.json response:{"responseRequired":false} request:{"command":"references","arguments":{"file":"/user/username/projects/myproject/a/index.ts","line":3,"offset":10},"seq":1,"type":"request"} +Finding references to /user/username/projects/myproject/a/index.ts position 40 in project /user/username/projects/myproject/a/tsconfig.json FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b/lib/index.d.ts.map 500 undefined WatchType: Closed Script info FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b/index.ts 500 undefined WatchType: Closed Script info Search path: /user/username/projects/myproject/b @@ -105,4 +106,5 @@ Project '/user/username/projects/myproject/b/tsconfig.json' (Configured) ----------------------------------------------- Search path: /user/username/projects/myproject/b For info: /user/username/projects/myproject/b/index.ts :: Config file name: /user/username/projects/myproject/b/tsconfig.json +Finding references to /user/username/projects/myproject/b/index.ts position 13 in project /user/username/projects/myproject/b/tsconfig.json response:{"response":{"refs":[{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":1,"offset":10},"end":{"line":1,"offset":11},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":30},"lineText":"import { B } from \"../b/lib\";","isWriteAccess":true,"isDefinition":true},{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":3,"offset":10},"end":{"line":3,"offset":11},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":3,"offset":18},"end":{"line":3,"offset":19},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/b/index.ts","start":{"line":1,"offset":14},"end":{"line":1,"offset":15},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":3,"offset":2},"lineText":"export class B {","isWriteAccess":true,"isDefinition":true},{"file":"/user/username/projects/myproject/b/helper.ts","start":{"line":1,"offset":10},"end":{"line":1,"offset":11},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":23},"lineText":"import { B } from \".\";","isWriteAccess":true,"isDefinition":false},{"file":"/user/username/projects/myproject/b/helper.ts","start":{"line":3,"offset":10},"end":{"line":3,"offset":11},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/b/helper.ts","start":{"line":3,"offset":18},"end":{"line":3,"offset":19},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false}],"symbolName":"B","symbolStartOffset":10,"symbolDisplayString":"(alias) class B\nimport B"},"responseRequired":true} \ No newline at end of file diff --git a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-missing.js b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-missing.js index 36260b89369b9..296aa5a020cfc 100644 --- a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-missing.js +++ b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-missing.js @@ -72,6 +72,7 @@ Open files: Projects: /user/username/projects/myproject/a/tsconfig.json response:{"responseRequired":false} request:{"command":"references","arguments":{"file":"/user/username/projects/myproject/a/index.ts","line":3,"offset":10},"seq":1,"type":"request"} +Finding references to /user/username/projects/myproject/a/index.ts position 40 in project /user/username/projects/myproject/a/tsconfig.json Search path: /user/username/projects/myproject/b For info: /user/username/projects/myproject/b/index.ts :: Config file name: /user/username/projects/myproject/b/tsconfig.json Creating configuration project /user/username/projects/myproject/b/tsconfig.json @@ -103,4 +104,5 @@ Project '/user/username/projects/myproject/b/tsconfig.json' (Configured) ----------------------------------------------- Search path: /user/username/projects/myproject/b For info: /user/username/projects/myproject/b/index.ts :: Config file name: /user/username/projects/myproject/b/tsconfig.json +Finding references to /user/username/projects/myproject/b/index.ts position 13 in project /user/username/projects/myproject/b/tsconfig.json response:{"response":{"refs":[{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":1,"offset":10},"end":{"line":1,"offset":11},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":30},"lineText":"import { B } from \"../b/lib\";","isWriteAccess":true,"isDefinition":true},{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":3,"offset":10},"end":{"line":3,"offset":11},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":3,"offset":18},"end":{"line":3,"offset":19},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/b/index.ts","start":{"line":1,"offset":14},"end":{"line":1,"offset":15},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":3,"offset":2},"lineText":"export class B {","isWriteAccess":true,"isDefinition":false},{"file":"/user/username/projects/myproject/b/helper.ts","start":{"line":1,"offset":10},"end":{"line":1,"offset":11},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":23},"lineText":"import { B } from \".\";","isWriteAccess":true,"isDefinition":false},{"file":"/user/username/projects/myproject/b/helper.ts","start":{"line":3,"offset":10},"end":{"line":3,"offset":11},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/b/helper.ts","start":{"line":3,"offset":18},"end":{"line":3,"offset":19},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false}],"symbolName":"B","symbolStartOffset":10,"symbolDisplayString":"(alias) class B\nimport B"},"responseRequired":true} \ No newline at end of file diff --git a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-present.js b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-present.js index 36260b89369b9..296aa5a020cfc 100644 --- a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-present.js +++ b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-present.js @@ -72,6 +72,7 @@ Open files: Projects: /user/username/projects/myproject/a/tsconfig.json response:{"responseRequired":false} request:{"command":"references","arguments":{"file":"/user/username/projects/myproject/a/index.ts","line":3,"offset":10},"seq":1,"type":"request"} +Finding references to /user/username/projects/myproject/a/index.ts position 40 in project /user/username/projects/myproject/a/tsconfig.json Search path: /user/username/projects/myproject/b For info: /user/username/projects/myproject/b/index.ts :: Config file name: /user/username/projects/myproject/b/tsconfig.json Creating configuration project /user/username/projects/myproject/b/tsconfig.json @@ -103,4 +104,5 @@ Project '/user/username/projects/myproject/b/tsconfig.json' (Configured) ----------------------------------------------- Search path: /user/username/projects/myproject/b For info: /user/username/projects/myproject/b/index.ts :: Config file name: /user/username/projects/myproject/b/tsconfig.json +Finding references to /user/username/projects/myproject/b/index.ts position 13 in project /user/username/projects/myproject/b/tsconfig.json response:{"response":{"refs":[{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":1,"offset":10},"end":{"line":1,"offset":11},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":30},"lineText":"import { B } from \"../b/lib\";","isWriteAccess":true,"isDefinition":true},{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":3,"offset":10},"end":{"line":3,"offset":11},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/a/index.ts","start":{"line":3,"offset":18},"end":{"line":3,"offset":19},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/b/index.ts","start":{"line":1,"offset":14},"end":{"line":1,"offset":15},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":3,"offset":2},"lineText":"export class B {","isWriteAccess":true,"isDefinition":false},{"file":"/user/username/projects/myproject/b/helper.ts","start":{"line":1,"offset":10},"end":{"line":1,"offset":11},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":23},"lineText":"import { B } from \".\";","isWriteAccess":true,"isDefinition":false},{"file":"/user/username/projects/myproject/b/helper.ts","start":{"line":3,"offset":10},"end":{"line":3,"offset":11},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/b/helper.ts","start":{"line":3,"offset":18},"end":{"line":3,"offset":19},"lineText":"const b: B = new B();","isWriteAccess":false,"isDefinition":false}],"symbolName":"B","symbolStartOffset":10,"symbolDisplayString":"(alias) class B\nimport B"},"responseRequired":true} \ No newline at end of file diff --git a/tests/baselines/reference/tsserver/projectReferences/finding-local-reference-doesnt-load-ancestor/sibling-projects.js b/tests/baselines/reference/tsserver/projectReferences/finding-local-reference-doesnt-load-ancestor/sibling-projects.js index 6c4e2142061c3..1e30c27ec76f2 100644 --- a/tests/baselines/reference/tsserver/projectReferences/finding-local-reference-doesnt-load-ancestor/sibling-projects.js +++ b/tests/baselines/reference/tsserver/projectReferences/finding-local-reference-doesnt-load-ancestor/sibling-projects.js @@ -58,8 +58,10 @@ Open files: Projects: /user/username/projects/solution/compiler/tsconfig.json response:{"responseRequired":false} request:{"command":"references","arguments":{"file":"/user/username/projects/solution/compiler/program.ts","line":4,"offset":48},"seq":1,"type":"request"} +Finding references to /user/username/projects/solution/compiler/program.ts position 133 in project /user/username/projects/solution/compiler/tsconfig.json response:{"response":{"refs":[{"file":"/user/username/projects/solution/compiler/program.ts","start":{"line":4,"offset":48},"end":{"line":4,"offset":61},"lineText":" getSourceFiles: () => [getSourceFile()]","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/solution/compiler/program.ts","start":{"line":6,"offset":30},"end":{"line":6,"offset":43},"contextStart":{"line":6,"offset":21},"contextEnd":{"line":6,"offset":69},"lineText":" function getSourceFile() { return \"something\"; }","isWriteAccess":true,"isDefinition":true}],"symbolName":"getSourceFile","symbolStartOffset":48,"symbolDisplayString":"function getSourceFile(): string"},"responseRequired":true} request:{"command":"references","arguments":{"file":"/user/username/projects/solution/compiler/program.ts","line":4,"offset":25},"seq":2,"type":"request"} +Finding references to /user/username/projects/solution/compiler/program.ts position 110 in project /user/username/projects/solution/compiler/tsconfig.json Loading configured project /user/username/projects/solution/tsconfig.json Config: /user/username/projects/solution/tsconfig.json : { "rootNames": [], @@ -127,6 +129,7 @@ Project '/user/username/projects/solution/services/tsconfig.json' (Configured) ----------------------------------------------- FileWatcher:: Added:: WatchInfo: /user/username/projects/solution/compiler/types.d.ts 2000 undefined Project: /user/username/projects/solution/compiler/tsconfig.json WatchType: Missing generated file +Finding references to /user/username/projects/solution/compiler/types.ts position 103 in project /user/username/projects/solution/services/tsconfig.json Search path: /user/username/projects/solution/compiler For info: /user/username/projects/solution/compiler/types.ts :: Config file name: /user/username/projects/solution/compiler/tsconfig.json response:{"response":{"refs":[{"file":"/user/username/projects/solution/compiler/types.ts","start":{"line":4,"offset":25},"end":{"line":4,"offset":39},"contextStart":{"line":4,"offset":25},"contextEnd":{"line":4,"offset":52},"lineText":" getSourceFiles(): string[];","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/solution/compiler/program.ts","start":{"line":4,"offset":25},"end":{"line":4,"offset":39},"contextStart":{"line":4,"offset":25},"contextEnd":{"line":4,"offset":64},"lineText":" getSourceFiles: () => [getSourceFile()]","isWriteAccess":true,"isDefinition":true},{"file":"/user/username/projects/solution/services/services.ts","start":{"line":3,"offset":44},"end":{"line":3,"offset":58},"lineText":" const result = program.getSourceFiles();","isWriteAccess":false,"isDefinition":false}],"symbolName":"getSourceFiles","symbolStartOffset":25,"symbolDisplayString":"(method) ts.Program.getSourceFiles(): string[]"},"responseRequired":true} \ No newline at end of file diff --git a/tests/baselines/reference/tsserver/projectReferences/project-is-directly-referenced-by-solution.js b/tests/baselines/reference/tsserver/projectReferences/project-is-directly-referenced-by-solution.js index ecc9eff43094d..c4e3dc48914b3 100644 --- a/tests/baselines/reference/tsserver/projectReferences/project-is-directly-referenced-by-solution.js +++ b/tests/baselines/reference/tsserver/projectReferences/project-is-directly-referenced-by-solution.js @@ -468,6 +468,7 @@ Open files: FileName: /dummy/dummy.ts ProjectRootPath: undefined Projects: /dev/null/inferredProject1* request:{"command":"references","arguments":{"file":"/user/username/projects/myproject/src/main.ts","line":2,"offset":10},"seq":2,"type":"request"} +Finding references to /user/username/projects/myproject/src/main.ts position 50 in project /user/username/projects/myproject/tsconfig-src.json FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/target/src/helpers/functions.d.ts 500 undefined WatchType: Closed Script info FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/target/src/helpers/functions.d.ts.map 500 undefined WatchType: Closed Script info response:{"response":{"refs":[{"file":"/user/username/projects/myproject/src/main.ts","start":{"line":1,"offset":10},"end":{"line":1,"offset":13},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":41},"lineText":"import { foo } from 'helpers/functions';","isWriteAccess":true,"isDefinition":false},{"file":"/user/username/projects/myproject/src/main.ts","start":{"line":2,"offset":10},"end":{"line":2,"offset":13},"contextStart":{"line":2,"offset":1},"contextEnd":{"line":2,"offset":16},"lineText":"export { foo };","isWriteAccess":true,"isDefinition":true},{"file":"/user/username/projects/myproject/src/helpers/functions.ts","start":{"line":1,"offset":14},"end":{"line":1,"offset":17},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":22},"lineText":"export const foo = 1;","isWriteAccess":true,"isDefinition":false}],"symbolName":"foo","symbolStartOffset":10,"symbolDisplayString":"(alias) const foo: 1\nexport foo"},"responseRequired":true} @@ -609,6 +610,7 @@ Open files: FileName: /user/username/projects/myproject/indirect3/main.ts ProjectRootPath: undefined Projects: /user/username/projects/myproject/indirect3/tsconfig.json request:{"command":"references","arguments":{"file":"/user/username/projects/myproject/indirect3/main.ts","line":1,"offset":10},"seq":3,"type":"request"} +Finding references to /user/username/projects/myproject/indirect3/main.ts position 9 in project /user/username/projects/myproject/indirect3/tsconfig.json FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/target/src/main.d.ts.map 500 undefined WatchType: Closed Script info FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/src/main.ts 500 undefined WatchType: Closed Script info Search path: /user/username/projects/myproject/src @@ -686,4 +688,5 @@ Search path: /user/username/projects/myproject/src/helpers For info: /user/username/projects/myproject/src/helpers/functions.ts :: Config file name: /user/username/projects/myproject/tsconfig.json Search path: /user/username/projects/myproject/src/helpers For info: /user/username/projects/myproject/src/helpers/functions.ts :: Config file name: /user/username/projects/myproject/tsconfig.json +Finding references to /user/username/projects/myproject/src/main.ts position 9 in project /user/username/projects/myproject/tsconfig-src.json response:{"response":{"refs":[{"file":"/user/username/projects/myproject/indirect3/main.ts","start":{"line":1,"offset":10},"end":{"line":1,"offset":13},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":28},"lineText":"import { foo } from 'main';","isWriteAccess":true,"isDefinition":true},{"file":"/user/username/projects/myproject/indirect3/main.ts","start":{"line":2,"offset":1},"end":{"line":2,"offset":4},"lineText":"foo;","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/src/main.ts","start":{"line":1,"offset":10},"end":{"line":1,"offset":13},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":41},"lineText":"import { foo } from 'helpers/functions';","isWriteAccess":true,"isDefinition":true},{"file":"/user/username/projects/myproject/src/main.ts","start":{"line":2,"offset":10},"end":{"line":2,"offset":13},"contextStart":{"line":2,"offset":1},"contextEnd":{"line":2,"offset":16},"lineText":"export { foo };","isWriteAccess":true,"isDefinition":false},{"file":"/user/username/projects/myproject/src/helpers/functions.ts","start":{"line":1,"offset":14},"end":{"line":1,"offset":17},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":22},"lineText":"export const foo = 1;","isWriteAccess":true,"isDefinition":false}],"symbolName":"foo","symbolStartOffset":10,"symbolDisplayString":"(alias) const foo: 1\nimport foo"},"responseRequired":true} \ No newline at end of file diff --git a/tests/baselines/reference/tsserver/projectReferences/project-is-indirectly-referenced-by-solution.js b/tests/baselines/reference/tsserver/projectReferences/project-is-indirectly-referenced-by-solution.js index 782a1e2f164b0..adae146583b71 100644 --- a/tests/baselines/reference/tsserver/projectReferences/project-is-indirectly-referenced-by-solution.js +++ b/tests/baselines/reference/tsserver/projectReferences/project-is-indirectly-referenced-by-solution.js @@ -588,6 +588,7 @@ Open files: FileName: /dummy/dummy.ts ProjectRootPath: undefined Projects: /dev/null/inferredProject1* request:{"command":"references","arguments":{"file":"/user/username/projects/myproject/src/main.ts","line":2,"offset":10},"seq":2,"type":"request"} +Finding references to /user/username/projects/myproject/src/main.ts position 50 in project /user/username/projects/myproject/tsconfig-src.json Creating configuration project /user/username/projects/myproject/tsconfig-indirect1.json event: {"seq":0,"type":"event","event":"projectLoadingStart","body":{"projectName":"/user/username/projects/myproject/tsconfig-indirect1.json","reason":"Creating project referenced by : /user/username/projects/myproject/tsconfig.json as it references project /user/username/projects/myproject/tsconfig-src.json"}} @@ -652,10 +653,12 @@ event: {"seq":0,"type":"event","event":"telemetry","body":{"telemetryEventName":"projectInfo","payload":{"projectId":"d9a040bddd6b85b85abd507a988a4b809b1515b5e61257ea3f8263da59589565","fileStats":{"js":0,"jsSize":0,"jsx":0,"jsxSize":0,"ts":3,"tsSize":134,"tsx":0,"tsxSize":0,"dts":1,"dtsSize":334,"deferred":0,"deferredSize":0},"compilerOptions":{"composite":true,"outDir":"","baseUrl":""},"typeAcquisition":{"enable":false,"include":false,"exclude":false},"extends":false,"files":true,"include":false,"exclude":false,"compileOnSave":false,"configFileName":"other","projectType":"configured","languageServiceEnabled":true,"version":"FakeVersion"}}} FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/target/src/helpers/functions.d.ts 500 undefined WatchType: Closed Script info FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/target/src/helpers/functions.d.ts.map 500 undefined WatchType: Closed Script info +Finding references to /user/username/projects/myproject/src/helpers/functions.ts position 13 in project /user/username/projects/myproject/tsconfig-indirect1.json Search path: /user/username/projects/myproject/src/helpers For info: /user/username/projects/myproject/src/helpers/functions.ts :: Config file name: /user/username/projects/myproject/tsconfig.json Search path: /user/username/projects/myproject/src For info: /user/username/projects/myproject/src/main.ts :: Config file name: /user/username/projects/myproject/tsconfig.json +Finding references to /user/username/projects/myproject/src/helpers/functions.ts position 13 in project /user/username/projects/myproject/tsconfig-indirect2.json Search path: /user/username/projects/myproject/src/helpers For info: /user/username/projects/myproject/src/helpers/functions.ts :: Config file name: /user/username/projects/myproject/tsconfig.json Search path: /user/username/projects/myproject/src @@ -861,6 +864,7 @@ Open files: FileName: /user/username/projects/myproject/indirect3/main.ts ProjectRootPath: undefined Projects: /user/username/projects/myproject/indirect3/tsconfig.json request:{"command":"references","arguments":{"file":"/user/username/projects/myproject/indirect3/main.ts","line":1,"offset":10},"seq":3,"type":"request"} +Finding references to /user/username/projects/myproject/indirect3/main.ts position 9 in project /user/username/projects/myproject/indirect3/tsconfig.json FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/target/src/main.d.ts.map 500 undefined WatchType: Closed Script info FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/src/main.ts 500 undefined WatchType: Closed Script info Search path: /user/username/projects/myproject/src @@ -1036,6 +1040,7 @@ Project '/user/username/projects/myproject/tsconfig-indirect2.json' (Configured) ----------------------------------------------- event: {"seq":0,"type":"event","event":"projectLoadingFinish","body":{"projectName":"/user/username/projects/myproject/tsconfig-indirect2.json"}} +Finding references to /user/username/projects/myproject/src/helpers/functions.ts position 13 in project /user/username/projects/myproject/tsconfig-indirect1.json Search path: /user/username/projects/myproject/src/helpers For info: /user/username/projects/myproject/src/helpers/functions.ts :: Config file name: /user/username/projects/myproject/tsconfig.json Search path: /user/username/projects/myproject/src/helpers @@ -1046,8 +1051,10 @@ Search path: /user/username/projects/myproject/src For info: /user/username/projects/myproject/src/main.ts :: Config file name: /user/username/projects/myproject/tsconfig.json Search path: /user/username/projects/myproject/src For info: /user/username/projects/myproject/src/main.ts :: Config file name: /user/username/projects/myproject/tsconfig.json +Finding references to /user/username/projects/myproject/src/helpers/functions.ts position 13 in project /user/username/projects/myproject/tsconfig-indirect2.json Search path: /user/username/projects/myproject/src/helpers For info: /user/username/projects/myproject/src/helpers/functions.ts :: Config file name: /user/username/projects/myproject/tsconfig.json Search path: /user/username/projects/myproject/src For info: /user/username/projects/myproject/src/main.ts :: Config file name: /user/username/projects/myproject/tsconfig.json +Finding references to /user/username/projects/myproject/src/main.ts position 9 in project /user/username/projects/myproject/tsconfig-src.json response:{"response":{"refs":[{"file":"/user/username/projects/myproject/indirect3/main.ts","start":{"line":1,"offset":10},"end":{"line":1,"offset":13},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":28},"lineText":"import { foo } from 'main';","isWriteAccess":true,"isDefinition":true},{"file":"/user/username/projects/myproject/indirect3/main.ts","start":{"line":2,"offset":1},"end":{"line":2,"offset":4},"lineText":"foo;","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/src/main.ts","start":{"line":1,"offset":10},"end":{"line":1,"offset":13},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":41},"lineText":"import { foo } from 'helpers/functions';","isWriteAccess":true,"isDefinition":false},{"file":"/user/username/projects/myproject/src/main.ts","start":{"line":2,"offset":10},"end":{"line":2,"offset":13},"contextStart":{"line":2,"offset":1},"contextEnd":{"line":2,"offset":16},"lineText":"export { foo };","isWriteAccess":true,"isDefinition":false},{"file":"/user/username/projects/myproject/src/helpers/functions.ts","start":{"line":1,"offset":14},"end":{"line":1,"offset":17},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":22},"lineText":"export const foo = 1;","isWriteAccess":true,"isDefinition":true},{"file":"/user/username/projects/myproject/indirect1/main.ts","start":{"line":1,"offset":10},"end":{"line":1,"offset":13},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":28},"lineText":"import { foo } from 'main';","isWriteAccess":true,"isDefinition":false},{"file":"/user/username/projects/myproject/indirect1/main.ts","start":{"line":2,"offset":1},"end":{"line":2,"offset":4},"lineText":"foo;","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/indirect2/main.ts","start":{"line":1,"offset":10},"end":{"line":1,"offset":13},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":28},"lineText":"import { foo } from 'main';","isWriteAccess":true,"isDefinition":false},{"file":"/user/username/projects/myproject/indirect2/main.ts","start":{"line":2,"offset":1},"end":{"line":2,"offset":4},"lineText":"foo;","isWriteAccess":false,"isDefinition":false}],"symbolName":"foo","symbolStartOffset":10,"symbolDisplayString":"(alias) const foo: 1\nimport foo"},"responseRequired":true} \ No newline at end of file diff --git a/tests/baselines/reference/tsserver/projectReferences/root-file-is-file-from-referenced-project-and-using-declaration-maps.js b/tests/baselines/reference/tsserver/projectReferences/root-file-is-file-from-referenced-project-and-using-declaration-maps.js index 8958312bb4c53..1545238ea7db4 100644 --- a/tests/baselines/reference/tsserver/projectReferences/root-file-is-file-from-referenced-project-and-using-declaration-maps.js +++ b/tests/baselines/reference/tsserver/projectReferences/root-file-is-file-from-referenced-project-and-using-declaration-maps.js @@ -145,7 +145,9 @@ Open files: Projects: /user/username/projects/project/src/tsconfig.json response:{"responseRequired":false} request:{"command":"references","arguments":{"file":"/user/username/projects/project/src/common/input/keyboard.ts","line":2,"offset":17},"seq":1,"type":"request"} +Finding references to /user/username/projects/project/src/common/input/keyboard.ts position 99 in project /user/username/projects/project/src/common/tsconfig.json FileWatcher:: Added:: WatchInfo: /user/username/projects/project/out/input/keyboard.d.ts.map 500 undefined WatchType: Closed Script info +Finding references to /user/username/projects/project/out/input/keyboard.d.ts position 24 in project /user/username/projects/project/src/tsconfig.json Search path: /user/username/projects/project/src/common/input For info: /user/username/projects/project/src/common/input/keyboard.ts :: Config file name: /user/username/projects/project/src/common/tsconfig.json Search path: /user/username/projects/project/src/common/input diff --git a/tests/baselines/reference/tsserver/projectReferences/root-file-is-file-from-referenced-project.js b/tests/baselines/reference/tsserver/projectReferences/root-file-is-file-from-referenced-project.js index 2e410d663d82d..a823144beeea4 100644 --- a/tests/baselines/reference/tsserver/projectReferences/root-file-is-file-from-referenced-project.js +++ b/tests/baselines/reference/tsserver/projectReferences/root-file-is-file-from-referenced-project.js @@ -143,6 +143,8 @@ Open files: Projects: /user/username/projects/project/src/tsconfig.json response:{"responseRequired":false} request:{"command":"references","arguments":{"file":"/user/username/projects/project/src/common/input/keyboard.ts","line":2,"offset":17},"seq":1,"type":"request"} +Finding references to /user/username/projects/project/src/common/input/keyboard.ts position 99 in project /user/username/projects/project/src/common/tsconfig.json +Finding references to /user/username/projects/project/src/common/input/keyboard.ts position 99 in project /user/username/projects/project/src/tsconfig.json Search path: /user/username/projects/project/src/common/input For info: /user/username/projects/project/src/common/input/keyboard.ts :: Config file name: /user/username/projects/project/src/common/tsconfig.json Search path: /user/username/projects/project/src/common/input diff --git a/tests/baselines/reference/tsserver/projectReferences/solution-with-its-own-files-and-project-found-is-not-solution-but-references-open-file-through-project-reference.js b/tests/baselines/reference/tsserver/projectReferences/solution-with-its-own-files-and-project-found-is-not-solution-but-references-open-file-through-project-reference.js index 72396b9c0ae74..76d8a82c68601 100644 --- a/tests/baselines/reference/tsserver/projectReferences/solution-with-its-own-files-and-project-found-is-not-solution-but-references-open-file-through-project-reference.js +++ b/tests/baselines/reference/tsserver/projectReferences/solution-with-its-own-files-and-project-found-is-not-solution-but-references-open-file-through-project-reference.js @@ -533,6 +533,7 @@ Open files: FileName: /dummy/dummy.ts ProjectRootPath: undefined Projects: /dev/null/inferredProject1* request:{"command":"references","arguments":{"file":"/user/username/projects/myproject/src/main.ts","line":2,"offset":10},"seq":2,"type":"request"} +Finding references to /user/username/projects/myproject/src/main.ts position 50 in project /user/username/projects/myproject/tsconfig.json Search path: /user/username/projects/myproject/src For info: /user/username/projects/myproject/src/main.ts :: Config file name: /user/username/projects/myproject/tsconfig.json Search path: /user/username/projects/myproject/src @@ -543,8 +544,10 @@ Search path: /user/username/projects/myproject/src/helpers For info: /user/username/projects/myproject/src/helpers/functions.ts :: Config file name: /user/username/projects/myproject/tsconfig.json Search path: /user/username/projects/myproject/src/helpers For info: /user/username/projects/myproject/src/helpers/functions.ts :: Config file name: /user/username/projects/myproject/tsconfig.json +Finding references to /user/username/projects/myproject/src/main.ts position 50 in project /user/username/projects/myproject/tsconfig-src.json FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/target/src/helpers/functions.d.ts 500 undefined WatchType: Closed Script info FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/target/src/helpers/functions.d.ts.map 500 undefined WatchType: Closed Script info +Finding references to /user/username/projects/myproject/src/main.ts position 9 in project /user/username/projects/myproject/tsconfig-src.json response:{"response":{"refs":[{"file":"/user/username/projects/myproject/src/main.ts","start":{"line":1,"offset":10},"end":{"line":1,"offset":13},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":41},"lineText":"import { foo } from 'helpers/functions';","isWriteAccess":true,"isDefinition":false},{"file":"/user/username/projects/myproject/src/main.ts","start":{"line":2,"offset":10},"end":{"line":2,"offset":13},"contextStart":{"line":2,"offset":1},"contextEnd":{"line":2,"offset":16},"lineText":"export { foo };","isWriteAccess":true,"isDefinition":true},{"file":"/user/username/projects/myproject/src/helpers/functions.ts","start":{"line":1,"offset":14},"end":{"line":1,"offset":17},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":22},"lineText":"export const foo = 1;","isWriteAccess":true,"isDefinition":false},{"file":"/user/username/projects/myproject/own/main.ts","start":{"line":1,"offset":10},"end":{"line":1,"offset":13},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":28},"lineText":"import { foo } from 'main';","isWriteAccess":true,"isDefinition":false},{"file":"/user/username/projects/myproject/own/main.ts","start":{"line":2,"offset":1},"end":{"line":2,"offset":4},"lineText":"foo;","isWriteAccess":false,"isDefinition":false}],"symbolName":"foo","symbolStartOffset":10,"symbolDisplayString":"(alias) const foo: 1\nexport foo"},"responseRequired":true} FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/src/main.ts 500 undefined WatchType: Closed Script info Project '/user/username/projects/myproject/tsconfig.json' (Configured) @@ -697,6 +700,7 @@ Open files: FileName: /user/username/projects/myproject/indirect3/main.ts ProjectRootPath: undefined Projects: /user/username/projects/myproject/indirect3/tsconfig.json request:{"command":"references","arguments":{"file":"/user/username/projects/myproject/indirect3/main.ts","line":1,"offset":10},"seq":3,"type":"request"} +Finding references to /user/username/projects/myproject/indirect3/main.ts position 9 in project /user/username/projects/myproject/indirect3/tsconfig.json FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/target/src/main.d.ts.map 500 undefined WatchType: Closed Script info FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/src/main.ts 500 undefined WatchType: Closed Script info Search path: /user/username/projects/myproject/src @@ -796,6 +800,8 @@ Search path: /user/username/projects/myproject/src/helpers For info: /user/username/projects/myproject/src/helpers/functions.ts :: Config file name: /user/username/projects/myproject/tsconfig.json Search path: /user/username/projects/myproject/src/helpers For info: /user/username/projects/myproject/src/helpers/functions.ts :: Config file name: /user/username/projects/myproject/tsconfig.json +Finding references to /user/username/projects/myproject/src/main.ts position 9 in project /user/username/projects/myproject/tsconfig-src.json +Finding references to /user/username/projects/myproject/src/main.ts position 9 in project /user/username/projects/myproject/tsconfig.json Search path: /user/username/projects/myproject/src For info: /user/username/projects/myproject/src/main.ts :: Config file name: /user/username/projects/myproject/tsconfig.json Search path: /user/username/projects/myproject/src/helpers diff --git a/tests/baselines/reference/tsserver/projectReferences/solution-with-its-own-files-and-project-is-indirectly-referenced-by-solution.js b/tests/baselines/reference/tsserver/projectReferences/solution-with-its-own-files-and-project-is-indirectly-referenced-by-solution.js index af48493f64233..110de4c02a4e6 100644 --- a/tests/baselines/reference/tsserver/projectReferences/solution-with-its-own-files-and-project-is-indirectly-referenced-by-solution.js +++ b/tests/baselines/reference/tsserver/projectReferences/solution-with-its-own-files-and-project-is-indirectly-referenced-by-solution.js @@ -667,6 +667,7 @@ Open files: FileName: /dummy/dummy.ts ProjectRootPath: undefined Projects: /dev/null/inferredProject1* request:{"command":"references","arguments":{"file":"/user/username/projects/myproject/src/main.ts","line":2,"offset":10},"seq":2,"type":"request"} +Finding references to /user/username/projects/myproject/src/main.ts position 50 in project /user/username/projects/myproject/tsconfig.json Search path: /user/username/projects/myproject/src For info: /user/username/projects/myproject/src/main.ts :: Config file name: /user/username/projects/myproject/tsconfig.json Search path: /user/username/projects/myproject/src @@ -713,6 +714,8 @@ Search path: /user/username/projects/myproject/indirect1 For info: /user/username/projects/myproject/indirect1/main.ts :: Config file name: /user/username/projects/myproject/tsconfig.json Search path: /user/username/projects/myproject/indirect1 For info: /user/username/projects/myproject/indirect1/main.ts :: Config file name: /user/username/projects/myproject/tsconfig.json +Finding references to /user/username/projects/myproject/src/main.ts position 50 in project /user/username/projects/myproject/tsconfig-src.json +Finding references to /user/username/projects/myproject/src/main.ts position 50 in project /user/username/projects/myproject/tsconfig-indirect1.json Search path: /user/username/projects/myproject/src For info: /user/username/projects/myproject/src/main.ts :: Config file name: /user/username/projects/myproject/tsconfig.json Search path: /user/username/projects/myproject/src/helpers @@ -748,16 +751,19 @@ event: {"seq":0,"type":"event","event":"projectLoadingFinish","body":{"projectName":"/user/username/projects/myproject/tsconfig-indirect2.json"}} event: {"seq":0,"type":"event","event":"telemetry","body":{"telemetryEventName":"projectInfo","payload":{"projectId":"d9a040bddd6b85b85abd507a988a4b809b1515b5e61257ea3f8263da59589565","fileStats":{"js":0,"jsSize":0,"jsx":0,"jsxSize":0,"ts":3,"tsSize":134,"tsx":0,"tsxSize":0,"dts":1,"dtsSize":334,"deferred":0,"deferredSize":0},"compilerOptions":{"composite":true,"outDir":"","baseUrl":""},"typeAcquisition":{"enable":false,"include":false,"exclude":false},"extends":false,"files":true,"include":false,"exclude":false,"compileOnSave":false,"configFileName":"other","projectType":"configured","languageServiceEnabled":true,"version":"FakeVersion"}}} +Finding references to /user/username/projects/myproject/src/helpers/functions.ts position 13 in project /user/username/projects/myproject/tsconfig-indirect2.json Search path: /user/username/projects/myproject/src/helpers For info: /user/username/projects/myproject/src/helpers/functions.ts :: Config file name: /user/username/projects/myproject/tsconfig.json Search path: /user/username/projects/myproject/src For info: /user/username/projects/myproject/src/main.ts :: Config file name: /user/username/projects/myproject/tsconfig.json FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/target/src/helpers/functions.d.ts 500 undefined WatchType: Closed Script info FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/target/src/helpers/functions.d.ts.map 500 undefined WatchType: Closed Script info +Finding references to /user/username/projects/myproject/indirect1/main.ts position 9 in project /user/username/projects/myproject/tsconfig-indirect1.json Search path: /user/username/projects/myproject/src For info: /user/username/projects/myproject/src/main.ts :: Config file name: /user/username/projects/myproject/tsconfig.json Search path: /user/username/projects/myproject/src/helpers For info: /user/username/projects/myproject/src/helpers/functions.ts :: Config file name: /user/username/projects/myproject/tsconfig.json +Finding references to /user/username/projects/myproject/src/main.ts position 9 in project /user/username/projects/myproject/tsconfig-src.json response:{"response":{"refs":[{"file":"/user/username/projects/myproject/src/main.ts","start":{"line":1,"offset":10},"end":{"line":1,"offset":13},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":41},"lineText":"import { foo } from 'helpers/functions';","isWriteAccess":true,"isDefinition":false},{"file":"/user/username/projects/myproject/src/main.ts","start":{"line":2,"offset":10},"end":{"line":2,"offset":13},"contextStart":{"line":2,"offset":1},"contextEnd":{"line":2,"offset":16},"lineText":"export { foo };","isWriteAccess":true,"isDefinition":true},{"file":"/user/username/projects/myproject/src/helpers/functions.ts","start":{"line":1,"offset":14},"end":{"line":1,"offset":17},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":22},"lineText":"export const foo = 1;","isWriteAccess":true,"isDefinition":false},{"file":"/user/username/projects/myproject/indirect1/main.ts","start":{"line":1,"offset":10},"end":{"line":1,"offset":13},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":28},"lineText":"import { foo } from 'main';","isWriteAccess":true,"isDefinition":false},{"file":"/user/username/projects/myproject/indirect1/main.ts","start":{"line":2,"offset":1},"end":{"line":2,"offset":4},"lineText":"foo;","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/myproject/indirect2/main.ts","start":{"line":1,"offset":10},"end":{"line":1,"offset":13},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":28},"lineText":"import { foo } from 'main';","isWriteAccess":true,"isDefinition":false},{"file":"/user/username/projects/myproject/indirect2/main.ts","start":{"line":2,"offset":1},"end":{"line":2,"offset":4},"lineText":"foo;","isWriteAccess":false,"isDefinition":false}],"symbolName":"foo","symbolStartOffset":10,"symbolDisplayString":"(alias) const foo: 1\nexport foo"},"responseRequired":true} FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/src/main.ts 500 undefined WatchType: Closed Script info Project '/user/username/projects/myproject/tsconfig.json' (Configured) @@ -975,6 +981,7 @@ Open files: FileName: /user/username/projects/myproject/indirect3/main.ts ProjectRootPath: undefined Projects: /user/username/projects/myproject/indirect3/tsconfig.json request:{"command":"references","arguments":{"file":"/user/username/projects/myproject/indirect3/main.ts","line":1,"offset":10},"seq":3,"type":"request"} +Finding references to /user/username/projects/myproject/indirect3/main.ts position 9 in project /user/username/projects/myproject/indirect3/tsconfig.json FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/target/src/main.d.ts.map 500 undefined WatchType: Closed Script info FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/src/main.ts 500 undefined WatchType: Closed Script info Search path: /user/username/projects/myproject/src @@ -1175,6 +1182,7 @@ Project '/user/username/projects/myproject/tsconfig-indirect2.json' (Configured) ----------------------------------------------- event: {"seq":0,"type":"event","event":"projectLoadingFinish","body":{"projectName":"/user/username/projects/myproject/tsconfig-indirect2.json"}} +Finding references to /user/username/projects/myproject/src/helpers/functions.ts position 13 in project /user/username/projects/myproject/tsconfig-indirect1.json Search path: /user/username/projects/myproject/src/helpers For info: /user/username/projects/myproject/src/helpers/functions.ts :: Config file name: /user/username/projects/myproject/tsconfig.json Search path: /user/username/projects/myproject/src/helpers @@ -1185,10 +1193,13 @@ Search path: /user/username/projects/myproject/src For info: /user/username/projects/myproject/src/main.ts :: Config file name: /user/username/projects/myproject/tsconfig.json Search path: /user/username/projects/myproject/src For info: /user/username/projects/myproject/src/main.ts :: Config file name: /user/username/projects/myproject/tsconfig.json +Finding references to /user/username/projects/myproject/src/helpers/functions.ts position 13 in project /user/username/projects/myproject/tsconfig-indirect2.json Search path: /user/username/projects/myproject/src/helpers For info: /user/username/projects/myproject/src/helpers/functions.ts :: Config file name: /user/username/projects/myproject/tsconfig.json Search path: /user/username/projects/myproject/src For info: /user/username/projects/myproject/src/main.ts :: Config file name: /user/username/projects/myproject/tsconfig.json +Finding references to /user/username/projects/myproject/src/main.ts position 9 in project /user/username/projects/myproject/tsconfig-src.json +Finding references to /user/username/projects/myproject/src/main.ts position 9 in project /user/username/projects/myproject/tsconfig.json Search path: /user/username/projects/myproject/src For info: /user/username/projects/myproject/src/main.ts :: Config file name: /user/username/projects/myproject/tsconfig.json Search path: /user/username/projects/myproject/src/helpers diff --git a/tests/baselines/reference/tsserver/projectReferences/special-handling-of-localness-when-using-arrow-function-as-object-literal-property-types.js b/tests/baselines/reference/tsserver/projectReferences/special-handling-of-localness-when-using-arrow-function-as-object-literal-property-types.js index 05dbc65c8940c..72b5274aa9794 100644 --- a/tests/baselines/reference/tsserver/projectReferences/special-handling-of-localness-when-using-arrow-function-as-object-literal-property-types.js +++ b/tests/baselines/reference/tsserver/projectReferences/special-handling-of-localness-when-using-arrow-function-as-object-literal-property-types.js @@ -82,6 +82,7 @@ Open files: Projects: /user/username/projects/solution/api/tsconfig.json response:{"responseRequired":false} request:{"command":"references","arguments":{"file":"/user/username/projects/solution/api/src/server.ts","line":2,"offset":12},"seq":1,"type":"request"} +Finding references to /user/username/projects/solution/api/src/server.ts position 56 in project /user/username/projects/solution/api/tsconfig.json Search path: /user/username/projects/solution/shared/src For info: /user/username/projects/solution/shared/src/index.ts :: Config file name: /user/username/projects/solution/shared/tsconfig.json Creating configuration project /user/username/projects/solution/shared/tsconfig.json @@ -175,6 +176,8 @@ Project '/user/username/projects/solution/app/tsconfig.json' (Configured) Matched by include pattern 'src' in 'tsconfig.json' ----------------------------------------------- +Finding references to /user/username/projects/solution/shared/src/index.ts position 21 in project /user/username/projects/solution/app/tsconfig.json Search path: /user/username/projects/solution/shared/src For info: /user/username/projects/solution/shared/src/index.ts :: Config file name: /user/username/projects/solution/shared/tsconfig.json +Finding references to /user/username/projects/solution/shared/src/index.ts position 21 in project /user/username/projects/solution/shared/tsconfig.json response:{"response":{"refs":[{"file":"/user/username/projects/solution/shared/src/index.ts","start":{"line":1,"offset":22},"end":{"line":1,"offset":25},"contextStart":{"line":1,"offset":22},"contextEnd":{"line":1,"offset":36},"lineText":"export const foo = { bar: () => { } };","isWriteAccess":true,"isDefinition":true},{"file":"/user/username/projects/solution/api/src/server.ts","start":{"line":2,"offset":12},"end":{"line":2,"offset":15},"lineText":"shared.foo.bar();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/solution/app/src/app.ts","start":{"line":2,"offset":12},"end":{"line":2,"offset":15},"lineText":"shared.foo.bar();","isWriteAccess":false,"isDefinition":false}],"symbolName":"bar","symbolStartOffset":12,"symbolDisplayString":"(property) bar: () => void"},"responseRequired":true} \ No newline at end of file diff --git a/tests/baselines/reference/tsserver/projectReferences/special-handling-of-localness-when-using-arrow-function-as-object-literal-property.js b/tests/baselines/reference/tsserver/projectReferences/special-handling-of-localness-when-using-arrow-function-as-object-literal-property.js index 002fd13a1027c..aa805ac65825d 100644 --- a/tests/baselines/reference/tsserver/projectReferences/special-handling-of-localness-when-using-arrow-function-as-object-literal-property.js +++ b/tests/baselines/reference/tsserver/projectReferences/special-handling-of-localness-when-using-arrow-function-as-object-literal-property.js @@ -82,6 +82,7 @@ Open files: Projects: /user/username/projects/solution/api/tsconfig.json response:{"responseRequired":false} request:{"command":"references","arguments":{"file":"/user/username/projects/solution/api/src/server.ts","line":2,"offset":12},"seq":1,"type":"request"} +Finding references to /user/username/projects/solution/api/src/server.ts position 56 in project /user/username/projects/solution/api/tsconfig.json Search path: /user/username/projects/solution/shared/src For info: /user/username/projects/solution/shared/src/index.ts :: Config file name: /user/username/projects/solution/shared/tsconfig.json Creating configuration project /user/username/projects/solution/shared/tsconfig.json @@ -106,4 +107,5 @@ Project '/user/username/projects/solution/shared/tsconfig.json' (Configured) ----------------------------------------------- Search path: /user/username/projects/solution/shared/src For info: /user/username/projects/solution/shared/src/index.ts :: Config file name: /user/username/projects/solution/shared/tsconfig.json +Finding references to /user/username/projects/solution/shared/src/index.ts position 16 in project /user/username/projects/solution/shared/tsconfig.json response:{"response":{"refs":[{"file":"/user/username/projects/solution/shared/src/index.ts","start":{"line":1,"offset":17},"end":{"line":1,"offset":20},"contextStart":{"line":1,"offset":17},"contextEnd":{"line":1,"offset":31},"lineText":"const local = { bar: () => { } };","isWriteAccess":true,"isDefinition":true},{"file":"/user/username/projects/solution/api/src/server.ts","start":{"line":2,"offset":12},"end":{"line":2,"offset":15},"lineText":"shared.foo.bar();","isWriteAccess":false,"isDefinition":false}],"symbolName":"bar","symbolStartOffset":12,"symbolDisplayString":"(property) bar: () => void"},"responseRequired":true} \ No newline at end of file diff --git a/tests/baselines/reference/tsserver/projectReferences/special-handling-of-localness-when-using-arrow-function-assignment.js b/tests/baselines/reference/tsserver/projectReferences/special-handling-of-localness-when-using-arrow-function-assignment.js index 94d141350d905..7347881108e29 100644 --- a/tests/baselines/reference/tsserver/projectReferences/special-handling-of-localness-when-using-arrow-function-assignment.js +++ b/tests/baselines/reference/tsserver/projectReferences/special-handling-of-localness-when-using-arrow-function-assignment.js @@ -82,6 +82,7 @@ Open files: Projects: /user/username/projects/solution/api/tsconfig.json response:{"responseRequired":false} request:{"command":"references","arguments":{"file":"/user/username/projects/solution/api/src/server.ts","line":2,"offset":8},"seq":1,"type":"request"} +Finding references to /user/username/projects/solution/api/src/server.ts position 52 in project /user/username/projects/solution/api/tsconfig.json Search path: /user/username/projects/solution/shared/src For info: /user/username/projects/solution/shared/src/index.ts :: Config file name: /user/username/projects/solution/shared/tsconfig.json Creating configuration project /user/username/projects/solution/shared/tsconfig.json @@ -175,6 +176,8 @@ Project '/user/username/projects/solution/app/tsconfig.json' (Configured) Matched by include pattern 'src' in 'tsconfig.json' ----------------------------------------------- +Finding references to /user/username/projects/solution/shared/src/index.ts position 13 in project /user/username/projects/solution/app/tsconfig.json Search path: /user/username/projects/solution/shared/src For info: /user/username/projects/solution/shared/src/index.ts :: Config file name: /user/username/projects/solution/shared/tsconfig.json +Finding references to /user/username/projects/solution/shared/src/index.ts position 13 in project /user/username/projects/solution/shared/tsconfig.json response:{"response":{"refs":[{"file":"/user/username/projects/solution/shared/src/index.ts","start":{"line":1,"offset":14},"end":{"line":1,"offset":17},"contextStart":{"line":1,"offset":1},"contextEnd":{"line":1,"offset":30},"lineText":"export const dog = () => { };","isWriteAccess":true,"isDefinition":true},{"file":"/user/username/projects/solution/api/src/server.ts","start":{"line":2,"offset":8},"end":{"line":2,"offset":11},"lineText":"shared.dog();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/solution/app/src/app.ts","start":{"line":2,"offset":8},"end":{"line":2,"offset":11},"lineText":"shared.dog();","isWriteAccess":false,"isDefinition":false}],"symbolName":"dog","symbolStartOffset":8,"symbolDisplayString":"const dog: () => void"},"responseRequired":true} \ No newline at end of file diff --git a/tests/baselines/reference/tsserver/projectReferences/special-handling-of-localness-when-using-method-of-class-expression.js b/tests/baselines/reference/tsserver/projectReferences/special-handling-of-localness-when-using-method-of-class-expression.js index 90ba1f57746a1..669405b2a4b13 100644 --- a/tests/baselines/reference/tsserver/projectReferences/special-handling-of-localness-when-using-method-of-class-expression.js +++ b/tests/baselines/reference/tsserver/projectReferences/special-handling-of-localness-when-using-method-of-class-expression.js @@ -82,6 +82,7 @@ Open files: Projects: /user/username/projects/solution/api/tsconfig.json response:{"responseRequired":false} request:{"command":"references","arguments":{"file":"/user/username/projects/solution/api/src/server.ts","line":3,"offset":10},"seq":1,"type":"request"} +Finding references to /user/username/projects/solution/api/src/server.ts position 89 in project /user/username/projects/solution/api/tsconfig.json Search path: /user/username/projects/solution/shared/src For info: /user/username/projects/solution/shared/src/index.ts :: Config file name: /user/username/projects/solution/shared/tsconfig.json Creating configuration project /user/username/projects/solution/shared/tsconfig.json @@ -175,6 +176,8 @@ Project '/user/username/projects/solution/app/tsconfig.json' (Configured) Matched by include pattern 'src' in 'tsconfig.json' ----------------------------------------------- +Finding references to /user/username/projects/solution/shared/src/index.ts position 27 in project /user/username/projects/solution/app/tsconfig.json Search path: /user/username/projects/solution/shared/src For info: /user/username/projects/solution/shared/src/index.ts :: Config file name: /user/username/projects/solution/shared/tsconfig.json +Finding references to /user/username/projects/solution/shared/src/index.ts position 27 in project /user/username/projects/solution/shared/tsconfig.json response:{"response":{"refs":[{"file":"/user/username/projects/solution/shared/src/index.ts","start":{"line":1,"offset":28},"end":{"line":1,"offset":31},"contextStart":{"line":1,"offset":28},"contextEnd":{"line":1,"offset":36},"lineText":"export const foo = class { fly() {} };","isWriteAccess":true,"isDefinition":true},{"file":"/user/username/projects/solution/api/src/server.ts","start":{"line":3,"offset":10},"end":{"line":3,"offset":13},"lineText":"instance.fly();","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/solution/app/src/app.ts","start":{"line":3,"offset":10},"end":{"line":3,"offset":13},"lineText":"instance.fly();","isWriteAccess":false,"isDefinition":false}],"symbolName":"fly","symbolStartOffset":10,"symbolDisplayString":"(method) foo.fly(): void"},"responseRequired":true} \ No newline at end of file diff --git a/tests/baselines/reference/tsserver/projectReferences/special-handling-of-localness-when-using-object-literal-property.js b/tests/baselines/reference/tsserver/projectReferences/special-handling-of-localness-when-using-object-literal-property.js index 08dfbe0bb76f3..0624f537c6ccb 100644 --- a/tests/baselines/reference/tsserver/projectReferences/special-handling-of-localness-when-using-object-literal-property.js +++ b/tests/baselines/reference/tsserver/projectReferences/special-handling-of-localness-when-using-object-literal-property.js @@ -82,6 +82,7 @@ Open files: Projects: /user/username/projects/solution/api/tsconfig.json response:{"responseRequired":false} request:{"command":"references","arguments":{"file":"/user/username/projects/solution/api/src/server.ts","line":2,"offset":12},"seq":1,"type":"request"} +Finding references to /user/username/projects/solution/api/src/server.ts position 56 in project /user/username/projects/solution/api/tsconfig.json Search path: /user/username/projects/solution/shared/src For info: /user/username/projects/solution/shared/src/index.ts :: Config file name: /user/username/projects/solution/shared/tsconfig.json Creating configuration project /user/username/projects/solution/shared/tsconfig.json @@ -175,6 +176,8 @@ Project '/user/username/projects/solution/app/tsconfig.json' (Configured) Matched by include pattern 'src' in 'tsconfig.json' ----------------------------------------------- +Finding references to /user/username/projects/solution/shared/src/index.ts position 22 in project /user/username/projects/solution/app/tsconfig.json Search path: /user/username/projects/solution/shared/src For info: /user/username/projects/solution/shared/src/index.ts :: Config file name: /user/username/projects/solution/shared/tsconfig.json +Finding references to /user/username/projects/solution/shared/src/index.ts position 22 in project /user/username/projects/solution/shared/tsconfig.json response:{"response":{"refs":[{"file":"/user/username/projects/solution/shared/src/index.ts","start":{"line":1,"offset":23},"end":{"line":1,"offset":26},"contextStart":{"line":1,"offset":23},"contextEnd":{"line":1,"offset":33},"lineText":"export const foo = { baz: \"BAZ\" };","isWriteAccess":true,"isDefinition":true},{"file":"/user/username/projects/solution/api/src/server.ts","start":{"line":2,"offset":12},"end":{"line":2,"offset":15},"lineText":"shared.foo.baz;","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/solution/app/src/app.ts","start":{"line":2,"offset":12},"end":{"line":2,"offset":15},"lineText":"shared.foo.baz;","isWriteAccess":false,"isDefinition":false}],"symbolName":"baz","symbolStartOffset":12,"symbolDisplayString":"(property) baz: string"},"responseRequired":true} \ No newline at end of file diff --git a/tests/baselines/reference/tsserver/projectReferences/when-files-from-two-projects-are-open-and-one-project-references.js b/tests/baselines/reference/tsserver/projectReferences/when-files-from-two-projects-are-open-and-one-project-references.js index f4b045872292a..6697be444c356 100644 --- a/tests/baselines/reference/tsserver/projectReferences/when-files-from-two-projects-are-open-and-one-project-references.js +++ b/tests/baselines/reference/tsserver/projectReferences/when-files-from-two-projects-are-open-and-one-project-references.js @@ -297,6 +297,7 @@ Open files: Projects: /user/username/projects/myproject/core/tsconfig.json response:{"responseRequired":false} request:{"command":"references","arguments":{"file":"/user/username/projects/myproject/core/src/file1.ts","line":1,"offset":14},"seq":1,"type":"request"} +Finding references to /user/username/projects/myproject/core/src/file1.ts position 13 in project /user/username/projects/myproject/core/tsconfig.json Creating configuration project /user/username/projects/myproject/indirect/tsconfig.json Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/indirect/src/file1.ts 500 undefined WatchType: Closed Script info diff --git a/tests/baselines/reference/tsserver/projectReferences/with-disableSolutionSearching-solution-and-siblings-are-not-loaded.js b/tests/baselines/reference/tsserver/projectReferences/with-disableSolutionSearching-solution-and-siblings-are-not-loaded.js index 8f78c6271a438..1caa7cf0e0256 100644 --- a/tests/baselines/reference/tsserver/projectReferences/with-disableSolutionSearching-solution-and-siblings-are-not-loaded.js +++ b/tests/baselines/reference/tsserver/projectReferences/with-disableSolutionSearching-solution-and-siblings-are-not-loaded.js @@ -49,4 +49,5 @@ Open files: Projects: /user/username/projects/solution/compiler/tsconfig.json response:{"responseRequired":false} request:{"command":"references","arguments":{"file":"/user/username/projects/solution/compiler/program.ts","line":4,"offset":25},"seq":1,"type":"request"} +Finding references to /user/username/projects/solution/compiler/program.ts position 110 in project /user/username/projects/solution/compiler/tsconfig.json response:{"response":{"refs":[{"file":"/user/username/projects/solution/compiler/types.ts","start":{"line":4,"offset":25},"end":{"line":4,"offset":39},"contextStart":{"line":4,"offset":25},"contextEnd":{"line":4,"offset":52},"lineText":" getSourceFiles(): string[];","isWriteAccess":false,"isDefinition":false},{"file":"/user/username/projects/solution/compiler/program.ts","start":{"line":4,"offset":25},"end":{"line":4,"offset":39},"contextStart":{"line":4,"offset":25},"contextEnd":{"line":4,"offset":64},"lineText":" getSourceFiles: () => [getSourceFile()]","isWriteAccess":true,"isDefinition":true}],"symbolName":"getSourceFiles","symbolStartOffset":25,"symbolDisplayString":"(method) ts.Program.getSourceFiles(): string[]"},"responseRequired":true} \ No newline at end of file From c216b2db5b7e469c6851c48241fa444e2bf58c00 Mon Sep 17 00:00:00 2001 From: Andrew Casey Date: Mon, 7 Feb 2022 16:10:38 -0800 Subject: [PATCH 22/55] Trace document registry operations (#47785) ...to help detect misconfigurations like #47687. --- src/services/documentRegistry.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/services/documentRegistry.ts b/src/services/documentRegistry.ts index 719f219025929..ff440a84543a3 100644 --- a/src/services/documentRegistry.ts +++ b/src/services/documentRegistry.ts @@ -202,7 +202,27 @@ namespace ts { scriptKind?: ScriptKind): SourceFile { scriptKind = ensureScriptKind(fileName, scriptKind); const scriptTarget = scriptKind === ScriptKind.JSON ? ScriptTarget.JSON : getEmitScriptTarget(compilationSettings); + + const oldBucketCount = buckets.size; const bucket = getOrUpdate(buckets, key, () => new Map()); + if (tracing) { + if (buckets.size > oldBucketCount) { + // It is interesting, but not definitively problematic if a build requires multiple document registry buckets - + // perhaps they are for two projects that don't have any overlap. + // Bonus: these events can help us interpret the more interesting event below. + tracing.instant(tracing.Phase.Session, "createdDocumentRegistryBucket", { configFilePath: compilationSettings.configFilePath, key }); + } + + // It is fairly suspicious to have one path in two buckets - you'd expect dependencies to have similar configurations. + // If this occurs unexpectedly, the fix is likely to synchronize the project settings. + // Skip .d.ts files to reduce noise (should also cover most of node_modules). + const otherBucketKey = !fileExtensionIs(path, Extension.Dts) && + forEachEntry(buckets, (bucket, bucketKey) => bucketKey !== key && bucket.has(path) && bucketKey); + if (otherBucketKey) { + tracing.instant(tracing.Phase.Session, "documentRegistryBucketOverlap", { path, key1: otherBucketKey, key2: key }); + } + } + const bucketEntry = bucket.get(path); let entry = bucketEntry && getDocumentRegistryEntry(bucketEntry, scriptKind); if (!entry && externalCache) { From 5b53e4ec28daf1f2404c81ae8e59f7e2457672a1 Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Tue, 8 Feb 2022 06:08:53 +0000 Subject: [PATCH 23/55] Update package-lock.json --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 739daaa36cd76..50bfff2c4109f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -676,9 +676,9 @@ "dev": true }, "@types/node": { - "version": "17.0.15", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.15.tgz", - "integrity": "sha512-zWt4SDDv1S9WRBNxLFxFRHxdD9tvH8f5/kg5/IaLFdnSNXsDY4eL3Q3XXN+VxUnWIhyVFDwcsmAprvwXoM/ClA==", + "version": "17.0.16", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.16.tgz", + "integrity": "sha512-ydLaGVfQOQ6hI1xK2A5nVh8bl0OGoIfYMxPWHqqYe9bTkWCfqiVvZoh2I/QF2sNSkZzZyROBoTefIEI+PB6iIA==", "dev": true }, "@types/node-fetch": { From 460908a4788165d245918d8d6b2a60877f26c39f Mon Sep 17 00:00:00 2001 From: csigs Date: Tue, 8 Feb 2022 03:23:26 -0800 Subject: [PATCH 24/55] LEGO: Merge pull request 47801 LEGO: Merge pull request 47801 --- .../diagnosticMessages.generated.json.lcl | 27 +++++++------------ .../diagnosticMessages.generated.json.lcl | 27 +++++++------------ .../diagnosticMessages.generated.json.lcl | 27 +++++++------------ .../diagnosticMessages.generated.json.lcl | 27 +++++++------------ .../diagnosticMessages.generated.json.lcl | 27 +++++++------------ .../diagnosticMessages.generated.json.lcl | 27 +++++++------------ .../diagnosticMessages.generated.json.lcl | 27 +++++++------------ .../diagnosticMessages.generated.json.lcl | 27 +++++++------------ .../diagnosticMessages.generated.json.lcl | 27 +++++++------------ .../diagnosticMessages.generated.json.lcl | 27 +++++++------------ 10 files changed, 90 insertions(+), 180 deletions(-) diff --git a/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl index da25824a7e47c..f8ad23580d758 100644 --- a/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -4041,6 +4041,15 @@ + + + + + + + + + @@ -10296,15 +10305,6 @@ - - - - - - - - - @@ -12192,15 +12192,6 @@ - - - - - - - - - diff --git a/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl index 6598b9dd06428..e34bdf388f652 100644 --- a/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -4050,6 +4050,15 @@ + + + + + + + + + @@ -10305,15 +10314,6 @@ - - - - - - - - - @@ -12201,15 +12201,6 @@ - - - - - - - - - diff --git a/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl index 0172c53119c9d..b33673e7ba9b7 100644 --- a/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -4053,6 +4053,15 @@ + + + + + + + + + @@ -10308,15 +10317,6 @@ - - - - - - - - - @@ -12204,15 +12204,6 @@ - - - - - - - - - diff --git a/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl index 9bfb659c5c5d4..2d3c5ccc8a156 100644 --- a/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -4053,6 +4053,15 @@ + + + + + + + + + @@ -10308,15 +10317,6 @@ - - - - - - - - - @@ -12204,15 +12204,6 @@ - - - - - - - - - diff --git a/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl index 05c217faa2b62..a6bba2fa1a990 100644 --- a/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -4041,6 +4041,15 @@ + + + + + + + + + @@ -10296,15 +10305,6 @@ - - - - - - - - - @@ -12192,15 +12192,6 @@ - - - - - - - - - diff --git a/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl index b260d613dd6d9..9acc744c145ee 100644 --- a/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -4041,6 +4041,15 @@ + + + + + + + + + @@ -10296,15 +10305,6 @@ - - - - - - - - - @@ -12192,15 +12192,6 @@ - - - - - - - - - diff --git a/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl index f77557e658c0f..b869efa17de70 100644 --- a/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -4041,6 +4041,15 @@ + + + + + + + + + @@ -10296,15 +10305,6 @@ - - - - - - - - - @@ -12192,15 +12192,6 @@ - - - - - - - - - diff --git a/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl index 40fa5fe21d3c9..896867bd6ce74 100644 --- a/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -4031,6 +4031,15 @@ + + + + + + + + + @@ -10283,15 +10292,6 @@ - - - - - - - - - @@ -12179,15 +12179,6 @@ - - - - - - - - - diff --git a/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl index 419a50339bc0a..f1b725a6ad337 100644 --- a/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -4034,6 +4034,15 @@ + + + + + + + + + @@ -10286,15 +10295,6 @@ - - - - - - - - - @@ -12182,15 +12182,6 @@ - - - - - - - - - diff --git a/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl index 63ac4ef5b77b9..888c916e24bd8 100644 --- a/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -4034,6 +4034,15 @@ + + + + + + + + + @@ -10289,15 +10298,6 @@ - - - - - - - - - @@ -12185,15 +12185,6 @@ - - - - - - - - - From 17b97ccc434ff68218dcc38fa0a9c3c610bc03bd Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Tue, 8 Feb 2022 21:36:45 +0200 Subject: [PATCH 25/55] fix(47788): forbid convertToMappedObjectType QF in invalid index signatures (#47798) --- src/services/codefixes/convertToMappedObjectType.ts | 9 ++++++--- .../fourslash/codeFixConvertToMappedObjectType13.ts | 7 +++++++ 2 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 tests/cases/fourslash/codeFixConvertToMappedObjectType13.ts diff --git a/src/services/codefixes/convertToMappedObjectType.ts b/src/services/codefixes/convertToMappedObjectType.ts index 340fcf2257ce0..7f9f6af4e80fa 100644 --- a/src/services/codefixes/convertToMappedObjectType.ts +++ b/src/services/codefixes/convertToMappedObjectType.ts @@ -25,9 +25,12 @@ namespace ts.codefix { interface Info { readonly indexSignature: IndexSignatureDeclaration; readonly container: FixableDeclaration; } function getInfo(sourceFile: SourceFile, pos: number): Info | undefined { const token = getTokenAtPosition(sourceFile, pos); - const indexSignature = cast(token.parent.parent, isIndexSignatureDeclaration); - if (isClassDeclaration(indexSignature.parent)) return undefined; - const container = isInterfaceDeclaration(indexSignature.parent) ? indexSignature.parent : cast(indexSignature.parent.parent, isTypeAliasDeclaration); + const indexSignature = tryCast(token.parent.parent, isIndexSignatureDeclaration); + if (!indexSignature) return undefined; + + const container = isInterfaceDeclaration(indexSignature.parent) ? indexSignature.parent : tryCast(indexSignature.parent.parent, isTypeAliasDeclaration); + if (!container) return undefined; + return { indexSignature, container }; } diff --git a/tests/cases/fourslash/codeFixConvertToMappedObjectType13.ts b/tests/cases/fourslash/codeFixConvertToMappedObjectType13.ts new file mode 100644 index 0000000000000..c5655f99f58f0 --- /dev/null +++ b/tests/cases/fourslash/codeFixConvertToMappedObjectType13.ts @@ -0,0 +1,7 @@ +/// + +////let x: { +//// [p: ""]: string; +////} + +verify.not.codeFixAvailable("fixConvertToMappedObjectType"); From c5b1011e94d58cadc7a720db0ee2836350ca60be Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Tue, 8 Feb 2022 12:57:34 -0800 Subject: [PATCH 26/55] Compute writeType from set accessors for union and intersection properties (#47674) * Compute write type from set accessors for union and intersection properties * Add test for deferred writeType * Always check for writeType of symbol --- src/compiler/checker.ts | 46 +++++- src/compiler/types.ts | 1 + src/compiler/utilities.ts | 4 + .../reference/divergentAccessorsTypes3.js | 108 ++++++++++++++ .../divergentAccessorsTypes3.symbols | 116 ++++++++++++++ .../reference/divergentAccessorsTypes3.types | 141 ++++++++++++++++++ .../divergentAccessorsTypes4.errors.txt | 36 +++++ .../reference/divergentAccessorsTypes4.js | 71 +++++++++ .../divergentAccessorsTypes4.symbols | 73 +++++++++ .../reference/divergentAccessorsTypes4.types | 82 ++++++++++ .../divergentAccessorsTypes5.errors.txt | 46 ++++++ .../reference/divergentAccessorsTypes5.js | 93 ++++++++++++ .../divergentAccessorsTypes5.symbols | 83 +++++++++++ .../reference/divergentAccessorsTypes5.types | 93 ++++++++++++ .../compiler/divergentAccessorsTypes3.ts | 44 ++++++ .../compiler/divergentAccessorsTypes4.ts | 31 ++++ .../compiler/divergentAccessorsTypes5.ts | 38 +++++ 17 files changed, 1105 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/divergentAccessorsTypes3.js create mode 100644 tests/baselines/reference/divergentAccessorsTypes3.symbols create mode 100644 tests/baselines/reference/divergentAccessorsTypes3.types create mode 100644 tests/baselines/reference/divergentAccessorsTypes4.errors.txt create mode 100644 tests/baselines/reference/divergentAccessorsTypes4.js create mode 100644 tests/baselines/reference/divergentAccessorsTypes4.symbols create mode 100644 tests/baselines/reference/divergentAccessorsTypes4.types create mode 100644 tests/baselines/reference/divergentAccessorsTypes5.errors.txt create mode 100644 tests/baselines/reference/divergentAccessorsTypes5.js create mode 100644 tests/baselines/reference/divergentAccessorsTypes5.symbols create mode 100644 tests/baselines/reference/divergentAccessorsTypes5.types create mode 100644 tests/cases/compiler/divergentAccessorsTypes3.ts create mode 100644 tests/cases/compiler/divergentAccessorsTypes4.ts create mode 100644 tests/cases/compiler/divergentAccessorsTypes5.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ecac36fafdc29..2201a3aa30264 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -9696,6 +9696,41 @@ namespace ts { return links.type; } + function getWriteTypeOfSymbolWithDeferredType(symbol: Symbol): Type | undefined { + const links = getSymbolLinks(symbol); + if (!links.writeType && links.deferralWriteConstituents) { + Debug.assertIsDefined(links.deferralParent); + Debug.assertIsDefined(links.deferralConstituents); + links.writeType = links.deferralParent.flags & TypeFlags.Union ? getUnionType(links.deferralWriteConstituents) : getIntersectionType(links.deferralWriteConstituents); + } + return links.writeType; + } + + /** + * Distinct write types come only from set accessors, but union and intersection + * properties deriving from set accessors will either pre-compute or defer the + * union or intersection of the writeTypes of their constituents. To account for + * this, we will assume that any deferred type or transient symbol may have a + * `writeType` (or a deferred write type ready to be computed) that should be + * used before looking for set accessor declarations. + */ + function getWriteTypeOfSymbol(symbol: Symbol): Type { + const checkFlags = getCheckFlags(symbol); + if (checkFlags & CheckFlags.DeferredType) { + const writeType = getWriteTypeOfSymbolWithDeferredType(symbol); + if (writeType) { + return writeType; + } + } + if (symbol.flags & SymbolFlags.Transient) { + const { writeType } = symbol as TransientSymbol; + if (writeType) { + return writeType; + } + } + return getSetAccessorTypeOfSymbol(symbol); + } + function getSetAccessorTypeOfSymbol(symbol: Symbol): Type { if (symbol.flags & SymbolFlags.Accessor) { const type = getTypeOfSetAccessor(symbol); @@ -12198,6 +12233,7 @@ namespace ts { let firstType: Type | undefined; let nameType: Type | undefined; const propTypes: Type[] = []; + let writeTypes: Type[] | undefined; let firstValueDeclaration: Declaration | undefined; let hasNonUniformValueDeclaration = false; for (const prop of props) { @@ -12213,6 +12249,10 @@ namespace ts { firstType = type; nameType = getSymbolLinks(prop).nameType; } + const writeType = getWriteTypeOfSymbol(prop); + if (writeTypes || writeType !== type) { + writeTypes = append(!writeTypes ? propTypes.slice() : writeTypes, writeType); + } else if (type !== firstType) { checkFlags |= CheckFlags.HasNonUniformType; } @@ -12243,9 +12283,13 @@ namespace ts { result.checkFlags |= CheckFlags.DeferredType; result.deferralParent = containingType; result.deferralConstituents = propTypes; + result.deferralWriteConstituents = writeTypes; } else { result.type = isUnion ? getUnionType(propTypes) : getIntersectionType(propTypes); + if (writeTypes) { + result.writeType = isUnion ? getUnionType(writeTypes) : getIntersectionType(writeTypes); + } } return result; } @@ -28509,7 +28553,7 @@ namespace ts { return errorType; } - propType = isThisPropertyAccessInConstructor(node, prop) ? autoType : writing ? getSetAccessorTypeOfSymbol(prop) : getTypeOfSymbol(prop); + propType = isThisPropertyAccessInConstructor(node, prop) ? autoType : writing ? getWriteTypeOfSymbol(prop) : getTypeOfSymbol(prop); } return getFlowTypeOfAccessExpression(node, prop, propType, right, checkMode); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 8a67511208893..ab1f5d9d6600e 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -4952,6 +4952,7 @@ namespace ts { extendedContainersByFile?: ESMap; // Containers (other than the parent) which this symbol is aliased in variances?: VarianceFlags[]; // Alias symbol type argument variance cache deferralConstituents?: Type[]; // Calculated list of constituents for a deferred type + deferralWriteConstituents?: Type[]; // Constituents of a deferred `writeType` deferralParent?: Type; // Source union/intersection of a deferred type cjsExportMerged?: Symbol; // Version of the symbol with all non export= exports merged with the export= target typeOnlyDeclaration?: TypeOnlyAliasDeclaration | false; // First resolved alias declaration that makes the symbol only usable in type constructs diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index ab7d0e6375ea5..c723305b84bb1 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -20,6 +20,10 @@ namespace ts { return undefined; } + export function getDeclarationsOfKind(symbol: Symbol, kind: T["kind"]): T[] { + return filter(symbol.declarations || emptyArray, d => d.kind === kind) as T[]; + } + export function createSymbolTable(symbols?: readonly Symbol[]): SymbolTable { const result = new Map<__String, Symbol>(); if (symbols) { diff --git a/tests/baselines/reference/divergentAccessorsTypes3.js b/tests/baselines/reference/divergentAccessorsTypes3.js new file mode 100644 index 0000000000000..775474f088f2e --- /dev/null +++ b/tests/baselines/reference/divergentAccessorsTypes3.js @@ -0,0 +1,108 @@ +//// [divergentAccessorsTypes3.ts] +class One { + get prop1(): string { return ""; } + set prop1(s: string | number) { } + + get prop2(): string { return ""; } + set prop2(s: string | number) { } + + prop3: number; + + get prop4(): string { return ""; } + set prop4(s: string | number) { } +} + +class Two { + get prop1(): string { return ""; } + set prop1(s: string | number) { } + + get prop2(): string { return ""; } + set prop2(s: string) { } + + get prop3(): string { return ""; } + set prop3(s: string | boolean) { } + + get prop4(): string { return ""; } + set prop4(s: string | boolean) { } +} + +declare const u1: One|Two; + +u1.prop1 = 42; +u1.prop1 = "hello"; + +u1.prop2 = 42; +u1.prop2 = "hello"; + +u1.prop3 = 42; +u1.prop3 = "hello"; +u1.prop3 = true; + +u1.prop4 = 42; +u1.prop4 = "hello"; +u1.prop4 = true; + + +//// [divergentAccessorsTypes3.js] +var One = /** @class */ (function () { + function One() { + } + Object.defineProperty(One.prototype, "prop1", { + get: function () { return ""; }, + set: function (s) { }, + enumerable: false, + configurable: true + }); + Object.defineProperty(One.prototype, "prop2", { + get: function () { return ""; }, + set: function (s) { }, + enumerable: false, + configurable: true + }); + Object.defineProperty(One.prototype, "prop4", { + get: function () { return ""; }, + set: function (s) { }, + enumerable: false, + configurable: true + }); + return One; +}()); +var Two = /** @class */ (function () { + function Two() { + } + Object.defineProperty(Two.prototype, "prop1", { + get: function () { return ""; }, + set: function (s) { }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Two.prototype, "prop2", { + get: function () { return ""; }, + set: function (s) { }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Two.prototype, "prop3", { + get: function () { return ""; }, + set: function (s) { }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Two.prototype, "prop4", { + get: function () { return ""; }, + set: function (s) { }, + enumerable: false, + configurable: true + }); + return Two; +}()); +u1.prop1 = 42; +u1.prop1 = "hello"; +u1.prop2 = 42; +u1.prop2 = "hello"; +u1.prop3 = 42; +u1.prop3 = "hello"; +u1.prop3 = true; +u1.prop4 = 42; +u1.prop4 = "hello"; +u1.prop4 = true; diff --git a/tests/baselines/reference/divergentAccessorsTypes3.symbols b/tests/baselines/reference/divergentAccessorsTypes3.symbols new file mode 100644 index 0000000000000..6b754eada400d --- /dev/null +++ b/tests/baselines/reference/divergentAccessorsTypes3.symbols @@ -0,0 +1,116 @@ +=== tests/cases/compiler/divergentAccessorsTypes3.ts === +class One { +>One : Symbol(One, Decl(divergentAccessorsTypes3.ts, 0, 0)) + + get prop1(): string { return ""; } +>prop1 : Symbol(One.prop1, Decl(divergentAccessorsTypes3.ts, 0, 11), Decl(divergentAccessorsTypes3.ts, 1, 36)) + + set prop1(s: string | number) { } +>prop1 : Symbol(One.prop1, Decl(divergentAccessorsTypes3.ts, 0, 11), Decl(divergentAccessorsTypes3.ts, 1, 36)) +>s : Symbol(s, Decl(divergentAccessorsTypes3.ts, 2, 12)) + + get prop2(): string { return ""; } +>prop2 : Symbol(One.prop2, Decl(divergentAccessorsTypes3.ts, 2, 35), Decl(divergentAccessorsTypes3.ts, 4, 36)) + + set prop2(s: string | number) { } +>prop2 : Symbol(One.prop2, Decl(divergentAccessorsTypes3.ts, 2, 35), Decl(divergentAccessorsTypes3.ts, 4, 36)) +>s : Symbol(s, Decl(divergentAccessorsTypes3.ts, 5, 12)) + + prop3: number; +>prop3 : Symbol(One.prop3, Decl(divergentAccessorsTypes3.ts, 5, 35)) + + get prop4(): string { return ""; } +>prop4 : Symbol(One.prop4, Decl(divergentAccessorsTypes3.ts, 7, 16), Decl(divergentAccessorsTypes3.ts, 9, 36)) + + set prop4(s: string | number) { } +>prop4 : Symbol(One.prop4, Decl(divergentAccessorsTypes3.ts, 7, 16), Decl(divergentAccessorsTypes3.ts, 9, 36)) +>s : Symbol(s, Decl(divergentAccessorsTypes3.ts, 10, 12)) +} + +class Two { +>Two : Symbol(Two, Decl(divergentAccessorsTypes3.ts, 11, 1)) + + get prop1(): string { return ""; } +>prop1 : Symbol(Two.prop1, Decl(divergentAccessorsTypes3.ts, 13, 11), Decl(divergentAccessorsTypes3.ts, 14, 36)) + + set prop1(s: string | number) { } +>prop1 : Symbol(Two.prop1, Decl(divergentAccessorsTypes3.ts, 13, 11), Decl(divergentAccessorsTypes3.ts, 14, 36)) +>s : Symbol(s, Decl(divergentAccessorsTypes3.ts, 15, 12)) + + get prop2(): string { return ""; } +>prop2 : Symbol(Two.prop2, Decl(divergentAccessorsTypes3.ts, 15, 35), Decl(divergentAccessorsTypes3.ts, 17, 36)) + + set prop2(s: string) { } +>prop2 : Symbol(Two.prop2, Decl(divergentAccessorsTypes3.ts, 15, 35), Decl(divergentAccessorsTypes3.ts, 17, 36)) +>s : Symbol(s, Decl(divergentAccessorsTypes3.ts, 18, 12)) + + get prop3(): string { return ""; } +>prop3 : Symbol(Two.prop3, Decl(divergentAccessorsTypes3.ts, 18, 26), Decl(divergentAccessorsTypes3.ts, 20, 36)) + + set prop3(s: string | boolean) { } +>prop3 : Symbol(Two.prop3, Decl(divergentAccessorsTypes3.ts, 18, 26), Decl(divergentAccessorsTypes3.ts, 20, 36)) +>s : Symbol(s, Decl(divergentAccessorsTypes3.ts, 21, 12)) + + get prop4(): string { return ""; } +>prop4 : Symbol(Two.prop4, Decl(divergentAccessorsTypes3.ts, 21, 36), Decl(divergentAccessorsTypes3.ts, 23, 36)) + + set prop4(s: string | boolean) { } +>prop4 : Symbol(Two.prop4, Decl(divergentAccessorsTypes3.ts, 21, 36), Decl(divergentAccessorsTypes3.ts, 23, 36)) +>s : Symbol(s, Decl(divergentAccessorsTypes3.ts, 24, 12)) +} + +declare const u1: One|Two; +>u1 : Symbol(u1, Decl(divergentAccessorsTypes3.ts, 27, 13)) +>One : Symbol(One, Decl(divergentAccessorsTypes3.ts, 0, 0)) +>Two : Symbol(Two, Decl(divergentAccessorsTypes3.ts, 11, 1)) + +u1.prop1 = 42; +>u1.prop1 : Symbol(prop1, Decl(divergentAccessorsTypes3.ts, 0, 11), Decl(divergentAccessorsTypes3.ts, 1, 36), Decl(divergentAccessorsTypes3.ts, 13, 11), Decl(divergentAccessorsTypes3.ts, 14, 36)) +>u1 : Symbol(u1, Decl(divergentAccessorsTypes3.ts, 27, 13)) +>prop1 : Symbol(prop1, Decl(divergentAccessorsTypes3.ts, 0, 11), Decl(divergentAccessorsTypes3.ts, 1, 36), Decl(divergentAccessorsTypes3.ts, 13, 11), Decl(divergentAccessorsTypes3.ts, 14, 36)) + +u1.prop1 = "hello"; +>u1.prop1 : Symbol(prop1, Decl(divergentAccessorsTypes3.ts, 0, 11), Decl(divergentAccessorsTypes3.ts, 1, 36), Decl(divergentAccessorsTypes3.ts, 13, 11), Decl(divergentAccessorsTypes3.ts, 14, 36)) +>u1 : Symbol(u1, Decl(divergentAccessorsTypes3.ts, 27, 13)) +>prop1 : Symbol(prop1, Decl(divergentAccessorsTypes3.ts, 0, 11), Decl(divergentAccessorsTypes3.ts, 1, 36), Decl(divergentAccessorsTypes3.ts, 13, 11), Decl(divergentAccessorsTypes3.ts, 14, 36)) + +u1.prop2 = 42; +>u1.prop2 : Symbol(prop2, Decl(divergentAccessorsTypes3.ts, 2, 35), Decl(divergentAccessorsTypes3.ts, 4, 36), Decl(divergentAccessorsTypes3.ts, 15, 35), Decl(divergentAccessorsTypes3.ts, 17, 36)) +>u1 : Symbol(u1, Decl(divergentAccessorsTypes3.ts, 27, 13)) +>prop2 : Symbol(prop2, Decl(divergentAccessorsTypes3.ts, 2, 35), Decl(divergentAccessorsTypes3.ts, 4, 36), Decl(divergentAccessorsTypes3.ts, 15, 35), Decl(divergentAccessorsTypes3.ts, 17, 36)) + +u1.prop2 = "hello"; +>u1.prop2 : Symbol(prop2, Decl(divergentAccessorsTypes3.ts, 2, 35), Decl(divergentAccessorsTypes3.ts, 4, 36), Decl(divergentAccessorsTypes3.ts, 15, 35), Decl(divergentAccessorsTypes3.ts, 17, 36)) +>u1 : Symbol(u1, Decl(divergentAccessorsTypes3.ts, 27, 13)) +>prop2 : Symbol(prop2, Decl(divergentAccessorsTypes3.ts, 2, 35), Decl(divergentAccessorsTypes3.ts, 4, 36), Decl(divergentAccessorsTypes3.ts, 15, 35), Decl(divergentAccessorsTypes3.ts, 17, 36)) + +u1.prop3 = 42; +>u1.prop3 : Symbol(prop3, Decl(divergentAccessorsTypes3.ts, 5, 35), Decl(divergentAccessorsTypes3.ts, 18, 26), Decl(divergentAccessorsTypes3.ts, 20, 36)) +>u1 : Symbol(u1, Decl(divergentAccessorsTypes3.ts, 27, 13)) +>prop3 : Symbol(prop3, Decl(divergentAccessorsTypes3.ts, 5, 35), Decl(divergentAccessorsTypes3.ts, 18, 26), Decl(divergentAccessorsTypes3.ts, 20, 36)) + +u1.prop3 = "hello"; +>u1.prop3 : Symbol(prop3, Decl(divergentAccessorsTypes3.ts, 5, 35), Decl(divergentAccessorsTypes3.ts, 18, 26), Decl(divergentAccessorsTypes3.ts, 20, 36)) +>u1 : Symbol(u1, Decl(divergentAccessorsTypes3.ts, 27, 13)) +>prop3 : Symbol(prop3, Decl(divergentAccessorsTypes3.ts, 5, 35), Decl(divergentAccessorsTypes3.ts, 18, 26), Decl(divergentAccessorsTypes3.ts, 20, 36)) + +u1.prop3 = true; +>u1.prop3 : Symbol(prop3, Decl(divergentAccessorsTypes3.ts, 5, 35), Decl(divergentAccessorsTypes3.ts, 18, 26), Decl(divergentAccessorsTypes3.ts, 20, 36)) +>u1 : Symbol(u1, Decl(divergentAccessorsTypes3.ts, 27, 13)) +>prop3 : Symbol(prop3, Decl(divergentAccessorsTypes3.ts, 5, 35), Decl(divergentAccessorsTypes3.ts, 18, 26), Decl(divergentAccessorsTypes3.ts, 20, 36)) + +u1.prop4 = 42; +>u1.prop4 : Symbol(prop4, Decl(divergentAccessorsTypes3.ts, 7, 16), Decl(divergentAccessorsTypes3.ts, 9, 36), Decl(divergentAccessorsTypes3.ts, 21, 36), Decl(divergentAccessorsTypes3.ts, 23, 36)) +>u1 : Symbol(u1, Decl(divergentAccessorsTypes3.ts, 27, 13)) +>prop4 : Symbol(prop4, Decl(divergentAccessorsTypes3.ts, 7, 16), Decl(divergentAccessorsTypes3.ts, 9, 36), Decl(divergentAccessorsTypes3.ts, 21, 36), Decl(divergentAccessorsTypes3.ts, 23, 36)) + +u1.prop4 = "hello"; +>u1.prop4 : Symbol(prop4, Decl(divergentAccessorsTypes3.ts, 7, 16), Decl(divergentAccessorsTypes3.ts, 9, 36), Decl(divergentAccessorsTypes3.ts, 21, 36), Decl(divergentAccessorsTypes3.ts, 23, 36)) +>u1 : Symbol(u1, Decl(divergentAccessorsTypes3.ts, 27, 13)) +>prop4 : Symbol(prop4, Decl(divergentAccessorsTypes3.ts, 7, 16), Decl(divergentAccessorsTypes3.ts, 9, 36), Decl(divergentAccessorsTypes3.ts, 21, 36), Decl(divergentAccessorsTypes3.ts, 23, 36)) + +u1.prop4 = true; +>u1.prop4 : Symbol(prop4, Decl(divergentAccessorsTypes3.ts, 7, 16), Decl(divergentAccessorsTypes3.ts, 9, 36), Decl(divergentAccessorsTypes3.ts, 21, 36), Decl(divergentAccessorsTypes3.ts, 23, 36)) +>u1 : Symbol(u1, Decl(divergentAccessorsTypes3.ts, 27, 13)) +>prop4 : Symbol(prop4, Decl(divergentAccessorsTypes3.ts, 7, 16), Decl(divergentAccessorsTypes3.ts, 9, 36), Decl(divergentAccessorsTypes3.ts, 21, 36), Decl(divergentAccessorsTypes3.ts, 23, 36)) + diff --git a/tests/baselines/reference/divergentAccessorsTypes3.types b/tests/baselines/reference/divergentAccessorsTypes3.types new file mode 100644 index 0000000000000..3f59e2c146323 --- /dev/null +++ b/tests/baselines/reference/divergentAccessorsTypes3.types @@ -0,0 +1,141 @@ +=== tests/cases/compiler/divergentAccessorsTypes3.ts === +class One { +>One : One + + get prop1(): string { return ""; } +>prop1 : string +>"" : "" + + set prop1(s: string | number) { } +>prop1 : string +>s : string | number + + get prop2(): string { return ""; } +>prop2 : string +>"" : "" + + set prop2(s: string | number) { } +>prop2 : string +>s : string | number + + prop3: number; +>prop3 : number + + get prop4(): string { return ""; } +>prop4 : string +>"" : "" + + set prop4(s: string | number) { } +>prop4 : string +>s : string | number +} + +class Two { +>Two : Two + + get prop1(): string { return ""; } +>prop1 : string +>"" : "" + + set prop1(s: string | number) { } +>prop1 : string +>s : string | number + + get prop2(): string { return ""; } +>prop2 : string +>"" : "" + + set prop2(s: string) { } +>prop2 : string +>s : string + + get prop3(): string { return ""; } +>prop3 : string +>"" : "" + + set prop3(s: string | boolean) { } +>prop3 : string +>s : string | boolean + + get prop4(): string { return ""; } +>prop4 : string +>"" : "" + + set prop4(s: string | boolean) { } +>prop4 : string +>s : string | boolean +} + +declare const u1: One|Two; +>u1 : One | Two + +u1.prop1 = 42; +>u1.prop1 = 42 : 42 +>u1.prop1 : string | number +>u1 : One | Two +>prop1 : string | number +>42 : 42 + +u1.prop1 = "hello"; +>u1.prop1 = "hello" : "hello" +>u1.prop1 : string | number +>u1 : One | Two +>prop1 : string | number +>"hello" : "hello" + +u1.prop2 = 42; +>u1.prop2 = 42 : 42 +>u1.prop2 : string | number +>u1 : One | Two +>prop2 : string | number +>42 : 42 + +u1.prop2 = "hello"; +>u1.prop2 = "hello" : "hello" +>u1.prop2 : string | number +>u1 : One | Two +>prop2 : string | number +>"hello" : "hello" + +u1.prop3 = 42; +>u1.prop3 = 42 : 42 +>u1.prop3 : string | number | boolean +>u1 : One | Two +>prop3 : string | number | boolean +>42 : 42 + +u1.prop3 = "hello"; +>u1.prop3 = "hello" : "hello" +>u1.prop3 : string | number | boolean +>u1 : One | Two +>prop3 : string | number | boolean +>"hello" : "hello" + +u1.prop3 = true; +>u1.prop3 = true : true +>u1.prop3 : string | number | boolean +>u1 : One | Two +>prop3 : string | number | boolean +>true : true + +u1.prop4 = 42; +>u1.prop4 = 42 : 42 +>u1.prop4 : string | number | boolean +>u1 : One | Two +>prop4 : string | number | boolean +>42 : 42 + +u1.prop4 = "hello"; +>u1.prop4 = "hello" : "hello" +>u1.prop4 : string | number | boolean +>u1 : One | Two +>prop4 : string | number | boolean +>"hello" : "hello" + +u1.prop4 = true; +>u1.prop4 = true : true +>u1.prop4 : string | number | boolean +>u1 : One | Two +>prop4 : string | number | boolean +>true : true + diff --git a/tests/baselines/reference/divergentAccessorsTypes4.errors.txt b/tests/baselines/reference/divergentAccessorsTypes4.errors.txt new file mode 100644 index 0000000000000..496e9e2f397de --- /dev/null +++ b/tests/baselines/reference/divergentAccessorsTypes4.errors.txt @@ -0,0 +1,36 @@ +tests/cases/compiler/divergentAccessorsTypes4.ts(29,1): error TS2322: Type '"hello"' is not assignable to type '42'. + + +==== tests/cases/compiler/divergentAccessorsTypes4.ts (1 errors) ==== + class One { + get prop1(): string { return ""; } + set prop1(s: string | number) { } + + prop2: number; + } + + class Two { + get prop1(): "hello" { return "hello"; } + set prop1(s: "hello" | number) { } + + get prop2(): string { return ""; } + set prop2(s: string | 42) { } + + } + + declare const i: One & Two; + + // "hello" + i.prop1; + // number | "hello" + i.prop1 = 42; + i.prop1 = "hello"; + + // never + i.prop2; + // 42 + i.prop2 = 42; + i.prop2 = "hello"; // error + ~~~~~~~ +!!! error TS2322: Type '"hello"' is not assignable to type '42'. + \ No newline at end of file diff --git a/tests/baselines/reference/divergentAccessorsTypes4.js b/tests/baselines/reference/divergentAccessorsTypes4.js new file mode 100644 index 0000000000000..74df41f5ef235 --- /dev/null +++ b/tests/baselines/reference/divergentAccessorsTypes4.js @@ -0,0 +1,71 @@ +//// [divergentAccessorsTypes4.ts] +class One { + get prop1(): string { return ""; } + set prop1(s: string | number) { } + + prop2: number; +} + +class Two { + get prop1(): "hello" { return "hello"; } + set prop1(s: "hello" | number) { } + + get prop2(): string { return ""; } + set prop2(s: string | 42) { } + +} + +declare const i: One & Two; + +// "hello" +i.prop1; +// number | "hello" +i.prop1 = 42; +i.prop1 = "hello"; + +// never +i.prop2; +// 42 +i.prop2 = 42; +i.prop2 = "hello"; // error + + +//// [divergentAccessorsTypes4.js] +var One = /** @class */ (function () { + function One() { + } + Object.defineProperty(One.prototype, "prop1", { + get: function () { return ""; }, + set: function (s) { }, + enumerable: false, + configurable: true + }); + return One; +}()); +var Two = /** @class */ (function () { + function Two() { + } + Object.defineProperty(Two.prototype, "prop1", { + get: function () { return "hello"; }, + set: function (s) { }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Two.prototype, "prop2", { + get: function () { return ""; }, + set: function (s) { }, + enumerable: false, + configurable: true + }); + return Two; +}()); +// "hello" +i.prop1; +// number | "hello" +i.prop1 = 42; +i.prop1 = "hello"; +// never +i.prop2; +// 42 +i.prop2 = 42; +i.prop2 = "hello"; // error diff --git a/tests/baselines/reference/divergentAccessorsTypes4.symbols b/tests/baselines/reference/divergentAccessorsTypes4.symbols new file mode 100644 index 0000000000000..263274063ed22 --- /dev/null +++ b/tests/baselines/reference/divergentAccessorsTypes4.symbols @@ -0,0 +1,73 @@ +=== tests/cases/compiler/divergentAccessorsTypes4.ts === +class One { +>One : Symbol(One, Decl(divergentAccessorsTypes4.ts, 0, 0)) + + get prop1(): string { return ""; } +>prop1 : Symbol(One.prop1, Decl(divergentAccessorsTypes4.ts, 0, 11), Decl(divergentAccessorsTypes4.ts, 1, 36)) + + set prop1(s: string | number) { } +>prop1 : Symbol(One.prop1, Decl(divergentAccessorsTypes4.ts, 0, 11), Decl(divergentAccessorsTypes4.ts, 1, 36)) +>s : Symbol(s, Decl(divergentAccessorsTypes4.ts, 2, 12)) + + prop2: number; +>prop2 : Symbol(One.prop2, Decl(divergentAccessorsTypes4.ts, 2, 35)) +} + +class Two { +>Two : Symbol(Two, Decl(divergentAccessorsTypes4.ts, 5, 1)) + + get prop1(): "hello" { return "hello"; } +>prop1 : Symbol(Two.prop1, Decl(divergentAccessorsTypes4.ts, 7, 11), Decl(divergentAccessorsTypes4.ts, 8, 42)) + + set prop1(s: "hello" | number) { } +>prop1 : Symbol(Two.prop1, Decl(divergentAccessorsTypes4.ts, 7, 11), Decl(divergentAccessorsTypes4.ts, 8, 42)) +>s : Symbol(s, Decl(divergentAccessorsTypes4.ts, 9, 12)) + + get prop2(): string { return ""; } +>prop2 : Symbol(Two.prop2, Decl(divergentAccessorsTypes4.ts, 9, 36), Decl(divergentAccessorsTypes4.ts, 11, 36)) + + set prop2(s: string | 42) { } +>prop2 : Symbol(Two.prop2, Decl(divergentAccessorsTypes4.ts, 9, 36), Decl(divergentAccessorsTypes4.ts, 11, 36)) +>s : Symbol(s, Decl(divergentAccessorsTypes4.ts, 12, 12)) + +} + +declare const i: One & Two; +>i : Symbol(i, Decl(divergentAccessorsTypes4.ts, 16, 13)) +>One : Symbol(One, Decl(divergentAccessorsTypes4.ts, 0, 0)) +>Two : Symbol(Two, Decl(divergentAccessorsTypes4.ts, 5, 1)) + +// "hello" +i.prop1; +>i.prop1 : Symbol(prop1, Decl(divergentAccessorsTypes4.ts, 0, 11), Decl(divergentAccessorsTypes4.ts, 1, 36), Decl(divergentAccessorsTypes4.ts, 7, 11), Decl(divergentAccessorsTypes4.ts, 8, 42)) +>i : Symbol(i, Decl(divergentAccessorsTypes4.ts, 16, 13)) +>prop1 : Symbol(prop1, Decl(divergentAccessorsTypes4.ts, 0, 11), Decl(divergentAccessorsTypes4.ts, 1, 36), Decl(divergentAccessorsTypes4.ts, 7, 11), Decl(divergentAccessorsTypes4.ts, 8, 42)) + +// number | "hello" +i.prop1 = 42; +>i.prop1 : Symbol(prop1, Decl(divergentAccessorsTypes4.ts, 0, 11), Decl(divergentAccessorsTypes4.ts, 1, 36), Decl(divergentAccessorsTypes4.ts, 7, 11), Decl(divergentAccessorsTypes4.ts, 8, 42)) +>i : Symbol(i, Decl(divergentAccessorsTypes4.ts, 16, 13)) +>prop1 : Symbol(prop1, Decl(divergentAccessorsTypes4.ts, 0, 11), Decl(divergentAccessorsTypes4.ts, 1, 36), Decl(divergentAccessorsTypes4.ts, 7, 11), Decl(divergentAccessorsTypes4.ts, 8, 42)) + +i.prop1 = "hello"; +>i.prop1 : Symbol(prop1, Decl(divergentAccessorsTypes4.ts, 0, 11), Decl(divergentAccessorsTypes4.ts, 1, 36), Decl(divergentAccessorsTypes4.ts, 7, 11), Decl(divergentAccessorsTypes4.ts, 8, 42)) +>i : Symbol(i, Decl(divergentAccessorsTypes4.ts, 16, 13)) +>prop1 : Symbol(prop1, Decl(divergentAccessorsTypes4.ts, 0, 11), Decl(divergentAccessorsTypes4.ts, 1, 36), Decl(divergentAccessorsTypes4.ts, 7, 11), Decl(divergentAccessorsTypes4.ts, 8, 42)) + +// never +i.prop2; +>i.prop2 : Symbol(prop2, Decl(divergentAccessorsTypes4.ts, 2, 35), Decl(divergentAccessorsTypes4.ts, 9, 36), Decl(divergentAccessorsTypes4.ts, 11, 36)) +>i : Symbol(i, Decl(divergentAccessorsTypes4.ts, 16, 13)) +>prop2 : Symbol(prop2, Decl(divergentAccessorsTypes4.ts, 2, 35), Decl(divergentAccessorsTypes4.ts, 9, 36), Decl(divergentAccessorsTypes4.ts, 11, 36)) + +// 42 +i.prop2 = 42; +>i.prop2 : Symbol(prop2, Decl(divergentAccessorsTypes4.ts, 2, 35), Decl(divergentAccessorsTypes4.ts, 9, 36), Decl(divergentAccessorsTypes4.ts, 11, 36)) +>i : Symbol(i, Decl(divergentAccessorsTypes4.ts, 16, 13)) +>prop2 : Symbol(prop2, Decl(divergentAccessorsTypes4.ts, 2, 35), Decl(divergentAccessorsTypes4.ts, 9, 36), Decl(divergentAccessorsTypes4.ts, 11, 36)) + +i.prop2 = "hello"; // error +>i.prop2 : Symbol(prop2, Decl(divergentAccessorsTypes4.ts, 2, 35), Decl(divergentAccessorsTypes4.ts, 9, 36), Decl(divergentAccessorsTypes4.ts, 11, 36)) +>i : Symbol(i, Decl(divergentAccessorsTypes4.ts, 16, 13)) +>prop2 : Symbol(prop2, Decl(divergentAccessorsTypes4.ts, 2, 35), Decl(divergentAccessorsTypes4.ts, 9, 36), Decl(divergentAccessorsTypes4.ts, 11, 36)) + diff --git a/tests/baselines/reference/divergentAccessorsTypes4.types b/tests/baselines/reference/divergentAccessorsTypes4.types new file mode 100644 index 0000000000000..eb3784b451dac --- /dev/null +++ b/tests/baselines/reference/divergentAccessorsTypes4.types @@ -0,0 +1,82 @@ +=== tests/cases/compiler/divergentAccessorsTypes4.ts === +class One { +>One : One + + get prop1(): string { return ""; } +>prop1 : string +>"" : "" + + set prop1(s: string | number) { } +>prop1 : string +>s : string | number + + prop2: number; +>prop2 : number +} + +class Two { +>Two : Two + + get prop1(): "hello" { return "hello"; } +>prop1 : "hello" +>"hello" : "hello" + + set prop1(s: "hello" | number) { } +>prop1 : "hello" +>s : number | "hello" + + get prop2(): string { return ""; } +>prop2 : string +>"" : "" + + set prop2(s: string | 42) { } +>prop2 : string +>s : string | 42 + +} + +declare const i: One & Two; +>i : One & Two + +// "hello" +i.prop1; +>i.prop1 : "hello" +>i : One & Two +>prop1 : "hello" + +// number | "hello" +i.prop1 = 42; +>i.prop1 = 42 : 42 +>i.prop1 : number | "hello" +>i : One & Two +>prop1 : number | "hello" +>42 : 42 + +i.prop1 = "hello"; +>i.prop1 = "hello" : "hello" +>i.prop1 : number | "hello" +>i : One & Two +>prop1 : number | "hello" +>"hello" : "hello" + +// never +i.prop2; +>i.prop2 : never +>i : One & Two +>prop2 : never + +// 42 +i.prop2 = 42; +>i.prop2 = 42 : 42 +>i.prop2 : 42 +>i : One & Two +>prop2 : 42 +>42 : 42 + +i.prop2 = "hello"; // error +>i.prop2 = "hello" : "hello" +>i.prop2 : 42 +>i : One & Two +>prop2 : 42 +>"hello" : "hello" + diff --git a/tests/baselines/reference/divergentAccessorsTypes5.errors.txt b/tests/baselines/reference/divergentAccessorsTypes5.errors.txt new file mode 100644 index 0000000000000..5f163a9b62ef1 --- /dev/null +++ b/tests/baselines/reference/divergentAccessorsTypes5.errors.txt @@ -0,0 +1,46 @@ +tests/cases/compiler/divergentAccessorsTypes5.ts(31,1): error TS2322: Type '42' is not assignable to type '"hello"'. +tests/cases/compiler/divergentAccessorsTypes5.ts(36,1): error TS2322: Type '"hello"' is not assignable to type '42'. + + +==== tests/cases/compiler/divergentAccessorsTypes5.ts (2 errors) ==== + // Not really different from divergentAccessorsTypes4.ts, + // but goes through the deferred type code + + class One { + get prop1(): string { return ""; } + set prop1(s: string | number) { } + + prop2: number; + } + + class Two { + get prop1(): "hello" { return "hello"; } + set prop1(s: "hello" | number) { } + + get prop2(): string { return ""; } + set prop2(s: string | 42) { } + + } + + class Three { + get prop1(): "hello" { return "hello"; } + set prop1(s: "hello" | boolean) { } + + get prop2(): string { return ""; } + set prop2(s: string | number | boolean) { } + } + + declare const i: One & Two & Three; + + // "hello" + i.prop1 = 42; // error + ~~~~~~~ +!!! error TS2322: Type '42' is not assignable to type '"hello"'. + i.prop1 = "hello"; + + // 42 + i.prop2 = 42; + i.prop2 = "hello"; // error + ~~~~~~~ +!!! error TS2322: Type '"hello"' is not assignable to type '42'. + \ No newline at end of file diff --git a/tests/baselines/reference/divergentAccessorsTypes5.js b/tests/baselines/reference/divergentAccessorsTypes5.js new file mode 100644 index 0000000000000..773289d1ddb06 --- /dev/null +++ b/tests/baselines/reference/divergentAccessorsTypes5.js @@ -0,0 +1,93 @@ +//// [divergentAccessorsTypes5.ts] +// Not really different from divergentAccessorsTypes4.ts, +// but goes through the deferred type code + +class One { + get prop1(): string { return ""; } + set prop1(s: string | number) { } + + prop2: number; +} + +class Two { + get prop1(): "hello" { return "hello"; } + set prop1(s: "hello" | number) { } + + get prop2(): string { return ""; } + set prop2(s: string | 42) { } + +} + +class Three { + get prop1(): "hello" { return "hello"; } + set prop1(s: "hello" | boolean) { } + + get prop2(): string { return ""; } + set prop2(s: string | number | boolean) { } +} + +declare const i: One & Two & Three; + +// "hello" +i.prop1 = 42; // error +i.prop1 = "hello"; + +// 42 +i.prop2 = 42; +i.prop2 = "hello"; // error + + +//// [divergentAccessorsTypes5.js] +// Not really different from divergentAccessorsTypes4.ts, +// but goes through the deferred type code +var One = /** @class */ (function () { + function One() { + } + Object.defineProperty(One.prototype, "prop1", { + get: function () { return ""; }, + set: function (s) { }, + enumerable: false, + configurable: true + }); + return One; +}()); +var Two = /** @class */ (function () { + function Two() { + } + Object.defineProperty(Two.prototype, "prop1", { + get: function () { return "hello"; }, + set: function (s) { }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Two.prototype, "prop2", { + get: function () { return ""; }, + set: function (s) { }, + enumerable: false, + configurable: true + }); + return Two; +}()); +var Three = /** @class */ (function () { + function Three() { + } + Object.defineProperty(Three.prototype, "prop1", { + get: function () { return "hello"; }, + set: function (s) { }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Three.prototype, "prop2", { + get: function () { return ""; }, + set: function (s) { }, + enumerable: false, + configurable: true + }); + return Three; +}()); +// "hello" +i.prop1 = 42; // error +i.prop1 = "hello"; +// 42 +i.prop2 = 42; +i.prop2 = "hello"; // error diff --git a/tests/baselines/reference/divergentAccessorsTypes5.symbols b/tests/baselines/reference/divergentAccessorsTypes5.symbols new file mode 100644 index 0000000000000..c698c9235bfe9 --- /dev/null +++ b/tests/baselines/reference/divergentAccessorsTypes5.symbols @@ -0,0 +1,83 @@ +=== tests/cases/compiler/divergentAccessorsTypes5.ts === +// Not really different from divergentAccessorsTypes4.ts, +// but goes through the deferred type code + +class One { +>One : Symbol(One, Decl(divergentAccessorsTypes5.ts, 0, 0)) + + get prop1(): string { return ""; } +>prop1 : Symbol(One.prop1, Decl(divergentAccessorsTypes5.ts, 3, 11), Decl(divergentAccessorsTypes5.ts, 4, 36)) + + set prop1(s: string | number) { } +>prop1 : Symbol(One.prop1, Decl(divergentAccessorsTypes5.ts, 3, 11), Decl(divergentAccessorsTypes5.ts, 4, 36)) +>s : Symbol(s, Decl(divergentAccessorsTypes5.ts, 5, 12)) + + prop2: number; +>prop2 : Symbol(One.prop2, Decl(divergentAccessorsTypes5.ts, 5, 35)) +} + +class Two { +>Two : Symbol(Two, Decl(divergentAccessorsTypes5.ts, 8, 1)) + + get prop1(): "hello" { return "hello"; } +>prop1 : Symbol(Two.prop1, Decl(divergentAccessorsTypes5.ts, 10, 11), Decl(divergentAccessorsTypes5.ts, 11, 42)) + + set prop1(s: "hello" | number) { } +>prop1 : Symbol(Two.prop1, Decl(divergentAccessorsTypes5.ts, 10, 11), Decl(divergentAccessorsTypes5.ts, 11, 42)) +>s : Symbol(s, Decl(divergentAccessorsTypes5.ts, 12, 12)) + + get prop2(): string { return ""; } +>prop2 : Symbol(Two.prop2, Decl(divergentAccessorsTypes5.ts, 12, 36), Decl(divergentAccessorsTypes5.ts, 14, 36)) + + set prop2(s: string | 42) { } +>prop2 : Symbol(Two.prop2, Decl(divergentAccessorsTypes5.ts, 12, 36), Decl(divergentAccessorsTypes5.ts, 14, 36)) +>s : Symbol(s, Decl(divergentAccessorsTypes5.ts, 15, 12)) + +} + +class Three { +>Three : Symbol(Three, Decl(divergentAccessorsTypes5.ts, 17, 1)) + + get prop1(): "hello" { return "hello"; } +>prop1 : Symbol(Three.prop1, Decl(divergentAccessorsTypes5.ts, 19, 13), Decl(divergentAccessorsTypes5.ts, 20, 42)) + + set prop1(s: "hello" | boolean) { } +>prop1 : Symbol(Three.prop1, Decl(divergentAccessorsTypes5.ts, 19, 13), Decl(divergentAccessorsTypes5.ts, 20, 42)) +>s : Symbol(s, Decl(divergentAccessorsTypes5.ts, 21, 12)) + + get prop2(): string { return ""; } +>prop2 : Symbol(Three.prop2, Decl(divergentAccessorsTypes5.ts, 21, 37), Decl(divergentAccessorsTypes5.ts, 23, 36)) + + set prop2(s: string | number | boolean) { } +>prop2 : Symbol(Three.prop2, Decl(divergentAccessorsTypes5.ts, 21, 37), Decl(divergentAccessorsTypes5.ts, 23, 36)) +>s : Symbol(s, Decl(divergentAccessorsTypes5.ts, 24, 12)) +} + +declare const i: One & Two & Three; +>i : Symbol(i, Decl(divergentAccessorsTypes5.ts, 27, 13)) +>One : Symbol(One, Decl(divergentAccessorsTypes5.ts, 0, 0)) +>Two : Symbol(Two, Decl(divergentAccessorsTypes5.ts, 8, 1)) +>Three : Symbol(Three, Decl(divergentAccessorsTypes5.ts, 17, 1)) + +// "hello" +i.prop1 = 42; // error +>i.prop1 : Symbol(prop1, Decl(divergentAccessorsTypes5.ts, 3, 11), Decl(divergentAccessorsTypes5.ts, 4, 36), Decl(divergentAccessorsTypes5.ts, 10, 11), Decl(divergentAccessorsTypes5.ts, 11, 42), Decl(divergentAccessorsTypes5.ts, 19, 13) ... and 1 more) +>i : Symbol(i, Decl(divergentAccessorsTypes5.ts, 27, 13)) +>prop1 : Symbol(prop1, Decl(divergentAccessorsTypes5.ts, 3, 11), Decl(divergentAccessorsTypes5.ts, 4, 36), Decl(divergentAccessorsTypes5.ts, 10, 11), Decl(divergentAccessorsTypes5.ts, 11, 42), Decl(divergentAccessorsTypes5.ts, 19, 13) ... and 1 more) + +i.prop1 = "hello"; +>i.prop1 : Symbol(prop1, Decl(divergentAccessorsTypes5.ts, 3, 11), Decl(divergentAccessorsTypes5.ts, 4, 36), Decl(divergentAccessorsTypes5.ts, 10, 11), Decl(divergentAccessorsTypes5.ts, 11, 42), Decl(divergentAccessorsTypes5.ts, 19, 13) ... and 1 more) +>i : Symbol(i, Decl(divergentAccessorsTypes5.ts, 27, 13)) +>prop1 : Symbol(prop1, Decl(divergentAccessorsTypes5.ts, 3, 11), Decl(divergentAccessorsTypes5.ts, 4, 36), Decl(divergentAccessorsTypes5.ts, 10, 11), Decl(divergentAccessorsTypes5.ts, 11, 42), Decl(divergentAccessorsTypes5.ts, 19, 13) ... and 1 more) + +// 42 +i.prop2 = 42; +>i.prop2 : Symbol(prop2, Decl(divergentAccessorsTypes5.ts, 5, 35), Decl(divergentAccessorsTypes5.ts, 12, 36), Decl(divergentAccessorsTypes5.ts, 14, 36), Decl(divergentAccessorsTypes5.ts, 21, 37), Decl(divergentAccessorsTypes5.ts, 23, 36)) +>i : Symbol(i, Decl(divergentAccessorsTypes5.ts, 27, 13)) +>prop2 : Symbol(prop2, Decl(divergentAccessorsTypes5.ts, 5, 35), Decl(divergentAccessorsTypes5.ts, 12, 36), Decl(divergentAccessorsTypes5.ts, 14, 36), Decl(divergentAccessorsTypes5.ts, 21, 37), Decl(divergentAccessorsTypes5.ts, 23, 36)) + +i.prop2 = "hello"; // error +>i.prop2 : Symbol(prop2, Decl(divergentAccessorsTypes5.ts, 5, 35), Decl(divergentAccessorsTypes5.ts, 12, 36), Decl(divergentAccessorsTypes5.ts, 14, 36), Decl(divergentAccessorsTypes5.ts, 21, 37), Decl(divergentAccessorsTypes5.ts, 23, 36)) +>i : Symbol(i, Decl(divergentAccessorsTypes5.ts, 27, 13)) +>prop2 : Symbol(prop2, Decl(divergentAccessorsTypes5.ts, 5, 35), Decl(divergentAccessorsTypes5.ts, 12, 36), Decl(divergentAccessorsTypes5.ts, 14, 36), Decl(divergentAccessorsTypes5.ts, 21, 37), Decl(divergentAccessorsTypes5.ts, 23, 36)) + diff --git a/tests/baselines/reference/divergentAccessorsTypes5.types b/tests/baselines/reference/divergentAccessorsTypes5.types new file mode 100644 index 0000000000000..5341163c3f808 --- /dev/null +++ b/tests/baselines/reference/divergentAccessorsTypes5.types @@ -0,0 +1,93 @@ +=== tests/cases/compiler/divergentAccessorsTypes5.ts === +// Not really different from divergentAccessorsTypes4.ts, +// but goes through the deferred type code + +class One { +>One : One + + get prop1(): string { return ""; } +>prop1 : string +>"" : "" + + set prop1(s: string | number) { } +>prop1 : string +>s : string | number + + prop2: number; +>prop2 : number +} + +class Two { +>Two : Two + + get prop1(): "hello" { return "hello"; } +>prop1 : "hello" +>"hello" : "hello" + + set prop1(s: "hello" | number) { } +>prop1 : "hello" +>s : number | "hello" + + get prop2(): string { return ""; } +>prop2 : string +>"" : "" + + set prop2(s: string | 42) { } +>prop2 : string +>s : string | 42 + +} + +class Three { +>Three : Three + + get prop1(): "hello" { return "hello"; } +>prop1 : "hello" +>"hello" : "hello" + + set prop1(s: "hello" | boolean) { } +>prop1 : "hello" +>s : boolean | "hello" + + get prop2(): string { return ""; } +>prop2 : string +>"" : "" + + set prop2(s: string | number | boolean) { } +>prop2 : string +>s : string | number | boolean +} + +declare const i: One & Two & Three; +>i : One & Two & Three + +// "hello" +i.prop1 = 42; // error +>i.prop1 = 42 : 42 +>i.prop1 : "hello" +>i : One & Two & Three +>prop1 : "hello" +>42 : 42 + +i.prop1 = "hello"; +>i.prop1 = "hello" : "hello" +>i.prop1 : "hello" +>i : One & Two & Three +>prop1 : "hello" +>"hello" : "hello" + +// 42 +i.prop2 = 42; +>i.prop2 = 42 : 42 +>i.prop2 : 42 +>i : One & Two & Three +>prop2 : 42 +>42 : 42 + +i.prop2 = "hello"; // error +>i.prop2 = "hello" : "hello" +>i.prop2 : 42 +>i : One & Two & Three +>prop2 : 42 +>"hello" : "hello" + diff --git a/tests/cases/compiler/divergentAccessorsTypes3.ts b/tests/cases/compiler/divergentAccessorsTypes3.ts new file mode 100644 index 0000000000000..557c73153ce90 --- /dev/null +++ b/tests/cases/compiler/divergentAccessorsTypes3.ts @@ -0,0 +1,44 @@ +// @target: es5 + +class One { + get prop1(): string { return ""; } + set prop1(s: string | number) { } + + get prop2(): string { return ""; } + set prop2(s: string | number) { } + + prop3: number; + + get prop4(): string { return ""; } + set prop4(s: string | number) { } +} + +class Two { + get prop1(): string { return ""; } + set prop1(s: string | number) { } + + get prop2(): string { return ""; } + set prop2(s: string) { } + + get prop3(): string { return ""; } + set prop3(s: string | boolean) { } + + get prop4(): string { return ""; } + set prop4(s: string | boolean) { } +} + +declare const u1: One|Two; + +u1.prop1 = 42; +u1.prop1 = "hello"; + +u1.prop2 = 42; +u1.prop2 = "hello"; + +u1.prop3 = 42; +u1.prop3 = "hello"; +u1.prop3 = true; + +u1.prop4 = 42; +u1.prop4 = "hello"; +u1.prop4 = true; diff --git a/tests/cases/compiler/divergentAccessorsTypes4.ts b/tests/cases/compiler/divergentAccessorsTypes4.ts new file mode 100644 index 0000000000000..802a1b4d2c63c --- /dev/null +++ b/tests/cases/compiler/divergentAccessorsTypes4.ts @@ -0,0 +1,31 @@ +// @target: es5 + +class One { + get prop1(): string { return ""; } + set prop1(s: string | number) { } + + prop2: number; +} + +class Two { + get prop1(): "hello" { return "hello"; } + set prop1(s: "hello" | number) { } + + get prop2(): string { return ""; } + set prop2(s: string | 42) { } + +} + +declare const i: One & Two; + +// "hello" +i.prop1; +// number | "hello" +i.prop1 = 42; +i.prop1 = "hello"; + +// never +i.prop2; +// 42 +i.prop2 = 42; +i.prop2 = "hello"; // error diff --git a/tests/cases/compiler/divergentAccessorsTypes5.ts b/tests/cases/compiler/divergentAccessorsTypes5.ts new file mode 100644 index 0000000000000..54d1099004a17 --- /dev/null +++ b/tests/cases/compiler/divergentAccessorsTypes5.ts @@ -0,0 +1,38 @@ +// @target: es5 + +// Not really different from divergentAccessorsTypes4.ts, +// but goes through the deferred type code + +class One { + get prop1(): string { return ""; } + set prop1(s: string | number) { } + + prop2: number; +} + +class Two { + get prop1(): "hello" { return "hello"; } + set prop1(s: "hello" | number) { } + + get prop2(): string { return ""; } + set prop2(s: string | 42) { } + +} + +class Three { + get prop1(): "hello" { return "hello"; } + set prop1(s: "hello" | boolean) { } + + get prop2(): string { return ""; } + set prop2(s: string | number | boolean) { } +} + +declare const i: One & Two & Three; + +// "hello" +i.prop1 = 42; // error +i.prop1 = "hello"; + +// 42 +i.prop2 = 42; +i.prop2 = "hello"; // error From c06849ad16a1ab9bb1e457755f3ef22cf231cac5 Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Tue, 8 Feb 2022 23:39:54 +0200 Subject: [PATCH 27/55] fix(47787): show QF to delete parameter in getter (#47797) --- src/services/codefixes/fixUnusedIdentifier.ts | 4 ++++ src/services/formatting/smartIndenter.ts | 2 ++ ...ixUnusedIdentifier_parameterInGetAccessor.ts | 17 +++++++++++++++++ 3 files changed, 23 insertions(+) create mode 100644 tests/cases/fourslash/codeFixUnusedIdentifier_parameterInGetAccessor.ts diff --git a/src/services/codefixes/fixUnusedIdentifier.ts b/src/services/codefixes/fixUnusedIdentifier.ts index f11c6bce72fd0..df44b8b2e5a3b 100644 --- a/src/services/codefixes/fixUnusedIdentifier.ts +++ b/src/services/codefixes/fixUnusedIdentifier.ts @@ -316,6 +316,10 @@ namespace ts.codefix { // Setter must have a parameter return false; + case SyntaxKind.GetAccessor: + // Getter cannot have parameters + return true; + default: return Debug.failBadSyntaxKind(parent); } diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index de22396383207..da74c36afcb2f 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -432,6 +432,8 @@ namespace ts.formatting { case SyntaxKind.ConstructorType: case SyntaxKind.ConstructSignature: return getList((node as SignatureDeclaration).typeParameters) || getList((node as SignatureDeclaration).parameters); + case SyntaxKind.GetAccessor: + return getList((node as GetAccessorDeclaration).parameters); case SyntaxKind.ClassDeclaration: case SyntaxKind.ClassExpression: case SyntaxKind.InterfaceDeclaration: diff --git a/tests/cases/fourslash/codeFixUnusedIdentifier_parameterInGetAccessor.ts b/tests/cases/fourslash/codeFixUnusedIdentifier_parameterInGetAccessor.ts new file mode 100644 index 0000000000000..e70afb997db5b --- /dev/null +++ b/tests/cases/fourslash/codeFixUnusedIdentifier_parameterInGetAccessor.ts @@ -0,0 +1,17 @@ +/// + +// @noUnusedLocals: true +// @noUnusedParameters: true + +////let foo = { +//// get x(/**/param) {} +////} + +verify.codeFix({ + description: "Remove unused declaration for: 'param'", + index: 0, + newFileContent: +`let foo = { + get x() {} +}` +}) From 2cf5afd49e975ec542c0486cbc2551fc77186a36 Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Wed, 9 Feb 2022 10:56:29 -0800 Subject: [PATCH 28/55] Avoid pulling on setter type when only getter type is needed to break circularity (#47818) --- src/compiler/checker.ts | 10 ++-- .../mappedTypeCircularReferenceInAccessor.js | 16 ++++++ ...pedTypeCircularReferenceInAccessor.symbols | 50 +++++++++++++++++++ ...appedTypeCircularReferenceInAccessor.types | 25 ++++++++++ .../mappedTypeCircularReferenceInAccessor.ts | 12 +++++ 5 files changed, 109 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/mappedTypeCircularReferenceInAccessor.js create mode 100644 tests/baselines/reference/mappedTypeCircularReferenceInAccessor.symbols create mode 100644 tests/baselines/reference/mappedTypeCircularReferenceInAccessor.types create mode 100644 tests/cases/compiler/mappedTypeCircularReferenceInAccessor.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2201a3aa30264..e218766a708e3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -9511,11 +9511,12 @@ namespace ts { const getter = getDeclarationOfKind(symbol, SyntaxKind.GetAccessor); const setter = getDeclarationOfKind(symbol, SyntaxKind.SetAccessor); - const setterType = getAnnotatedAccessorType(setter); - // For write operations, prioritize type annotations on the setter - if (writing && setterType) { - return instantiateTypeIfNeeded(setterType, symbol); + if (writing) { + const setterType = getAnnotatedAccessorType(setter); + if (setterType) { + return instantiateTypeIfNeeded(setterType, symbol); + } } // Else defer to the getter type @@ -9533,6 +9534,7 @@ namespace ts { } // If the user didn't specify a return type, try to use the set-accessor's parameter type. + const setterType = getAnnotatedAccessorType(setter); if (setterType) { return setterType; } diff --git a/tests/baselines/reference/mappedTypeCircularReferenceInAccessor.js b/tests/baselines/reference/mappedTypeCircularReferenceInAccessor.js new file mode 100644 index 0000000000000..f48a16541cdda --- /dev/null +++ b/tests/baselines/reference/mappedTypeCircularReferenceInAccessor.js @@ -0,0 +1,16 @@ +//// [mappedTypeCircularReferenceInAccessor.ts] +interface User { + firstName: string, + level: number, + get bestFriend(): User + set bestFriend(user: SerializablePartial) +} + +type FilteredKeys = { [K in keyof T]: T[K] extends number ? K : T[K] extends string ? K : T[K] extends boolean ? K : never }[keyof T]; + +type SerializablePartial = { + [K in FilteredKeys]: T[K] +}; + + +//// [mappedTypeCircularReferenceInAccessor.js] diff --git a/tests/baselines/reference/mappedTypeCircularReferenceInAccessor.symbols b/tests/baselines/reference/mappedTypeCircularReferenceInAccessor.symbols new file mode 100644 index 0000000000000..9b7be7485a1af --- /dev/null +++ b/tests/baselines/reference/mappedTypeCircularReferenceInAccessor.symbols @@ -0,0 +1,50 @@ +=== tests/cases/compiler/mappedTypeCircularReferenceInAccessor.ts === +interface User { +>User : Symbol(User, Decl(mappedTypeCircularReferenceInAccessor.ts, 0, 0)) + + firstName: string, +>firstName : Symbol(User.firstName, Decl(mappedTypeCircularReferenceInAccessor.ts, 0, 16)) + + level: number, +>level : Symbol(User.level, Decl(mappedTypeCircularReferenceInAccessor.ts, 1, 20)) + + get bestFriend(): User +>bestFriend : Symbol(User.bestFriend, Decl(mappedTypeCircularReferenceInAccessor.ts, 2, 16), Decl(mappedTypeCircularReferenceInAccessor.ts, 3, 24)) +>User : Symbol(User, Decl(mappedTypeCircularReferenceInAccessor.ts, 0, 0)) + + set bestFriend(user: SerializablePartial) +>bestFriend : Symbol(User.bestFriend, Decl(mappedTypeCircularReferenceInAccessor.ts, 2, 16), Decl(mappedTypeCircularReferenceInAccessor.ts, 3, 24)) +>user : Symbol(user, Decl(mappedTypeCircularReferenceInAccessor.ts, 4, 17)) +>SerializablePartial : Symbol(SerializablePartial, Decl(mappedTypeCircularReferenceInAccessor.ts, 7, 137)) +>User : Symbol(User, Decl(mappedTypeCircularReferenceInAccessor.ts, 0, 0)) +} + +type FilteredKeys = { [K in keyof T]: T[K] extends number ? K : T[K] extends string ? K : T[K] extends boolean ? K : never }[keyof T]; +>FilteredKeys : Symbol(FilteredKeys, Decl(mappedTypeCircularReferenceInAccessor.ts, 5, 1)) +>T : Symbol(T, Decl(mappedTypeCircularReferenceInAccessor.ts, 7, 18)) +>K : Symbol(K, Decl(mappedTypeCircularReferenceInAccessor.ts, 7, 26)) +>T : Symbol(T, Decl(mappedTypeCircularReferenceInAccessor.ts, 7, 18)) +>T : Symbol(T, Decl(mappedTypeCircularReferenceInAccessor.ts, 7, 18)) +>K : Symbol(K, Decl(mappedTypeCircularReferenceInAccessor.ts, 7, 26)) +>K : Symbol(K, Decl(mappedTypeCircularReferenceInAccessor.ts, 7, 26)) +>T : Symbol(T, Decl(mappedTypeCircularReferenceInAccessor.ts, 7, 18)) +>K : Symbol(K, Decl(mappedTypeCircularReferenceInAccessor.ts, 7, 26)) +>K : Symbol(K, Decl(mappedTypeCircularReferenceInAccessor.ts, 7, 26)) +>T : Symbol(T, Decl(mappedTypeCircularReferenceInAccessor.ts, 7, 18)) +>K : Symbol(K, Decl(mappedTypeCircularReferenceInAccessor.ts, 7, 26)) +>K : Symbol(K, Decl(mappedTypeCircularReferenceInAccessor.ts, 7, 26)) +>T : Symbol(T, Decl(mappedTypeCircularReferenceInAccessor.ts, 7, 18)) + +type SerializablePartial = { +>SerializablePartial : Symbol(SerializablePartial, Decl(mappedTypeCircularReferenceInAccessor.ts, 7, 137)) +>T : Symbol(T, Decl(mappedTypeCircularReferenceInAccessor.ts, 9, 25)) + + [K in FilteredKeys]: T[K] +>K : Symbol(K, Decl(mappedTypeCircularReferenceInAccessor.ts, 10, 3)) +>FilteredKeys : Symbol(FilteredKeys, Decl(mappedTypeCircularReferenceInAccessor.ts, 5, 1)) +>T : Symbol(T, Decl(mappedTypeCircularReferenceInAccessor.ts, 9, 25)) +>T : Symbol(T, Decl(mappedTypeCircularReferenceInAccessor.ts, 9, 25)) +>K : Symbol(K, Decl(mappedTypeCircularReferenceInAccessor.ts, 10, 3)) + +}; + diff --git a/tests/baselines/reference/mappedTypeCircularReferenceInAccessor.types b/tests/baselines/reference/mappedTypeCircularReferenceInAccessor.types new file mode 100644 index 0000000000000..0f713d6f1c08d --- /dev/null +++ b/tests/baselines/reference/mappedTypeCircularReferenceInAccessor.types @@ -0,0 +1,25 @@ +=== tests/cases/compiler/mappedTypeCircularReferenceInAccessor.ts === +interface User { + firstName: string, +>firstName : string + + level: number, +>level : number + + get bestFriend(): User +>bestFriend : User + + set bestFriend(user: SerializablePartial) +>bestFriend : User +>user : SerializablePartial +} + +type FilteredKeys = { [K in keyof T]: T[K] extends number ? K : T[K] extends string ? K : T[K] extends boolean ? K : never }[keyof T]; +>FilteredKeys : FilteredKeys + +type SerializablePartial = { +>SerializablePartial : SerializablePartial + + [K in FilteredKeys]: T[K] +}; + diff --git a/tests/cases/compiler/mappedTypeCircularReferenceInAccessor.ts b/tests/cases/compiler/mappedTypeCircularReferenceInAccessor.ts new file mode 100644 index 0000000000000..82138b5ff0aac --- /dev/null +++ b/tests/cases/compiler/mappedTypeCircularReferenceInAccessor.ts @@ -0,0 +1,12 @@ +interface User { + firstName: string, + level: number, + get bestFriend(): User + set bestFriend(user: SerializablePartial) +} + +type FilteredKeys = { [K in keyof T]: T[K] extends number ? K : T[K] extends string ? K : T[K] extends boolean ? K : never }[keyof T]; + +type SerializablePartial = { + [K in FilteredKeys]: T[K] +}; From d5c3015516a1a3423e2b71433a4e9cff9d750bb5 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 9 Feb 2022 11:22:33 -0800 Subject: [PATCH 29/55] Constructor function methods:Add two missing tag lookups (#47742) 1. During name resolution, `@param` and `@return` tags should walk up through the jsdoc comment and then jump to the host function. Previously they did not, which would cause them to not resolve type parameters bound in the scope of a host that was not a sibling of the comment. The example from #46618 is a prototype method: ```js /** * @template {T} * @param {T} t */ C.prototype.m = function (t) { } ``` 2. During name resolution, prototype methods are supposed to resolve types both from the host function's location and from the containing class' location. The containing class lookup happens in a separate call to `resolveName`. Previously, the code that finds the containing class only worked for the above style of comment, which is on the outer ExpressionStatement, but not for the below style, which is on the function expression itself: ```js C.prototype.m = /** * @template {T} * @param {T} t */ function (t) { } ``` --- src/compiler/checker.ts | 20 +++-- src/compiler/utilities.ts | 2 +- ...ructorFunctionMethodTypeParameters.symbols | 73 +++++++++++++++ ...structorFunctionMethodTypeParameters.types | 88 +++++++++++++++++++ ...constructorFunctionMethodTypeParameters.ts | 37 ++++++++ 5 files changed, 212 insertions(+), 8 deletions(-) create mode 100644 tests/baselines/reference/constructorFunctionMethodTypeParameters.symbols create mode 100644 tests/baselines/reference/constructorFunctionMethodTypeParameters.types create mode 100644 tests/cases/conformance/salsa/constructorFunctionMethodTypeParameters.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e218766a708e3..dae973d634603 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1833,6 +1833,8 @@ namespace ts { // type parameters are visible in parameter list, return type and type parameter list ? lastLocation === (location as FunctionLikeDeclaration).type || lastLocation.kind === SyntaxKind.Parameter || + lastLocation.kind === SyntaxKind.JSDocParameterTag || + lastLocation.kind === SyntaxKind.JSDocReturnTag || lastLocation.kind === SyntaxKind.TypeParameter // local types not visible outside the function body : false; @@ -2101,8 +2103,8 @@ namespace ts { lastSelfReferenceLocation = location; } lastLocation = location; - location = isJSDocTemplateTag(location) ? - getEffectiveContainerForJSDocTemplateTag(location) || location.parent : + location = isJSDocTemplateTag(location) ? getEffectiveContainerForJSDocTemplateTag(location) || location.parent : + isJSDocParameterTag(location) || isJSDocReturnTag(location) ? getHostSignatureFromJSDoc(location) || location.parent : location.parent; } @@ -3374,16 +3376,20 @@ namespace ts { return; } const host = getJSDocHost(node); - if (host && - isExpressionStatement(host) && - isBinaryExpression(host.expression) && - getAssignmentDeclarationKind(host.expression) === AssignmentDeclarationKind.PrototypeProperty) { - // X.prototype.m = /** @param {K} p */ function () { } <-- look for K on X's declaration + if (host && isExpressionStatement(host) && isPrototypePropertyAssignment(host.expression)) { + // /** @param {K} p */ X.prototype.m = function () { } <-- look for K on X's declaration const symbol = getSymbolOfNode(host.expression.left); if (symbol) { return getDeclarationOfJSPrototypeContainer(symbol); } } + if (host && isFunctionExpression(host) && isPrototypePropertyAssignment(host.parent) && isExpressionStatement(host.parent.parent)) { + // X.prototype.m = /** @param {K} p */ function () { } <-- look for K on X's declaration + const symbol = getSymbolOfNode(host.parent.left); + if (symbol) { + return getDeclarationOfJSPrototypeContainer(symbol); + } + } if (host && (isObjectLiteralMethod(host) || isPropertyAssignment(host)) && isBinaryExpression(host.parent.parent) && getAssignmentDeclarationKind(host.parent.parent) === AssignmentDeclarationKind.Prototype) { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index c723305b84bb1..cabcb2f9b6cac 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2510,7 +2510,7 @@ namespace ts { return expr.right; } - export function isPrototypePropertyAssignment(node: Node): boolean { + export function isPrototypePropertyAssignment(node: Node): node is BinaryExpression { return isBinaryExpression(node) && getAssignmentDeclarationKind(node) === AssignmentDeclarationKind.PrototypeProperty; } diff --git a/tests/baselines/reference/constructorFunctionMethodTypeParameters.symbols b/tests/baselines/reference/constructorFunctionMethodTypeParameters.symbols new file mode 100644 index 0000000000000..7af38bcb4cf29 --- /dev/null +++ b/tests/baselines/reference/constructorFunctionMethodTypeParameters.symbols @@ -0,0 +1,73 @@ +=== tests/cases/conformance/salsa/constructorFunctionMethodTypeParameters.js === +/** + * @template {string} T + * @param {T} t + */ +function Cls(t) { +>Cls : Symbol(Cls, Decl(constructorFunctionMethodTypeParameters.js, 0, 0)) +>t : Symbol(t, Decl(constructorFunctionMethodTypeParameters.js, 4, 13)) + + this.t = t; +>this.t : Symbol(Cls.t, Decl(constructorFunctionMethodTypeParameters.js, 4, 17)) +>this : Symbol(Cls, Decl(constructorFunctionMethodTypeParameters.js, 0, 0)) +>t : Symbol(Cls.t, Decl(constructorFunctionMethodTypeParameters.js, 4, 17)) +>t : Symbol(t, Decl(constructorFunctionMethodTypeParameters.js, 4, 13)) +} + +/** + * @template {string} V + * @param {T} t + * @param {V} v + * @return {V} + */ +Cls.prototype.topLevelComment = function (t, v) { +>Cls.prototype : Symbol(Cls.topLevelComment, Decl(constructorFunctionMethodTypeParameters.js, 6, 1)) +>Cls : Symbol(Cls, Decl(constructorFunctionMethodTypeParameters.js, 0, 0)) +>prototype : Symbol(Function.prototype, Decl(lib.es5.d.ts, --, --)) +>topLevelComment : Symbol(Cls.topLevelComment, Decl(constructorFunctionMethodTypeParameters.js, 6, 1)) +>t : Symbol(t, Decl(constructorFunctionMethodTypeParameters.js, 14, 42)) +>v : Symbol(v, Decl(constructorFunctionMethodTypeParameters.js, 14, 44)) + + return v +>v : Symbol(v, Decl(constructorFunctionMethodTypeParameters.js, 14, 44)) + +}; + +Cls.prototype.nestedComment = +>Cls.prototype : Symbol(Cls.nestedComment, Decl(constructorFunctionMethodTypeParameters.js, 16, 2)) +>Cls : Symbol(Cls, Decl(constructorFunctionMethodTypeParameters.js, 0, 0)) +>prototype : Symbol(Function.prototype, Decl(lib.es5.d.ts, --, --)) +>nestedComment : Symbol(Cls.nestedComment, Decl(constructorFunctionMethodTypeParameters.js, 16, 2)) + + /** + * @template {string} U + * @param {T} t + * @param {U} u + * @return {T} + */ + function (t, u) { +>t : Symbol(t, Decl(constructorFunctionMethodTypeParameters.js, 25, 14)) +>u : Symbol(u, Decl(constructorFunctionMethodTypeParameters.js, 25, 16)) + + return t +>t : Symbol(t, Decl(constructorFunctionMethodTypeParameters.js, 25, 14)) + + }; + +var c = new Cls('a'); +>c : Symbol(c, Decl(constructorFunctionMethodTypeParameters.js, 29, 3)) +>Cls : Symbol(Cls, Decl(constructorFunctionMethodTypeParameters.js, 0, 0)) + +const s = c.topLevelComment('a', 'b'); +>s : Symbol(s, Decl(constructorFunctionMethodTypeParameters.js, 30, 5)) +>c.topLevelComment : Symbol(Cls.topLevelComment, Decl(constructorFunctionMethodTypeParameters.js, 6, 1)) +>c : Symbol(c, Decl(constructorFunctionMethodTypeParameters.js, 29, 3)) +>topLevelComment : Symbol(Cls.topLevelComment, Decl(constructorFunctionMethodTypeParameters.js, 6, 1)) + +const t = c.nestedComment('a', 'b'); +>t : Symbol(t, Decl(constructorFunctionMethodTypeParameters.js, 31, 5)) +>c.nestedComment : Symbol(Cls.nestedComment, Decl(constructorFunctionMethodTypeParameters.js, 16, 2)) +>c : Symbol(c, Decl(constructorFunctionMethodTypeParameters.js, 29, 3)) +>nestedComment : Symbol(Cls.nestedComment, Decl(constructorFunctionMethodTypeParameters.js, 16, 2)) + + diff --git a/tests/baselines/reference/constructorFunctionMethodTypeParameters.types b/tests/baselines/reference/constructorFunctionMethodTypeParameters.types new file mode 100644 index 0000000000000..707a8922c1ac0 --- /dev/null +++ b/tests/baselines/reference/constructorFunctionMethodTypeParameters.types @@ -0,0 +1,88 @@ +=== tests/cases/conformance/salsa/constructorFunctionMethodTypeParameters.js === +/** + * @template {string} T + * @param {T} t + */ +function Cls(t) { +>Cls : typeof Cls +>t : T + + this.t = t; +>this.t = t : T +>this.t : any +>this : this +>t : any +>t : T +} + +/** + * @template {string} V + * @param {T} t + * @param {V} v + * @return {V} + */ +Cls.prototype.topLevelComment = function (t, v) { +>Cls.prototype.topLevelComment = function (t, v) { return v} : (t: T, v: V) => V +>Cls.prototype.topLevelComment : any +>Cls.prototype : any +>Cls : typeof Cls +>prototype : any +>topLevelComment : any +>function (t, v) { return v} : (t: T, v: V) => V +>t : T +>v : V + + return v +>v : V + +}; + +Cls.prototype.nestedComment = +>Cls.prototype.nestedComment = /** * @template {string} U * @param {T} t * @param {U} u * @return {T} */ function (t, u) { return t } : (t: T, u: U) => T +>Cls.prototype.nestedComment : any +>Cls.prototype : any +>Cls : typeof Cls +>prototype : any +>nestedComment : any + + /** + * @template {string} U + * @param {T} t + * @param {U} u + * @return {T} + */ + function (t, u) { +>function (t, u) { return t } : (t: T, u: U) => T +>t : T +>u : U + + return t +>t : T + + }; + +var c = new Cls('a'); +>c : Cls<"a"> +>new Cls('a') : Cls<"a"> +>Cls : typeof Cls +>'a' : "a" + +const s = c.topLevelComment('a', 'b'); +>s : "b" +>c.topLevelComment('a', 'b') : "b" +>c.topLevelComment : (t: "a", v: V) => V +>c : Cls<"a"> +>topLevelComment : (t: "a", v: V) => V +>'a' : "a" +>'b' : "b" + +const t = c.nestedComment('a', 'b'); +>t : "a" +>c.nestedComment('a', 'b') : "a" +>c.nestedComment : (t: "a", u: U) => "a" +>c : Cls<"a"> +>nestedComment : (t: "a", u: U) => "a" +>'a' : "a" +>'b' : "b" + + diff --git a/tests/cases/conformance/salsa/constructorFunctionMethodTypeParameters.ts b/tests/cases/conformance/salsa/constructorFunctionMethodTypeParameters.ts new file mode 100644 index 0000000000000..bbe6810a15090 --- /dev/null +++ b/tests/cases/conformance/salsa/constructorFunctionMethodTypeParameters.ts @@ -0,0 +1,37 @@ +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @filename: constructorFunctionMethodTypeParameters.js +/** + * @template {string} T + * @param {T} t + */ +function Cls(t) { + this.t = t; +} + +/** + * @template {string} V + * @param {T} t + * @param {V} v + * @return {V} + */ +Cls.prototype.topLevelComment = function (t, v) { + return v +}; + +Cls.prototype.nestedComment = + /** + * @template {string} U + * @param {T} t + * @param {U} u + * @return {T} + */ + function (t, u) { + return t + }; + +var c = new Cls('a'); +const s = c.topLevelComment('a', 'b'); +const t = c.nestedComment('a', 'b'); + From 2d0a00d45739d6344c4996f2b073580570de05e7 Mon Sep 17 00:00:00 2001 From: Gabriela Araujo Britto Date: Wed, 9 Feb 2022 17:25:07 -0300 Subject: [PATCH 30/55] Fix destructuring and narrowing interaction (#47337) * WIP: pass in checkmode to getNarrowableTypeForReference * add tests * another pass through new check mode argument * rename new check mode * only use rest flag for rest elements in objects * add and update tests * change check mode flag name * restore package-lock.json * fix comments * get rid of fourslash tests * fix caching in checkExpressionCached when checkMode is not normal * Don't distinguish between object and array rest elements * get rid of undefined check mode * don't make includeOptionality into checkmode flag --- src/compiler/checker.ts | 82 ++++++---- .../genericObjectSpreadResultInSwitch.types | 2 +- .../reference/narrowingDestructuring.js | 89 +++++++++++ .../reference/narrowingDestructuring.symbols | 148 +++++++++++++++++ .../reference/narrowingDestructuring.types | 150 ++++++++++++++++++ .../reference/restInvalidArgumentType.types | 2 +- .../cases/compiler/narrowingDestructuring.ts | 39 +++++ 7 files changed, 480 insertions(+), 32 deletions(-) create mode 100644 tests/baselines/reference/narrowingDestructuring.js create mode 100644 tests/baselines/reference/narrowingDestructuring.symbols create mode 100644 tests/baselines/reference/narrowingDestructuring.types create mode 100644 tests/cases/compiler/narrowingDestructuring.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index dae973d634603..36176613d6246 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -175,12 +175,15 @@ namespace ts { } const enum CheckMode { - Normal = 0, // Normal type checking - Contextual = 1 << 0, // Explicitly assigned contextual type, therefore not cacheable - Inferential = 1 << 1, // Inferential typing - SkipContextSensitive = 1 << 2, // Skip context sensitive function expressions - SkipGenericFunctions = 1 << 3, // Skip single signature generic functions - IsForSignatureHelp = 1 << 4, // Call resolution for purposes of signature help + Normal = 0, // Normal type checking + Contextual = 1 << 0, // Explicitly assigned contextual type, therefore not cacheable + Inferential = 1 << 1, // Inferential typing + SkipContextSensitive = 1 << 2, // Skip context sensitive function expressions + SkipGenericFunctions = 1 << 3, // Skip single signature generic functions + IsForSignatureHelp = 1 << 4, // Call resolution for purposes of signature help + RestBindingElement = 1 << 5, // Checking a type that is going to be used to determine the type of a rest binding element + // e.g. in `const { a, ...rest } = foo`, when checking the type of `foo` to determine the type of `rest`, + // we need to preserve generic types instead of substituting them for constraints } const enum SignatureCheckMode { @@ -8461,9 +8464,12 @@ namespace ts { // Return the type of a binding element parent. We check SymbolLinks first to see if a type has been // assigned by contextual typing. - function getTypeForBindingElementParent(node: BindingElementGrandparent) { + function getTypeForBindingElementParent(node: BindingElementGrandparent, checkMode: CheckMode) { + if (checkMode !== CheckMode.Normal) { + return getTypeForVariableLikeDeclaration(node, /*includeOptionality*/ false, checkMode); + } const symbol = getSymbolOfNode(node); - return symbol && getSymbolLinks(symbol).type || getTypeForVariableLikeDeclaration(node, /*includeOptionality*/ false); + return symbol && getSymbolLinks(symbol).type || getTypeForVariableLikeDeclaration(node, /*includeOptionality*/ false, checkMode); } function getRestType(source: Type, properties: PropertyName[], symbol: Symbol | undefined): Type { @@ -8594,7 +8600,8 @@ namespace ts { /** Return the inferred type for a binding element */ function getTypeForBindingElement(declaration: BindingElement): Type | undefined { - const parentType = getTypeForBindingElementParent(declaration.parent.parent); + const checkMode = declaration.dotDotDotToken ? CheckMode.RestBindingElement : CheckMode.Normal; + const parentType = getTypeForBindingElementParent(declaration.parent.parent, checkMode); return parentType && getBindingElementTypeFromParentType(declaration, parentType); } @@ -8667,9 +8674,9 @@ namespace ts { if (getEffectiveTypeAnnotationNode(walkUpBindingElementsAndPatterns(declaration))) { // In strict null checking mode, if a default value of a non-undefined type is specified, remove // undefined from the final type. - return strictNullChecks && !(getFalsyFlags(checkDeclarationInitializer(declaration)) & TypeFlags.Undefined) ? getNonUndefinedType(type) : type; + return strictNullChecks && !(getFalsyFlags(checkDeclarationInitializer(declaration, CheckMode.Normal)) & TypeFlags.Undefined) ? getNonUndefinedType(type) : type; } - return widenTypeInferredFromInitializer(declaration, getUnionType([getNonUndefinedType(type), checkDeclarationInitializer(declaration)], UnionReduction.Subtype)); + return widenTypeInferredFromInitializer(declaration, getUnionType([getNonUndefinedType(type), checkDeclarationInitializer(declaration, CheckMode.Normal)], UnionReduction.Subtype)); } function getTypeForDeclarationFromJSDocComment(declaration: Node) { @@ -8695,11 +8702,15 @@ namespace ts { } // Return the inferred type for a variable, parameter, or property declaration - function getTypeForVariableLikeDeclaration(declaration: ParameterDeclaration | PropertyDeclaration | PropertySignature | VariableDeclaration | BindingElement | JSDocPropertyLikeTag, includeOptionality: boolean): Type | undefined { + function getTypeForVariableLikeDeclaration( + declaration: ParameterDeclaration | PropertyDeclaration | PropertySignature | VariableDeclaration | BindingElement | JSDocPropertyLikeTag, + includeOptionality: boolean, + checkMode: CheckMode, + ): Type | undefined { // A variable declared in a for..in statement is of type string, or of type keyof T when the // right hand expression is of a type parameter type. if (isVariableDeclaration(declaration) && declaration.parent.parent.kind === SyntaxKind.ForInStatement) { - const indexType = getIndexType(getNonNullableTypeIfNeeded(checkExpression(declaration.parent.parent.expression))); + const indexType = getIndexType(getNonNullableTypeIfNeeded(checkExpression(declaration.parent.parent.expression, /*checkMode*/ checkMode))); return indexType.flags & (TypeFlags.TypeParameter | TypeFlags.Index) ? getExtractStringType(indexType) : stringType; } @@ -8784,7 +8795,7 @@ namespace ts { return containerObjectType; } } - const type = widenTypeInferredFromInitializer(declaration, checkDeclarationInitializer(declaration)); + const type = widenTypeInferredFromInitializer(declaration, checkDeclarationInitializer(declaration, checkMode)); return addOptionality(type, isProperty, isOptional); } @@ -9177,7 +9188,7 @@ namespace ts { // 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, contextualType))); + return addOptionality(widenTypeInferredFromInitializer(element, checkDeclarationInitializer(element, CheckMode.Normal, contextualType))); } if (isBindingPattern(element.name)) { return getTypeFromBindingPattern(element.name, includePatternInType, reportErrors); @@ -9269,7 +9280,7 @@ namespace ts { // binding pattern [x, s = ""]. Because the contextual type is a tuple type, the resulting type of [1, "one"] is the // tuple type [number, string]. Thus, the type inferred for 'x' is number and the type inferred for 's' is string. function getWidenedTypeForVariableLikeDeclaration(declaration: ParameterDeclaration | PropertyDeclaration | PropertySignature | VariableDeclaration | BindingElement | JSDocPropertyLikeTag, reportErrors?: boolean): Type { - return widenTypeForVariableLikeDeclaration(getTypeForVariableLikeDeclaration(declaration, /*includeOptionality*/ true), declaration, reportErrors); + return widenTypeForVariableLikeDeclaration(getTypeForVariableLikeDeclaration(declaration, /*includeOptionality*/ true, CheckMode.Normal), declaration, reportErrors); } function isGlobalSymbolConstructor(node: Node) { @@ -25019,12 +25030,16 @@ namespace ts { return !!(type.flags & TypeFlags.Instantiable && !maybeTypeOfKind(getBaseConstraintOrType(type), TypeFlags.Nullable)); } - function hasNonBindingPatternContextualTypeWithNoGenericTypes(node: Node) { + function hasContextualTypeWithNoGenericTypes(node: Node, checkMode: CheckMode | undefined) { // Computing the contextual type for a child of a JSX element involves resolving the type of the // element's tag name, so we exclude that here to avoid circularities. + // If check mode has `CheckMode.RestBindingElement`, we skip binding pattern contextual types, + // as we want the type of a rest element to be generic when possible. const contextualType = (isIdentifier(node) || isPropertyAccessExpression(node) || isElementAccessExpression(node)) && !((isJsxOpeningElement(node.parent) || isJsxSelfClosingElement(node.parent)) && node.parent.tagName === node) && - getContextualType(node, ContextFlags.SkipBindingPatterns); + (checkMode && checkMode & CheckMode.RestBindingElement ? + getContextualType(node, ContextFlags.SkipBindingPatterns) + : getContextualType(node)); return contextualType && !isGenericType(contextualType); } @@ -25038,7 +25053,7 @@ namespace ts { // 'string | undefined' to give control flow analysis the opportunity to narrow to type 'string'. const substituteConstraints = !(checkMode && checkMode & CheckMode.Inferential) && someType(type, isGenericTypeWithUnionConstraint) && - (isConstraintPosition(type, reference) || hasNonBindingPatternContextualTypeWithNoGenericTypes(reference)); + (isConstraintPosition(type, reference) || hasContextualTypeWithNoGenericTypes(reference, checkMode)); return substituteConstraints ? mapType(type, t => t.flags & TypeFlags.Instantiable && !isMappedTypeGenericIndexedAccess(t) ? getBaseConstraintOrType(t) : t) : type; } @@ -25110,7 +25125,7 @@ namespace ts { const links = getNodeLinks(location); if (!(links.flags & NodeCheckFlags.InCheckIdentifier)) { links.flags |= NodeCheckFlags.InCheckIdentifier; - const parentType = getTypeForBindingElementParent(parent); + const parentType = getTypeForBindingElementParent(parent, CheckMode.Normal); links.flags &= ~NodeCheckFlags.InCheckIdentifier; if (parentType && parentType.flags & TypeFlags.Union && !(parent.kind === SyntaxKind.Parameter && isSymbolAssigned(symbol))) { const pattern = declaration.parent; @@ -26047,7 +26062,7 @@ namespace ts { const parent = declaration.parent.parent; const name = declaration.propertyName || declaration.name; const parentType = getContextualTypeForVariableLikeDeclaration(parent) || - parent.kind !== SyntaxKind.BindingElement && parent.initializer && checkDeclarationInitializer(parent); + parent.kind !== SyntaxKind.BindingElement && parent.initializer && checkDeclarationInitializer(parent, declaration.dotDotDotToken ? CheckMode.RestBindingElement : CheckMode.Normal); if (!parentType || isBindingPattern(name) || isComputedNonLiteralName(name)) return undefined; if (parent.name.kind === SyntaxKind.ArrayBindingPattern) { const index = indexOfNode(declaration.parent.elements, declaration); @@ -31807,7 +31822,7 @@ namespace ts { const links = getSymbolLinks(parameter); if (!links.type) { const declaration = parameter.valueDeclaration as ParameterDeclaration; - links.type = type || getWidenedTypeForVariableLikeDeclaration(declaration, /*includeOptionality*/ true); + links.type = type || getWidenedTypeForVariableLikeDeclaration(declaration, /*reportErrors*/ true); if (declaration.name.kind !== SyntaxKind.Identifier) { // if inference didn't come up with anything but unknown, fall back to the binding pattern if present. if (links.type === unknownType) { @@ -33724,11 +33739,11 @@ namespace ts { } function checkExpressionCached(node: Expression | QualifiedName, checkMode?: CheckMode): Type { + if (checkMode && checkMode !== CheckMode.Normal) { + return checkExpression(node, checkMode); + } const links = getNodeLinks(node); if (!links.resolvedType) { - if (checkMode && checkMode !== CheckMode.Normal) { - return checkExpression(node, checkMode); - } // When computing a type that we're going to cache, we need to ignore any ongoing control flow // analysis because variables may have transient types in indeterminable states. Moving flowLoopStart // to the top of the stack ensures all transient types are computed from a known point. @@ -33750,10 +33765,16 @@ namespace ts { isJSDocTypeAssertion(node); } - function checkDeclarationInitializer(declaration: HasExpressionInitializer, contextualType?: Type | undefined) { + function checkDeclarationInitializer( + declaration: HasExpressionInitializer, + checkMode: CheckMode, + contextualType?: Type | undefined + ) { const initializer = getEffectiveInitializer(declaration)!; const type = getQuickTypeOfExpression(initializer) || - (contextualType ? checkExpressionWithContextualType(initializer, contextualType, /*inferenceContext*/ undefined, CheckMode.Normal) : checkExpressionCached(initializer)); + (contextualType ? + checkExpressionWithContextualType(initializer, contextualType, /*inferenceContext*/ undefined, checkMode || CheckMode.Normal) + : checkExpressionCached(initializer, checkMode)); return isParameter(declaration) && declaration.name.kind === SyntaxKind.ArrayBindingPattern && isTupleType(type) && !type.target.hasRestElement && getTypeReferenceArity(type) < declaration.name.elements.length ? padTupleType(type, declaration.name) : type; @@ -37011,7 +37032,8 @@ namespace ts { // check private/protected variable access const parent = node.parent.parent; - const parentType = getTypeForBindingElementParent(parent); + const parentCheckMode = node.dotDotDotToken ? CheckMode.RestBindingElement : CheckMode.Normal; + const parentType = getTypeForBindingElementParent(parent, parentCheckMode); const name = node.propertyName || node.name; if (parentType && !isBindingPattern(name)) { const exprType = getLiteralTypeFromPropertyName(name); @@ -38409,7 +38431,7 @@ namespace ts { const declaration = catchClause.variableDeclaration; const typeNode = getEffectiveTypeAnnotationNode(getRootDeclaration(declaration)); if (typeNode) { - const type = getTypeForVariableLikeDeclaration(declaration, /*includeOptionality*/ false); + const type = getTypeForVariableLikeDeclaration(declaration, /*includeOptionality*/ false, CheckMode.Normal); if (type && !(type.flags & TypeFlags.AnyOrUnknown)) { grammarErrorOnFirstToken(typeNode, Diagnostics.Catch_clause_variable_type_annotation_must_be_any_or_unknown_if_specified); } @@ -41440,7 +41462,7 @@ namespace ts { } if (isBindingPattern(node)) { - return getTypeForVariableLikeDeclaration(node.parent, /*includeOptionality*/ true) || errorType; + return getTypeForVariableLikeDeclaration(node.parent, /*includeOptionality*/ true, CheckMode.Normal) || errorType; } if (isInRightSideOfImportOrExportAssignment(node as Identifier)) { diff --git a/tests/baselines/reference/genericObjectSpreadResultInSwitch.types b/tests/baselines/reference/genericObjectSpreadResultInSwitch.types index 33f485c465bd3..4c9ca429daa37 100644 --- a/tests/baselines/reference/genericObjectSpreadResultInSwitch.types +++ b/tests/baselines/reference/genericObjectSpreadResultInSwitch.types @@ -25,7 +25,7 @@ const getType =

(params: P) => { >rest : Omit } = params; ->params : P +>params : Params return rest; >rest : Omit diff --git a/tests/baselines/reference/narrowingDestructuring.js b/tests/baselines/reference/narrowingDestructuring.js new file mode 100644 index 0000000000000..4bc052b7fa0f4 --- /dev/null +++ b/tests/baselines/reference/narrowingDestructuring.js @@ -0,0 +1,89 @@ +//// [narrowingDestructuring.ts] +type X = { kind: "a", a: string } | { kind: "b", b: string } + +function func(value: T) { + if (value.kind === "a") { + value.a; + const { a } = value; + } else { + value.b; + const { b } = value; + } +} + +type Z = { kind: "f", f: { a: number, b: string, c: number } } + | { kind: "g", g: { a: string, b: number, c: string }}; + +function func2(value: T) { + if (value.kind === "f") { + const { f: f1 } = value; + const { f: { a, ...spread } } = value; + value.f; + } else { + const { g: { c, ...spread } } = value; + value.g; + } +} + +function func3(t: T) { + if (t.kind === "a") { + const { kind, ...r1 } = t; + const r2 = (({ kind, ...rest }) => rest)(t); + } +} + +function farr(x: T) { + const [head, ...tail] = x; + if (x[0] === 'number') { + const [head, ...tail] = x; + } +} + +//// [narrowingDestructuring.js] +var __rest = (this && this.__rest) || function (s, e) { + var t = {}; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) + t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === "function") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { + if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) + t[p[i]] = s[p[i]]; + } + return t; +}; +function func(value) { + if (value.kind === "a") { + value.a; + var a = value.a; + } + else { + value.b; + var b = value.b; + } +} +function func2(value) { + if (value.kind === "f") { + var f1 = value.f; + var _a = value.f, a = _a.a, spread = __rest(_a, ["a"]); + value.f; + } + else { + var _b = value.g, c = _b.c, spread = __rest(_b, ["c"]); + value.g; + } +} +function func3(t) { + if (t.kind === "a") { + var kind = t.kind, r1 = __rest(t, ["kind"]); + var r2 = (function (_a) { + var kind = _a.kind, rest = __rest(_a, ["kind"]); + return rest; + })(t); + } +} +function farr(x) { + var head = x[0], tail = x.slice(1); + if (x[0] === 'number') { + var head_1 = x[0], tail_1 = x.slice(1); + } +} diff --git a/tests/baselines/reference/narrowingDestructuring.symbols b/tests/baselines/reference/narrowingDestructuring.symbols new file mode 100644 index 0000000000000..9e7b65997d6a2 --- /dev/null +++ b/tests/baselines/reference/narrowingDestructuring.symbols @@ -0,0 +1,148 @@ +=== tests/cases/compiler/narrowingDestructuring.ts === +type X = { kind: "a", a: string } | { kind: "b", b: string } +>X : Symbol(X, Decl(narrowingDestructuring.ts, 0, 0)) +>kind : Symbol(kind, Decl(narrowingDestructuring.ts, 0, 10)) +>a : Symbol(a, Decl(narrowingDestructuring.ts, 0, 21)) +>kind : Symbol(kind, Decl(narrowingDestructuring.ts, 0, 37)) +>b : Symbol(b, Decl(narrowingDestructuring.ts, 0, 48)) + +function func(value: T) { +>func : Symbol(func, Decl(narrowingDestructuring.ts, 0, 60)) +>T : Symbol(T, Decl(narrowingDestructuring.ts, 2, 14)) +>X : Symbol(X, Decl(narrowingDestructuring.ts, 0, 0)) +>value : Symbol(value, Decl(narrowingDestructuring.ts, 2, 27)) +>T : Symbol(T, Decl(narrowingDestructuring.ts, 2, 14)) + + if (value.kind === "a") { +>value.kind : Symbol(kind, Decl(narrowingDestructuring.ts, 0, 10), Decl(narrowingDestructuring.ts, 0, 37)) +>value : Symbol(value, Decl(narrowingDestructuring.ts, 2, 27)) +>kind : Symbol(kind, Decl(narrowingDestructuring.ts, 0, 10), Decl(narrowingDestructuring.ts, 0, 37)) + + value.a; +>value.a : Symbol(a, Decl(narrowingDestructuring.ts, 0, 21)) +>value : Symbol(value, Decl(narrowingDestructuring.ts, 2, 27)) +>a : Symbol(a, Decl(narrowingDestructuring.ts, 0, 21)) + + const { a } = value; +>a : Symbol(a, Decl(narrowingDestructuring.ts, 5, 15)) +>value : Symbol(value, Decl(narrowingDestructuring.ts, 2, 27)) + + } else { + value.b; +>value.b : Symbol(b, Decl(narrowingDestructuring.ts, 0, 48)) +>value : Symbol(value, Decl(narrowingDestructuring.ts, 2, 27)) +>b : Symbol(b, Decl(narrowingDestructuring.ts, 0, 48)) + + const { b } = value; +>b : Symbol(b, Decl(narrowingDestructuring.ts, 8, 15)) +>value : Symbol(value, Decl(narrowingDestructuring.ts, 2, 27)) + } +} + +type Z = { kind: "f", f: { a: number, b: string, c: number } } +>Z : Symbol(Z, Decl(narrowingDestructuring.ts, 10, 1)) +>kind : Symbol(kind, Decl(narrowingDestructuring.ts, 12, 10)) +>f : Symbol(f, Decl(narrowingDestructuring.ts, 12, 21)) +>a : Symbol(a, Decl(narrowingDestructuring.ts, 12, 26)) +>b : Symbol(b, Decl(narrowingDestructuring.ts, 12, 37)) +>c : Symbol(c, Decl(narrowingDestructuring.ts, 12, 48)) + + | { kind: "g", g: { a: string, b: number, c: string }}; +>kind : Symbol(kind, Decl(narrowingDestructuring.ts, 13, 7)) +>g : Symbol(g, Decl(narrowingDestructuring.ts, 13, 18)) +>a : Symbol(a, Decl(narrowingDestructuring.ts, 13, 23)) +>b : Symbol(b, Decl(narrowingDestructuring.ts, 13, 34)) +>c : Symbol(c, Decl(narrowingDestructuring.ts, 13, 45)) + +function func2(value: T) { +>func2 : Symbol(func2, Decl(narrowingDestructuring.ts, 13, 59)) +>T : Symbol(T, Decl(narrowingDestructuring.ts, 15, 15)) +>Z : Symbol(Z, Decl(narrowingDestructuring.ts, 10, 1)) +>value : Symbol(value, Decl(narrowingDestructuring.ts, 15, 28)) +>T : Symbol(T, Decl(narrowingDestructuring.ts, 15, 15)) + + if (value.kind === "f") { +>value.kind : Symbol(kind, Decl(narrowingDestructuring.ts, 12, 10), Decl(narrowingDestructuring.ts, 13, 7)) +>value : Symbol(value, Decl(narrowingDestructuring.ts, 15, 28)) +>kind : Symbol(kind, Decl(narrowingDestructuring.ts, 12, 10), Decl(narrowingDestructuring.ts, 13, 7)) + + const { f: f1 } = value; +>f : Symbol(f, Decl(narrowingDestructuring.ts, 12, 21)) +>f1 : Symbol(f1, Decl(narrowingDestructuring.ts, 17, 15)) +>value : Symbol(value, Decl(narrowingDestructuring.ts, 15, 28)) + + const { f: { a, ...spread } } = value; +>f : Symbol(f, Decl(narrowingDestructuring.ts, 12, 21)) +>a : Symbol(a, Decl(narrowingDestructuring.ts, 18, 20)) +>spread : Symbol(spread, Decl(narrowingDestructuring.ts, 18, 23)) +>value : Symbol(value, Decl(narrowingDestructuring.ts, 15, 28)) + + value.f; +>value.f : Symbol(f, Decl(narrowingDestructuring.ts, 12, 21)) +>value : Symbol(value, Decl(narrowingDestructuring.ts, 15, 28)) +>f : Symbol(f, Decl(narrowingDestructuring.ts, 12, 21)) + + } else { + const { g: { c, ...spread } } = value; +>g : Symbol(g, Decl(narrowingDestructuring.ts, 13, 18)) +>c : Symbol(c, Decl(narrowingDestructuring.ts, 21, 20)) +>spread : Symbol(spread, Decl(narrowingDestructuring.ts, 21, 23)) +>value : Symbol(value, Decl(narrowingDestructuring.ts, 15, 28)) + + value.g; +>value.g : Symbol(g, Decl(narrowingDestructuring.ts, 13, 18)) +>value : Symbol(value, Decl(narrowingDestructuring.ts, 15, 28)) +>g : Symbol(g, Decl(narrowingDestructuring.ts, 13, 18)) + } +} + +function func3(t: T) { +>func3 : Symbol(func3, Decl(narrowingDestructuring.ts, 24, 1)) +>T : Symbol(T, Decl(narrowingDestructuring.ts, 26, 15)) +>kind : Symbol(kind, Decl(narrowingDestructuring.ts, 26, 26)) +>a : Symbol(a, Decl(narrowingDestructuring.ts, 26, 37)) +>kind : Symbol(kind, Decl(narrowingDestructuring.ts, 26, 53)) +>b : Symbol(b, Decl(narrowingDestructuring.ts, 26, 64)) +>t : Symbol(t, Decl(narrowingDestructuring.ts, 26, 78)) +>T : Symbol(T, Decl(narrowingDestructuring.ts, 26, 15)) + + if (t.kind === "a") { +>t.kind : Symbol(kind, Decl(narrowingDestructuring.ts, 26, 26), Decl(narrowingDestructuring.ts, 26, 53)) +>t : Symbol(t, Decl(narrowingDestructuring.ts, 26, 78)) +>kind : Symbol(kind, Decl(narrowingDestructuring.ts, 26, 26), Decl(narrowingDestructuring.ts, 26, 53)) + + const { kind, ...r1 } = t; +>kind : Symbol(kind, Decl(narrowingDestructuring.ts, 28, 15)) +>r1 : Symbol(r1, Decl(narrowingDestructuring.ts, 28, 21)) +>t : Symbol(t, Decl(narrowingDestructuring.ts, 26, 78)) + + const r2 = (({ kind, ...rest }) => rest)(t); +>r2 : Symbol(r2, Decl(narrowingDestructuring.ts, 29, 13)) +>kind : Symbol(kind, Decl(narrowingDestructuring.ts, 29, 22)) +>rest : Symbol(rest, Decl(narrowingDestructuring.ts, 29, 28)) +>rest : Symbol(rest, Decl(narrowingDestructuring.ts, 29, 28)) +>t : Symbol(t, Decl(narrowingDestructuring.ts, 26, 78)) + } +} + +function farr(x: T) { +>farr : Symbol(farr, Decl(narrowingDestructuring.ts, 31, 1)) +>T : Symbol(T, Decl(narrowingDestructuring.ts, 33, 14)) +>x : Symbol(x, Decl(narrowingDestructuring.ts, 33, 77)) +>T : Symbol(T, Decl(narrowingDestructuring.ts, 33, 14)) + + const [head, ...tail] = x; +>head : Symbol(head, Decl(narrowingDestructuring.ts, 34, 11)) +>tail : Symbol(tail, Decl(narrowingDestructuring.ts, 34, 16)) +>x : Symbol(x, Decl(narrowingDestructuring.ts, 33, 77)) + + if (x[0] === 'number') { +>x : Symbol(x, Decl(narrowingDestructuring.ts, 33, 77)) +>0 : Symbol(0) + + const [head, ...tail] = x; +>head : Symbol(head, Decl(narrowingDestructuring.ts, 36, 15)) +>tail : Symbol(tail, Decl(narrowingDestructuring.ts, 36, 20)) +>x : Symbol(x, Decl(narrowingDestructuring.ts, 33, 77)) + } +} diff --git a/tests/baselines/reference/narrowingDestructuring.types b/tests/baselines/reference/narrowingDestructuring.types new file mode 100644 index 0000000000000..a942e163da860 --- /dev/null +++ b/tests/baselines/reference/narrowingDestructuring.types @@ -0,0 +1,150 @@ +=== tests/cases/compiler/narrowingDestructuring.ts === +type X = { kind: "a", a: string } | { kind: "b", b: string } +>X : X +>kind : "a" +>a : string +>kind : "b" +>b : string + +function func(value: T) { +>func : (value: T) => void +>value : T + + if (value.kind === "a") { +>value.kind === "a" : boolean +>value.kind : "a" | "b" +>value : X +>kind : "a" | "b" +>"a" : "a" + + value.a; +>value.a : string +>value : { kind: "a"; a: string; } +>a : string + + const { a } = value; +>a : string +>value : { kind: "a"; a: string; } + + } else { + value.b; +>value.b : string +>value : { kind: "b"; b: string; } +>b : string + + const { b } = value; +>b : string +>value : { kind: "b"; b: string; } + } +} + +type Z = { kind: "f", f: { a: number, b: string, c: number } } +>Z : Z +>kind : "f" +>f : { a: number; b: string; c: number; } +>a : number +>b : string +>c : number + + | { kind: "g", g: { a: string, b: number, c: string }}; +>kind : "g" +>g : { a: string; b: number; c: string; } +>a : string +>b : number +>c : string + +function func2(value: T) { +>func2 : (value: T) => void +>value : T + + if (value.kind === "f") { +>value.kind === "f" : boolean +>value.kind : "f" | "g" +>value : Z +>kind : "f" | "g" +>"f" : "f" + + const { f: f1 } = value; +>f : any +>f1 : { a: number; b: string; c: number; } +>value : { kind: "f"; f: { a: number; b: string; c: number; }; } + + const { f: { a, ...spread } } = value; +>f : any +>a : number +>spread : { b: string; c: number; } +>value : { kind: "f"; f: { a: number; b: string; c: number; }; } + + value.f; +>value.f : { a: number; b: string; c: number; } +>value : { kind: "f"; f: { a: number; b: string; c: number; }; } +>f : { a: number; b: string; c: number; } + + } else { + const { g: { c, ...spread } } = value; +>g : any +>c : string +>spread : { a: string; b: number; } +>value : { kind: "g"; g: { a: string; b: number; c: string; }; } + + value.g; +>value.g : { a: string; b: number; c: string; } +>value : { kind: "g"; g: { a: string; b: number; c: string; }; } +>g : { a: string; b: number; c: string; } + } +} + +function func3(t: T) { +>func3 : (t: T) => void +>kind : "a" +>a : string +>kind : "b" +>b : number +>t : T + + if (t.kind === "a") { +>t.kind === "a" : boolean +>t.kind : "a" | "b" +>t : { kind: "a"; a: string; } | { kind: "b"; b: number; } +>kind : "a" | "b" +>"a" : "a" + + const { kind, ...r1 } = t; +>kind : "a" +>r1 : Omit +>t : { kind: "a"; a: string; } + + const r2 = (({ kind, ...rest }) => rest)(t); +>r2 : { a: string; } +>(({ kind, ...rest }) => rest)(t) : { a: string; } +>(({ kind, ...rest }) => rest) : ({ kind, ...rest }: { kind: "a"; a: string; }) => { a: string; } +>({ kind, ...rest }) => rest : ({ kind, ...rest }: { kind: "a"; a: string; }) => { a: string; } +>kind : "a" +>rest : { a: string; } +>rest : { a: string; } +>t : { kind: "a"; a: string; } + } +} + +function farr(x: T) { +>farr : (x: T) => void +>x : T + + const [head, ...tail] = x; +>head : string | number +>tail : (string | number)[] +>x : [number, string, string] | [string, number, number] + + if (x[0] === 'number') { +>x[0] === 'number' : boolean +>x[0] : string | number +>x : [number, string, string] | [string, number, number] +>0 : 0 +>'number' : "number" + + const [head, ...tail] = x; +>head : "number" +>tail : (string | number)[] +>x : [number, string, string] | [string, number, number] + } +} diff --git a/tests/baselines/reference/restInvalidArgumentType.types b/tests/baselines/reference/restInvalidArgumentType.types index 0e44cdfe95ccb..119b0394726da 100644 --- a/tests/baselines/reference/restInvalidArgumentType.types +++ b/tests/baselines/reference/restInvalidArgumentType.types @@ -84,7 +84,7 @@ function f(p1: T, p2: T[]) { var {...r5} = k; // Error, index >r5 : any ->k : keyof T +>k : string | number | symbol var {...r6} = mapped_generic; // Error, generic mapped object type >r6 : { [P in keyof T]: T[P]; } diff --git a/tests/cases/compiler/narrowingDestructuring.ts b/tests/cases/compiler/narrowingDestructuring.ts new file mode 100644 index 0000000000000..a745802825945 --- /dev/null +++ b/tests/cases/compiler/narrowingDestructuring.ts @@ -0,0 +1,39 @@ +type X = { kind: "a", a: string } | { kind: "b", b: string } + +function func(value: T) { + if (value.kind === "a") { + value.a; + const { a } = value; + } else { + value.b; + const { b } = value; + } +} + +type Z = { kind: "f", f: { a: number, b: string, c: number } } + | { kind: "g", g: { a: string, b: number, c: string }}; + +function func2(value: T) { + if (value.kind === "f") { + const { f: f1 } = value; + const { f: { a, ...spread } } = value; + value.f; + } else { + const { g: { c, ...spread } } = value; + value.g; + } +} + +function func3(t: T) { + if (t.kind === "a") { + const { kind, ...r1 } = t; + const r2 = (({ kind, ...rest }) => rest)(t); + } +} + +function farr(x: T) { + const [head, ...tail] = x; + if (x[0] === 'number') { + const [head, ...tail] = x; + } +} \ No newline at end of file From 95c22d1750d16592317ad42affd005fb9344ceed Mon Sep 17 00:00:00 2001 From: islandryu <65934663+islandryu@users.noreply.github.com> Date: Thu, 10 Feb 2022 06:19:30 +0900 Subject: [PATCH 31/55] fix(47076):Fix error term of declaration in modules (#47087) * Fix error term of declaration in modules * fix test * change error code of "An import declaration can only be used at the top level of a module." * Separate js and ts files for export errors in module. * Change non-top-level error in namespace * format Co-authored-by: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> --- src/compiler/checker.ts | 8 ++-- src/compiler/diagnosticMessages.json | 16 +++++-- src/compiler/program.ts | 4 +- ...DeclarationInModuleDeclaration2.errors.txt | 9 ++++ ...ortDeclarationInModuleDeclaration2.symbols | 6 +++ ...mportDeclarationInModuleDeclaration2.types | 6 +++ .../labeledStatementWithLabel.errors.txt | 8 ++-- ...abeledStatementWithLabel_es2015.errors.txt | 8 ++-- ...abeledStatementWithLabel_strict.errors.txt | 8 ++-- .../moduleElementsInWrongContext.errors.txt | 48 +++++++++---------- .../moduleElementsInWrongContext2.errors.txt | 48 +++++++++---------- .../moduleElementsInWrongContext3.errors.txt | 48 +++++++++---------- .../reference/plainJSGrammarErrors.errors.txt | 8 ++-- .../importDeclarationInModuleDeclaration2.ts | 8 ++++ 14 files changed, 135 insertions(+), 98 deletions(-) create mode 100644 tests/baselines/reference/importDeclarationInModuleDeclaration2.errors.txt create mode 100644 tests/baselines/reference/importDeclarationInModuleDeclaration2.symbols create mode 100644 tests/baselines/reference/importDeclarationInModuleDeclaration2.types create mode 100644 tests/cases/compiler/importDeclarationInModuleDeclaration2.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 36176613d6246..f901db2ab4c5c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -39683,7 +39683,7 @@ namespace ts { const isAmbientExternalModule: boolean = isAmbientModule(node); const contextErrorMessage = isAmbientExternalModule ? Diagnostics.An_ambient_module_declaration_is_only_allowed_at_the_top_level_in_a_file - : Diagnostics.A_namespace_declaration_is_only_allowed_in_a_namespace_or_module; + : Diagnostics.A_namespace_declaration_is_only_allowed_at_the_top_level_of_a_namespace_or_module; if (checkGrammarModuleElementContext(node, contextErrorMessage)) { // If we hit a module declaration in an illegal context, just bail out to avoid cascading errors. return; @@ -40021,7 +40021,7 @@ namespace ts { } function checkImportDeclaration(node: ImportDeclaration) { - if (checkGrammarModuleElementContext(node, Diagnostics.An_import_declaration_can_only_be_used_in_a_namespace_or_module)) { + 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. return; } @@ -40055,7 +40055,7 @@ namespace ts { } function checkImportEqualsDeclaration(node: ImportEqualsDeclaration) { - if (checkGrammarModuleElementContext(node, Diagnostics.An_import_declaration_can_only_be_used_in_a_namespace_or_module)) { + 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. return; } @@ -40094,7 +40094,7 @@ namespace ts { } function checkExportDeclaration(node: ExportDeclaration) { - if (checkGrammarModuleElementContext(node, Diagnostics.An_export_declaration_can_only_be_used_in_a_module)) { + if (checkGrammarModuleElementContext(node, isInJSFile(node) ? Diagnostics.An_export_declaration_can_only_be_used_at_the_top_level_of_a_module : Diagnostics.An_export_declaration_can_only_be_used_at_the_top_level_of_a_namespace_or_module)) { // If we hit an export in an illegal context, just bail out to avoid cascading errors. return; } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 34685f0ef7b28..a51336a4829dc 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -727,11 +727,11 @@ "category": "Error", "code": 1231 }, - "An import declaration can only be used in a namespace or module.": { + "An import declaration can only be used at the top level of a namespace or module.": { "category": "Error", "code": 1232 }, - "An export declaration can only be used in a module.": { + "An export declaration can only be used at the top level of a namespace or module.": { "category": "Error", "code": 1233 }, @@ -739,7 +739,7 @@ "category": "Error", "code": 1234 }, - "A namespace declaration is only allowed in a namespace or module.": { + "A namespace declaration is only allowed at the top level of a namespace or module.": { "category": "Error", "code": 1235 }, @@ -1413,7 +1413,15 @@ "category": "Error", "code": 1472 }, - + "An import declaration can only be used at the top level of a module.": { + "category": "Error", + "code": 1473 + }, + "An export declaration can only be used at the top level of a module.": { + "category": "Error", + "code": 1474 + }, + "The types of '{0}' are incompatible between these types.": { "category": "Error", "code": 2200 diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 7017f138224e9..f6cacfe719881 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -861,9 +861,9 @@ namespace ts { Diagnostics.A_return_statement_cannot_be_used_inside_a_class_static_block.code, Diagnostics.A_set_accessor_cannot_have_rest_parameter.code, Diagnostics.A_set_accessor_must_have_exactly_one_parameter.code, - Diagnostics.An_export_declaration_can_only_be_used_in_a_module.code, + Diagnostics.An_export_declaration_can_only_be_used_at_the_top_level_of_a_module.code, Diagnostics.An_export_declaration_cannot_have_modifiers.code, - Diagnostics.An_import_declaration_can_only_be_used_in_a_namespace_or_module.code, + Diagnostics.An_import_declaration_can_only_be_used_at_the_top_level_of_a_module.code, Diagnostics.An_import_declaration_cannot_have_modifiers.code, Diagnostics.An_object_member_cannot_be_declared_optional.code, Diagnostics.Argument_of_dynamic_import_cannot_be_spread_element.code, diff --git a/tests/baselines/reference/importDeclarationInModuleDeclaration2.errors.txt b/tests/baselines/reference/importDeclarationInModuleDeclaration2.errors.txt new file mode 100644 index 0000000000000..2541c20897fa5 --- /dev/null +++ b/tests/baselines/reference/importDeclarationInModuleDeclaration2.errors.txt @@ -0,0 +1,9 @@ +tests/cases/compiler/check.js(2,5): error TS1473: An import declaration can only be used at the top level of a module. + + +==== tests/cases/compiler/check.js (1 errors) ==== + function container() { + import "fs"; + ~~~~~~ +!!! error TS1473: An import declaration can only be used at the top level of a module. + } \ No newline at end of file diff --git a/tests/baselines/reference/importDeclarationInModuleDeclaration2.symbols b/tests/baselines/reference/importDeclarationInModuleDeclaration2.symbols new file mode 100644 index 0000000000000..ae8fbc1291a0c --- /dev/null +++ b/tests/baselines/reference/importDeclarationInModuleDeclaration2.symbols @@ -0,0 +1,6 @@ +=== tests/cases/compiler/check.js === +function container() { +>container : Symbol(container, Decl(check.js, 0, 0)) + + import "fs"; +} diff --git a/tests/baselines/reference/importDeclarationInModuleDeclaration2.types b/tests/baselines/reference/importDeclarationInModuleDeclaration2.types new file mode 100644 index 0000000000000..a100c277dca5e --- /dev/null +++ b/tests/baselines/reference/importDeclarationInModuleDeclaration2.types @@ -0,0 +1,6 @@ +=== tests/cases/compiler/check.js === +function container() { +>container : () => void + + import "fs"; +} diff --git a/tests/baselines/reference/labeledStatementWithLabel.errors.txt b/tests/baselines/reference/labeledStatementWithLabel.errors.txt index c7259e484eaaa..64dd004249f81 100644 --- a/tests/baselines/reference/labeledStatementWithLabel.errors.txt +++ b/tests/baselines/reference/labeledStatementWithLabel.errors.txt @@ -1,5 +1,5 @@ -tests/cases/conformance/statements/labeledStatements/labeledStatementWithLabel.ts(11,8): error TS1235: A namespace declaration is only allowed in a namespace or module. -tests/cases/conformance/statements/labeledStatements/labeledStatementWithLabel.ts(12,8): error TS1235: A namespace declaration is only allowed in a namespace or module. +tests/cases/conformance/statements/labeledStatements/labeledStatementWithLabel.ts(11,8): error TS1235: A namespace declaration is only allowed at the top level of a namespace or module. +tests/cases/conformance/statements/labeledStatements/labeledStatementWithLabel.ts(12,8): error TS1235: A namespace declaration is only allowed at the top level of a namespace or module. ==== tests/cases/conformance/statements/labeledStatements/labeledStatementWithLabel.ts (2 errors) ==== @@ -15,9 +15,9 @@ tests/cases/conformance/statements/labeledStatements/labeledStatementWithLabel.t label: module M { } ~~~~~~ -!!! error TS1235: A namespace declaration is only allowed in a namespace or module. +!!! error TS1235: A namespace declaration is only allowed at the top level of a namespace or module. label: namespace N {} ~~~~~~~~~ -!!! error TS1235: A namespace declaration is only allowed in a namespace or module. +!!! error TS1235: A namespace declaration is only allowed at the top level of a namespace or module. label: type T = {} \ No newline at end of file diff --git a/tests/baselines/reference/labeledStatementWithLabel_es2015.errors.txt b/tests/baselines/reference/labeledStatementWithLabel_es2015.errors.txt index 95c136b953de6..c2945254121ed 100644 --- a/tests/baselines/reference/labeledStatementWithLabel_es2015.errors.txt +++ b/tests/baselines/reference/labeledStatementWithLabel_es2015.errors.txt @@ -1,5 +1,5 @@ -tests/cases/conformance/statements/labeledStatements/labeledStatementWithLabel_es2015.ts(11,8): error TS1235: A namespace declaration is only allowed in a namespace or module. -tests/cases/conformance/statements/labeledStatements/labeledStatementWithLabel_es2015.ts(12,8): error TS1235: A namespace declaration is only allowed in a namespace or module. +tests/cases/conformance/statements/labeledStatements/labeledStatementWithLabel_es2015.ts(11,8): error TS1235: A namespace declaration is only allowed at the top level of a namespace or module. +tests/cases/conformance/statements/labeledStatements/labeledStatementWithLabel_es2015.ts(12,8): error TS1235: A namespace declaration is only allowed at the top level of a namespace or module. ==== tests/cases/conformance/statements/labeledStatements/labeledStatementWithLabel_es2015.ts (2 errors) ==== @@ -15,9 +15,9 @@ tests/cases/conformance/statements/labeledStatements/labeledStatementWithLabel_e label: module M { } ~~~~~~ -!!! error TS1235: A namespace declaration is only allowed in a namespace or module. +!!! error TS1235: A namespace declaration is only allowed at the top level of a namespace or module. label: namespace N {} ~~~~~~~~~ -!!! error TS1235: A namespace declaration is only allowed in a namespace or module. +!!! error TS1235: A namespace declaration is only allowed at the top level of a namespace or module. label: type T = {} \ No newline at end of file diff --git a/tests/baselines/reference/labeledStatementWithLabel_strict.errors.txt b/tests/baselines/reference/labeledStatementWithLabel_strict.errors.txt index 863604a083680..01f09aeab4df1 100644 --- a/tests/baselines/reference/labeledStatementWithLabel_strict.errors.txt +++ b/tests/baselines/reference/labeledStatementWithLabel_strict.errors.txt @@ -8,9 +8,9 @@ tests/cases/conformance/statements/labeledStatements/labeledStatementWithLabel_s tests/cases/conformance/statements/labeledStatements/labeledStatementWithLabel_strict.ts(9,1): error TS1344: 'A label is not allowed here. tests/cases/conformance/statements/labeledStatements/labeledStatementWithLabel_strict.ts(10,1): error TS1344: 'A label is not allowed here. tests/cases/conformance/statements/labeledStatements/labeledStatementWithLabel_strict.ts(12,1): error TS1344: 'A label is not allowed here. -tests/cases/conformance/statements/labeledStatements/labeledStatementWithLabel_strict.ts(12,8): error TS1235: A namespace declaration is only allowed in a namespace or module. +tests/cases/conformance/statements/labeledStatements/labeledStatementWithLabel_strict.ts(12,8): error TS1235: A namespace declaration is only allowed at the top level of a namespace or module. tests/cases/conformance/statements/labeledStatements/labeledStatementWithLabel_strict.ts(13,1): error TS1344: 'A label is not allowed here. -tests/cases/conformance/statements/labeledStatements/labeledStatementWithLabel_strict.ts(13,8): error TS1235: A namespace declaration is only allowed in a namespace or module. +tests/cases/conformance/statements/labeledStatements/labeledStatementWithLabel_strict.ts(13,8): error TS1235: A namespace declaration is only allowed at the top level of a namespace or module. tests/cases/conformance/statements/labeledStatements/labeledStatementWithLabel_strict.ts(14,1): error TS1344: 'A label is not allowed here. @@ -48,12 +48,12 @@ tests/cases/conformance/statements/labeledStatements/labeledStatementWithLabel_s ~~~~~ !!! error TS1344: 'A label is not allowed here. ~~~~~~ -!!! error TS1235: A namespace declaration is only allowed in a namespace or module. +!!! error TS1235: A namespace declaration is only allowed at the top level of a namespace or module. label: namespace N {} ~~~~~ !!! error TS1344: 'A label is not allowed here. ~~~~~~~~~ -!!! error TS1235: A namespace declaration is only allowed in a namespace or module. +!!! error TS1235: A namespace declaration is only allowed at the top level of a namespace or module. label: type T = {} ~~~~~ !!! error TS1344: 'A label is not allowed here. diff --git a/tests/baselines/reference/moduleElementsInWrongContext.errors.txt b/tests/baselines/reference/moduleElementsInWrongContext.errors.txt index 146a6dcd951df..4226266e82992 100644 --- a/tests/baselines/reference/moduleElementsInWrongContext.errors.txt +++ b/tests/baselines/reference/moduleElementsInWrongContext.errors.txt @@ -1,36 +1,36 @@ -tests/cases/compiler/moduleElementsInWrongContext.ts(2,5): error TS1235: A namespace declaration is only allowed in a namespace or module. -tests/cases/compiler/moduleElementsInWrongContext.ts(3,5): error TS1235: A namespace declaration is only allowed in a namespace or module. -tests/cases/compiler/moduleElementsInWrongContext.ts(7,5): error TS1235: A namespace declaration is only allowed in a namespace or module. +tests/cases/compiler/moduleElementsInWrongContext.ts(2,5): error TS1235: A namespace declaration is only allowed at the top level of a namespace or module. +tests/cases/compiler/moduleElementsInWrongContext.ts(3,5): error TS1235: A namespace declaration is only allowed at the top level of a namespace or module. +tests/cases/compiler/moduleElementsInWrongContext.ts(7,5): error TS1235: A namespace declaration is only allowed at the top level of a namespace or module. tests/cases/compiler/moduleElementsInWrongContext.ts(9,5): error TS1234: An ambient module declaration is only allowed at the top level in a file. tests/cases/compiler/moduleElementsInWrongContext.ts(13,5): error TS1231: An export assignment must be at the top level of a file or module declaration. -tests/cases/compiler/moduleElementsInWrongContext.ts(17,5): error TS1233: An export declaration can only be used in a module. -tests/cases/compiler/moduleElementsInWrongContext.ts(18,5): error TS1233: An export declaration can only be used in a module. -tests/cases/compiler/moduleElementsInWrongContext.ts(19,5): error TS1233: An export declaration can only be used in a module. +tests/cases/compiler/moduleElementsInWrongContext.ts(17,5): error TS1233: An export declaration can only be used at the top level of a namespace or module. +tests/cases/compiler/moduleElementsInWrongContext.ts(18,5): error TS1233: An export declaration can only be used at the top level of a namespace or module. +tests/cases/compiler/moduleElementsInWrongContext.ts(19,5): error TS1233: An export declaration can only be used at the top level of a namespace or module. tests/cases/compiler/moduleElementsInWrongContext.ts(20,5): error TS1258: A default export must be at the top level of a file or module declaration. tests/cases/compiler/moduleElementsInWrongContext.ts(21,5): error TS1184: Modifiers cannot appear here. tests/cases/compiler/moduleElementsInWrongContext.ts(22,5): error TS1184: Modifiers cannot appear here. -tests/cases/compiler/moduleElementsInWrongContext.ts(23,5): error TS1232: An import declaration can only be used in a namespace or module. -tests/cases/compiler/moduleElementsInWrongContext.ts(24,5): error TS1232: An import declaration can only be used in a namespace or module. -tests/cases/compiler/moduleElementsInWrongContext.ts(25,5): error TS1232: An import declaration can only be used in a namespace or module. -tests/cases/compiler/moduleElementsInWrongContext.ts(26,5): error TS1232: An import declaration can only be used in a namespace or module. -tests/cases/compiler/moduleElementsInWrongContext.ts(27,5): error TS1232: An import declaration can only be used in a namespace or module. -tests/cases/compiler/moduleElementsInWrongContext.ts(28,5): error TS1232: An import declaration can only be used in a namespace or module. +tests/cases/compiler/moduleElementsInWrongContext.ts(23,5): error TS1232: An import declaration can only be used at the top level of a namespace or module. +tests/cases/compiler/moduleElementsInWrongContext.ts(24,5): error TS1232: An import declaration can only be used at the top level of a namespace or module. +tests/cases/compiler/moduleElementsInWrongContext.ts(25,5): error TS1232: An import declaration can only be used at the top level of a namespace or module. +tests/cases/compiler/moduleElementsInWrongContext.ts(26,5): error TS1232: An import declaration can only be used at the top level of a namespace or module. +tests/cases/compiler/moduleElementsInWrongContext.ts(27,5): error TS1232: An import declaration can only be used at the top level of a namespace or module. +tests/cases/compiler/moduleElementsInWrongContext.ts(28,5): error TS1232: An import declaration can only be used at the top level of a namespace or module. ==== tests/cases/compiler/moduleElementsInWrongContext.ts (17 errors) ==== { module M { } ~~~~~~ -!!! error TS1235: A namespace declaration is only allowed in a namespace or module. +!!! error TS1235: A namespace declaration is only allowed at the top level of a namespace or module. export namespace N { ~~~~~~ -!!! error TS1235: A namespace declaration is only allowed in a namespace or module. +!!! error TS1235: A namespace declaration is only allowed at the top level of a namespace or module. export interface I { } } namespace Q.K { } ~~~~~~~~~ -!!! error TS1235: A namespace declaration is only allowed in a namespace or module. +!!! error TS1235: A namespace declaration is only allowed at the top level of a namespace or module. declare module "ambient" { ~~~~~~~ @@ -46,13 +46,13 @@ tests/cases/compiler/moduleElementsInWrongContext.ts(28,5): error TS1232: An imp function foo() { } export * from "ambient"; ~~~~~~ -!!! error TS1233: An export declaration can only be used in a module. +!!! error TS1233: An export declaration can only be used at the top level of a namespace or module. export { foo }; ~~~~~~ -!!! error TS1233: An export declaration can only be used in a module. +!!! error TS1233: An export declaration can only be used at the top level of a namespace or module. export { baz as b } from "ambient"; ~~~~~~ -!!! error TS1233: An export declaration can only be used in a module. +!!! error TS1233: An export declaration can only be used at the top level of a namespace or module. export default v; ~~~~~~ !!! error TS1258: A default export must be at the top level of a file or module declaration. @@ -64,21 +64,21 @@ tests/cases/compiler/moduleElementsInWrongContext.ts(28,5): error TS1232: An imp !!! error TS1184: Modifiers cannot appear here. import I = M; ~~~~~~ -!!! error TS1232: An import declaration can only be used in a namespace or module. +!!! error TS1232: An import declaration can only be used at the top level of a namespace or module. import I2 = require("foo"); ~~~~~~ -!!! error TS1232: An import declaration can only be used in a namespace or module. +!!! error TS1232: An import declaration can only be used at the top level of a namespace or module. import * as Foo from "ambient"; ~~~~~~ -!!! error TS1232: An import declaration can only be used in a namespace or module. +!!! error TS1232: An import declaration can only be used at the top level of a namespace or module. import bar from "ambient"; ~~~~~~ -!!! error TS1232: An import declaration can only be used in a namespace or module. +!!! error TS1232: An import declaration can only be used at the top level of a namespace or module. import { baz } from "ambient"; ~~~~~~ -!!! error TS1232: An import declaration can only be used in a namespace or module. +!!! error TS1232: An import declaration can only be used at the top level of a namespace or module. import "ambient"; ~~~~~~ -!!! error TS1232: An import declaration can only be used in a namespace or module. +!!! error TS1232: An import declaration can only be used at the top level of a namespace or module. } \ No newline at end of file diff --git a/tests/baselines/reference/moduleElementsInWrongContext2.errors.txt b/tests/baselines/reference/moduleElementsInWrongContext2.errors.txt index f858bf9923e2b..22fa234747db1 100644 --- a/tests/baselines/reference/moduleElementsInWrongContext2.errors.txt +++ b/tests/baselines/reference/moduleElementsInWrongContext2.errors.txt @@ -1,36 +1,36 @@ -tests/cases/compiler/moduleElementsInWrongContext2.ts(2,5): error TS1235: A namespace declaration is only allowed in a namespace or module. -tests/cases/compiler/moduleElementsInWrongContext2.ts(3,5): error TS1235: A namespace declaration is only allowed in a namespace or module. -tests/cases/compiler/moduleElementsInWrongContext2.ts(7,5): error TS1235: A namespace declaration is only allowed in a namespace or module. +tests/cases/compiler/moduleElementsInWrongContext2.ts(2,5): error TS1235: A namespace declaration is only allowed at the top level of a namespace or module. +tests/cases/compiler/moduleElementsInWrongContext2.ts(3,5): error TS1235: A namespace declaration is only allowed at the top level of a namespace or module. +tests/cases/compiler/moduleElementsInWrongContext2.ts(7,5): error TS1235: A namespace declaration is only allowed at the top level of a namespace or module. tests/cases/compiler/moduleElementsInWrongContext2.ts(9,5): error TS1234: An ambient module declaration is only allowed at the top level in a file. tests/cases/compiler/moduleElementsInWrongContext2.ts(13,5): error TS1231: An export assignment must be at the top level of a file or module declaration. -tests/cases/compiler/moduleElementsInWrongContext2.ts(17,5): error TS1233: An export declaration can only be used in a module. -tests/cases/compiler/moduleElementsInWrongContext2.ts(18,5): error TS1233: An export declaration can only be used in a module. -tests/cases/compiler/moduleElementsInWrongContext2.ts(19,5): error TS1233: An export declaration can only be used in a module. +tests/cases/compiler/moduleElementsInWrongContext2.ts(17,5): error TS1233: An export declaration can only be used at the top level of a namespace or module. +tests/cases/compiler/moduleElementsInWrongContext2.ts(18,5): error TS1233: An export declaration can only be used at the top level of a namespace or module. +tests/cases/compiler/moduleElementsInWrongContext2.ts(19,5): error TS1233: An export declaration can only be used at the top level of a namespace or module. tests/cases/compiler/moduleElementsInWrongContext2.ts(20,5): error TS1258: A default export must be at the top level of a file or module declaration. tests/cases/compiler/moduleElementsInWrongContext2.ts(21,5): error TS1184: Modifiers cannot appear here. tests/cases/compiler/moduleElementsInWrongContext2.ts(22,5): error TS1184: Modifiers cannot appear here. -tests/cases/compiler/moduleElementsInWrongContext2.ts(23,5): error TS1232: An import declaration can only be used in a namespace or module. -tests/cases/compiler/moduleElementsInWrongContext2.ts(24,5): error TS1232: An import declaration can only be used in a namespace or module. -tests/cases/compiler/moduleElementsInWrongContext2.ts(25,5): error TS1232: An import declaration can only be used in a namespace or module. -tests/cases/compiler/moduleElementsInWrongContext2.ts(26,5): error TS1232: An import declaration can only be used in a namespace or module. -tests/cases/compiler/moduleElementsInWrongContext2.ts(27,5): error TS1232: An import declaration can only be used in a namespace or module. -tests/cases/compiler/moduleElementsInWrongContext2.ts(28,5): error TS1232: An import declaration can only be used in a namespace or module. +tests/cases/compiler/moduleElementsInWrongContext2.ts(23,5): error TS1232: An import declaration can only be used at the top level of a namespace or module. +tests/cases/compiler/moduleElementsInWrongContext2.ts(24,5): error TS1232: An import declaration can only be used at the top level of a namespace or module. +tests/cases/compiler/moduleElementsInWrongContext2.ts(25,5): error TS1232: An import declaration can only be used at the top level of a namespace or module. +tests/cases/compiler/moduleElementsInWrongContext2.ts(26,5): error TS1232: An import declaration can only be used at the top level of a namespace or module. +tests/cases/compiler/moduleElementsInWrongContext2.ts(27,5): error TS1232: An import declaration can only be used at the top level of a namespace or module. +tests/cases/compiler/moduleElementsInWrongContext2.ts(28,5): error TS1232: An import declaration can only be used at the top level of a namespace or module. ==== tests/cases/compiler/moduleElementsInWrongContext2.ts (17 errors) ==== function blah () { module M { } ~~~~~~ -!!! error TS1235: A namespace declaration is only allowed in a namespace or module. +!!! error TS1235: A namespace declaration is only allowed at the top level of a namespace or module. export namespace N { ~~~~~~ -!!! error TS1235: A namespace declaration is only allowed in a namespace or module. +!!! error TS1235: A namespace declaration is only allowed at the top level of a namespace or module. export interface I { } } namespace Q.K { } ~~~~~~~~~ -!!! error TS1235: A namespace declaration is only allowed in a namespace or module. +!!! error TS1235: A namespace declaration is only allowed at the top level of a namespace or module. declare module "ambient" { ~~~~~~~ @@ -46,13 +46,13 @@ tests/cases/compiler/moduleElementsInWrongContext2.ts(28,5): error TS1232: An im function foo() { } export * from "ambient"; ~~~~~~ -!!! error TS1233: An export declaration can only be used in a module. +!!! error TS1233: An export declaration can only be used at the top level of a namespace or module. export { foo }; ~~~~~~ -!!! error TS1233: An export declaration can only be used in a module. +!!! error TS1233: An export declaration can only be used at the top level of a namespace or module. export { baz as b } from "ambient"; ~~~~~~ -!!! error TS1233: An export declaration can only be used in a module. +!!! error TS1233: An export declaration can only be used at the top level of a namespace or module. export default v; ~~~~~~ !!! error TS1258: A default export must be at the top level of a file or module declaration. @@ -64,21 +64,21 @@ tests/cases/compiler/moduleElementsInWrongContext2.ts(28,5): error TS1232: An im !!! error TS1184: Modifiers cannot appear here. import I = M; ~~~~~~ -!!! error TS1232: An import declaration can only be used in a namespace or module. +!!! error TS1232: An import declaration can only be used at the top level of a namespace or module. import I2 = require("foo"); ~~~~~~ -!!! error TS1232: An import declaration can only be used in a namespace or module. +!!! error TS1232: An import declaration can only be used at the top level of a namespace or module. import * as Foo from "ambient"; ~~~~~~ -!!! error TS1232: An import declaration can only be used in a namespace or module. +!!! error TS1232: An import declaration can only be used at the top level of a namespace or module. import bar from "ambient"; ~~~~~~ -!!! error TS1232: An import declaration can only be used in a namespace or module. +!!! error TS1232: An import declaration can only be used at the top level of a namespace or module. import { baz } from "ambient"; ~~~~~~ -!!! error TS1232: An import declaration can only be used in a namespace or module. +!!! error TS1232: An import declaration can only be used at the top level of a namespace or module. import "ambient"; ~~~~~~ -!!! error TS1232: An import declaration can only be used in a namespace or module. +!!! error TS1232: An import declaration can only be used at the top level of a namespace or module. } \ No newline at end of file diff --git a/tests/baselines/reference/moduleElementsInWrongContext3.errors.txt b/tests/baselines/reference/moduleElementsInWrongContext3.errors.txt index df78fa08741f1..55d9ec47c03bf 100644 --- a/tests/baselines/reference/moduleElementsInWrongContext3.errors.txt +++ b/tests/baselines/reference/moduleElementsInWrongContext3.errors.txt @@ -1,20 +1,20 @@ -tests/cases/compiler/moduleElementsInWrongContext3.ts(3,9): error TS1235: A namespace declaration is only allowed in a namespace or module. -tests/cases/compiler/moduleElementsInWrongContext3.ts(4,9): error TS1235: A namespace declaration is only allowed in a namespace or module. -tests/cases/compiler/moduleElementsInWrongContext3.ts(8,9): error TS1235: A namespace declaration is only allowed in a namespace or module. +tests/cases/compiler/moduleElementsInWrongContext3.ts(3,9): error TS1235: A namespace declaration is only allowed at the top level of a namespace or module. +tests/cases/compiler/moduleElementsInWrongContext3.ts(4,9): error TS1235: A namespace declaration is only allowed at the top level of a namespace or module. +tests/cases/compiler/moduleElementsInWrongContext3.ts(8,9): error TS1235: A namespace declaration is only allowed at the top level of a namespace or module. tests/cases/compiler/moduleElementsInWrongContext3.ts(10,9): error TS1234: An ambient module declaration is only allowed at the top level in a file. tests/cases/compiler/moduleElementsInWrongContext3.ts(14,9): error TS1231: An export assignment must be at the top level of a file or module declaration. -tests/cases/compiler/moduleElementsInWrongContext3.ts(18,9): error TS1233: An export declaration can only be used in a module. -tests/cases/compiler/moduleElementsInWrongContext3.ts(19,9): error TS1233: An export declaration can only be used in a module. -tests/cases/compiler/moduleElementsInWrongContext3.ts(20,9): error TS1233: An export declaration can only be used in a module. +tests/cases/compiler/moduleElementsInWrongContext3.ts(18,9): error TS1233: An export declaration can only be used at the top level of a namespace or module. +tests/cases/compiler/moduleElementsInWrongContext3.ts(19,9): error TS1233: An export declaration can only be used at the top level of a namespace or module. +tests/cases/compiler/moduleElementsInWrongContext3.ts(20,9): error TS1233: An export declaration can only be used at the top level of a namespace or module. tests/cases/compiler/moduleElementsInWrongContext3.ts(21,9): error TS1258: A default export must be at the top level of a file or module declaration. tests/cases/compiler/moduleElementsInWrongContext3.ts(22,9): error TS1184: Modifiers cannot appear here. tests/cases/compiler/moduleElementsInWrongContext3.ts(23,9): error TS1184: Modifiers cannot appear here. -tests/cases/compiler/moduleElementsInWrongContext3.ts(24,9): error TS1232: An import declaration can only be used in a namespace or module. -tests/cases/compiler/moduleElementsInWrongContext3.ts(25,9): error TS1232: An import declaration can only be used in a namespace or module. -tests/cases/compiler/moduleElementsInWrongContext3.ts(26,9): error TS1232: An import declaration can only be used in a namespace or module. -tests/cases/compiler/moduleElementsInWrongContext3.ts(27,9): error TS1232: An import declaration can only be used in a namespace or module. -tests/cases/compiler/moduleElementsInWrongContext3.ts(28,9): error TS1232: An import declaration can only be used in a namespace or module. -tests/cases/compiler/moduleElementsInWrongContext3.ts(29,9): error TS1232: An import declaration can only be used in a namespace or module. +tests/cases/compiler/moduleElementsInWrongContext3.ts(24,9): error TS1232: An import declaration can only be used at the top level of a namespace or module. +tests/cases/compiler/moduleElementsInWrongContext3.ts(25,9): error TS1232: An import declaration can only be used at the top level of a namespace or module. +tests/cases/compiler/moduleElementsInWrongContext3.ts(26,9): error TS1232: An import declaration can only be used at the top level of a namespace or module. +tests/cases/compiler/moduleElementsInWrongContext3.ts(27,9): error TS1232: An import declaration can only be used at the top level of a namespace or module. +tests/cases/compiler/moduleElementsInWrongContext3.ts(28,9): error TS1232: An import declaration can only be used at the top level of a namespace or module. +tests/cases/compiler/moduleElementsInWrongContext3.ts(29,9): error TS1232: An import declaration can only be used at the top level of a namespace or module. ==== tests/cases/compiler/moduleElementsInWrongContext3.ts (17 errors) ==== @@ -22,16 +22,16 @@ tests/cases/compiler/moduleElementsInWrongContext3.ts(29,9): error TS1232: An im { module M { } ~~~~~~ -!!! error TS1235: A namespace declaration is only allowed in a namespace or module. +!!! error TS1235: A namespace declaration is only allowed at the top level of a namespace or module. export namespace N { ~~~~~~ -!!! error TS1235: A namespace declaration is only allowed in a namespace or module. +!!! error TS1235: A namespace declaration is only allowed at the top level of a namespace or module. export interface I { } } namespace Q.K { } ~~~~~~~~~ -!!! error TS1235: A namespace declaration is only allowed in a namespace or module. +!!! error TS1235: A namespace declaration is only allowed at the top level of a namespace or module. declare module "ambient" { ~~~~~~~ @@ -47,13 +47,13 @@ tests/cases/compiler/moduleElementsInWrongContext3.ts(29,9): error TS1232: An im function foo() { } export * from "ambient"; ~~~~~~ -!!! error TS1233: An export declaration can only be used in a module. +!!! error TS1233: An export declaration can only be used at the top level of a namespace or module. export { foo }; ~~~~~~ -!!! error TS1233: An export declaration can only be used in a module. +!!! error TS1233: An export declaration can only be used at the top level of a namespace or module. export { baz as b } from "ambient"; ~~~~~~ -!!! error TS1233: An export declaration can only be used in a module. +!!! error TS1233: An export declaration can only be used at the top level of a namespace or module. export default v; ~~~~~~ !!! error TS1258: A default export must be at the top level of a file or module declaration. @@ -65,21 +65,21 @@ tests/cases/compiler/moduleElementsInWrongContext3.ts(29,9): error TS1232: An im !!! error TS1184: Modifiers cannot appear here. import I = M; ~~~~~~ -!!! error TS1232: An import declaration can only be used in a namespace or module. +!!! error TS1232: An import declaration can only be used at the top level of a namespace or module. import I2 = require("foo"); ~~~~~~ -!!! error TS1232: An import declaration can only be used in a namespace or module. +!!! error TS1232: An import declaration can only be used at the top level of a namespace or module. import * as Foo from "ambient"; ~~~~~~ -!!! error TS1232: An import declaration can only be used in a namespace or module. +!!! error TS1232: An import declaration can only be used at the top level of a namespace or module. import bar from "ambient"; ~~~~~~ -!!! error TS1232: An import declaration can only be used in a namespace or module. +!!! error TS1232: An import declaration can only be used at the top level of a namespace or module. import { baz } from "ambient"; ~~~~~~ -!!! error TS1232: An import declaration can only be used in a namespace or module. +!!! error TS1232: An import declaration can only be used at the top level of a namespace or module. import "ambient"; ~~~~~~ -!!! error TS1232: An import declaration can only be used in a namespace or module. +!!! error TS1232: An import declaration can only be used at the top level of a namespace or module. } } \ No newline at end of file diff --git a/tests/baselines/reference/plainJSGrammarErrors.errors.txt b/tests/baselines/reference/plainJSGrammarErrors.errors.txt index fa3affdb840ed..c49f7618bf424 100644 --- a/tests/baselines/reference/plainJSGrammarErrors.errors.txt +++ b/tests/baselines/reference/plainJSGrammarErrors.errors.txt @@ -44,8 +44,8 @@ tests/cases/conformance/salsa/plainJSGrammarErrors.js(65,1): error TS1042: 'asyn tests/cases/conformance/salsa/plainJSGrammarErrors.js(66,1): error TS1042: 'async' modifier cannot be used here. tests/cases/conformance/salsa/plainJSGrammarErrors.js(67,1): error TS1191: An import declaration cannot have modifiers. tests/cases/conformance/salsa/plainJSGrammarErrors.js(68,1): error TS1193: An export declaration cannot have modifiers. -tests/cases/conformance/salsa/plainJSGrammarErrors.js(70,5): error TS1233: An export declaration can only be used in a module. -tests/cases/conformance/salsa/plainJSGrammarErrors.js(71,5): error TS1232: An import declaration can only be used in a namespace or module. +tests/cases/conformance/salsa/plainJSGrammarErrors.js(70,5): error TS1474: An export declaration can only be used at the top level of a module. +tests/cases/conformance/salsa/plainJSGrammarErrors.js(71,5): error TS1473: An import declaration can only be used at the top level of a module. tests/cases/conformance/salsa/plainJSGrammarErrors.js(72,5): error TS1258: A default export must be at the top level of a file or module declaration. tests/cases/conformance/salsa/plainJSGrammarErrors.js(75,5): error TS1184: Modifiers cannot appear here. tests/cases/conformance/salsa/plainJSGrammarErrors.js(78,5): error TS1042: 'static' modifier cannot be used here. @@ -267,10 +267,10 @@ tests/cases/conformance/salsa/plainJSGrammarErrors.js(207,1): error TS1108: A 'r function nestedExports() { export { staticParam } ~~~~~~ -!!! error TS1233: An export declaration can only be used in a module. +!!! error TS1474: An export declaration can only be used at the top level of a module. import 'fs' ~~~~~~ -!!! error TS1232: An import declaration can only be used in a namespace or module. +!!! error TS1473: An import declaration can only be used at the top level of a module. export default 12 ~~~~~~ !!! error TS1258: A default export must be at the top level of a file or module declaration. diff --git a/tests/cases/compiler/importDeclarationInModuleDeclaration2.ts b/tests/cases/compiler/importDeclarationInModuleDeclaration2.ts new file mode 100644 index 0000000000000..2df0aadb8ae67 --- /dev/null +++ b/tests/cases/compiler/importDeclarationInModuleDeclaration2.ts @@ -0,0 +1,8 @@ +// @allowJs: true +// @noEmit: true +// @checkJs: true + +// @filename: check.js +function container() { + import "fs"; +} \ No newline at end of file From 42aa18bf442c4df147e30deaf27261a41cbdc617 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 9 Feb 2022 16:26:27 -0800 Subject: [PATCH 32/55] mergeSymbol in checker:Remove block-scoped duplicate declaration errors in plain JS (#47825) * Checker:Remove block-scoped duplicate declaration errors in plain JS Previously they were issued in mergeSymbol, not they are not issued. * fix semicolon lint --- src/compiler/checker.ts | 19 ++++++++++--------- src/compiler/program.ts | 2 +- src/compiler/utilities.ts | 4 ++++ .../plainJSReservedStrict.errors.txt | 6 +----- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f901db2ab4c5c..bf198f02e911b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1320,13 +1320,14 @@ namespace ts { else { // error const isEitherEnum = !!(target.flags & SymbolFlags.Enum || source.flags & SymbolFlags.Enum); const isEitherBlockScoped = !!(target.flags & SymbolFlags.BlockScopedVariable || source.flags & SymbolFlags.BlockScopedVariable); - const message = isEitherEnum - ? Diagnostics.Enum_declarations_can_only_merge_with_namespace_or_other_enum_declarations - : isEitherBlockScoped - ? Diagnostics.Cannot_redeclare_block_scoped_variable_0 - : Diagnostics.Duplicate_identifier_0; + const message = isEitherEnum ? Diagnostics.Enum_declarations_can_only_merge_with_namespace_or_other_enum_declarations + : isEitherBlockScoped ? Diagnostics.Cannot_redeclare_block_scoped_variable_0 + : Diagnostics.Duplicate_identifier_0; const sourceSymbolFile = source.declarations && getSourceFileOfNode(source.declarations[0]); const targetSymbolFile = target.declarations && getSourceFileOfNode(target.declarations[0]); + + const isSourcePlainJs = isPlainJsFile(sourceSymbolFile, compilerOptions.checkJs); + const isTargetPlainJs = isPlainJsFile(targetSymbolFile, compilerOptions.checkJs); const symbolName = symbolToString(source); // Collect top-level duplicate identifier errors into one mapping, so we can then merge their diagnostics if there are a bunch @@ -1337,12 +1338,12 @@ namespace ts { ({ firstFile, secondFile, conflictingSymbols: new Map() } as DuplicateInfoForFiles)); const conflictingSymbolInfo = getOrUpdate(filesDuplicates.conflictingSymbols, symbolName, () => ({ isBlockScoped: isEitherBlockScoped, firstFileLocations: [], secondFileLocations: [] } as DuplicateInfoForSymbol)); - addDuplicateLocations(conflictingSymbolInfo.firstFileLocations, source); - addDuplicateLocations(conflictingSymbolInfo.secondFileLocations, target); + if (!isSourcePlainJs) addDuplicateLocations(conflictingSymbolInfo.firstFileLocations, source); + if (!isTargetPlainJs) addDuplicateLocations(conflictingSymbolInfo.secondFileLocations, target); } else { - addDuplicateDeclarationErrorsForSymbols(source, message, symbolName, target); - addDuplicateDeclarationErrorsForSymbols(target, message, symbolName, source); + if (!isSourcePlainJs) addDuplicateDeclarationErrorsForSymbols(source, message, symbolName, target); + if (!isTargetPlainJs) addDuplicateDeclarationErrorsForSymbols(target, message, symbolName, source); } } return target; diff --git a/src/compiler/program.ts b/src/compiler/program.ts index f6cacfe719881..d8d22046674dc 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -2102,7 +2102,7 @@ namespace ts { const isJs = sourceFile.scriptKind === ScriptKind.JS || sourceFile.scriptKind === ScriptKind.JSX; const isCheckJs = isJs && isCheckJsEnabledForFile(sourceFile, options); - const isPlainJs = isJs && !sourceFile.checkJsDirective && options.checkJs === undefined; + const isPlainJs = isPlainJsFile(sourceFile, options.checkJs); const isTsNoCheck = !!sourceFile.checkJsDirective && sourceFile.checkJsDirective.enabled === false; // By default, only type-check .ts, .tsx, Deferred, plain JS, checked JS and External diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index cabcb2f9b6cac..186df09456d14 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -271,6 +271,10 @@ namespace ts { return getSourceFileOfNode(module.valueDeclaration || getNonAugmentationDeclaration(module)); } + export function isPlainJsFile(file: SourceFile | undefined, checkJs: boolean | undefined): boolean { + return !!file && (file.scriptKind === ScriptKind.JS || file.scriptKind === ScriptKind.JSX) && !file.checkJsDirective && checkJs === undefined; + } + export function isStatementWithLocals(node: Node) { switch (node.kind) { case SyntaxKind.Block: diff --git a/tests/baselines/reference/plainJSReservedStrict.errors.txt b/tests/baselines/reference/plainJSReservedStrict.errors.txt index a040fce591c17..db4714a10c194 100644 --- a/tests/baselines/reference/plainJSReservedStrict.errors.txt +++ b/tests/baselines/reference/plainJSReservedStrict.errors.txt @@ -1,16 +1,12 @@ tests/cases/conformance/salsa/plainJSReservedStrict.js(2,7): error TS1100: Invalid use of 'eval' in strict mode. -tests/cases/conformance/salsa/plainJSReservedStrict.js(2,7): error TS2451: Cannot redeclare block-scoped variable 'eval'. tests/cases/conformance/salsa/plainJSReservedStrict.js(3,7): error TS1100: Invalid use of 'arguments' in strict mode. -==== tests/cases/conformance/salsa/plainJSReservedStrict.js (3 errors) ==== +==== tests/cases/conformance/salsa/plainJSReservedStrict.js (2 errors) ==== "use strict" const eval = 1 ~~~~ !!! error TS1100: Invalid use of 'eval' in strict mode. - ~~~~ -!!! error TS2451: Cannot redeclare block-scoped variable 'eval'. -!!! related TS6203 /.ts/lib.es5.d.ts:32:18: 'eval' was also declared here. const arguments = 2 ~~~~~~~~~ !!! error TS1100: Invalid use of 'arguments' in strict mode. From df673f74f5cf4fa1948ad2f8c25e6a0290d212ea Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Thu, 10 Feb 2022 06:07:00 +0000 Subject: [PATCH 33/55] Update package-lock.json --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 50bfff2c4109f..7e3c413b5939b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -676,9 +676,9 @@ "dev": true }, "@types/node": { - "version": "17.0.16", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.16.tgz", - "integrity": "sha512-ydLaGVfQOQ6hI1xK2A5nVh8bl0OGoIfYMxPWHqqYe9bTkWCfqiVvZoh2I/QF2sNSkZzZyROBoTefIEI+PB6iIA==", + "version": "17.0.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.17.tgz", + "integrity": "sha512-e8PUNQy1HgJGV3iU/Bp2+D/DXh3PYeyli8LgIwsQcs1Ar1LoaWHSIT6Rw+H2rNJmiq6SNWiDytfx8+gYj7wDHw==", "dev": true }, "@types/node-fetch": { From 954ce5b2780f17d76d1a45e29069f4f648ba2d37 Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Thu, 10 Feb 2022 19:17:30 +0200 Subject: [PATCH 34/55] fix(46611): allow to use jsdoc type on class methods (#46688) --- src/compiler/checker.ts | 15 +++++++++------ .../reference/checkJsdocTypeTag7.symbols | 15 +++++++++++++++ .../baselines/reference/checkJsdocTypeTag7.types | 15 +++++++++++++++ .../cases/conformance/jsdoc/checkJsdocTypeTag7.ts | 13 +++++++++++++ 4 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 tests/baselines/reference/checkJsdocTypeTag7.symbols create mode 100644 tests/baselines/reference/checkJsdocTypeTag7.types create mode 100644 tests/cases/conformance/jsdoc/checkJsdocTypeTag7.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index bf198f02e911b..48eef5c0956fd 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8773,12 +8773,8 @@ namespace ts { } } if (isInJSFile(declaration)) { - const typeTag = getJSDocType(func); - if (typeTag && isFunctionTypeNode(typeTag)) { - const signature = getSignatureFromDeclaration(typeTag); - const pos = func.parameters.indexOf(declaration); - return declaration.dotDotDotToken ? getRestTypeAtPosition(signature, pos) : getTypeAtPosition(signature, pos); - } + const type = getParameterTypeOfTypeTag(func, declaration); + if (type) return type; } // Use contextual parameter type if one is available const type = declaration.symbol.escapedName === InternalSymbolName.This ? getContextualThisParameterType(func) : getContextuallyTypedParameterType(declaration); @@ -12776,6 +12772,13 @@ namespace ts { return typeTag?.typeExpression && getSingleCallSignature(getTypeFromTypeNode(typeTag.typeExpression)); } + function getParameterTypeOfTypeTag(func: FunctionLikeDeclaration, parameter: ParameterDeclaration) { + const signature = getSignatureOfTypeTag(func); + if (!signature) return undefined; + const pos = func.parameters.indexOf(parameter); + return parameter.dotDotDotToken ? getRestTypeAtPosition(signature, pos) : getTypeAtPosition(signature, pos); + } + function getReturnTypeOfTypeTag(node: SignatureDeclaration | JSDocSignature) { const signature = getSignatureOfTypeTag(node); return signature && getReturnTypeOfSignature(signature); diff --git a/tests/baselines/reference/checkJsdocTypeTag7.symbols b/tests/baselines/reference/checkJsdocTypeTag7.symbols new file mode 100644 index 0000000000000..7013bb921a5a9 --- /dev/null +++ b/tests/baselines/reference/checkJsdocTypeTag7.symbols @@ -0,0 +1,15 @@ +=== tests/cases/conformance/jsdoc/test.js === +/** + * @typedef {(a: string, b: number) => void} Foo + */ + +class C { +>C : Symbol(C, Decl(test.js, 0, 0)) + + /** @type {Foo} */ + foo(a, b) {} +>foo : Symbol(C.foo, Decl(test.js, 4, 9)) +>a : Symbol(a, Decl(test.js, 6, 8)) +>b : Symbol(b, Decl(test.js, 6, 10)) +} + diff --git a/tests/baselines/reference/checkJsdocTypeTag7.types b/tests/baselines/reference/checkJsdocTypeTag7.types new file mode 100644 index 0000000000000..f4aac580feefa --- /dev/null +++ b/tests/baselines/reference/checkJsdocTypeTag7.types @@ -0,0 +1,15 @@ +=== tests/cases/conformance/jsdoc/test.js === +/** + * @typedef {(a: string, b: number) => void} Foo + */ + +class C { +>C : C + + /** @type {Foo} */ + foo(a, b) {} +>foo : (a: string, b: number) => void +>a : string +>b : number +} + diff --git a/tests/cases/conformance/jsdoc/checkJsdocTypeTag7.ts b/tests/cases/conformance/jsdoc/checkJsdocTypeTag7.ts new file mode 100644 index 0000000000000..c65b206a859b3 --- /dev/null +++ b/tests/cases/conformance/jsdoc/checkJsdocTypeTag7.ts @@ -0,0 +1,13 @@ +// @checkJs: true +// @allowJs: true +// @noEmit: true +// @Filename: test.js + +/** + * @typedef {(a: string, b: number) => void} Foo + */ + +class C { + /** @type {Foo} */ + foo(a, b) {} +} From b456702755f86bb2e5c814e2f166f34880fe2102 Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Thu, 10 Feb 2022 20:02:07 +0200 Subject: [PATCH 35/55] feat(11378): check param names in JSDoc (#47257) --- src/compiler/checker.ts | 73 ++++++------ src/compiler/diagnosticMessages.json | 12 ++ .../codefixes/fixUnmatchedParameter.ts | 104 ++++++++++++++++++ src/services/textChanges.ts | 27 ++--- src/services/tsconfig.json | 1 + ...iableDeclaredFunctionExpression.errors.txt | 23 ++++ .../codeFixDeleteUnmatchedParameter1.ts | 23 ++++ .../codeFixDeleteUnmatchedParameter2.ts | 26 +++++ .../codeFixDeleteUnmatchedParameter3.ts | 30 +++++ .../codeFixDeleteUnmatchedParameter4.ts | 19 ++++ .../codeFixDeleteUnmatchedParameterJS1.ts | 27 +++++ .../codeFixDeleteUnmatchedParameterJS2.ts | 29 +++++ .../codeFixDeleteUnmatchedParameterJS3.ts | 33 ++++++ .../codeFixDeleteUnmatchedParameterJS4.ts | 22 ++++ .../codeFixDeleteUnmatchedParameter_all.ts | 51 +++++++++ .../codeFixDeleteUnmatchedParameter_allJS.ts | 53 +++++++++ .../codeFixRenameUnmatchedParameter1.ts | 30 +++++ .../codeFixRenameUnmatchedParameter2.ts | 34 ++++++ .../codeFixRenameUnmatchedParameter3.ts | 64 +++++++++++ .../codeFixRenameUnmatchedParameterJS1.ts | 34 ++++++ .../codeFixRenameUnmatchedParameterJS2.ts | 38 +++++++ .../codeFixRenameUnmatchedParameterJS3.ts | 72 ++++++++++++ 22 files changed, 779 insertions(+), 46 deletions(-) create mode 100644 src/services/codefixes/fixUnmatchedParameter.ts create mode 100644 tests/baselines/reference/checkJsdocParamOnVariableDeclaredFunctionExpression.errors.txt create mode 100644 tests/cases/fourslash/codeFixDeleteUnmatchedParameter1.ts create mode 100644 tests/cases/fourslash/codeFixDeleteUnmatchedParameter2.ts create mode 100644 tests/cases/fourslash/codeFixDeleteUnmatchedParameter3.ts create mode 100644 tests/cases/fourslash/codeFixDeleteUnmatchedParameter4.ts create mode 100644 tests/cases/fourslash/codeFixDeleteUnmatchedParameterJS1.ts create mode 100644 tests/cases/fourslash/codeFixDeleteUnmatchedParameterJS2.ts create mode 100644 tests/cases/fourslash/codeFixDeleteUnmatchedParameterJS3.ts create mode 100644 tests/cases/fourslash/codeFixDeleteUnmatchedParameterJS4.ts create mode 100644 tests/cases/fourslash/codeFixDeleteUnmatchedParameter_all.ts create mode 100644 tests/cases/fourslash/codeFixDeleteUnmatchedParameter_allJS.ts create mode 100644 tests/cases/fourslash/codeFixRenameUnmatchedParameter1.ts create mode 100644 tests/cases/fourslash/codeFixRenameUnmatchedParameter2.ts create mode 100644 tests/cases/fourslash/codeFixRenameUnmatchedParameter3.ts create mode 100644 tests/cases/fourslash/codeFixRenameUnmatchedParameterJS1.ts create mode 100644 tests/cases/fourslash/codeFixRenameUnmatchedParameterJS2.ts create mode 100644 tests/cases/fourslash/codeFixRenameUnmatchedParameterJS3.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 48eef5c0956fd..2830de0c49d98 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -34472,6 +34472,7 @@ namespace ts { } checkTypeParameters(getEffectiveTypeParameterDeclarations(node)); + checkUnmatchedJSDocParameters(node); forEach(node.parameters, checkParameter); @@ -36235,40 +36236,7 @@ namespace ts { function checkJSDocParameterTag(node: JSDocParameterTag) { checkSourceElement(node.typeExpression); - if (!getParameterSymbolFromJSDoc(node)) { - const decl = getHostSignatureFromJSDoc(node); - // don't issue an error for invalid hosts -- just functions -- - // and give a better error message when the host function mentions `arguments` - // but the tag doesn't have an array type - if (decl) { - const i = getJSDocTags(decl).filter(isJSDocParameterTag).indexOf(node); - if (i > -1 && i < decl.parameters.length && isBindingPattern(decl.parameters[i].name)) { - return; - } - if (!containsArgumentsReference(decl)) { - if (isQualifiedName(node.name)) { - error(node.name, - Diagnostics.Qualified_name_0_is_not_allowed_without_a_leading_param_object_1, - entityNameToString(node.name), - entityNameToString(node.name.left)); - } - else { - error(node.name, - Diagnostics.JSDoc_param_tag_has_name_0_but_there_is_no_parameter_with_that_name, - idText(node.name)); - } - } - else if (findLast(getJSDocTags(decl), isJSDocParameterTag) === node && - node.typeExpression && node.typeExpression.type && - !isArrayType(getTypeFromTypeNode(node.typeExpression.type))) { - error(node.name, - Diagnostics.JSDoc_param_tag_has_name_0_but_there_is_no_parameter_with_that_name_It_would_match_arguments_if_it_had_an_array_type, - idText(node.name.kind === SyntaxKind.QualifiedName ? node.name.right : node.name)); - } - } - } } - function checkJSDocPropertyTag(node: JSDocPropertyTag) { checkSourceElement(node.typeExpression); } @@ -38564,6 +38532,45 @@ namespace ts { } } + function checkUnmatchedJSDocParameters(node: SignatureDeclaration) { + const jsdocParameters = filter(getJSDocTags(node), isJSDocParameterTag); + if (!length(jsdocParameters)) return; + + const isJs = isInJSFile(node); + const parameters = new Set<__String>(); + const excludedParameters = new Set(); + forEach(node.parameters, ({ name }, index) => { + if (isIdentifier(name)) { + parameters.add(name.escapedText); + } + if (isBindingPattern(name)) { + excludedParameters.add(index); + } + }); + + const containsArguments = containsArgumentsReference(node); + if (containsArguments) { + const lastJSDocParam = lastOrUndefined(jsdocParameters); + if (lastJSDocParam && isIdentifier(lastJSDocParam.name) && lastJSDocParam.typeExpression && + lastJSDocParam.typeExpression.type && !parameters.has(lastJSDocParam.name.escapedText) && !isArrayType(getTypeFromTypeNode(lastJSDocParam.typeExpression.type))) { + errorOrSuggestion(isJs, lastJSDocParam.name, Diagnostics.JSDoc_param_tag_has_name_0_but_there_is_no_parameter_with_that_name_It_would_match_arguments_if_it_had_an_array_type, idText(lastJSDocParam.name)); + } + } + else { + forEach(jsdocParameters, ({ name }, index) => { + if (excludedParameters.has(index) || isIdentifier(name) && parameters.has(name.escapedText)) { + return; + } + if (isQualifiedName(name)) { + errorOrSuggestion(isJs, name, Diagnostics.Qualified_name_0_is_not_allowed_without_a_leading_param_object_1, entityNameToString(name), entityNameToString(name.left)); + } + else { + errorOrSuggestion(isJs, name, Diagnostics.JSDoc_param_tag_has_name_0_but_there_is_no_parameter_with_that_name, idText(name)); + } + }); + } + } + /** * Check each type parameter and check that type parameters have no duplicate type parameter declarations */ diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index a51336a4829dc..cd4f562612a9a 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -7135,6 +7135,18 @@ "category": "Message", "code": 95170 }, + "Delete unused '@param' tag '{0}'": { + "category": "Message", + "code": 95171 + }, + "Delete all unused '@param' tags": { + "category": "Message", + "code": 95172 + }, + "Rename '@param' tag name '{0}' to '{1}'": { + "category": "Message", + "code": 95173 + }, "No value exists in scope for the shorthand property '{0}'. Either declare one or provide an initializer.": { "category": "Error", diff --git a/src/services/codefixes/fixUnmatchedParameter.ts b/src/services/codefixes/fixUnmatchedParameter.ts new file mode 100644 index 0000000000000..b0dc5db0a85ae --- /dev/null +++ b/src/services/codefixes/fixUnmatchedParameter.ts @@ -0,0 +1,104 @@ +/* @internal */ +namespace ts.codefix { + const deleteUnmatchedParameter = "deleteUnmatchedParameter"; + const renameUnmatchedParameter = "renameUnmatchedParameter"; + + const errorCodes = [ + Diagnostics.JSDoc_param_tag_has_name_0_but_there_is_no_parameter_with_that_name.code, + ]; + + registerCodeFix({ + fixIds: [deleteUnmatchedParameter, renameUnmatchedParameter], + errorCodes, + getCodeActions: function getCodeActionsToFixUnmatchedParameter(context) { + const { sourceFile, span } = context; + const actions: CodeFixAction[] = []; + const info = getInfo(sourceFile, span.start); + if (info) { + append(actions, getDeleteAction(context, info)); + append(actions, getRenameAction(context, info)); + return actions; + } + return undefined; + }, + getAllCodeActions: function getAllCodeActionsToFixUnmatchedParameter(context) { + const tagsToSignature = new Map(); + return createCombinedCodeActions(textChanges.ChangeTracker.with(context, changes => { + eachDiagnostic(context, errorCodes, ({ file, start }) => { + const info = getInfo(file, start); + if (info) { + tagsToSignature.set(info.signature, append(tagsToSignature.get(info.signature), info.jsDocParameterTag)); + } + }); + + tagsToSignature.forEach((tags, signature) => { + if (context.fixId === deleteUnmatchedParameter) { + const tagsSet = new Set(tags); + changes.filterJSDocTags(signature.getSourceFile(), signature, t => !tagsSet.has(t)); + } + }); + })); + } + }); + + function getDeleteAction(context: CodeFixContext, { name, signature, jsDocParameterTag }: Info) { + const changes = textChanges.ChangeTracker.with(context, changeTracker => + changeTracker.filterJSDocTags(context.sourceFile, signature, t => t !== jsDocParameterTag)); + return createCodeFixAction( + deleteUnmatchedParameter, + changes, + [Diagnostics.Delete_unused_param_tag_0, name.getText(context.sourceFile)], + deleteUnmatchedParameter, + Diagnostics.Delete_all_unused_param_tags + ); + } + + function getRenameAction(context: CodeFixContext, { name, signature, jsDocParameterTag }: Info) { + if (!length(signature.parameters)) return undefined; + + const sourceFile = context.sourceFile; + const tags = getJSDocTags(signature); + const names = new Set<__String>(); + for (const tag of tags) { + if (isJSDocParameterTag(tag) && isIdentifier(tag.name)) { + names.add(tag.name.escapedText); + } + } + // @todo - match to all available names instead to the first parameter name + // @see /codeFixRenameUnmatchedParameter3.ts + const parameterName = firstDefined(signature.parameters, p => + isIdentifier(p.name) && !names.has(p.name.escapedText) ? p.name.getText(sourceFile) : undefined); + if (parameterName === undefined) return undefined; + + const newJSDocParameterTag = factory.updateJSDocParameterTag( + jsDocParameterTag, + jsDocParameterTag.tagName, + factory.createIdentifier(parameterName), + jsDocParameterTag.isBracketed, + jsDocParameterTag.typeExpression, + jsDocParameterTag.isNameFirst, + jsDocParameterTag.comment + ); + const changes = textChanges.ChangeTracker.with(context, changeTracker => + changeTracker.replaceJSDocComment(sourceFile, signature, map(tags, t => t === jsDocParameterTag ? newJSDocParameterTag : t))); + return createCodeFixActionWithoutFixAll(renameUnmatchedParameter, changes, [Diagnostics.Rename_param_tag_name_0_to_1, name.getText(sourceFile), parameterName]); + } + + interface Info { + readonly signature: SignatureDeclaration; + readonly jsDocParameterTag: JSDocParameterTag; + readonly name: Identifier; + } + + function getInfo(sourceFile: SourceFile, pos: number): Info | undefined { + const token = getTokenAtPosition(sourceFile, pos); + if (token.parent && isJSDocParameterTag(token.parent) && isIdentifier(token.parent.name)) { + const jsDocParameterTag = token.parent; + const signature = getHostSignatureFromJSDoc(jsDocParameterTag); + if (signature) { + return { signature, name: token.parent.name, jsDocParameterTag }; + } + } + return undefined; + } +} diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index 83d5acb9d7291..f697571607541 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -495,29 +495,30 @@ namespace ts.textChanges { this.insertNodeAt(sourceFile, fnStart, tag, { preserveLeadingWhitespace: false, suffix: this.newLineCharacter + indent }); } + private createJSDocText(sourceFile: SourceFile, node: HasJSDoc) { + const comments = flatMap(node.jsDoc, jsDoc => + isString(jsDoc.comment) ? factory.createJSDocText(jsDoc.comment) : jsDoc.comment) as JSDocComment[]; + const jsDoc = singleOrUndefined(node.jsDoc); + return jsDoc && positionsAreOnSameLine(jsDoc.pos, jsDoc.end, sourceFile) && length(comments) === 0 ? undefined : + factory.createNodeArray(intersperse(comments, factory.createJSDocText("\n"))); + } + + public replaceJSDocComment(sourceFile: SourceFile, node: HasJSDoc, tags: readonly JSDocTag[]) { + this.insertJsdocCommentBefore(sourceFile, updateJSDocHost(node), factory.createJSDocComment(this.createJSDocText(sourceFile, node), factory.createNodeArray(tags))); + } + public addJSDocTags(sourceFile: SourceFile, parent: HasJSDoc, newTags: readonly JSDocTag[]): void { - const comments = flatMap(parent.jsDoc, j => typeof j.comment === "string" ? factory.createJSDocText(j.comment) : j.comment) as JSDocComment[]; const oldTags = flatMapToMutable(parent.jsDoc, j => j.tags); const unmergedNewTags = newTags.filter(newTag => !oldTags.some((tag, i) => { const merged = tryMergeJsdocTags(tag, newTag); if (merged) oldTags[i] = merged; return !!merged; })); - const tags = [...oldTags, ...unmergedNewTags]; - const jsDoc = singleOrUndefined(parent.jsDoc); - const comment = jsDoc && positionsAreOnSameLine(jsDoc.pos, jsDoc.end, sourceFile) && !length(comments) ? undefined : - factory.createNodeArray(intersperse(comments, factory.createJSDocText("\n"))); - const tag = factory.createJSDocComment(comment, factory.createNodeArray(tags)); - const host = updateJSDocHost(parent); - this.insertJsdocCommentBefore(sourceFile, host, tag); + this.replaceJSDocComment(sourceFile, parent, [...oldTags, ...unmergedNewTags]); } public filterJSDocTags(sourceFile: SourceFile, parent: HasJSDoc, predicate: (tag: JSDocTag) => boolean): void { - const comments = flatMap(parent.jsDoc, j => typeof j.comment === "string" ? factory.createJSDocText(j.comment) : j.comment) as JSDocComment[]; - const oldTags = flatMapToMutable(parent.jsDoc, j => j.tags); - const tag = factory.createJSDocComment(factory.createNodeArray(intersperse(comments, factory.createJSDocText("\n"))), factory.createNodeArray([...(filter(oldTags, predicate) || emptyArray)])); - const host = updateJSDocHost(parent); - this.insertJsdocCommentBefore(sourceFile, host, tag); + this.replaceJSDocComment(sourceFile, parent, filter(flatMapToMutable(parent.jsDoc, j => j.tags), predicate)); } public replaceRangeWithText(sourceFile: SourceFile, range: TextRange, text: string): void { diff --git a/src/services/tsconfig.json b/src/services/tsconfig.json index d2119947f8fa8..3cd2188314613 100644 --- a/src/services/tsconfig.json +++ b/src/services/tsconfig.json @@ -87,6 +87,7 @@ "codefixes/fixExtendsInterfaceBecomesImplements.ts", "codefixes/fixForgottenThisPropertyAccess.ts", "codefixes/fixInvalidJsxCharacters.ts", + "codefixes/fixUnmatchedParameter.ts", "codefixes/fixUnusedIdentifier.ts", "codefixes/fixUnreachableCode.ts", "codefixes/fixUnusedLabel.ts", diff --git a/tests/baselines/reference/checkJsdocParamOnVariableDeclaredFunctionExpression.errors.txt b/tests/baselines/reference/checkJsdocParamOnVariableDeclaredFunctionExpression.errors.txt new file mode 100644 index 0000000000000..f3ea79ea97cfa --- /dev/null +++ b/tests/baselines/reference/checkJsdocParamOnVariableDeclaredFunctionExpression.errors.txt @@ -0,0 +1,23 @@ +tests/cases/conformance/jsdoc/0.js(14,20): error TS8024: JSDoc '@param' tag has name 's', but there is no parameter with that name. + + +==== tests/cases/conformance/jsdoc/0.js (1 errors) ==== + // @ts-check + /** + * @param {number=} n + * @param {string} [s] + */ + var x = function foo(n, s) {} + var y; + /** + * @param {boolean!} b + */ + y = function bar(b) {} + + /** + * @param {string} s + ~ +!!! error TS8024: JSDoc '@param' tag has name 's', but there is no parameter with that name. + */ + var one = function (s) { }, two = function (untyped) { }; + \ No newline at end of file diff --git a/tests/cases/fourslash/codeFixDeleteUnmatchedParameter1.ts b/tests/cases/fourslash/codeFixDeleteUnmatchedParameter1.ts new file mode 100644 index 0000000000000..caad37daa44a7 --- /dev/null +++ b/tests/cases/fourslash/codeFixDeleteUnmatchedParameter1.ts @@ -0,0 +1,23 @@ +/// + +// @filename: a.ts +/////** +//// * @param {number} a +//// * @param {number} b +//// */ +////function foo() {} + +verify.codeFixAvailable([ + { description: "Delete unused '@param' tag 'a'" }, + { description: "Delete unused '@param' tag 'b'" }, +]); + +verify.codeFix({ + description: [ts.Diagnostics.Delete_unused_param_tag_0.message, "a"], + index: 0, + newFileContent: +`/** + * @param {number} b + */ +function foo() {}`, +}); diff --git a/tests/cases/fourslash/codeFixDeleteUnmatchedParameter2.ts b/tests/cases/fourslash/codeFixDeleteUnmatchedParameter2.ts new file mode 100644 index 0000000000000..5a9adbce8116f --- /dev/null +++ b/tests/cases/fourslash/codeFixDeleteUnmatchedParameter2.ts @@ -0,0 +1,26 @@ +/// + +// @filename: a.ts +/////** +//// * @param {number} a +//// * @param {string} b +//// */ +////function foo(a: number) { +//// a; +////} + +verify.codeFixAvailable([ + { description: "Delete unused '@param' tag 'b'" }, +]); + +verify.codeFix({ + description: [ts.Diagnostics.Delete_unused_param_tag_0.message, "b"], + index: 0, + newFileContent: +`/** + * @param {number} a + */ +function foo(a: number) { + a; +}` +}); diff --git a/tests/cases/fourslash/codeFixDeleteUnmatchedParameter3.ts b/tests/cases/fourslash/codeFixDeleteUnmatchedParameter3.ts new file mode 100644 index 0000000000000..1f053813182fc --- /dev/null +++ b/tests/cases/fourslash/codeFixDeleteUnmatchedParameter3.ts @@ -0,0 +1,30 @@ +/// + +// @filename: a.ts +/////** +//// * @param {number} a +//// * @param {string} b +//// * @param {number} c +//// */ +////function foo(a: number, c: number) { +//// a; +//// c; +////} + +verify.codeFixAvailable([ + { description: "Delete unused '@param' tag 'b'" }, +]); + +verify.codeFix({ + description: [ts.Diagnostics.Delete_unused_param_tag_0.message, "b"], + index: 0, + newFileContent: +`/** + * @param {number} a + * @param {number} c + */ +function foo(a: number, c: number) { + a; + c; +}` +}); diff --git a/tests/cases/fourslash/codeFixDeleteUnmatchedParameter4.ts b/tests/cases/fourslash/codeFixDeleteUnmatchedParameter4.ts new file mode 100644 index 0000000000000..c84f721ab7508 --- /dev/null +++ b/tests/cases/fourslash/codeFixDeleteUnmatchedParameter4.ts @@ -0,0 +1,19 @@ +/// + +// @filename: a.ts +/////** +//// * @param {number} a +//// */ +////function foo() {} + +verify.codeFixAvailable([ + { description: "Delete unused '@param' tag 'a'" }, +]); + +verify.codeFix({ + description: [ts.Diagnostics.Delete_unused_param_tag_0.message, "a"], + index: 0, + newFileContent: +`/** */ +function foo() {}` +}); diff --git a/tests/cases/fourslash/codeFixDeleteUnmatchedParameterJS1.ts b/tests/cases/fourslash/codeFixDeleteUnmatchedParameterJS1.ts new file mode 100644 index 0000000000000..75fa6515cd117 --- /dev/null +++ b/tests/cases/fourslash/codeFixDeleteUnmatchedParameterJS1.ts @@ -0,0 +1,27 @@ +/// + +// @allowJs: true +// @checkJs: true +// @filename: /a.js +/////** +//// * @param {number} a +//// * @param {number} b +//// */ +////function foo() {} + +verify.codeFixAvailable([ + { description: "Delete unused '@param' tag 'a'" }, + { description: "Disable checking for this file" }, + { description: "Delete unused '@param' tag 'b'" }, + { description: "Disable checking for this file" }, +]); + +verify.codeFix({ + description: [ts.Diagnostics.Delete_unused_param_tag_0.message, "a"], + index: 0, + newFileContent: +`/** + * @param {number} b + */ +function foo() {}`, +}); diff --git a/tests/cases/fourslash/codeFixDeleteUnmatchedParameterJS2.ts b/tests/cases/fourslash/codeFixDeleteUnmatchedParameterJS2.ts new file mode 100644 index 0000000000000..f8324b3116a2b --- /dev/null +++ b/tests/cases/fourslash/codeFixDeleteUnmatchedParameterJS2.ts @@ -0,0 +1,29 @@ +/// + +// @allowJs: true +// @checkJs: true +// @filename: /a.js +/////** +//// * @param {number} a +//// * @param {string} b +//// */ +////function foo(a) { +//// a; +////} + +verify.codeFixAvailable([ + { description: "Delete unused '@param' tag 'b'" }, + { description: "Disable checking for this file" }, +]); + +verify.codeFix({ + description: [ts.Diagnostics.Delete_unused_param_tag_0.message, "b"], + index: 0, + newFileContent: +`/** + * @param {number} a + */ +function foo(a) { + a; +}` +}); diff --git a/tests/cases/fourslash/codeFixDeleteUnmatchedParameterJS3.ts b/tests/cases/fourslash/codeFixDeleteUnmatchedParameterJS3.ts new file mode 100644 index 0000000000000..e02c1f51c0421 --- /dev/null +++ b/tests/cases/fourslash/codeFixDeleteUnmatchedParameterJS3.ts @@ -0,0 +1,33 @@ +/// + +// @allowJs: true +// @checkJs: true +// @filename: /a.js +/////** +//// * @param {number} a +//// * @param {string} b +//// * @param {number} c +//// */ +////function foo(a, c) { +//// a; +//// c; +////} + +verify.codeFixAvailable([ + { description: "Delete unused '@param' tag 'b'" }, + { description: "Disable checking for this file" }, +]); + +verify.codeFix({ + description: [ts.Diagnostics.Delete_unused_param_tag_0.message, "b"], + index: 0, + newFileContent: +`/** + * @param {number} a + * @param {number} c + */ +function foo(a, c) { + a; + c; +}` +}); diff --git a/tests/cases/fourslash/codeFixDeleteUnmatchedParameterJS4.ts b/tests/cases/fourslash/codeFixDeleteUnmatchedParameterJS4.ts new file mode 100644 index 0000000000000..272f49d1096a2 --- /dev/null +++ b/tests/cases/fourslash/codeFixDeleteUnmatchedParameterJS4.ts @@ -0,0 +1,22 @@ +/// + +// @allowJs: true +// @checkJs: true +// @filename: /a.js +/////** +//// * @param {number} a +//// */ +////function foo() {} + +verify.codeFixAvailable([ + { description: "Delete unused '@param' tag 'a'" }, + { description: "Disable checking for this file" }, +]); + +verify.codeFix({ + description: [ts.Diagnostics.Delete_unused_param_tag_0.message, "a"], + index: 0, + newFileContent: +`/** */ +function foo() {}` +}); diff --git a/tests/cases/fourslash/codeFixDeleteUnmatchedParameter_all.ts b/tests/cases/fourslash/codeFixDeleteUnmatchedParameter_all.ts new file mode 100644 index 0000000000000..ee62961df6e81 --- /dev/null +++ b/tests/cases/fourslash/codeFixDeleteUnmatchedParameter_all.ts @@ -0,0 +1,51 @@ +/// + +// @filename: /a.ts +/////** +//// * @param {number} a +//// * @param {number} b +//// */ +////function f1() {} +//// +/////** +//// * @param {number} a +//// * @param {string} b +//// */ +////function f2(a: number) { +//// a; +////} +//// +/////** +//// * @param {number} a +//// * @param {string} b +//// * @param {number} c +//// */ +////function f3(a: number, c: number) { +//// a; +//// c; +////} + +goTo.file("/a.ts"); +verify.codeFixAll({ + fixId: "deleteUnmatchedParameter", + fixAllDescription: ts.Diagnostics.Delete_all_unused_param_tags.message, + newFileContent: +`/** */ +function f1() {} + +/** + * @param {number} a + */ +function f2(a: number) { + a; +} + +/** + * @param {number} a + * @param {number} c + */ +function f3(a: number, c: number) { + a; + c; +}`, +}); diff --git a/tests/cases/fourslash/codeFixDeleteUnmatchedParameter_allJS.ts b/tests/cases/fourslash/codeFixDeleteUnmatchedParameter_allJS.ts new file mode 100644 index 0000000000000..f139514e72d74 --- /dev/null +++ b/tests/cases/fourslash/codeFixDeleteUnmatchedParameter_allJS.ts @@ -0,0 +1,53 @@ +/// + +// @allowJs: true +// @checkJs: true +// @filename: /a.js +/////** +//// * @param {number} a +//// * @param {number} b +//// */ +////function f1() {} +//// +/////** +//// * @param {number} a +//// * @param {string} b +//// */ +////function f2(a) { +//// a; +////} +//// +/////** +//// * @param {number} a +//// * @param {string} b +//// * @param {number} c +//// */ +////function f3(a, c) { +//// a; +//// c; +////} + +goTo.file("/a.js"); +verify.codeFixAll({ + fixId: "deleteUnmatchedParameter", + fixAllDescription: ts.Diagnostics.Delete_all_unused_param_tags.message, + newFileContent: +`/** */ +function f1() {} + +/** + * @param {number} a + */ +function f2(a) { + a; +} + +/** + * @param {number} a + * @param {number} c + */ +function f3(a, c) { + a; + c; +}`, +}); diff --git a/tests/cases/fourslash/codeFixRenameUnmatchedParameter1.ts b/tests/cases/fourslash/codeFixRenameUnmatchedParameter1.ts new file mode 100644 index 0000000000000..743c9da9073e0 --- /dev/null +++ b/tests/cases/fourslash/codeFixRenameUnmatchedParameter1.ts @@ -0,0 +1,30 @@ +/// + +// @filename: a.ts +/////** +//// * @param {number} a +//// * @param {number} c +//// */ +////function foo(a: number, b: string) { +//// a; +//// b; +////} + +verify.codeFixAvailable([ + { description: "Delete unused '@param' tag 'c'" }, + { description: "Rename '@param' tag name 'c' to 'b'" }, +]); + +verify.codeFix({ + description: [ts.Diagnostics.Rename_param_tag_name_0_to_1.message, "c", "b"], + index: 1, + newFileContent: +`/** + * @param {number} a + * @param {number} b + */ +function foo(a: number, b: string) { + a; + b; +}` +}); diff --git a/tests/cases/fourslash/codeFixRenameUnmatchedParameter2.ts b/tests/cases/fourslash/codeFixRenameUnmatchedParameter2.ts new file mode 100644 index 0000000000000..cc002d07ed6f4 --- /dev/null +++ b/tests/cases/fourslash/codeFixRenameUnmatchedParameter2.ts @@ -0,0 +1,34 @@ +/// + +// @filename: a.ts +/////** +//// * @param {number} d +//// * @param {number} a +//// * @param {number} b +//// */ +////function foo(a: number, b: string, c: string) { +//// a; +//// b; +//// c; +////} + +verify.codeFixAvailable([ + { description: "Delete unused '@param' tag 'd'" }, + { description: "Rename '@param' tag name 'd' to 'c'" }, +]); + +verify.codeFix({ + description: [ts.Diagnostics.Rename_param_tag_name_0_to_1.message, "d", "c"], + index: 1, + newFileContent: +`/** + * @param {number} c + * @param {number} a + * @param {number} b + */ +function foo(a: number, b: string, c: string) { + a; + b; + c; +}` +}); diff --git a/tests/cases/fourslash/codeFixRenameUnmatchedParameter3.ts b/tests/cases/fourslash/codeFixRenameUnmatchedParameter3.ts new file mode 100644 index 0000000000000..daf725ee5fab4 --- /dev/null +++ b/tests/cases/fourslash/codeFixRenameUnmatchedParameter3.ts @@ -0,0 +1,64 @@ +/// + +// @filename: a.ts +/////** +//// * @param {number} notDefined1 +//// * @param {number} notDefined2 +//// * @param {number} a +//// * @param {number} b +//// */ +////function foo(a: number, b: string, typo1: string, typo2: string) { +//// a; +//// b; +//// typo1; +//// typo2; +////} + +verify.codeFixAvailable([ + { description: "Delete unused '@param' tag 'notDefined1'" }, + { description: "Rename '@param' tag name 'notDefined1' to 'typo1'" }, + { description: "Delete unused '@param' tag 'notDefined2'" }, + { description: "Rename '@param' tag name 'notDefined2' to 'typo1'" }, +]); + +verify.codeFix({ + description: [ts.Diagnostics.Rename_param_tag_name_0_to_1.message, "notDefined1", "typo1"], + index: 1, + newFileContent: +`/** + * @param {number} typo1 + * @param {number} notDefined2 + * @param {number} a + * @param {number} b + */ +function foo(a: number, b: string, typo1: string, typo2: string) { + a; + b; + typo1; + typo2; +}`, + applyChanges: true +}); + +verify.codeFixAvailable([ + { description: "Delete unused '@param' tag 'notDefined2'" }, + { description: "Rename '@param' tag name 'notDefined2' to 'typo2'" }, +]); + +verify.codeFix({ + description: [ts.Diagnostics.Rename_param_tag_name_0_to_1.message, "notDefined2", "typo2"], + index: 1, + newFileContent: +`/** + * @param {number} typo1 + * @param {number} typo2 + * @param {number} a + * @param {number} b + */ +function foo(a: number, b: string, typo1: string, typo2: string) { + a; + b; + typo1; + typo2; +}`, +}); diff --git a/tests/cases/fourslash/codeFixRenameUnmatchedParameterJS1.ts b/tests/cases/fourslash/codeFixRenameUnmatchedParameterJS1.ts new file mode 100644 index 0000000000000..ccc7c97115026 --- /dev/null +++ b/tests/cases/fourslash/codeFixRenameUnmatchedParameterJS1.ts @@ -0,0 +1,34 @@ +/// + +// @allowJs: true +// @checkJs: true +// @filename: /a.js +/////** +//// * @param {number} a +//// * @param {number} c +//// */ +////function foo(a, b) { +//// a; +//// b; +////} + +verify.codeFixAvailable([ + { description: "Delete unused '@param' tag 'c'" }, + { description: "Rename '@param' tag name 'c' to 'b'" }, + { description: "Disable checking for this file" }, + { description: "Infer parameter types from usage" }, +]); + +verify.codeFix({ + description: [ts.Diagnostics.Rename_param_tag_name_0_to_1.message, "c", "b"], + index: 1, + newFileContent: +`/** + * @param {number} a + * @param {number} b + */ +function foo(a, b) { + a; + b; +}` +}); diff --git a/tests/cases/fourslash/codeFixRenameUnmatchedParameterJS2.ts b/tests/cases/fourslash/codeFixRenameUnmatchedParameterJS2.ts new file mode 100644 index 0000000000000..89acd2ff5904f --- /dev/null +++ b/tests/cases/fourslash/codeFixRenameUnmatchedParameterJS2.ts @@ -0,0 +1,38 @@ +/// + +// @allowJs: true +// @checkJs: true +// @filename: /a.js +/////** +//// * @param {number} d +//// * @param {number} a +//// * @param {number} b +//// */ +////function foo(a, b, c) { +//// a; +//// b; +//// c; +////} + +verify.codeFixAvailable([ + { description: "Delete unused '@param' tag 'd'" }, + { description: "Rename '@param' tag name 'd' to 'c'" }, + { description: "Disable checking for this file" }, + { description: "Infer parameter types from usage" }, +]); + +verify.codeFix({ + description: [ts.Diagnostics.Rename_param_tag_name_0_to_1.message, "d", "c"], + index: 1, + newFileContent: +`/** + * @param {number} c + * @param {number} a + * @param {number} b + */ +function foo(a, b, c) { + a; + b; + c; +}` +}); diff --git a/tests/cases/fourslash/codeFixRenameUnmatchedParameterJS3.ts b/tests/cases/fourslash/codeFixRenameUnmatchedParameterJS3.ts new file mode 100644 index 0000000000000..13c11a224c9b9 --- /dev/null +++ b/tests/cases/fourslash/codeFixRenameUnmatchedParameterJS3.ts @@ -0,0 +1,72 @@ +/// + +// @allowJs: true +// @checkJs: true +// @filename: /a.js +/////** +//// * @param {number} notDefined1 +//// * @param {number} notDefined2 +//// * @param {number} a +//// * @param {number} b +//// */ +////function foo(a, b, typo1, typo2) { +//// a; +//// b; +//// typo1; +//// typo2; +////} + +verify.codeFixAvailable([ + { description: "Delete unused '@param' tag 'notDefined1'" }, + { description: "Rename '@param' tag name 'notDefined1' to 'typo1'" }, + { description: "Disable checking for this file" }, + { description: "Delete unused '@param' tag 'notDefined2'" }, + { description: "Rename '@param' tag name 'notDefined2' to 'typo1'" }, + { description: "Disable checking for this file" }, + { description: "Infer parameter types from usage" }, + { description: "Infer parameter types from usage" }, +]); + +verify.codeFix({ + description: [ts.Diagnostics.Rename_param_tag_name_0_to_1.message, "notDefined1", "typo1"], + index: 1, + newFileContent: +`/** + * @param {number} typo1 + * @param {number} notDefined2 + * @param {number} a + * @param {number} b + */ +function foo(a, b, typo1, typo2) { + a; + b; + typo1; + typo2; +}`, + applyChanges: true +}); + +verify.codeFixAvailable([ + { description: "Delete unused '@param' tag 'notDefined2'" }, + { description: "Rename '@param' tag name 'notDefined2' to 'typo2'" }, + { description: "Disable checking for this file" }, + { description: "Infer parameter types from usage" }, +]); + +verify.codeFix({ + description: [ts.Diagnostics.Rename_param_tag_name_0_to_1.message, "notDefined2", "typo2"], + index: 1, + newFileContent: +`/** + * @param {number} typo1 + * @param {number} typo2 + * @param {number} a + * @param {number} b + */ +function foo(a, b, typo1, typo2) { + a; + b; + typo1; + typo2; +}`, +}); From 954d0442eb8c58ca50cf14e0d94def69f5f844b3 Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Thu, 10 Feb 2022 15:05:08 -0800 Subject: [PATCH 36/55] Avoid auto-importing from barrel re-exporting index files that are likely to make an import cycle (#47516) * Avoid auto-importing from barrel re-exporting index files that are likely to make an import cycle * Finish fixing merge conflict --- src/harness/fourslashImpl.ts | 5 +- src/harness/fourslashInterfaceImpl.ts | 4 +- src/services/codefixes/importFixes.ts | 100 ++++++++++++------ tests/cases/fourslash/fourslash.ts | 2 +- .../importNameCodeFix_barrelExport2.ts | 33 ++++++ .../importNameCodeFix_barrelExport3.ts | 32 ++++++ 6 files changed, 140 insertions(+), 36 deletions(-) create mode 100644 tests/cases/fourslash/importNameCodeFix_barrelExport2.ts create mode 100644 tests/cases/fourslash/importNameCodeFix_barrelExport3.ts diff --git a/src/harness/fourslashImpl.ts b/src/harness/fourslashImpl.ts index 3dd8f01663816..7a8cb46688f88 100644 --- a/src/harness/fourslashImpl.ts +++ b/src/harness/fourslashImpl.ts @@ -3146,11 +3146,12 @@ namespace FourSlash { }); } - public verifyImportFixModuleSpecifiers(markerName: string, moduleSpecifiers: string[]) { + public verifyImportFixModuleSpecifiers(markerName: string, moduleSpecifiers: string[], preferences?: ts.UserPreferences) { const marker = this.getMarkerByName(markerName); const codeFixes = this.getCodeFixes(marker.fileName, ts.Diagnostics.Cannot_find_name_0.code, { includeCompletionsForModuleExports: true, - includeCompletionsWithInsertText: true + includeCompletionsWithInsertText: true, + ...preferences, }, marker.position).filter(f => f.fixName === ts.codefix.importFixName); const actualModuleSpecifiers = ts.mapDefined(codeFixes, fix => { diff --git a/src/harness/fourslashInterfaceImpl.ts b/src/harness/fourslashInterfaceImpl.ts index 208631c135767..dc0779de3d827 100644 --- a/src/harness/fourslashInterfaceImpl.ts +++ b/src/harness/fourslashInterfaceImpl.ts @@ -478,8 +478,8 @@ namespace FourSlashInterface { this.state.verifyImportFixAtPosition(expectedTextArray, errorCode, preferences); } - public importFixModuleSpecifiers(marker: string, moduleSpecifiers: string[]) { - this.state.verifyImportFixModuleSpecifiers(marker, moduleSpecifiers); + public importFixModuleSpecifiers(marker: string, moduleSpecifiers: string[], preferences?: ts.UserPreferences) { + this.state.verifyImportFixModuleSpecifiers(marker, moduleSpecifiers, preferences); } public navigationBar(json: any, options?: { checkSpans?: boolean }) { diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index 3c1dc5026ac86..57c50e460f74f 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -81,9 +81,9 @@ namespace ts.codefix { const symbolName = getNameForExportedSymbol(exportedSymbol, getEmitScriptTarget(compilerOptions)); const checker = program.getTypeChecker(); const symbol = checker.getMergedSymbol(skipAlias(exportedSymbol, checker)); - const exportInfos = getAllReExportingModules(sourceFile, symbol, moduleSymbol, symbolName, /*isJsxTagName*/ false, host, program, preferences, useAutoImportProvider); + const exportInfo = getAllReExportingModules(sourceFile, symbol, moduleSymbol, symbolName, /*isJsxTagName*/ false, host, program, preferences, useAutoImportProvider); const useRequire = shouldUseRequire(sourceFile, program); - const fix = getImportFixForSymbol(sourceFile, exportInfos, moduleSymbol, symbolName, program, /*position*/ undefined, !!isValidTypeOnlyUseSite, useRequire, host, preferences); + const fix = getImportFixForSymbol(sourceFile, exportInfo, moduleSymbol, symbolName, program, /*position*/ undefined, !!isValidTypeOnlyUseSite, useRequire, host, preferences); if (fix) { addImport({ fixes: [fix], symbolName, errorIdentifierText: undefined }); } @@ -248,32 +248,35 @@ namespace ts.codefix { } type ImportFix = FixUseNamespaceImport | FixAddJsdocTypeImport | FixAddToExistingImport | FixAddNewImport | FixPromoteTypeOnlyImport; type ImportFixWithModuleSpecifier = FixUseNamespaceImport | FixAddJsdocTypeImport | FixAddToExistingImport | FixAddNewImport; - interface FixUseNamespaceImport { + + // Properties are be undefined if fix is derived from an existing import + interface ImportFixBase { + readonly isReExport?: boolean; + readonly exportInfo?: SymbolExportInfo; + readonly moduleSpecifier: string; + } + interface FixUseNamespaceImport extends ImportFixBase { readonly kind: ImportFixKind.UseNamespace; readonly namespacePrefix: string; readonly position: number; - readonly moduleSpecifier: string; } - interface FixAddJsdocTypeImport { + interface FixAddJsdocTypeImport extends ImportFixBase { readonly kind: ImportFixKind.JsdocTypeImport; - readonly moduleSpecifier: string; readonly position: number; + readonly isReExport: boolean; readonly exportInfo: SymbolExportInfo; } - interface FixAddToExistingImport { + interface FixAddToExistingImport extends ImportFixBase { readonly kind: ImportFixKind.AddToExisting; readonly importClauseOrBindingPattern: ImportClause | ObjectBindingPattern; - readonly moduleSpecifier: string; readonly importKind: ImportKind.Default | ImportKind.Named; readonly addAsTypeOnly: AddAsTypeOnly; } - interface FixAddNewImport { + interface FixAddNewImport extends ImportFixBase { readonly kind: ImportFixKind.AddNew; - readonly moduleSpecifier: string; readonly importKind: ImportKind; readonly addAsTypeOnly: AddAsTypeOnly; readonly useRequire: boolean; - readonly exportInfo?: SymbolExportInfo; } interface FixPromoteTypeOnlyImport { readonly kind: ImportFixKind.PromoteTypeOnly; @@ -331,7 +334,7 @@ namespace ts.codefix { function getImportFixForSymbol(sourceFile: SourceFile, exportInfos: readonly SymbolExportInfo[], moduleSymbol: Symbol, symbolName: string, program: Program, position: number | undefined, isValidTypeOnlyUseSite: boolean, useRequire: boolean, host: LanguageServiceHost, preferences: UserPreferences) { Debug.assert(exportInfos.some(info => info.moduleSymbol === moduleSymbol || info.symbol.parent === moduleSymbol), "Some exportInfo should match the specified moduleSymbol"); const packageJsonImportFilter = createPackageJsonImportFilter(sourceFile, preferences, host); - return getBestFix(getImportFixes(exportInfos, symbolName, position, isValidTypeOnlyUseSite, useRequire, program, sourceFile, host, preferences), sourceFile, program, packageJsonImportFilter); + return getBestFix(getImportFixes(exportInfos, symbolName, position, isValidTypeOnlyUseSite, useRequire, program, sourceFile, host, preferences), sourceFile, program, packageJsonImportFilter, host); } function codeFixActionToCodeAction({ description, changes, commands }: CodeFixAction): CodeAction { @@ -410,7 +413,7 @@ namespace ts.codefix { host, preferences, fromCacheOnly); - const result = getBestFix(fixes, importingFile, program, packageJsonImportFilter || createPackageJsonImportFilter(importingFile, preferences, host)); + const result = getBestFix(fixes, importingFile, program, packageJsonImportFilter || createPackageJsonImportFilter(importingFile, preferences, host), host); return result && { ...result, computedWithoutCacheCount }; } @@ -606,7 +609,7 @@ namespace ts.codefix { position: number | undefined, isValidTypeOnlyUseSite: boolean, useRequire: boolean, - moduleSymbols: readonly SymbolExportInfo[], + exportInfo: readonly SymbolExportInfo[], host: LanguageServiceHost, preferences: UserPreferences, fromCacheOnly?: boolean, @@ -620,7 +623,7 @@ namespace ts.codefix { : (moduleSymbol: Symbol, checker: TypeChecker) => moduleSpecifiers.getModuleSpecifiersWithCacheInfo(moduleSymbol, checker, compilerOptions, sourceFile, moduleSpecifierResolutionHost, preferences); let computedWithoutCacheCount = 0; - const fixes = flatMap(moduleSymbols, exportInfo => { + const fixes = flatMap(exportInfo, (exportInfo, i) => { const checker = getChecker(exportInfo.isFromPackageJson); const { computedWithoutCache, moduleSpecifiers } = getModuleSpecifiers(exportInfo.moduleSymbol, checker); const importedSymbolHasValueMeaning = !!(exportInfo.targetFlags & SymbolFlags.Value); @@ -629,7 +632,7 @@ namespace ts.codefix { return moduleSpecifiers?.map((moduleSpecifier): FixAddNewImport | FixAddJsdocTypeImport => // `position` should only be undefined at a missing jsx namespace, in which case we shouldn't be looking for pure types. !importedSymbolHasValueMeaning && isJs && position !== undefined - ? { kind: ImportFixKind.JsdocTypeImport, moduleSpecifier, position, exportInfo } + ? { kind: ImportFixKind.JsdocTypeImport, moduleSpecifier, position, exportInfo, isReExport: i > 0 } : { kind: ImportFixKind.AddNew, moduleSpecifier, @@ -637,6 +640,7 @@ namespace ts.codefix { useRequire, addAsTypeOnly, exportInfo, + isReExport: i > 0, } ); }); @@ -675,7 +679,7 @@ namespace ts.codefix { } } - interface FixesInfo { readonly fixes: readonly ImportFix[]; readonly symbolName: string; readonly errorIdentifierText: string | undefined; } + interface FixesInfo { readonly fixes: readonly ImportFix[], readonly symbolName: string, readonly errorIdentifierText: string | undefined } function getFixesInfo(context: CodeFixContextBase, errorCode: number, pos: number, useAutoImportProvider: boolean): FixesInfo | undefined { const symbolToken = getTokenAtPosition(context.sourceFile, pos); let info; @@ -695,39 +699,73 @@ namespace ts.codefix { } const packageJsonImportFilter = createPackageJsonImportFilter(context.sourceFile, context.preferences, context.host); - return info && { ...info, fixes: sortFixes(info.fixes, context.sourceFile, context.program, packageJsonImportFilter) }; + return info && { ...info, fixes: sortFixes(info.fixes, context.sourceFile, context.program, packageJsonImportFilter, context.host) }; } - function sortFixes(fixes: readonly ImportFixWithModuleSpecifier[], sourceFile: SourceFile, program: Program, packageJsonImportFilter: PackageJsonImportFilter): readonly ImportFixWithModuleSpecifier[] { - return sort(fixes, (a, b) => compareValues(a.kind, b.kind) || compareModuleSpecifiers(a, b, sourceFile, program, packageJsonImportFilter.allowsImportingSpecifier)); + function sortFixes(fixes: readonly ImportFixWithModuleSpecifier[], sourceFile: SourceFile, program: Program, packageJsonImportFilter: PackageJsonImportFilter, host: LanguageServiceHost): readonly ImportFixWithModuleSpecifier[] { + const _toPath = (fileName: string) => toPath(fileName, host.getCurrentDirectory(), hostGetCanonicalFileName(host)); + return sort(fixes, (a, b) => compareValues(a.kind, b.kind) || compareModuleSpecifiers(a, b, sourceFile, program, packageJsonImportFilter.allowsImportingSpecifier, _toPath)); } - function getBestFix(fixes: readonly T[], sourceFile: SourceFile, program: Program, packageJsonImportFilter: PackageJsonImportFilter): T | undefined { + function getBestFix(fixes: readonly ImportFixWithModuleSpecifier[], sourceFile: SourceFile, program: Program, packageJsonImportFilter: PackageJsonImportFilter, host: LanguageServiceHost): ImportFixWithModuleSpecifier | undefined { if (!some(fixes)) return; // These will always be placed first if available, and are better than other kinds if (fixes[0].kind === ImportFixKind.UseNamespace || fixes[0].kind === ImportFixKind.AddToExisting) { return fixes[0]; } + return fixes.reduce((best, fix) => // Takes true branch of conditional if `fix` is better than `best` - compareModuleSpecifiers(fix, best, sourceFile, program, packageJsonImportFilter.allowsImportingSpecifier) === Comparison.LessThan ? fix : best + compareModuleSpecifiers( + fix, + best, + sourceFile, + program, + packageJsonImportFilter.allowsImportingSpecifier, + fileName => toPath(fileName, host.getCurrentDirectory(), hostGetCanonicalFileName(host)), + ) === Comparison.LessThan ? fix : best ); } /** @returns `Comparison.LessThan` if `a` is better than `b`. */ - function compareModuleSpecifiers(a: ImportFixWithModuleSpecifier, b: ImportFixWithModuleSpecifier, importingFile: SourceFile, program: Program, allowsImportingSpecifier: (specifier: string) => boolean): Comparison { + function compareModuleSpecifiers( + a: ImportFixWithModuleSpecifier, + b: ImportFixWithModuleSpecifier, + importingFile: SourceFile, + program: Program, + allowsImportingSpecifier: (specifier: string) => boolean, + toPath: (fileName: string) => Path, + ): Comparison { if (a.kind !== ImportFixKind.UseNamespace && b.kind !== ImportFixKind.UseNamespace) { return compareBooleans(allowsImportingSpecifier(b.moduleSpecifier), allowsImportingSpecifier(a.moduleSpecifier)) || compareNodeCoreModuleSpecifiers(a.moduleSpecifier, b.moduleSpecifier, importingFile, program) - || compareBooleans(isOnlyDotsAndSlashes(a.moduleSpecifier), isOnlyDotsAndSlashes(b.moduleSpecifier)) + || compareBooleans( + isFixPossiblyReExportingImportingFile(a, importingFile, program.getCompilerOptions(), toPath), + isFixPossiblyReExportingImportingFile(b, importingFile, program.getCompilerOptions(), toPath)) || compareNumberOfDirectorySeparators(a.moduleSpecifier, b.moduleSpecifier); } return Comparison.EqualTo; } - const notDotOrSlashPattern = /[^.\/]/; - function isOnlyDotsAndSlashes(path: string) { - return !notDotOrSlashPattern.test(path); + // This is a simple heuristic to try to avoid creating an import cycle with a barrel re-export. + // E.g., do not `import { Foo } from ".."` when you could `import { Foo } from "../Foo"`. + // This can produce false positives or negatives if re-exports cross into sibling directories + // (e.g. `export * from "../whatever"`) or are not named "index" (we don't even try to consider + // this if we're in a resolution mode where you can't drop trailing "/index" from paths). + function isFixPossiblyReExportingImportingFile(fix: ImportFixWithModuleSpecifier, importingFile: SourceFile, compilerOptions: CompilerOptions, toPath: (fileName: string) => Path): boolean { + if (fix.isReExport && + fix.exportInfo?.moduleFileName && + getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.NodeJs && + isIndexFileName(fix.exportInfo.moduleFileName) + ) { + const reExportDir = toPath(getDirectoryPath(fix.exportInfo.moduleFileName)); + return startsWith((importingFile.path), reExportDir); + } + return false; + } + + function isIndexFileName(fileName: string) { + return getBaseFileName(fileName, [".js", ".jsx", ".d.ts", ".ts", ".tsx"], /*ignoreCase*/ true) === "index"; } function compareNodeCoreModuleSpecifiers(a: string, b: string, importingFile: SourceFile, program: Program): Comparison { @@ -742,9 +780,9 @@ namespace ts.codefix { if (!umdSymbol) return undefined; const symbol = checker.getAliasedSymbol(umdSymbol); const symbolName = umdSymbol.name; - const exportInfos: readonly SymbolExportInfo[] = [{ symbol: umdSymbol, moduleSymbol: symbol, moduleFileName: undefined, exportKind: ExportKind.UMD, targetFlags: symbol.flags, isFromPackageJson: false }]; + const exportInfo: readonly SymbolExportInfo[] = [{ symbol: umdSymbol, moduleSymbol: symbol, moduleFileName: undefined, exportKind: ExportKind.UMD, targetFlags: symbol.flags, isFromPackageJson: false }]; const useRequire = shouldUseRequire(sourceFile, program); - const fixes = getImportFixes(exportInfos, symbolName, isIdentifier(token) ? token.getStart(sourceFile) : undefined, /*isValidTypeOnlyUseSite*/ false, useRequire, program, sourceFile, host, preferences); + const fixes = getImportFixes(exportInfo, symbolName, isIdentifier(token) ? token.getStart(sourceFile) : undefined, /*isValidTypeOnlyUseSite*/ false, useRequire, program, sourceFile, host, preferences); return { fixes, symbolName, errorIdentifierText: tryCast(token, isIdentifier)?.text }; } function getUmdSymbol(token: Node, checker: TypeChecker): Symbol | undefined { @@ -814,8 +852,8 @@ namespace ts.codefix { const isValidTypeOnlyUseSite = isValidTypeOnlyAliasUseSite(symbolToken); const useRequire = shouldUseRequire(sourceFile, program); - const exportInfos = getExportInfos(symbolName, isJSXTagName(symbolToken), getMeaningFromLocation(symbolToken), cancellationToken, sourceFile, program, useAutoImportProvider, host, preferences); - const fixes = arrayFrom(flatMapIterator(exportInfos.entries(), ([_, exportInfos]) => + const exportInfo = getExportInfos(symbolName, isJSXTagName(symbolToken), getMeaningFromLocation(symbolToken), cancellationToken, sourceFile, program, useAutoImportProvider, host, preferences); + const fixes = arrayFrom(flatMapIterator(exportInfo.entries(), ([_, exportInfos]) => getImportFixes(exportInfos, symbolName, symbolToken.getStart(sourceFile), isValidTypeOnlyUseSite, useRequire, program, sourceFile, host, preferences))); return { fixes, symbolName, errorIdentifierText: symbolToken.text }; } diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 8f40bd2ffa6f6..955d87c6f6346 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -364,7 +364,7 @@ declare namespace FourSlashInterface { fileAfterApplyingRefactorAtMarker(markerName: string, expectedContent: string, refactorNameToApply: string, formattingOptions?: FormatCodeOptions): void; getAndApplyCodeFix(errorCode?: number, index?: number): void; importFixAtPosition(expectedTextArray: string[], errorCode?: number, options?: UserPreferences): void; - importFixModuleSpecifiers(marker: string, moduleSpecifiers: string[]): void; + importFixModuleSpecifiers(marker: string, moduleSpecifiers: string[], options?: UserPreferences): void; navigationBar(json: any, options?: { checkSpans?: boolean }): void; navigationTree(json: any, options?: { checkSpans?: boolean }): void; diff --git a/tests/cases/fourslash/importNameCodeFix_barrelExport2.ts b/tests/cases/fourslash/importNameCodeFix_barrelExport2.ts new file mode 100644 index 0000000000000..97a2926ae1167 --- /dev/null +++ b/tests/cases/fourslash/importNameCodeFix_barrelExport2.ts @@ -0,0 +1,33 @@ +/// + +// @module: commonjs +// @baseUrl: / + +// @Filename: /proj/foo/a.ts +//// export const A = 0; + +// @Filename: /proj/foo/b.ts +//// export {}; +//// A/*sibling*/ + +// @Filename: /proj/foo/index.ts +//// export * from "./a"; +//// export * from "./b"; + +// @Filename: /proj/index.ts +//// export * from "./foo"; +//// export * from "./src"; + +// @Filename: /proj/src/a.ts +//// export {}; +//// A/*parent*/ + +// @Filename: /proj/src/utils.ts +//// export function util() { return "util"; } +//// export { A } from "../foo/a"; + +// @Filename: /proj/src/index.ts +//// export * from "./a"; + +verify.importFixModuleSpecifiers("sibling", ["proj/foo/a", "proj/src/utils", "proj", "proj/foo"], { importModuleSpecifierPreference: "non-relative" }); +verify.importFixModuleSpecifiers("parent", ["proj/foo", "proj/foo/a", "proj/src/utils", "proj"], { importModuleSpecifierPreference: "non-relative" }); diff --git a/tests/cases/fourslash/importNameCodeFix_barrelExport3.ts b/tests/cases/fourslash/importNameCodeFix_barrelExport3.ts new file mode 100644 index 0000000000000..108df23b6f0e6 --- /dev/null +++ b/tests/cases/fourslash/importNameCodeFix_barrelExport3.ts @@ -0,0 +1,32 @@ +/// + +// @module: commonjs + +// @Filename: /foo/a.ts +//// export const A = 0; + +// @Filename: /foo/b.ts +//// export {}; +//// A/*sibling*/ + +// @Filename: /foo/index.ts +//// export * from "./a"; +//// export * from "./b"; + +// @Filename: /index.ts +//// export * from "./foo"; +//// export * from "./src"; + +// @Filename: /src/a.ts +//// export {}; +//// A/*parent*/ + +// @Filename: /src/index.ts +//// export * from "./a"; + +verify.importFixModuleSpecifiers("sibling", ["./a", "./index", "../index"], { importModuleSpecifierEnding: "index" }); +// Here, "../foo/a" and "../foo/index" actually have the same sorting score, +// so the original program order is preserved, which seems coincidentally probably good? +// In other words, a re-export is preferable only if it saves on directory separators +// and isn't in an ancestor directory of the importing file. +verify.importFixModuleSpecifiers("parent", ["../foo/a", "../foo/index", "../index"], { importModuleSpecifierEnding: "index" }); From 0655f32e05125372a8fb46adcca9a9fddd2dffdf Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Thu, 10 Feb 2022 16:13:04 -0800 Subject: [PATCH 37/55] Add missing isolatedModules error for `export import` (#47838) * Add missing isolatedModules error for `export import` * Update existing baseline --- src/compiler/checker.ts | 3 ++ src/compiler/diagnosticMessages.json | 6 +++- ...rtImportUninstantiatedNamespace.errors.txt | 25 ++++++++++++++ ...ulesExportImportUninstantiatedNamespace.js | 33 +++++++++++++++++++ .../isolatedModulesReExportType.errors.txt | 5 ++- ...ulesExportImportUninstantiatedNamespace.ts | 23 +++++++++++++ 6 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/isolatedModulesExportImportUninstantiatedNamespace.errors.txt create mode 100644 tests/baselines/reference/isolatedModulesExportImportUninstantiatedNamespace.js create mode 100644 tests/cases/compiler/isolatedModulesExportImportUninstantiatedNamespace.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2830de0c49d98..a97f3596e9a03 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -39940,6 +39940,9 @@ namespace ts { name ); } + if (isType && node.kind === SyntaxKind.ImportEqualsDeclaration && hasEffectiveModifier(node, ModifierFlags.Export)) { + error(node, Diagnostics.Cannot_use_export_import_on_a_type_or_type_only_namespace_when_the_isolatedModules_flag_is_provided); + } break; } case SyntaxKind.ExportSpecifier: { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index cd4f562612a9a..f8a2cfafe6e66 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -867,6 +867,10 @@ "category": "Error", "code": 1268 }, + "Cannot use 'export import' on a type or type-only namespace when the '--isolatedModules' flag is provided.": { + "category": "Error", + "code": 1269 + }, "'with' statements are not allowed in an async function block.": { "category": "Error", @@ -1421,7 +1425,7 @@ "category": "Error", "code": 1474 }, - + "The types of '{0}' are incompatible between these types.": { "category": "Error", "code": 2200 diff --git a/tests/baselines/reference/isolatedModulesExportImportUninstantiatedNamespace.errors.txt b/tests/baselines/reference/isolatedModulesExportImportUninstantiatedNamespace.errors.txt new file mode 100644 index 0000000000000..f4d14877543d6 --- /dev/null +++ b/tests/baselines/reference/isolatedModulesExportImportUninstantiatedNamespace.errors.txt @@ -0,0 +1,25 @@ +tests/cases/compiler/factory.ts(3,1): error TS1269: Cannot use 'export import' on a type or type-only namespace when the '--isolatedModules' flag is provided. + + +==== tests/cases/compiler/jsx.ts (0 errors) ==== + export namespace JSXInternal { + export type HTMLAttributes = string + export type ComponentChildren = string + } + +==== tests/cases/compiler/factory.ts (1 errors) ==== + import { JSXInternal } from "./jsx" + + export import JSX = JSXInternal; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS1269: Cannot use 'export import' on a type or type-only namespace when the '--isolatedModules' flag is provided. + + export function createElement( + tagName: string, + attributes: JSX.HTMLAttributes, + ...children: JSX.ComponentChildren[] + ): any { + //... + } + + \ No newline at end of file diff --git a/tests/baselines/reference/isolatedModulesExportImportUninstantiatedNamespace.js b/tests/baselines/reference/isolatedModulesExportImportUninstantiatedNamespace.js new file mode 100644 index 0000000000000..c2107c1b34f17 --- /dev/null +++ b/tests/baselines/reference/isolatedModulesExportImportUninstantiatedNamespace.js @@ -0,0 +1,33 @@ +//// [tests/cases/compiler/isolatedModulesExportImportUninstantiatedNamespace.ts] //// + +//// [jsx.ts] +export namespace JSXInternal { + export type HTMLAttributes = string + export type ComponentChildren = string +} + +//// [factory.ts] +import { JSXInternal } from "./jsx" + +export import JSX = JSXInternal; + +export function createElement( + tagName: string, + attributes: JSX.HTMLAttributes, + ...children: JSX.ComponentChildren[] +): any { + //... +} + + + +//// [jsx.js] +export {}; +//// [factory.js] +export function createElement(tagName, attributes) { + var children = []; + for (var _i = 2; _i < arguments.length; _i++) { + children[_i - 2] = arguments[_i]; + } + //... +} diff --git a/tests/baselines/reference/isolatedModulesReExportType.errors.txt b/tests/baselines/reference/isolatedModulesReExportType.errors.txt index 3d89ddf487a53..f615abd52c7ce 100644 --- a/tests/baselines/reference/isolatedModulesReExportType.errors.txt +++ b/tests/baselines/reference/isolatedModulesReExportType.errors.txt @@ -1,14 +1,17 @@ /user.ts(2,10): error TS1205: Re-exporting a type when the '--isolatedModules' flag is provided requires using 'export type'. +/user.ts(3,1): error TS1269: Cannot use 'export import' on a type or type-only namespace when the '--isolatedModules' flag is provided. /user.ts(17,10): error TS1205: Re-exporting a type when the '--isolatedModules' flag is provided requires using 'export type'. /user.ts(25,10): error TS1448: 'CC' resolves to a type-only declaration and must be re-exported using a type-only re-export when 'isolatedModules' is enabled. -==== /user.ts (3 errors) ==== +==== /user.ts (4 errors) ==== // Error, can't re-export something that's only a type. export { T } from "./exportT"; ~ !!! error TS1205: Re-exporting a type when the '--isolatedModules' flag is provided requires using 'export type'. export import T2 = require("./exportEqualsT"); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS1269: Cannot use 'export import' on a type or type-only namespace when the '--isolatedModules' flag is provided. // OK, has a value side export { C } from "./exportValue"; diff --git a/tests/cases/compiler/isolatedModulesExportImportUninstantiatedNamespace.ts b/tests/cases/compiler/isolatedModulesExportImportUninstantiatedNamespace.ts new file mode 100644 index 0000000000000..68582dc2ebd19 --- /dev/null +++ b/tests/cases/compiler/isolatedModulesExportImportUninstantiatedNamespace.ts @@ -0,0 +1,23 @@ +// @module: esnext +// @isolatedModules: true +// @noTypesAndSymbols: true + +// @Filename: jsx.ts +export namespace JSXInternal { + export type HTMLAttributes = string + export type ComponentChildren = string +} + +// @Filename: factory.ts +import { JSXInternal } from "./jsx" + +export import JSX = JSXInternal; + +export function createElement( + tagName: string, + attributes: JSX.HTMLAttributes, + ...children: JSX.ComponentChildren[] +): any { + //... +} + From 2bd91a6e3a3830e4f818706a035aad2ddc2fcdd0 Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Fri, 11 Feb 2022 06:06:18 +0000 Subject: [PATCH 38/55] Update package-lock.json --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7e3c413b5939b..1cbd5ded242a0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5113,9 +5113,9 @@ } }, "loupe": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.3.tgz", - "integrity": "sha512-krIV4Cf1BIGIx2t1e6tucThhrBemUnIUjMtD2vN4mrMxnxpBvrcosBSpooqunBqP/hOEEV1w/Cr1YskGtqw5Jg==", + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz", + "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==", "dev": true, "requires": { "get-func-name": "^2.0.0" From 3945e5cbaf80fc6d27a5214f59e12fc81c287607 Mon Sep 17 00:00:00 2001 From: csigs Date: Fri, 11 Feb 2022 03:00:55 -0800 Subject: [PATCH 39/55] LEGO: Merge pull request 47843 LEGO: Merge pull request 47843 --- .../diagnosticMessages.generated.json.lcl | 36 ++++++++++++++----- .../diagnosticMessages.generated.json.lcl | 36 ++++++++++++++----- .../diagnosticMessages.generated.json.lcl | 36 ++++++++++++++----- .../diagnosticMessages.generated.json.lcl | 36 ++++++++++++++----- .../diagnosticMessages.generated.json.lcl | 36 ++++++++++++++----- .../diagnosticMessages.generated.json.lcl | 36 ++++++++++++++----- .../diagnosticMessages.generated.json.lcl | 36 ++++++++++++++----- .../diagnosticMessages.generated.json.lcl | 36 ++++++++++++++----- 8 files changed, 216 insertions(+), 72 deletions(-) diff --git a/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl index f8ad23580d758..2d096f65c4bf1 100644 --- a/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -537,11 +537,11 @@ - + - + - + @@ -1860,11 +1860,20 @@ - + - + - + + + + + + + + + + @@ -1944,11 +1953,20 @@ - + + + + + + + + + + - + - + diff --git a/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl index 7617eab686352..cd0eac45ef996 100644 --- a/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -537,11 +537,11 @@ - + - + - + @@ -1857,11 +1857,20 @@ - + - + - + + + + + + + + + + @@ -1941,11 +1950,20 @@ - + + + + + + + + + + - + - + diff --git a/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl index b33673e7ba9b7..d232c611b1225 100644 --- a/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -546,11 +546,11 @@ - + - + - + @@ -1872,11 +1872,20 @@ - + - + - + + + + + + + + + + @@ -1956,11 +1965,20 @@ - + + + + + + + + + + - + - + diff --git a/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl index 9acc744c145ee..41d5ec0685717 100644 --- a/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -537,11 +537,11 @@ - + - + - + @@ -1860,11 +1860,20 @@ - + - + - + + + + + + + + + + @@ -1944,11 +1953,20 @@ - + + + + + + + + + + - + - + diff --git a/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl index b869efa17de70..c281ba1b6d671 100644 --- a/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -537,11 +537,11 @@ - + - + - + @@ -1860,11 +1860,20 @@ - + - + - + + + + + + + + + + @@ -1944,11 +1953,20 @@ - + + + + + + + + + + - + - + diff --git a/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl index f1b725a6ad337..15ee7bd72014f 100644 --- a/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -530,11 +530,11 @@ - + - + - + @@ -1853,11 +1853,20 @@ - + - + - + + + + + + + + + + @@ -1937,11 +1946,20 @@ - + + + + + + + + + + - + - + diff --git a/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl index d0bda41a2ecef..923ff0b6aafc7 100644 --- a/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -536,11 +536,11 @@ - + - + - + @@ -1859,11 +1859,20 @@ - + - + - + + + + + + + + + + @@ -1943,11 +1952,20 @@ - + + + + + + + + + + - + - + diff --git a/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl index 888c916e24bd8..2b367f919a9b6 100644 --- a/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -530,11 +530,11 @@ - + - + - + @@ -1853,11 +1853,20 @@ - + - + - + + + + + + + + + + @@ -1937,11 +1946,20 @@ - + + + + + + + + + + - + - + From 4c80036b7d86f5423a0448b8a59515a6a7f0eda6 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Fri, 11 Feb 2022 10:54:04 -0800 Subject: [PATCH 40/55] Enable path completions for node12/nodenext (#47836) * Enable path completions for node12/nodenext * Explicitly pull path completions from export maps when available * Explicitly handle pattern exports by stopping up to the star --- src/services/stringCompletions.ts | 72 +++++++++++++++++-- .../nodeNextPathCompletions.baseline | 29 ++++++++ .../server/nodeNextPathCompletions.ts | 43 +++++++++++ 3 files changed, 140 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/nodeNextPathCompletions.baseline create mode 100644 tests/cases/fourslash/server/nodeNextPathCompletions.ts diff --git a/src/services/stringCompletions.ts b/src/services/stringCompletions.ts index e453443526cc7..ecf3fd73642ce 100644 --- a/src/services/stringCompletions.ts +++ b/src/services/stringCompletions.ts @@ -368,9 +368,20 @@ namespace ts.Completions.StringCompletions { } } + function isEmitResolutionKindUsingNodeModules(compilerOptions: CompilerOptions): boolean { + return getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.NodeJs || + getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Node12 || + getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.NodeNext; + } + + function isEmitModuleResolutionRespectingExportMaps(compilerOptions: CompilerOptions) { + return getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Node12 || + getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.NodeNext; + } + function getSupportedExtensionsForModuleResolution(compilerOptions: CompilerOptions): readonly Extension[][] { const extensions = getSupportedExtensions(compilerOptions); - return getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.NodeJs ? + return isEmitResolutionKindUsingNodeModules(compilerOptions) ? getSupportedExtensionsWithJsonIfResolveJsonModule(compilerOptions, extensions) : extensions; } @@ -549,7 +560,7 @@ namespace ts.Completions.StringCompletions { getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, fragmentDirectory, extensionOptions, result); - if (getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.NodeJs) { + if (isEmitResolutionKindUsingNodeModules(compilerOptions)) { // If looking for a global package name, don't just include everything in `node_modules` because that includes dependencies' own dependencies. // (But do if we didn't find anything, e.g. 'package.json' missing.) let foundGlobal = false; @@ -562,12 +573,65 @@ namespace ts.Completions.StringCompletions { } } if (!foundGlobal) { - forEachAncestorDirectory(scriptPath, ancestor => { + let ancestorLookup: (directory: string) => void | undefined = ancestor => { const nodeModules = combinePaths(ancestor, "node_modules"); if (tryDirectoryExists(host, nodeModules)) { getCompletionEntriesForDirectoryFragment(fragment, nodeModules, extensionOptions, host, /*exclude*/ undefined, result); } - }); + }; + if (fragmentDirectory && isEmitModuleResolutionRespectingExportMaps(compilerOptions)) { + const nodeModulesDirectoryLookup = ancestorLookup; + ancestorLookup = ancestor => { + const components = getPathComponents(fragment); + components.shift(); // shift off empty root + let packagePath = components.shift(); + if (!packagePath) { + return nodeModulesDirectoryLookup(ancestor); + } + if (startsWith(packagePath, "@")) { + const subName = components.shift(); + if (!subName) { + return nodeModulesDirectoryLookup(ancestor); + } + packagePath = combinePaths(packagePath, subName); + } + const packageFile = combinePaths(ancestor, "node_modules", packagePath, "package.json"); + if (tryFileExists(host, packageFile)) { + const packageJson = readJson(packageFile, host as { readFile: (filename: string) => string | undefined }); + const exports = (packageJson as any).exports; + if (exports) { + if (typeof exports !== "object" || exports === null) { // eslint-disable-line no-null/no-null + return; // null exports or entrypoint only, no sub-modules available + } + const keys = getOwnKeys(exports); + const fragmentSubpath = components.join("/"); + const processedKeys = mapDefined(keys, k => { + if (k === ".") return undefined; + if (!startsWith(k, "./")) return undefined; + const subpath = k.substring(2); + if (!startsWith(subpath, fragmentSubpath)) return undefined; + // subpath is a valid export (barring conditions, which we don't currently check here) + if (!stringContains(subpath, "*")) { + return subpath; + } + // pattern export - only return everything up to the `*`, so the user can autocomplete, then + // keep filling in the pattern (we could speculatively return a list of options by hitting disk, + // but conditions will make that somewhat awkward, as each condition may have a different set of possible + // options for the `*`. + return subpath.slice(0, subpath.indexOf("*")); + }); + forEach(processedKeys, k => { + if (k) { + result.push(nameAndKind(k, ScriptElementKind.externalModuleName, /*extension*/ undefined)); + } + }); + return; + } + } + return nodeModulesDirectoryLookup(ancestor); + }; + } + forEachAncestorDirectory(scriptPath, ancestorLookup); } } diff --git a/tests/baselines/reference/nodeNextPathCompletions.baseline b/tests/baselines/reference/nodeNextPathCompletions.baseline new file mode 100644 index 0000000000000..3e493c991d426 --- /dev/null +++ b/tests/baselines/reference/nodeNextPathCompletions.baseline @@ -0,0 +1,29 @@ +[ + { + "marker": { + "fileName": "/src/foo.ts", + "position": 30, + "name": "" + }, + "completionList": { + "isGlobalCompletion": false, + "isMemberCompletion": false, + "isNewIdentifierLocation": true, + "entries": [ + { + "name": "dependency", + "kind": "external module name", + "kindModifiers": "", + "sortText": "11", + "displayParts": [ + { + "text": "dependency", + "kind": "text" + } + ], + "tags": [] + } + ] + } + } +] \ No newline at end of file diff --git a/tests/cases/fourslash/server/nodeNextPathCompletions.ts b/tests/cases/fourslash/server/nodeNextPathCompletions.ts new file mode 100644 index 0000000000000..800e7d0a98aa5 --- /dev/null +++ b/tests/cases/fourslash/server/nodeNextPathCompletions.ts @@ -0,0 +1,43 @@ +/// + +// @Filename: /node_modules/dependency/package.json +//// { +//// "type": "module", +//// "name": "dependency", +//// "version": "1.0.0", +//// "exports": { +//// ".": { +//// "types": "./lib/index.d.ts" +//// }, +//// "./lol": { +//// "types": "./lib/lol.d.ts" +//// }, +//// "./dir/*": "./lib/*" +//// } +//// } + +// @Filename: /node_modules/dependency/lib/index.d.ts +//// export function fooFromIndex(): void; + +// @Filename: /node_modules/dependency/lib/lol.d.ts +//// export function fooFromLol(): void; + +// @Filename: /package.json +//// { +//// "type": "module", +//// "dependencies": { +//// "dependency": "^1.0.0" +//// } +//// } + +// @Filename: /tsconfig.json +//// { "compilerOptions": { "module": "nodenext" }, "files": ["./src/foo.ts"] } + +// @Filename: /src/foo.ts +//// import { fooFromIndex } from "/**/"; + +verify.baselineCompletions(); +edit.insert("dependency/"); +verify.completions({ exact: ["lol", "dir/"], isNewIdentifierLocation: true }); +edit.insert("l"); +verify.completions({ exact: ["lol"], isNewIdentifierLocation: true }); From 73506f351278d0967edd24a8b123bc1aed30b297 Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Fri, 11 Feb 2022 21:13:26 +0200 Subject: [PATCH 41/55] fix(46803): remove unused react imports with enabled react-jsxdev, react-jsx (#47247) --- src/services/codefixes/importFixes.ts | 4 --- src/services/organizeImports.ts | 3 +- src/services/utilities.ts | 4 +++ .../organizeImports/JsxFactoryUsedJs.ts | 1 - .../fourslash/organizeImportsReactJsx.ts | 33 +++++++++++++++++++ .../fourslash/organizeImportsReactJsxDev.ts | 33 +++++++++++++++++++ 6 files changed, 72 insertions(+), 6 deletions(-) create mode 100644 tests/cases/fourslash/organizeImportsReactJsx.ts create mode 100644 tests/cases/fourslash/organizeImportsReactJsxDev.ts diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index 57c50e460f74f..c3e6087839bd9 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -869,10 +869,6 @@ namespace ts.codefix { return { kind: ImportFixKind.PromoteTypeOnly, typeOnlyAliasDeclaration }; } - function jsxModeNeedsExplicitImport(jsx: JsxEmit | undefined) { - return jsx === JsxEmit.React || jsx === JsxEmit.ReactNative; - } - function getSymbolName(sourceFile: SourceFile, checker: TypeChecker, symbolToken: Identifier, compilerOptions: CompilerOptions): string { const parent = symbolToken.parent; if ((isJsxOpeningLikeElement(parent) || isJsxClosingElement(parent)) && parent.tagName === symbolToken && jsxModeNeedsExplicitImport(compilerOptions.jsx)) { diff --git a/src/services/organizeImports.ts b/src/services/organizeImports.ts index 77fba1707b0e8..d01f2eae5f6d6 100644 --- a/src/services/organizeImports.ts +++ b/src/services/organizeImports.ts @@ -95,6 +95,7 @@ namespace ts.OrganizeImports { } const typeChecker = program.getTypeChecker(); + const compilerOptions = program.getCompilerOptions(); const jsxNamespace = typeChecker.getJsxNamespace(sourceFile); const jsxFragmentFactory = typeChecker.getJsxFragmentFactory(sourceFile); const jsxElementsPresent = !!(sourceFile.transformFlags & TransformFlags.ContainsJsx); @@ -162,7 +163,7 @@ namespace ts.OrganizeImports { function isDeclarationUsed(identifier: Identifier) { // The JSX factory symbol is always used if JSX elements are present - even if they are not allowed. - return jsxElementsPresent && (identifier.text === jsxNamespace || jsxFragmentFactory && identifier.text === jsxFragmentFactory) || + return jsxElementsPresent && (identifier.text === jsxNamespace || jsxFragmentFactory && identifier.text === jsxFragmentFactory) && jsxModeNeedsExplicitImport(compilerOptions.jsx) || FindAllReferences.Core.isSymbolReferencedInFile(identifier, typeChecker, sourceFile); } } diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 016eb35227eda..ccbd9d1c557e9 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -3335,5 +3335,9 @@ namespace ts { }; } + export function jsxModeNeedsExplicitImport(jsx: JsxEmit | undefined) { + return jsx === JsxEmit.React || jsx === JsxEmit.ReactNative; + } + // #endregion } diff --git a/tests/baselines/reference/organizeImports/JsxFactoryUsedJs.ts b/tests/baselines/reference/organizeImports/JsxFactoryUsedJs.ts index 430a5b12cd4d4..74da2f99139e0 100644 --- a/tests/baselines/reference/organizeImports/JsxFactoryUsedJs.ts +++ b/tests/baselines/reference/organizeImports/JsxFactoryUsedJs.ts @@ -6,6 +6,5 @@ import { React, Other } from "react"; // ==ORGANIZED== -import { React } from "react";

; diff --git a/tests/cases/fourslash/organizeImportsReactJsx.ts b/tests/cases/fourslash/organizeImportsReactJsx.ts new file mode 100644 index 0000000000000..38529f1bd0e7a --- /dev/null +++ b/tests/cases/fourslash/organizeImportsReactJsx.ts @@ -0,0 +1,33 @@ +/// + +// @allowSyntheticDefaultImports: true +// @moduleResolution: node +// @noUnusedLocals: true +// @target: es2018 +// @jsx: react-jsx + +// @filename: test.tsx +////import React from 'react'; +////export default () =>
+ +// @filename: node_modules/react/package.json +////{ +//// "name": "react", +//// "types": "index.d.ts", +////} + +// @filename: node_modules/react/index.d.ts +////export = React; +////declare namespace JSX { +//// interface IntrinsicElements { [x: string]: any; } +////} +////declare namespace React {} + +// @filename: node_modules/react/jsx-runtime.d.ts +////import './'; + +// @filename: node_modules/react/jsx-dev-runtime.d.ts +////import './'; + +goTo.file("test.tsx"); +verify.organizeImports(`export default () =>
`); diff --git a/tests/cases/fourslash/organizeImportsReactJsxDev.ts b/tests/cases/fourslash/organizeImportsReactJsxDev.ts new file mode 100644 index 0000000000000..0bf5b4f884867 --- /dev/null +++ b/tests/cases/fourslash/organizeImportsReactJsxDev.ts @@ -0,0 +1,33 @@ +/// + +// @allowSyntheticDefaultImports: true +// @moduleResolution: node +// @noUnusedLocals: true +// @target: es2018 +// @jsx: react-jsxdev + +// @filename: test.tsx +////import React from 'react'; +////export default () =>
+ +// @filename: node_modules/react/package.json +////{ +//// "name": "react", +//// "types": "index.d.ts", +////} + +// @filename: node_modules/react/index.d.ts +////export = React; +////declare namespace JSX { +//// interface IntrinsicElements { [x: string]: any; } +////} +////declare namespace React {} + +// @filename: node_modules/react/jsx-runtime.d.ts +////import './'; + +// @filename: node_modules/react/jsx-dev-runtime.d.ts +////import './'; + +goTo.file("test.tsx"); +verify.organizeImports(`export default () =>
`); From 7f022c58fb8b7253f23c49f0d9eee6fde82b477b Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Fri, 11 Feb 2022 11:14:07 -0800 Subject: [PATCH 42/55] Correctly resolve imports ending with "." and ".." (#47850) --- src/compiler/moduleNameResolver.ts | 18 +++++++++++-- src/compiler/path.ts | 12 --------- .../reference/importFromDot.errors.txt | 14 ++++++++++ tests/baselines/reference/importFromDot.js | 25 ++++++++++++++++++ .../baselines/reference/importFromDot.symbols | 13 ++++++++++ tests/baselines/reference/importFromDot.types | 15 +++++++++++ .../importWithTrailingSlash.errors.txt | 26 +++++++++++++++++++ .../reference/importWithTrailingSlash.symbols | 4 --- .../importWithTrailingSlash.trace.json | 16 +++++++----- .../reference/importWithTrailingSlash.types | 16 ++++++------ ...-are-disabled-and-a-decl-map-is-missing.js | 2 -- ...-are-disabled-and-a-decl-map-is-present.js | 2 -- ...s-are-enabled-and-a-decl-map-is-missing.js | 2 -- ...s-are-enabled-and-a-decl-map-is-present.js | 2 -- ...-are-disabled-and-a-decl-map-is-missing.js | 2 -- ...-are-disabled-and-a-decl-map-is-present.js | 2 -- ...s-are-enabled-and-a-decl-map-is-missing.js | 2 -- ...s-are-enabled-and-a-decl-map-is-present.js | 2 -- ...-are-disabled-and-a-decl-map-is-present.js | 2 -- ...s-are-enabled-and-a-decl-map-is-missing.js | 2 -- ...s-are-enabled-and-a-decl-map-is-present.js | 2 -- .../moduleResolution/importFromDot.ts | 10 +++++++ 22 files changed, 136 insertions(+), 55 deletions(-) create mode 100644 tests/baselines/reference/importFromDot.errors.txt create mode 100644 tests/baselines/reference/importFromDot.js create mode 100644 tests/baselines/reference/importFromDot.symbols create mode 100644 tests/baselines/reference/importFromDot.types create mode 100644 tests/baselines/reference/importWithTrailingSlash.errors.txt create mode 100644 tests/cases/conformance/moduleResolution/importFromDot.ts diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index 5ea72a6bbf2d8..7d6d0f67d7aee 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -417,7 +417,7 @@ namespace ts { result = searchResult && searchResult.value; } else { - const { path: candidate } = normalizePathAndParts(combinePaths(initialLocationForSecondaryLookup, typeReferenceDirectiveName)); + const { path: candidate } = normalizePathForCJSResolution(initialLocationForSecondaryLookup, typeReferenceDirectiveName); result = nodeLoadModuleByRelativeName(Extensions.DtsOnly, candidate, /*onlyRecordFailures*/ false, moduleResolutionState, /*considerPackageJson*/ true); } return resolvedTypeScriptOnly(result); @@ -1329,12 +1329,26 @@ namespace ts { return { value: resolvedValue && { resolved: resolvedValue, isExternalLibraryImport: true } }; } else { - const { path: candidate, parts } = normalizePathAndParts(combinePaths(containingDirectory, moduleName)); + const { path: candidate, parts } = normalizePathForCJSResolution(containingDirectory, moduleName); const resolved = nodeLoadModuleByRelativeName(extensions, candidate, /*onlyRecordFailures*/ false, state, /*considerPackageJson*/ true); // Treat explicit "node_modules" import as an external library import. return resolved && toSearchResult({ resolved, isExternalLibraryImport: contains(parts, "node_modules") }); } } + + } + + // If you import from "." inside a containing directory "/foo", the result of `normalizePath` + // would be "/foo", but this loses the information that `foo` is a directory and we intended + // to look inside of it. The Node CommonJS resolution algorithm doesn't call this out + // (https://nodejs.org/api/modules.html#all-together), but it seems that module paths ending + // in `.` are actually normalized to `./` before proceeding with the resolution algorithm. + function normalizePathForCJSResolution(containingDirectory: string, moduleName: string) { + const combined = combinePaths(containingDirectory, moduleName); + const parts = getPathComponents(combined); + const lastPart = lastOrUndefined(parts); + const path = lastPart === "." || lastPart === ".." ? ensureTrailingDirectorySeparator(normalizePath(combined)) : normalizePath(combined); + return { path, parts }; } function realPath(path: string, host: ModuleResolutionHost, traceEnabled: boolean): string { diff --git a/src/compiler/path.ts b/src/compiler/path.ts index d09108d34c7f3..ebc837feb33a3 100644 --- a/src/compiler/path.ts +++ b/src/compiler/path.ts @@ -585,18 +585,6 @@ namespace ts { return getCanonicalFileName(nonCanonicalizedPath) as Path; } - export function normalizePathAndParts(path: string): { path: string, parts: string[] } { - path = normalizeSlashes(path); - const [root, ...parts] = reducePathComponents(getPathComponents(path)); - if (parts.length) { - const joinedParts = root + parts.join(directorySeparator); - return { path: hasTrailingDirectorySeparator(path) ? ensureTrailingDirectorySeparator(joinedParts) : joinedParts, parts }; - } - else { - return { path: root, parts }; - } - } - //// Path Mutation /** diff --git a/tests/baselines/reference/importFromDot.errors.txt b/tests/baselines/reference/importFromDot.errors.txt new file mode 100644 index 0000000000000..567c61451d9f5 --- /dev/null +++ b/tests/baselines/reference/importFromDot.errors.txt @@ -0,0 +1,14 @@ +tests/cases/conformance/moduleResolution/a/b.ts(1,20): error TS2305: Module '"."' has no exported member 'rootA'. + + +==== tests/cases/conformance/moduleResolution/a.ts (0 errors) ==== + export const rootA = 0; + +==== tests/cases/conformance/moduleResolution/a/index.ts (0 errors) ==== + export const indexInA = 0; + +==== tests/cases/conformance/moduleResolution/a/b.ts (1 errors) ==== + import { indexInA, rootA } from "."; + ~~~~~ +!!! error TS2305: Module '"."' has no exported member 'rootA'. + \ No newline at end of file diff --git a/tests/baselines/reference/importFromDot.js b/tests/baselines/reference/importFromDot.js new file mode 100644 index 0000000000000..0bccb84eeb2ad --- /dev/null +++ b/tests/baselines/reference/importFromDot.js @@ -0,0 +1,25 @@ +//// [tests/cases/conformance/moduleResolution/importFromDot.ts] //// + +//// [a.ts] +export const rootA = 0; + +//// [index.ts] +export const indexInA = 0; + +//// [b.ts] +import { indexInA, rootA } from "."; + + +//// [a.js] +"use strict"; +exports.__esModule = true; +exports.rootA = void 0; +exports.rootA = 0; +//// [index.js] +"use strict"; +exports.__esModule = true; +exports.indexInA = void 0; +exports.indexInA = 0; +//// [b.js] +"use strict"; +exports.__esModule = true; diff --git a/tests/baselines/reference/importFromDot.symbols b/tests/baselines/reference/importFromDot.symbols new file mode 100644 index 0000000000000..2431f381a341c --- /dev/null +++ b/tests/baselines/reference/importFromDot.symbols @@ -0,0 +1,13 @@ +=== tests/cases/conformance/moduleResolution/a.ts === +export const rootA = 0; +>rootA : Symbol(rootA, Decl(a.ts, 0, 12)) + +=== tests/cases/conformance/moduleResolution/a/index.ts === +export const indexInA = 0; +>indexInA : Symbol(indexInA, Decl(index.ts, 0, 12)) + +=== tests/cases/conformance/moduleResolution/a/b.ts === +import { indexInA, rootA } from "."; +>indexInA : Symbol(indexInA, Decl(b.ts, 0, 8)) +>rootA : Symbol(rootA, Decl(b.ts, 0, 18)) + diff --git a/tests/baselines/reference/importFromDot.types b/tests/baselines/reference/importFromDot.types new file mode 100644 index 0000000000000..f595b92a9961e --- /dev/null +++ b/tests/baselines/reference/importFromDot.types @@ -0,0 +1,15 @@ +=== tests/cases/conformance/moduleResolution/a.ts === +export const rootA = 0; +>rootA : 0 +>0 : 0 + +=== tests/cases/conformance/moduleResolution/a/index.ts === +export const indexInA = 0; +>indexInA : 0 +>0 : 0 + +=== tests/cases/conformance/moduleResolution/a/b.ts === +import { indexInA, rootA } from "."; +>indexInA : 0 +>rootA : any + diff --git a/tests/baselines/reference/importWithTrailingSlash.errors.txt b/tests/baselines/reference/importWithTrailingSlash.errors.txt new file mode 100644 index 0000000000000..60125b35a5847 --- /dev/null +++ b/tests/baselines/reference/importWithTrailingSlash.errors.txt @@ -0,0 +1,26 @@ +/a/b/test.ts(3,3): error TS2339: Property 'a' does not exist on type '{ aIndex: number; }'. +/a/test.ts(3,3): error TS2339: Property 'a' does not exist on type '{ aIndex: number; }'. + + +==== /a.ts (0 errors) ==== + export default { a: 0 }; + +==== /a/index.ts (0 errors) ==== + export default { aIndex: 0 }; + +==== /a/test.ts (1 errors) ==== + import a from "."; + import aIndex from "./"; + a.a; + ~ +!!! error TS2339: Property 'a' does not exist on type '{ aIndex: number; }'. + aIndex.aIndex; + +==== /a/b/test.ts (1 errors) ==== + import a from ".."; + import aIndex from "../"; + a.a; + ~ +!!! error TS2339: Property 'a' does not exist on type '{ aIndex: number; }'. + aIndex.aIndex; + \ No newline at end of file diff --git a/tests/baselines/reference/importWithTrailingSlash.symbols b/tests/baselines/reference/importWithTrailingSlash.symbols index c6c4946438010..ddaf5befb066e 100644 --- a/tests/baselines/reference/importWithTrailingSlash.symbols +++ b/tests/baselines/reference/importWithTrailingSlash.symbols @@ -14,9 +14,7 @@ import aIndex from "./"; >aIndex : Symbol(aIndex, Decl(test.ts, 1, 6)) a.a; ->a.a : Symbol(a, Decl(a.ts, 0, 16)) >a : Symbol(a, Decl(test.ts, 0, 6)) ->a : Symbol(a, Decl(a.ts, 0, 16)) aIndex.aIndex; >aIndex.aIndex : Symbol(aIndex, Decl(index.ts, 0, 16)) @@ -31,9 +29,7 @@ import aIndex from "../"; >aIndex : Symbol(aIndex, Decl(test.ts, 1, 6)) a.a; ->a.a : Symbol(a, Decl(a.ts, 0, 16)) >a : Symbol(a, Decl(test.ts, 0, 6)) ->a : Symbol(a, Decl(a.ts, 0, 16)) aIndex.aIndex; >aIndex.aIndex : Symbol(aIndex, Decl(index.ts, 0, 16)) diff --git a/tests/baselines/reference/importWithTrailingSlash.trace.json b/tests/baselines/reference/importWithTrailingSlash.trace.json index fb77f85298840..b60d3bc6aab90 100644 --- a/tests/baselines/reference/importWithTrailingSlash.trace.json +++ b/tests/baselines/reference/importWithTrailingSlash.trace.json @@ -1,20 +1,22 @@ [ "======== Resolving module '.' from '/a/test.ts'. ========", "Explicitly specified module resolution kind: 'NodeJs'.", - "Loading module as file / folder, candidate module location '/a', target file type 'TypeScript'.", - "File '/a.ts' exist - use it as a name resolution result.", - "======== Module name '.' was successfully resolved to '/a.ts'. ========", + "Loading module as file / folder, candidate module location '/a/', target file type 'TypeScript'.", + "File '/a/package.json' does not exist.", + "File '/a/index.ts' exist - use it as a name resolution result.", + "======== Module name '.' was successfully resolved to '/a/index.ts'. ========", "======== Resolving module './' from '/a/test.ts'. ========", "Explicitly specified module resolution kind: 'NodeJs'.", "Loading module as file / folder, candidate module location '/a/', target file type 'TypeScript'.", - "File '/a/package.json' does not exist.", + "File '/a/package.json' does not exist according to earlier cached lookups.", "File '/a/index.ts' exist - use it as a name resolution result.", "======== Module name './' was successfully resolved to '/a/index.ts'. ========", "======== Resolving module '..' from '/a/b/test.ts'. ========", "Explicitly specified module resolution kind: 'NodeJs'.", - "Loading module as file / folder, candidate module location '/a', target file type 'TypeScript'.", - "File '/a.ts' exist - use it as a name resolution result.", - "======== Module name '..' was successfully resolved to '/a.ts'. ========", + "Loading module as file / folder, candidate module location '/a/', target file type 'TypeScript'.", + "File '/a/package.json' does not exist according to earlier cached lookups.", + "File '/a/index.ts' exist - use it as a name resolution result.", + "======== Module name '..' was successfully resolved to '/a/index.ts'. ========", "======== Resolving module '../' from '/a/b/test.ts'. ========", "Explicitly specified module resolution kind: 'NodeJs'.", "Loading module as file / folder, candidate module location '/a/', target file type 'TypeScript'.", diff --git a/tests/baselines/reference/importWithTrailingSlash.types b/tests/baselines/reference/importWithTrailingSlash.types index beec18ea4aad9..41c2a160afa40 100644 --- a/tests/baselines/reference/importWithTrailingSlash.types +++ b/tests/baselines/reference/importWithTrailingSlash.types @@ -12,15 +12,15 @@ export default { aIndex: 0 }; === /a/test.ts === import a from "."; ->a : { a: number; } +>a : { aIndex: number; } import aIndex from "./"; >aIndex : { aIndex: number; } a.a; ->a.a : number ->a : { a: number; } ->a : number +>a.a : any +>a : { aIndex: number; } +>a : any aIndex.aIndex; >aIndex.aIndex : number @@ -29,15 +29,15 @@ aIndex.aIndex; === /a/b/test.ts === import a from ".."; ->a : { a: number; } +>a : { aIndex: number; } import aIndex from "../"; >aIndex : { aIndex: number; } a.a; ->a.a : number ->a : { a: number; } ->a : number +>a.a : any +>a : { aIndex: number; } +>a : any aIndex.aIndex; >aIndex.aIndex : number diff --git a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-missing.js b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-missing.js index e4a796ad6a22c..ce3688b728598 100644 --- a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-missing.js +++ b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-missing.js @@ -78,8 +78,6 @@ Creating configuration project /user/username/projects/myproject/b/tsconfig.json Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b/index.ts 500 undefined WatchType: Closed Script info Starting updateGraphWorker: Project: /user/username/projects/myproject/b/tsconfig.json -DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations -Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 500 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Missing file diff --git a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-present.js b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-present.js index de2955e6e7be2..1bc9dd129483d 100644 --- a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-present.js +++ b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-present.js @@ -78,8 +78,6 @@ Creating configuration project /user/username/projects/myproject/b/tsconfig.json Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b/index.ts 500 undefined WatchType: Closed Script info Starting updateGraphWorker: Project: /user/username/projects/myproject/b/tsconfig.json -DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations -Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 500 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Missing file diff --git a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-missing.js b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-missing.js index b1df27518b1b0..4711ea0e97bb8 100644 --- a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-missing.js +++ b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-missing.js @@ -77,8 +77,6 @@ For info: /user/username/projects/myproject/b/helper.ts :: Config file name: /us Creating configuration project /user/username/projects/myproject/b/tsconfig.json Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded Starting updateGraphWorker: Project: /user/username/projects/myproject/b/tsconfig.json -DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations -Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 500 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Missing file diff --git a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-present.js b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-present.js index b1df27518b1b0..4711ea0e97bb8 100644 --- a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-present.js +++ b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-disabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-present.js @@ -77,8 +77,6 @@ For info: /user/username/projects/myproject/b/helper.ts :: Config file name: /us Creating configuration project /user/username/projects/myproject/b/tsconfig.json Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded Starting updateGraphWorker: Project: /user/username/projects/myproject/b/tsconfig.json -DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations -Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 500 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Missing file diff --git a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-missing.js b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-missing.js index 67cd7b768598a..8f623cafddeb2 100644 --- a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-missing.js +++ b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-missing.js @@ -78,8 +78,6 @@ Creating configuration project /user/username/projects/myproject/b/tsconfig.json Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b/index.ts 500 undefined WatchType: Closed Script info Starting updateGraphWorker: Project: /user/username/projects/myproject/b/tsconfig.json -DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations -Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 500 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Missing file diff --git a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-present.js b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-present.js index e647f2e2f5c68..42e5e3e6e5109 100644 --- a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-present.js +++ b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-present.js @@ -78,8 +78,6 @@ Creating configuration project /user/username/projects/myproject/b/tsconfig.json Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b/index.ts 500 undefined WatchType: Closed Script info Starting updateGraphWorker: Project: /user/username/projects/myproject/b/tsconfig.json -DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations -Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 500 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Missing file diff --git a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-missing.js b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-missing.js index 74ca1adfc4a5f..dc8a96898a8c6 100644 --- a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-missing.js +++ b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-missing.js @@ -77,8 +77,6 @@ For info: /user/username/projects/myproject/b/helper.ts :: Config file name: /us Creating configuration project /user/username/projects/myproject/b/tsconfig.json Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded Starting updateGraphWorker: Project: /user/username/projects/myproject/b/tsconfig.json -DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations -Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 500 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Missing file diff --git a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-present.js b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-present.js index 74ca1adfc4a5f..dc8a96898a8c6 100644 --- a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-present.js +++ b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-present.js @@ -77,8 +77,6 @@ For info: /user/username/projects/myproject/b/helper.ts :: Config file name: /us Creating configuration project /user/username/projects/myproject/b/tsconfig.json Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded Starting updateGraphWorker: Project: /user/username/projects/myproject/b/tsconfig.json -DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations -Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 500 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Missing file diff --git a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-present.js b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-present.js index 73acf6730c022..b702f7ee33a75 100644 --- a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-present.js +++ b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-disabled-and-a-decl-map-is-present.js @@ -81,8 +81,6 @@ Creating configuration project /user/username/projects/myproject/b/tsconfig.json Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b/helper.ts 500 undefined WatchType: Closed Script info Starting updateGraphWorker: Project: /user/username/projects/myproject/b/tsconfig.json -DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations -Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 500 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Missing file diff --git a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-missing.js b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-missing.js index 296aa5a020cfc..55d79cb9042d0 100644 --- a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-missing.js +++ b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-missing.js @@ -79,8 +79,6 @@ Creating configuration project /user/username/projects/myproject/b/tsconfig.json Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b/helper.ts 500 undefined WatchType: Closed Script info Starting updateGraphWorker: Project: /user/username/projects/myproject/b/tsconfig.json -DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations -Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 500 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Missing file diff --git a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-present.js b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-present.js index 296aa5a020cfc..55d79cb9042d0 100644 --- a/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-present.js +++ b/tests/baselines/reference/tsserver/projectReferences/find-refs-to-decl-in-other-proj-when-proj-is-not-loaded-and-refd-proj-loading-is-enabled-and-proj-ref-redirects-are-enabled-and-a-decl-map-is-present.js @@ -79,8 +79,6 @@ Creating configuration project /user/username/projects/myproject/b/tsconfig.json Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b/helper.ts 500 undefined WatchType: Closed Script info Starting updateGraphWorker: Project: /user/username/projects/myproject/b/tsconfig.json -DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations -Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b 0 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Failed Lookup Locations FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 500 undefined Project: /user/username/projects/myproject/b/tsconfig.json WatchType: Missing file diff --git a/tests/cases/conformance/moduleResolution/importFromDot.ts b/tests/cases/conformance/moduleResolution/importFromDot.ts new file mode 100644 index 0000000000000..eb28f6943f6ca --- /dev/null +++ b/tests/cases/conformance/moduleResolution/importFromDot.ts @@ -0,0 +1,10 @@ +// @module: commonjs + +// @Filename: a.ts +export const rootA = 0; + +// @Filename: a/index.ts +export const indexInA = 0; + +// @Filename: a/b.ts +import { indexInA, rootA } from "."; From 033f9e0081bde7a90e23d7a8427d04f6a61e8c8b Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Fri, 11 Feb 2022 14:58:31 -0800 Subject: [PATCH 43/55] Consider a symbol visible for declaration emit when it is the target of an ambient module's export= (#47835) * Consider a symbol visible for declaration emit when it is the target of an ambient module's export= * Just use resolveExternalModuleSymbol --- src/compiler/checker.ts | 11 ++- .../reference/amdLikeInputDeclarationEmit.js | 40 ++++++++++ .../amdLikeInputDeclarationEmit.symbols | 66 +++++++++++++++++ .../amdLikeInputDeclarationEmit.types | 74 +++++++++++++++++++ .../importDeclFromTypeNodeInJsSource.types | 2 +- .../reference/importTypeAmbient.types | 2 +- .../reference/incompatibleExports1.types | 2 +- .../compiler/amdLikeInputDeclarationEmit.ts | 34 +++++++++ 8 files changed, 226 insertions(+), 5 deletions(-) create mode 100644 tests/baselines/reference/amdLikeInputDeclarationEmit.js create mode 100644 tests/baselines/reference/amdLikeInputDeclarationEmit.symbols create mode 100644 tests/baselines/reference/amdLikeInputDeclarationEmit.types create mode 100644 tests/cases/compiler/amdLikeInputDeclarationEmit.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a97f3596e9a03..cd33d83ff494f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3981,8 +3981,15 @@ namespace ts { return res; } const candidates = mapDefined(symbol.declarations, d => { - if (!isAmbientModule(d) && d.parent && hasNonGlobalAugmentationExternalModuleSymbol(d.parent)) { - return getSymbolOfNode(d.parent); + if (!isAmbientModule(d) && d.parent){ + // direct children of a module + if (hasNonGlobalAugmentationExternalModuleSymbol(d.parent)) { + return getSymbolOfNode(d.parent); + } + // export ='d member of an ambient module + if (isModuleBlock(d.parent) && d.parent.parent && resolveExternalModuleSymbol(getSymbolOfNode(d.parent.parent)) === symbol) { + return getSymbolOfNode(d.parent.parent); + } } if (isClassExpression(d) && isBinaryExpression(d.parent) && d.parent.operatorToken.kind === SyntaxKind.EqualsToken && isAccessExpression(d.parent.left) && isEntityNameExpression(d.parent.left.expression)) { if (isModuleExportsAccessExpression(d.parent.left) || isExportsIdentifier(d.parent.left.expression)) { diff --git a/tests/baselines/reference/amdLikeInputDeclarationEmit.js b/tests/baselines/reference/amdLikeInputDeclarationEmit.js new file mode 100644 index 0000000000000..a34697f4f3e4f --- /dev/null +++ b/tests/baselines/reference/amdLikeInputDeclarationEmit.js @@ -0,0 +1,40 @@ +//// [tests/cases/compiler/amdLikeInputDeclarationEmit.ts] //// + +//// [typing.d.ts] +declare function define(name: string, modules: string[], ready: (...modules: unknown[]) => T); +//// [BaseClass.d.ts] +declare module "deps/BaseClass" { + class BaseClass { + static extends(a: A): new () => A & BaseClass; + } + export = BaseClass; +} +//// [ExtendedClass.js] +define("lib/ExtendedClass", ["deps/BaseClass"], +/** + * {typeof import("deps/BaseClass")} + * @param {typeof import("deps/BaseClass")} BaseClass + * @returns + */ +(BaseClass) => { + + const ExtendedClass = BaseClass.extends({ + f: function() { + return "something"; + } + }); + + // Exports the module in a way tsc recognize class export + const module = {}; + module.exports = ExtendedClass + return module.exports; +}); + + + +//// [ExtendedClass.d.ts] +/// +export = ExtendedClass; +declare const ExtendedClass: new () => { + f: () => "something"; +} & import("deps/BaseClass"); diff --git a/tests/baselines/reference/amdLikeInputDeclarationEmit.symbols b/tests/baselines/reference/amdLikeInputDeclarationEmit.symbols new file mode 100644 index 0000000000000..4b9e455840f1a --- /dev/null +++ b/tests/baselines/reference/amdLikeInputDeclarationEmit.symbols @@ -0,0 +1,66 @@ +=== tests/cases/compiler/typing.d.ts === +declare function define(name: string, modules: string[], ready: (...modules: unknown[]) => T); +>define : Symbol(define, Decl(typing.d.ts, 0, 0)) +>T : Symbol(T, Decl(typing.d.ts, 0, 24)) +>name : Symbol(name, Decl(typing.d.ts, 0, 35)) +>modules : Symbol(modules, Decl(typing.d.ts, 0, 48)) +>ready : Symbol(ready, Decl(typing.d.ts, 0, 67)) +>modules : Symbol(modules, Decl(typing.d.ts, 0, 76)) +>T : Symbol(T, Decl(typing.d.ts, 0, 24)) + +=== tests/cases/compiler/deps/BaseClass.d.ts === +declare module "deps/BaseClass" { +>"deps/BaseClass" : Symbol("deps/BaseClass", Decl(BaseClass.d.ts, 0, 0)) + + class BaseClass { +>BaseClass : Symbol(BaseClass, Decl(BaseClass.d.ts, 0, 33)) + + static extends(a: A): new () => A & BaseClass; +>extends : Symbol(BaseClass.extends, Decl(BaseClass.d.ts, 1, 21)) +>A : Symbol(A, Decl(BaseClass.d.ts, 2, 23)) +>a : Symbol(a, Decl(BaseClass.d.ts, 2, 26)) +>A : Symbol(A, Decl(BaseClass.d.ts, 2, 23)) +>A : Symbol(A, Decl(BaseClass.d.ts, 2, 23)) +>BaseClass : Symbol(BaseClass, Decl(BaseClass.d.ts, 0, 33)) + } + export = BaseClass; +>BaseClass : Symbol(BaseClass, Decl(BaseClass.d.ts, 0, 33)) +} +=== tests/cases/compiler/ExtendedClass.js === +define("lib/ExtendedClass", ["deps/BaseClass"], +>define : Symbol(define, Decl(typing.d.ts, 0, 0)) + +/** + * {typeof import("deps/BaseClass")} + * @param {typeof import("deps/BaseClass")} BaseClass + * @returns + */ +(BaseClass) => { +>BaseClass : Symbol(BaseClass, Decl(ExtendedClass.js, 6, 1)) + + const ExtendedClass = BaseClass.extends({ +>ExtendedClass : Symbol(ExtendedClass, Decl(ExtendedClass.js, 8, 9)) +>BaseClass.extends : Symbol(BaseClass.extends, Decl(BaseClass.d.ts, 1, 21)) +>BaseClass : Symbol(BaseClass, Decl(ExtendedClass.js, 6, 1)) +>extends : Symbol(BaseClass.extends, Decl(BaseClass.d.ts, 1, 21)) + + f: function() { +>f : Symbol(f, Decl(ExtendedClass.js, 8, 45)) + + return "something"; + } + }); + + // Exports the module in a way tsc recognize class export + const module = {}; +>module : Symbol(module, Decl(ExtendedClass.js, 15, 9)) + + module.exports = ExtendedClass +>module : Symbol(export=, Decl(ExtendedClass.js, 15, 22)) +>exports : Symbol(export=, Decl(ExtendedClass.js, 15, 22)) +>ExtendedClass : Symbol(ExtendedClass, Decl(ExtendedClass.js, 8, 9)) + + return module.exports; +>module : Symbol(module, Decl(ExtendedClass.js, 15, 9)) + +}); diff --git a/tests/baselines/reference/amdLikeInputDeclarationEmit.types b/tests/baselines/reference/amdLikeInputDeclarationEmit.types new file mode 100644 index 0000000000000..6bf0319f5e200 --- /dev/null +++ b/tests/baselines/reference/amdLikeInputDeclarationEmit.types @@ -0,0 +1,74 @@ +=== tests/cases/compiler/typing.d.ts === +declare function define(name: string, modules: string[], ready: (...modules: unknown[]) => T); +>define : (name: string, modules: string[], ready: (...modules: unknown[]) => T) => any +>name : string +>modules : string[] +>ready : (...modules: unknown[]) => T +>modules : unknown[] + +=== tests/cases/compiler/deps/BaseClass.d.ts === +declare module "deps/BaseClass" { +>"deps/BaseClass" : typeof import("deps/BaseClass") + + class BaseClass { +>BaseClass : BaseClass + + static extends(a: A): new () => A & BaseClass; +>extends : (a: A) => new () => A & BaseClass +>a : A + } + export = BaseClass; +>BaseClass : BaseClass +} +=== tests/cases/compiler/ExtendedClass.js === +define("lib/ExtendedClass", ["deps/BaseClass"], +>define("lib/ExtendedClass", ["deps/BaseClass"], /** * {typeof import("deps/BaseClass")} * @param {typeof import("deps/BaseClass")} BaseClass * @returns */(BaseClass) => { const ExtendedClass = BaseClass.extends({ f: function() { return "something"; } }); // Exports the module in a way tsc recognize class export const module = {}; module.exports = ExtendedClass return module.exports;}) : any +>define : (name: string, modules: string[], ready: (...modules: unknown[]) => T) => any +>"lib/ExtendedClass" : "lib/ExtendedClass" +>["deps/BaseClass"] : string[] +>"deps/BaseClass" : "deps/BaseClass" + +/** + * {typeof import("deps/BaseClass")} + * @param {typeof import("deps/BaseClass")} BaseClass + * @returns + */ +(BaseClass) => { +>(BaseClass) => { const ExtendedClass = BaseClass.extends({ f: function() { return "something"; } }); // Exports the module in a way tsc recognize class export const module = {}; module.exports = ExtendedClass return module.exports;} : (BaseClass: typeof import("deps/BaseClass")) => any +>BaseClass : typeof import("deps/BaseClass") + + const ExtendedClass = BaseClass.extends({ +>ExtendedClass : new () => { f: () => "something"; } & import("deps/BaseClass") +>BaseClass.extends({ f: function() { return "something"; } }) : new () => { f: () => "something"; } & import("deps/BaseClass") +>BaseClass.extends : (a: A) => new () => A & import("deps/BaseClass") +>BaseClass : typeof import("deps/BaseClass") +>extends : (a: A) => new () => A & import("deps/BaseClass") +>{ f: function() { return "something"; } } : { f: () => "something"; } + + f: function() { +>f : () => "something" +>function() { return "something"; } : () => "something" + + return "something"; +>"something" : "something" + } + }); + + // Exports the module in a way tsc recognize class export + const module = {}; +>module : {} +>{} : {} + + module.exports = ExtendedClass +>module.exports = ExtendedClass : any +>module.exports : any +>module : {} +>exports : any +>ExtendedClass : new () => { f: () => "something"; } & import("deps/BaseClass") + + return module.exports; +>module.exports : any +>module : {} +>exports : any + +}); diff --git a/tests/baselines/reference/importDeclFromTypeNodeInJsSource.types b/tests/baselines/reference/importDeclFromTypeNodeInJsSource.types index 231dbdc6d3a29..2f8af5e09dbd4 100644 --- a/tests/baselines/reference/importDeclFromTypeNodeInJsSource.types +++ b/tests/baselines/reference/importDeclFromTypeNodeInJsSource.types @@ -5,7 +5,7 @@ declare module "events" { >"events" : typeof import("events") namespace EventEmitter { ->EventEmitter : typeof EventEmitter +>EventEmitter : typeof import("events") class EventEmitter { >EventEmitter : EventEmitter diff --git a/tests/baselines/reference/importTypeAmbient.types b/tests/baselines/reference/importTypeAmbient.types index 3a36a1d64fb4e..d59207e523224 100644 --- a/tests/baselines/reference/importTypeAmbient.types +++ b/tests/baselines/reference/importTypeAmbient.types @@ -13,7 +13,7 @@ declare module "foo" { >Point : Point } const x: import("foo") = { x: 0, y: 0 }; ->x : Point +>x : import("foo") >{ x: 0, y: 0 } : { x: number; y: number; } >x : number >0 : 0 diff --git a/tests/baselines/reference/incompatibleExports1.types b/tests/baselines/reference/incompatibleExports1.types index 82017c63ff6c0..3421f58e9bf16 100644 --- a/tests/baselines/reference/incompatibleExports1.types +++ b/tests/baselines/reference/incompatibleExports1.types @@ -23,7 +23,7 @@ declare module "baz" { } module c { ->c : typeof c +>c : typeof import("baz") export var c: string; >c : string diff --git a/tests/cases/compiler/amdLikeInputDeclarationEmit.ts b/tests/cases/compiler/amdLikeInputDeclarationEmit.ts new file mode 100644 index 0000000000000..91cb244525027 --- /dev/null +++ b/tests/cases/compiler/amdLikeInputDeclarationEmit.ts @@ -0,0 +1,34 @@ +// @declaration: true +// @declarationDir: definitions +// @emitDeclarationOnly: true +// @checkJs: true +// @allowJs: true +// @filename: typing.d.ts +declare function define(name: string, modules: string[], ready: (...modules: unknown[]) => T); +// @filename: deps/BaseClass.d.ts +declare module "deps/BaseClass" { + class BaseClass { + static extends(a: A): new () => A & BaseClass; + } + export = BaseClass; +} +// @filename: ExtendedClass.js +define("lib/ExtendedClass", ["deps/BaseClass"], +/** + * {typeof import("deps/BaseClass")} + * @param {typeof import("deps/BaseClass")} BaseClass + * @returns + */ +(BaseClass) => { + + const ExtendedClass = BaseClass.extends({ + f: function() { + return "something"; + } + }); + + // Exports the module in a way tsc recognize class export + const module = {}; + module.exports = ExtendedClass + return module.exports; +}); \ No newline at end of file From e204acfa2607f45815a637e3e84b91cac6871659 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Fri, 11 Feb 2022 14:59:01 -0800 Subject: [PATCH 44/55] Ensure subtype relation ordering for readonly properties (#47069) * Ensure subtype relation ordering for readonly properties * Probably fix post-LKG assignability error --- src/compiler/checker.ts | 12 ++ src/services/textChanges.ts | 2 +- ...PropertySubtypeRelationDirected.errors.txt | 104 +++++++++ ...readonlyPropertySubtypeRelationDirected.js | 145 +++++++++++++ ...nlyPropertySubtypeRelationDirected.symbols | 162 ++++++++++++++ ...donlyPropertySubtypeRelationDirected.types | 202 ++++++++++++++++++ ...readonlyPropertySubtypeRelationDirected.ts | 79 +++++++ 7 files changed, 705 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/readonlyPropertySubtypeRelationDirected.errors.txt create mode 100644 tests/baselines/reference/readonlyPropertySubtypeRelationDirected.js create mode 100644 tests/baselines/reference/readonlyPropertySubtypeRelationDirected.symbols create mode 100644 tests/baselines/reference/readonlyPropertySubtypeRelationDirected.types create mode 100644 tests/cases/compiler/readonlyPropertySubtypeRelationDirected.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index cd33d83ff494f..1c78f3315b8fa 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -19732,6 +19732,18 @@ namespace ts { } return Ternary.False; } + + // Ensure {readonly a: whatever} is not a subtype of {a: whatever}, + // while {a: whatever} is a subtype of {readonly a: whatever}. + // This ensures the subtype relationship is ordered, and preventing declaration order + // from deciding which type "wins" in union subtype reduction. + // They're still assignable to one another, since `readonly` doesn't affect assignability. + if ( + (relation === subtypeRelation || relation === strictSubtypeRelation) && + !!(sourcePropFlags & ModifierFlags.Readonly) && !(targetPropFlags & ModifierFlags.Readonly) + ) { + return Ternary.False; + } // If the target comes from a partial union prop, allow `undefined` in the target type const related = isPropertySymbolTypeRelated(sourceProp, targetProp, getTypeOfSourceProperty, reportErrors, intersectionState); if (!related) { diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index f697571607541..dc2918572d02c 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -303,7 +303,7 @@ namespace ts.textChanges { export class ChangeTracker { private readonly changes: Change[] = []; private readonly newFiles: { readonly oldFile: SourceFile | undefined, readonly fileName: string, readonly statements: readonly (Statement | SyntaxKind.NewLineTrivia)[] }[] = []; - private readonly classesWithNodesInsertedAtStart = new Map(); // Set implemented as Map + private readonly classesWithNodesInsertedAtStart = new Map(); // Set implemented as Map private readonly deletedNodes: { readonly sourceFile: SourceFile, readonly node: Node | NodeArray }[] = []; public static fromContext(context: TextChangesContext): ChangeTracker { diff --git a/tests/baselines/reference/readonlyPropertySubtypeRelationDirected.errors.txt b/tests/baselines/reference/readonlyPropertySubtypeRelationDirected.errors.txt new file mode 100644 index 0000000000000..dab2892c5fdb5 --- /dev/null +++ b/tests/baselines/reference/readonlyPropertySubtypeRelationDirected.errors.txt @@ -0,0 +1,104 @@ +tests/cases/compiler/four.ts(11,11): error TS2540: Cannot assign to 'a' because it is a read-only property. +tests/cases/compiler/four.ts(15,11): error TS2540: Cannot assign to 'a' because it is a read-only property. +tests/cases/compiler/one.ts(11,11): error TS2540: Cannot assign to 'a' because it is a read-only property. +tests/cases/compiler/one.ts(15,11): error TS2540: Cannot assign to 'a' because it is a read-only property. +tests/cases/compiler/three.ts(11,11): error TS2540: Cannot assign to 'a' because it is a read-only property. +tests/cases/compiler/three.ts(15,11): error TS2540: Cannot assign to 'a' because it is a read-only property. +tests/cases/compiler/two.ts(11,11): error TS2540: Cannot assign to 'a' because it is a read-only property. +tests/cases/compiler/two.ts(15,11): error TS2540: Cannot assign to 'a' because it is a read-only property. + + +==== tests/cases/compiler/one.ts (2 errors) ==== + export {}; + // When the non-readonly type is declared first, the unioned type of `three` in `doSomething` is never treated as readonly + const two: { a: string } = { a: 'two' }; + const one: { readonly a: string } = { a: 'one' }; + + function doSomething(condition: boolean) { + // when `one` comes first in the conditional check, the return type of `doSomething` is inferred as `a` is readonly, but `a` is + // only treated as readonly (i.e. it will produce a diagnostic if you try to assign to it) based on the order of declarations of `one` and `two` above + const three = (condition) ? one : two; + + three.a = 'foo'; + ~ +!!! error TS2540: Cannot assign to 'a' because it is a read-only property. + + // the inferred (displayed?) type of `a` also depends on the order of the condition above. When `one` comes first, the displayed type is `any` + // when `two` comes first, the displayed type is `string`, but the diagnostic will always correctly find that it's string + three.a = 'foo2'; + ~ +!!! error TS2540: Cannot assign to 'a' because it is a read-only property. + + return three; + } +==== tests/cases/compiler/two.ts (2 errors) ==== + export {}; + // When the non-readonly type is declared first, the unioned type of `three` in `doSomething` is never treated as readonly + const two: { a: string } = { a: 'two' }; + const one: { readonly a: string } = { a: 'one' }; + + function doSomething(condition: boolean) { + // when `two` comes first in the conditional check, the return type of `doSomething` is inferred as not readonly but produces the same diagnostics as above + // based on the declaration order of `one` and `two` + const three = (condition) ? two : one; + + three.a = 'foo'; + ~ +!!! error TS2540: Cannot assign to 'a' because it is a read-only property. + + // the inferred (displayed?) type of `a` also depends on the order of the condition above. When `one` comes first, the displayed type is `any` + // when `two` comes first, the displayed type is `string`, but the diagnostic will always correctly find that it's string + three.a = 'foo2'; + ~ +!!! error TS2540: Cannot assign to 'a' because it is a read-only property. + + return three; + } + +==== tests/cases/compiler/three.ts (2 errors) ==== + export {}; + // When the readonly type is declared first, the unioned type of `three` in `doSomething` is always treated as readonly by the compiler + const one: { readonly a: string } = { a: 'one' }; + const two: { a: string } = { a: 'two' }; + + function doSomething(condition: boolean) { + // when `one` comes first in the conditional check, the return type of `doSomething` is inferred as `a` is readonly, but `a` is + // only treated as readonly (i.e. it will produce a diagnostic if you try to assign to it) based on the order of declarations of `one` and `two` above + const three = (condition) ? one : two; + + three.a = 'foo'; + ~ +!!! error TS2540: Cannot assign to 'a' because it is a read-only property. + + // the inferred (displayed?) type of `a` also depends on the order of the condition above. When `one` comes first, the displayed type is `any` + // when `two` comes first, the displayed type is `string`, but the diagnostic will always correctly find that it's string + three.a = 'foo2'; + ~ +!!! error TS2540: Cannot assign to 'a' because it is a read-only property. + + return three; + } + +==== tests/cases/compiler/four.ts (2 errors) ==== + export {}; + // When the readonly type is declared first, the unioned type of `three` in `doSomething` is always treated as readonly by the compiler + const one: { readonly a: string } = { a: 'one' }; + const two: { a: string } = { a: 'two' }; + + function doSomething(condition: boolean) { + // when `two` comes first in the conditional check, the return type of `doSomething` is inferred as not readonly but produces the same diagnostics as above + // based on the declaration order of `one` and `two` + const three = (condition) ? two : one; + + three.a = 'foo'; + ~ +!!! error TS2540: Cannot assign to 'a' because it is a read-only property. + + // the inferred (displayed?) type of `a` also depends on the order of the condition above. When `one` comes first, the displayed type is `any` + // when `two` comes first, the displayed type is `string`, but the diagnostic will always correctly find that it's string + three.a = 'foo2'; + ~ +!!! error TS2540: Cannot assign to 'a' because it is a read-only property. + + return three; + } \ No newline at end of file diff --git a/tests/baselines/reference/readonlyPropertySubtypeRelationDirected.js b/tests/baselines/reference/readonlyPropertySubtypeRelationDirected.js new file mode 100644 index 0000000000000..2ef516de0caff --- /dev/null +++ b/tests/baselines/reference/readonlyPropertySubtypeRelationDirected.js @@ -0,0 +1,145 @@ +//// [tests/cases/compiler/readonlyPropertySubtypeRelationDirected.ts] //// + +//// [one.ts] +export {}; +// When the non-readonly type is declared first, the unioned type of `three` in `doSomething` is never treated as readonly +const two: { a: string } = { a: 'two' }; +const one: { readonly a: string } = { a: 'one' }; + +function doSomething(condition: boolean) { + // when `one` comes first in the conditional check, the return type of `doSomething` is inferred as `a` is readonly, but `a` is + // only treated as readonly (i.e. it will produce a diagnostic if you try to assign to it) based on the order of declarations of `one` and `two` above + const three = (condition) ? one : two; + + three.a = 'foo'; + + // the inferred (displayed?) type of `a` also depends on the order of the condition above. When `one` comes first, the displayed type is `any` + // when `two` comes first, the displayed type is `string`, but the diagnostic will always correctly find that it's string + three.a = 'foo2'; + + return three; +} +//// [two.ts] +export {}; +// When the non-readonly type is declared first, the unioned type of `three` in `doSomething` is never treated as readonly +const two: { a: string } = { a: 'two' }; +const one: { readonly a: string } = { a: 'one' }; + +function doSomething(condition: boolean) { + // when `two` comes first in the conditional check, the return type of `doSomething` is inferred as not readonly but produces the same diagnostics as above + // based on the declaration order of `one` and `two` + const three = (condition) ? two : one; + + three.a = 'foo'; + + // the inferred (displayed?) type of `a` also depends on the order of the condition above. When `one` comes first, the displayed type is `any` + // when `two` comes first, the displayed type is `string`, but the diagnostic will always correctly find that it's string + three.a = 'foo2'; + + return three; +} + +//// [three.ts] +export {}; +// When the readonly type is declared first, the unioned type of `three` in `doSomething` is always treated as readonly by the compiler +const one: { readonly a: string } = { a: 'one' }; +const two: { a: string } = { a: 'two' }; + +function doSomething(condition: boolean) { + // when `one` comes first in the conditional check, the return type of `doSomething` is inferred as `a` is readonly, but `a` is + // only treated as readonly (i.e. it will produce a diagnostic if you try to assign to it) based on the order of declarations of `one` and `two` above + const three = (condition) ? one : two; + + three.a = 'foo'; + + // the inferred (displayed?) type of `a` also depends on the order of the condition above. When `one` comes first, the displayed type is `any` + // when `two` comes first, the displayed type is `string`, but the diagnostic will always correctly find that it's string + three.a = 'foo2'; + + return three; +} + +//// [four.ts] +export {}; +// When the readonly type is declared first, the unioned type of `three` in `doSomething` is always treated as readonly by the compiler +const one: { readonly a: string } = { a: 'one' }; +const two: { a: string } = { a: 'two' }; + +function doSomething(condition: boolean) { + // when `two` comes first in the conditional check, the return type of `doSomething` is inferred as not readonly but produces the same diagnostics as above + // based on the declaration order of `one` and `two` + const three = (condition) ? two : one; + + three.a = 'foo'; + + // the inferred (displayed?) type of `a` also depends on the order of the condition above. When `one` comes first, the displayed type is `any` + // when `two` comes first, the displayed type is `string`, but the diagnostic will always correctly find that it's string + three.a = 'foo2'; + + return three; +} + +//// [one.js] +"use strict"; +exports.__esModule = true; +// When the non-readonly type is declared first, the unioned type of `three` in `doSomething` is never treated as readonly +var two = { a: 'two' }; +var one = { a: 'one' }; +function doSomething(condition) { + // when `one` comes first in the conditional check, the return type of `doSomething` is inferred as `a` is readonly, but `a` is + // only treated as readonly (i.e. it will produce a diagnostic if you try to assign to it) based on the order of declarations of `one` and `two` above + var three = (condition) ? one : two; + three.a = 'foo'; + // the inferred (displayed?) type of `a` also depends on the order of the condition above. When `one` comes first, the displayed type is `any` + // when `two` comes first, the displayed type is `string`, but the diagnostic will always correctly find that it's string + three.a = 'foo2'; + return three; +} +//// [two.js] +"use strict"; +exports.__esModule = true; +// When the non-readonly type is declared first, the unioned type of `three` in `doSomething` is never treated as readonly +var two = { a: 'two' }; +var one = { a: 'one' }; +function doSomething(condition) { + // when `two` comes first in the conditional check, the return type of `doSomething` is inferred as not readonly but produces the same diagnostics as above + // based on the declaration order of `one` and `two` + var three = (condition) ? two : one; + three.a = 'foo'; + // the inferred (displayed?) type of `a` also depends on the order of the condition above. When `one` comes first, the displayed type is `any` + // when `two` comes first, the displayed type is `string`, but the diagnostic will always correctly find that it's string + three.a = 'foo2'; + return three; +} +//// [three.js] +"use strict"; +exports.__esModule = true; +// When the readonly type is declared first, the unioned type of `three` in `doSomething` is always treated as readonly by the compiler +var one = { a: 'one' }; +var two = { a: 'two' }; +function doSomething(condition) { + // when `one` comes first in the conditional check, the return type of `doSomething` is inferred as `a` is readonly, but `a` is + // only treated as readonly (i.e. it will produce a diagnostic if you try to assign to it) based on the order of declarations of `one` and `two` above + var three = (condition) ? one : two; + three.a = 'foo'; + // the inferred (displayed?) type of `a` also depends on the order of the condition above. When `one` comes first, the displayed type is `any` + // when `two` comes first, the displayed type is `string`, but the diagnostic will always correctly find that it's string + three.a = 'foo2'; + return three; +} +//// [four.js] +"use strict"; +exports.__esModule = true; +// When the readonly type is declared first, the unioned type of `three` in `doSomething` is always treated as readonly by the compiler +var one = { a: 'one' }; +var two = { a: 'two' }; +function doSomething(condition) { + // when `two` comes first in the conditional check, the return type of `doSomething` is inferred as not readonly but produces the same diagnostics as above + // based on the declaration order of `one` and `two` + var three = (condition) ? two : one; + three.a = 'foo'; + // the inferred (displayed?) type of `a` also depends on the order of the condition above. When `one` comes first, the displayed type is `any` + // when `two` comes first, the displayed type is `string`, but the diagnostic will always correctly find that it's string + three.a = 'foo2'; + return three; +} diff --git a/tests/baselines/reference/readonlyPropertySubtypeRelationDirected.symbols b/tests/baselines/reference/readonlyPropertySubtypeRelationDirected.symbols new file mode 100644 index 0000000000000..9a19925057ed8 --- /dev/null +++ b/tests/baselines/reference/readonlyPropertySubtypeRelationDirected.symbols @@ -0,0 +1,162 @@ +=== tests/cases/compiler/one.ts === +export {}; +// When the non-readonly type is declared first, the unioned type of `three` in `doSomething` is never treated as readonly +const two: { a: string } = { a: 'two' }; +>two : Symbol(two, Decl(one.ts, 2, 5)) +>a : Symbol(a, Decl(one.ts, 2, 12)) +>a : Symbol(a, Decl(one.ts, 2, 28)) + +const one: { readonly a: string } = { a: 'one' }; +>one : Symbol(one, Decl(one.ts, 3, 5)) +>a : Symbol(a, Decl(one.ts, 3, 12)) +>a : Symbol(a, Decl(one.ts, 3, 37)) + +function doSomething(condition: boolean) { +>doSomething : Symbol(doSomething, Decl(one.ts, 3, 49)) +>condition : Symbol(condition, Decl(one.ts, 5, 21)) + + // when `one` comes first in the conditional check, the return type of `doSomething` is inferred as `a` is readonly, but `a` is + // only treated as readonly (i.e. it will produce a diagnostic if you try to assign to it) based on the order of declarations of `one` and `two` above + const three = (condition) ? one : two; +>three : Symbol(three, Decl(one.ts, 8, 9)) +>condition : Symbol(condition, Decl(one.ts, 5, 21)) +>one : Symbol(one, Decl(one.ts, 3, 5)) +>two : Symbol(two, Decl(one.ts, 2, 5)) + + three.a = 'foo'; +>three.a : Symbol(a, Decl(one.ts, 3, 12)) +>three : Symbol(three, Decl(one.ts, 8, 9)) +>a : Symbol(a, Decl(one.ts, 3, 12)) + + // the inferred (displayed?) type of `a` also depends on the order of the condition above. When `one` comes first, the displayed type is `any` + // when `two` comes first, the displayed type is `string`, but the diagnostic will always correctly find that it's string + three.a = 'foo2'; +>three.a : Symbol(a, Decl(one.ts, 3, 12)) +>three : Symbol(three, Decl(one.ts, 8, 9)) +>a : Symbol(a, Decl(one.ts, 3, 12)) + + return three; +>three : Symbol(three, Decl(one.ts, 8, 9)) +} +=== tests/cases/compiler/two.ts === +export {}; +// When the non-readonly type is declared first, the unioned type of `three` in `doSomething` is never treated as readonly +const two: { a: string } = { a: 'two' }; +>two : Symbol(two, Decl(two.ts, 2, 5)) +>a : Symbol(a, Decl(two.ts, 2, 12)) +>a : Symbol(a, Decl(two.ts, 2, 28)) + +const one: { readonly a: string } = { a: 'one' }; +>one : Symbol(one, Decl(two.ts, 3, 5)) +>a : Symbol(a, Decl(two.ts, 3, 12)) +>a : Symbol(a, Decl(two.ts, 3, 37)) + +function doSomething(condition: boolean) { +>doSomething : Symbol(doSomething, Decl(two.ts, 3, 49)) +>condition : Symbol(condition, Decl(two.ts, 5, 21)) + + // when `two` comes first in the conditional check, the return type of `doSomething` is inferred as not readonly but produces the same diagnostics as above + // based on the declaration order of `one` and `two` + const three = (condition) ? two : one; +>three : Symbol(three, Decl(two.ts, 8, 9)) +>condition : Symbol(condition, Decl(two.ts, 5, 21)) +>two : Symbol(two, Decl(two.ts, 2, 5)) +>one : Symbol(one, Decl(two.ts, 3, 5)) + + three.a = 'foo'; +>three.a : Symbol(a, Decl(two.ts, 3, 12)) +>three : Symbol(three, Decl(two.ts, 8, 9)) +>a : Symbol(a, Decl(two.ts, 3, 12)) + + // the inferred (displayed?) type of `a` also depends on the order of the condition above. When `one` comes first, the displayed type is `any` + // when `two` comes first, the displayed type is `string`, but the diagnostic will always correctly find that it's string + three.a = 'foo2'; +>three.a : Symbol(a, Decl(two.ts, 3, 12)) +>three : Symbol(three, Decl(two.ts, 8, 9)) +>a : Symbol(a, Decl(two.ts, 3, 12)) + + return three; +>three : Symbol(three, Decl(two.ts, 8, 9)) +} + +=== tests/cases/compiler/three.ts === +export {}; +// When the readonly type is declared first, the unioned type of `three` in `doSomething` is always treated as readonly by the compiler +const one: { readonly a: string } = { a: 'one' }; +>one : Symbol(one, Decl(three.ts, 2, 5)) +>a : Symbol(a, Decl(three.ts, 2, 12)) +>a : Symbol(a, Decl(three.ts, 2, 37)) + +const two: { a: string } = { a: 'two' }; +>two : Symbol(two, Decl(three.ts, 3, 5)) +>a : Symbol(a, Decl(three.ts, 3, 12)) +>a : Symbol(a, Decl(three.ts, 3, 28)) + +function doSomething(condition: boolean) { +>doSomething : Symbol(doSomething, Decl(three.ts, 3, 40)) +>condition : Symbol(condition, Decl(three.ts, 5, 21)) + + // when `one` comes first in the conditional check, the return type of `doSomething` is inferred as `a` is readonly, but `a` is + // only treated as readonly (i.e. it will produce a diagnostic if you try to assign to it) based on the order of declarations of `one` and `two` above + const three = (condition) ? one : two; +>three : Symbol(three, Decl(three.ts, 8, 9)) +>condition : Symbol(condition, Decl(three.ts, 5, 21)) +>one : Symbol(one, Decl(three.ts, 2, 5)) +>two : Symbol(two, Decl(three.ts, 3, 5)) + + three.a = 'foo'; +>three.a : Symbol(a, Decl(three.ts, 2, 12)) +>three : Symbol(three, Decl(three.ts, 8, 9)) +>a : Symbol(a, Decl(three.ts, 2, 12)) + + // the inferred (displayed?) type of `a` also depends on the order of the condition above. When `one` comes first, the displayed type is `any` + // when `two` comes first, the displayed type is `string`, but the diagnostic will always correctly find that it's string + three.a = 'foo2'; +>three.a : Symbol(a, Decl(three.ts, 2, 12)) +>three : Symbol(three, Decl(three.ts, 8, 9)) +>a : Symbol(a, Decl(three.ts, 2, 12)) + + return three; +>three : Symbol(three, Decl(three.ts, 8, 9)) +} + +=== tests/cases/compiler/four.ts === +export {}; +// When the readonly type is declared first, the unioned type of `three` in `doSomething` is always treated as readonly by the compiler +const one: { readonly a: string } = { a: 'one' }; +>one : Symbol(one, Decl(four.ts, 2, 5)) +>a : Symbol(a, Decl(four.ts, 2, 12)) +>a : Symbol(a, Decl(four.ts, 2, 37)) + +const two: { a: string } = { a: 'two' }; +>two : Symbol(two, Decl(four.ts, 3, 5)) +>a : Symbol(a, Decl(four.ts, 3, 12)) +>a : Symbol(a, Decl(four.ts, 3, 28)) + +function doSomething(condition: boolean) { +>doSomething : Symbol(doSomething, Decl(four.ts, 3, 40)) +>condition : Symbol(condition, Decl(four.ts, 5, 21)) + + // when `two` comes first in the conditional check, the return type of `doSomething` is inferred as not readonly but produces the same diagnostics as above + // based on the declaration order of `one` and `two` + const three = (condition) ? two : one; +>three : Symbol(three, Decl(four.ts, 8, 9)) +>condition : Symbol(condition, Decl(four.ts, 5, 21)) +>two : Symbol(two, Decl(four.ts, 3, 5)) +>one : Symbol(one, Decl(four.ts, 2, 5)) + + three.a = 'foo'; +>three.a : Symbol(a, Decl(four.ts, 2, 12)) +>three : Symbol(three, Decl(four.ts, 8, 9)) +>a : Symbol(a, Decl(four.ts, 2, 12)) + + // the inferred (displayed?) type of `a` also depends on the order of the condition above. When `one` comes first, the displayed type is `any` + // when `two` comes first, the displayed type is `string`, but the diagnostic will always correctly find that it's string + three.a = 'foo2'; +>three.a : Symbol(a, Decl(four.ts, 2, 12)) +>three : Symbol(three, Decl(four.ts, 8, 9)) +>a : Symbol(a, Decl(four.ts, 2, 12)) + + return three; +>three : Symbol(three, Decl(four.ts, 8, 9)) +} diff --git a/tests/baselines/reference/readonlyPropertySubtypeRelationDirected.types b/tests/baselines/reference/readonlyPropertySubtypeRelationDirected.types new file mode 100644 index 0000000000000..30e4b0d32c7db --- /dev/null +++ b/tests/baselines/reference/readonlyPropertySubtypeRelationDirected.types @@ -0,0 +1,202 @@ +=== tests/cases/compiler/one.ts === +export {}; +// When the non-readonly type is declared first, the unioned type of `three` in `doSomething` is never treated as readonly +const two: { a: string } = { a: 'two' }; +>two : { a: string; } +>a : string +>{ a: 'two' } : { a: string; } +>a : string +>'two' : "two" + +const one: { readonly a: string } = { a: 'one' }; +>one : { readonly a: string; } +>a : string +>{ a: 'one' } : { a: string; } +>a : string +>'one' : "one" + +function doSomething(condition: boolean) { +>doSomething : (condition: boolean) => { readonly a: string; } +>condition : boolean + + // when `one` comes first in the conditional check, the return type of `doSomething` is inferred as `a` is readonly, but `a` is + // only treated as readonly (i.e. it will produce a diagnostic if you try to assign to it) based on the order of declarations of `one` and `two` above + const three = (condition) ? one : two; +>three : { readonly a: string; } +>(condition) ? one : two : { readonly a: string; } +>(condition) : boolean +>condition : boolean +>one : { readonly a: string; } +>two : { a: string; } + + three.a = 'foo'; +>three.a = 'foo' : "foo" +>three.a : any +>three : { readonly a: string; } +>a : any +>'foo' : "foo" + + // the inferred (displayed?) type of `a` also depends on the order of the condition above. When `one` comes first, the displayed type is `any` + // when `two` comes first, the displayed type is `string`, but the diagnostic will always correctly find that it's string + three.a = 'foo2'; +>three.a = 'foo2' : "foo2" +>three.a : any +>three : { readonly a: string; } +>a : any +>'foo2' : "foo2" + + return three; +>three : { readonly a: string; } +} +=== tests/cases/compiler/two.ts === +export {}; +// When the non-readonly type is declared first, the unioned type of `three` in `doSomething` is never treated as readonly +const two: { a: string } = { a: 'two' }; +>two : { a: string; } +>a : string +>{ a: 'two' } : { a: string; } +>a : string +>'two' : "two" + +const one: { readonly a: string } = { a: 'one' }; +>one : { readonly a: string; } +>a : string +>{ a: 'one' } : { a: string; } +>a : string +>'one' : "one" + +function doSomething(condition: boolean) { +>doSomething : (condition: boolean) => { readonly a: string; } +>condition : boolean + + // when `two` comes first in the conditional check, the return type of `doSomething` is inferred as not readonly but produces the same diagnostics as above + // based on the declaration order of `one` and `two` + const three = (condition) ? two : one; +>three : { readonly a: string; } +>(condition) ? two : one : { readonly a: string; } +>(condition) : boolean +>condition : boolean +>two : { a: string; } +>one : { readonly a: string; } + + three.a = 'foo'; +>three.a = 'foo' : "foo" +>three.a : any +>three : { readonly a: string; } +>a : any +>'foo' : "foo" + + // the inferred (displayed?) type of `a` also depends on the order of the condition above. When `one` comes first, the displayed type is `any` + // when `two` comes first, the displayed type is `string`, but the diagnostic will always correctly find that it's string + three.a = 'foo2'; +>three.a = 'foo2' : "foo2" +>three.a : any +>three : { readonly a: string; } +>a : any +>'foo2' : "foo2" + + return three; +>three : { readonly a: string; } +} + +=== tests/cases/compiler/three.ts === +export {}; +// When the readonly type is declared first, the unioned type of `three` in `doSomething` is always treated as readonly by the compiler +const one: { readonly a: string } = { a: 'one' }; +>one : { readonly a: string; } +>a : string +>{ a: 'one' } : { a: string; } +>a : string +>'one' : "one" + +const two: { a: string } = { a: 'two' }; +>two : { a: string; } +>a : string +>{ a: 'two' } : { a: string; } +>a : string +>'two' : "two" + +function doSomething(condition: boolean) { +>doSomething : (condition: boolean) => { readonly a: string; } +>condition : boolean + + // when `one` comes first in the conditional check, the return type of `doSomething` is inferred as `a` is readonly, but `a` is + // only treated as readonly (i.e. it will produce a diagnostic if you try to assign to it) based on the order of declarations of `one` and `two` above + const three = (condition) ? one : two; +>three : { readonly a: string; } +>(condition) ? one : two : { readonly a: string; } +>(condition) : boolean +>condition : boolean +>one : { readonly a: string; } +>two : { a: string; } + + three.a = 'foo'; +>three.a = 'foo' : "foo" +>three.a : any +>three : { readonly a: string; } +>a : any +>'foo' : "foo" + + // the inferred (displayed?) type of `a` also depends on the order of the condition above. When `one` comes first, the displayed type is `any` + // when `two` comes first, the displayed type is `string`, but the diagnostic will always correctly find that it's string + three.a = 'foo2'; +>three.a = 'foo2' : "foo2" +>three.a : any +>three : { readonly a: string; } +>a : any +>'foo2' : "foo2" + + return three; +>three : { readonly a: string; } +} + +=== tests/cases/compiler/four.ts === +export {}; +// When the readonly type is declared first, the unioned type of `three` in `doSomething` is always treated as readonly by the compiler +const one: { readonly a: string } = { a: 'one' }; +>one : { readonly a: string; } +>a : string +>{ a: 'one' } : { a: string; } +>a : string +>'one' : "one" + +const two: { a: string } = { a: 'two' }; +>two : { a: string; } +>a : string +>{ a: 'two' } : { a: string; } +>a : string +>'two' : "two" + +function doSomething(condition: boolean) { +>doSomething : (condition: boolean) => { readonly a: string; } +>condition : boolean + + // when `two` comes first in the conditional check, the return type of `doSomething` is inferred as not readonly but produces the same diagnostics as above + // based on the declaration order of `one` and `two` + const three = (condition) ? two : one; +>three : { readonly a: string; } +>(condition) ? two : one : { readonly a: string; } +>(condition) : boolean +>condition : boolean +>two : { a: string; } +>one : { readonly a: string; } + + three.a = 'foo'; +>three.a = 'foo' : "foo" +>three.a : any +>three : { readonly a: string; } +>a : any +>'foo' : "foo" + + // the inferred (displayed?) type of `a` also depends on the order of the condition above. When `one` comes first, the displayed type is `any` + // when `two` comes first, the displayed type is `string`, but the diagnostic will always correctly find that it's string + three.a = 'foo2'; +>three.a = 'foo2' : "foo2" +>three.a : any +>three : { readonly a: string; } +>a : any +>'foo2' : "foo2" + + return three; +>three : { readonly a: string; } +} diff --git a/tests/cases/compiler/readonlyPropertySubtypeRelationDirected.ts b/tests/cases/compiler/readonlyPropertySubtypeRelationDirected.ts new file mode 100644 index 0000000000000..aadd4bec5a0fd --- /dev/null +++ b/tests/cases/compiler/readonlyPropertySubtypeRelationDirected.ts @@ -0,0 +1,79 @@ +// @strict: true +// @filename: one.ts +export {}; +// When the non-readonly type is declared first, the unioned type of `three` in `doSomething` is never treated as readonly +const two: { a: string } = { a: 'two' }; +const one: { readonly a: string } = { a: 'one' }; + +function doSomething(condition: boolean) { + // when `one` comes first in the conditional check, the return type of `doSomething` is inferred as `a` is readonly, but `a` is + // only treated as readonly (i.e. it will produce a diagnostic if you try to assign to it) based on the order of declarations of `one` and `two` above + const three = (condition) ? one : two; + + three.a = 'foo'; + + // the inferred (displayed?) type of `a` also depends on the order of the condition above. When `one` comes first, the displayed type is `any` + // when `two` comes first, the displayed type is `string`, but the diagnostic will always correctly find that it's string + three.a = 'foo2'; + + return three; +} +// @filename: two.ts +export {}; +// When the non-readonly type is declared first, the unioned type of `three` in `doSomething` is never treated as readonly +const two: { a: string } = { a: 'two' }; +const one: { readonly a: string } = { a: 'one' }; + +function doSomething(condition: boolean) { + // when `two` comes first in the conditional check, the return type of `doSomething` is inferred as not readonly but produces the same diagnostics as above + // based on the declaration order of `one` and `two` + const three = (condition) ? two : one; + + three.a = 'foo'; + + // the inferred (displayed?) type of `a` also depends on the order of the condition above. When `one` comes first, the displayed type is `any` + // when `two` comes first, the displayed type is `string`, but the diagnostic will always correctly find that it's string + three.a = 'foo2'; + + return three; +} + +// @filename: three.ts +export {}; +// When the readonly type is declared first, the unioned type of `three` in `doSomething` is always treated as readonly by the compiler +const one: { readonly a: string } = { a: 'one' }; +const two: { a: string } = { a: 'two' }; + +function doSomething(condition: boolean) { + // when `one` comes first in the conditional check, the return type of `doSomething` is inferred as `a` is readonly, but `a` is + // only treated as readonly (i.e. it will produce a diagnostic if you try to assign to it) based on the order of declarations of `one` and `two` above + const three = (condition) ? one : two; + + three.a = 'foo'; + + // the inferred (displayed?) type of `a` also depends on the order of the condition above. When `one` comes first, the displayed type is `any` + // when `two` comes first, the displayed type is `string`, but the diagnostic will always correctly find that it's string + three.a = 'foo2'; + + return three; +} + +// @filename: four.ts +export {}; +// When the readonly type is declared first, the unioned type of `three` in `doSomething` is always treated as readonly by the compiler +const one: { readonly a: string } = { a: 'one' }; +const two: { a: string } = { a: 'two' }; + +function doSomething(condition: boolean) { + // when `two` comes first in the conditional check, the return type of `doSomething` is inferred as not readonly but produces the same diagnostics as above + // based on the declaration order of `one` and `two` + const three = (condition) ? two : one; + + three.a = 'foo'; + + // the inferred (displayed?) type of `a` also depends on the order of the condition above. When `one` comes first, the displayed type is `any` + // when `two` comes first, the displayed type is `string`, but the diagnostic will always correctly find that it's string + three.a = 'foo2'; + + return three; +} \ No newline at end of file From 1bdb0d90bfa5bee51ea1598b92076c2dfd01b452 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Fri, 11 Feb 2022 15:44:11 -0800 Subject: [PATCH 45/55] ESM mode nonrelative imports should assume index.js entrypoints even if no package `main` is present (#47854) --- src/compiler/moduleNameResolver.ts | 20 ++++++++++-- ...portModeImplicitIndexResolution.errors.txt | 31 +++++++++++++++++++ ...deNextImportModeImplicitIndexResolution.js | 28 +++++++++++++++++ ...tImportModeImplicitIndexResolution.symbols | 18 +++++++++++ ...extImportModeImplicitIndexResolution.types | 22 +++++++++++++ ...deNextImportModeImplicitIndexResolution.ts | 23 ++++++++++++++ 6 files changed, 140 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/nodeNextImportModeImplicitIndexResolution.errors.txt create mode 100644 tests/baselines/reference/nodeNextImportModeImplicitIndexResolution.js create mode 100644 tests/baselines/reference/nodeNextImportModeImplicitIndexResolution.symbols create mode 100644 tests/baselines/reference/nodeNextImportModeImplicitIndexResolution.types create mode 100644 tests/cases/compiler/nodeNextImportModeImplicitIndexResolution.ts diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index 7d6d0f67d7aee..24d4c845acae5 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -1394,7 +1394,13 @@ namespace ts { onlyRecordFailures = true; } } - return loadNodeModuleFromDirectory(extensions, candidate, onlyRecordFailures, state, considerPackageJson); + // esm mode relative imports shouldn't do any directory lookups (either inside `package.json` + // files or implicit `index.js`es). This is a notable depature from cjs norms, where `./foo/pkg` + // could have been redirected by `./foo/pkg/package.json` to an arbitrary location! + if (!(state.features & NodeResolutionFeatures.EsmMode)) { + return loadNodeModuleFromDirectory(extensions, candidate, onlyRecordFailures, state, considerPackageJson); + } + return undefined; } /*@internal*/ @@ -2178,7 +2184,7 @@ namespace ts { if (packageInfo && packageInfo.packageJsonContent.exports && state.features & NodeResolutionFeatures.Exports) { return loadModuleFromExports(packageInfo, extensions, combinePaths(".", rest), state, cache, redirectedReference)?.value; } - const pathAndExtension = + let pathAndExtension = loadModuleFromFile(extensions, candidate, onlyRecordFailures, state) || loadNodeModuleFromDirectoryWorker( extensions, @@ -2188,6 +2194,16 @@ namespace ts { packageInfo && packageInfo.packageJsonContent, packageInfo && packageInfo.versionPaths ); + if ( + !pathAndExtension && packageInfo + && packageInfo.packageJsonContent.exports === undefined + && packageInfo.packageJsonContent.main === undefined + && state.features & NodeResolutionFeatures.EsmMode + ) { + // EsmMode disables index lookup in `loadNodeModuleFromDirectoryWorker` generally, however non-relative package resolutions still assume + // a default `index.js` entrypoint if no `main` or `exports` are present + pathAndExtension = loadModuleFromFile(extensions, combinePaths(candidate, "index.js"), onlyRecordFailures, state); + } return withPackageId(packageInfo, pathAndExtension); }; diff --git a/tests/baselines/reference/nodeNextImportModeImplicitIndexResolution.errors.txt b/tests/baselines/reference/nodeNextImportModeImplicitIndexResolution.errors.txt new file mode 100644 index 0000000000000..cf759f6040d06 --- /dev/null +++ b/tests/baselines/reference/nodeNextImportModeImplicitIndexResolution.errors.txt @@ -0,0 +1,31 @@ +tests/cases/compiler/index.ts(2,31): error TS2834: Relative import paths need explicit file extensions in EcmaScript imports when '--moduleResolution' is 'node12' or 'nodenext'. Consider adding an extension to the import path. +tests/cases/compiler/index.ts(3,31): error TS2834: Relative import paths need explicit file extensions in EcmaScript imports when '--moduleResolution' is 'node12' or 'nodenext'. Consider adding an extension to the import path. + + +==== tests/cases/compiler/node_modules/pkg/package.json (0 errors) ==== + { + "name": "pkg", + "version": "0.0.1" + } +==== tests/cases/compiler/node_modules/pkg/index.d.ts (0 errors) ==== + export const item = 4; +==== tests/cases/compiler/pkg/package.json (0 errors) ==== + { + "private": true + } +==== tests/cases/compiler/pkg/index.d.ts (0 errors) ==== + export const item = 4; +==== tests/cases/compiler/package.json (0 errors) ==== + { + "type": "module", + "private": true + } +==== tests/cases/compiler/index.ts (2 errors) ==== + import { item } from "pkg"; // should work (`index.js` is assumed to be the entrypoint for packages found via nonrelative import) + import { item as item2 } from "./pkg"; // shouldn't work (`index.js` is _not_ assumed to be the entrypoint for packages found via relative import) + ~~~~~~~ +!!! error TS2834: Relative import paths need explicit file extensions in EcmaScript imports when '--moduleResolution' is 'node12' or 'nodenext'. Consider adding an extension to the import path. + import { item as item3 } from "./node_modules/pkg" // _even if they're in a node_modules folder_ + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS2834: Relative import paths need explicit file extensions in EcmaScript imports when '--moduleResolution' is 'node12' or 'nodenext'. Consider adding an extension to the import path. + \ No newline at end of file diff --git a/tests/baselines/reference/nodeNextImportModeImplicitIndexResolution.js b/tests/baselines/reference/nodeNextImportModeImplicitIndexResolution.js new file mode 100644 index 0000000000000..9ae72ef450a5e --- /dev/null +++ b/tests/baselines/reference/nodeNextImportModeImplicitIndexResolution.js @@ -0,0 +1,28 @@ +//// [tests/cases/compiler/nodeNextImportModeImplicitIndexResolution.ts] //// + +//// [package.json] +{ + "name": "pkg", + "version": "0.0.1" +} +//// [index.d.ts] +export const item = 4; +//// [package.json] +{ + "private": true +} +//// [index.d.ts] +export const item = 4; +//// [package.json] +{ + "type": "module", + "private": true +} +//// [index.ts] +import { item } from "pkg"; // should work (`index.js` is assumed to be the entrypoint for packages found via nonrelative import) +import { item as item2 } from "./pkg"; // shouldn't work (`index.js` is _not_ assumed to be the entrypoint for packages found via relative import) +import { item as item3 } from "./node_modules/pkg" // _even if they're in a node_modules folder_ + + +//// [index.js] +export {}; diff --git a/tests/baselines/reference/nodeNextImportModeImplicitIndexResolution.symbols b/tests/baselines/reference/nodeNextImportModeImplicitIndexResolution.symbols new file mode 100644 index 0000000000000..c58b28d74ee89 --- /dev/null +++ b/tests/baselines/reference/nodeNextImportModeImplicitIndexResolution.symbols @@ -0,0 +1,18 @@ +=== tests/cases/compiler/node_modules/pkg/index.d.ts === +export const item = 4; +>item : Symbol(item, Decl(index.d.ts, 0, 12)) + +=== tests/cases/compiler/pkg/index.d.ts === +export const item = 4; +>item : Symbol(item, Decl(index.d.ts, 0, 12)) + +=== tests/cases/compiler/index.ts === +import { item } from "pkg"; // should work (`index.js` is assumed to be the entrypoint for packages found via nonrelative import) +>item : Symbol(item, Decl(index.ts, 0, 8)) + +import { item as item2 } from "./pkg"; // shouldn't work (`index.js` is _not_ assumed to be the entrypoint for packages found via relative import) +>item2 : Symbol(item2, Decl(index.ts, 1, 8)) + +import { item as item3 } from "./node_modules/pkg" // _even if they're in a node_modules folder_ +>item3 : Symbol(item3, Decl(index.ts, 2, 8)) + diff --git a/tests/baselines/reference/nodeNextImportModeImplicitIndexResolution.types b/tests/baselines/reference/nodeNextImportModeImplicitIndexResolution.types new file mode 100644 index 0000000000000..c90e8c11e83cc --- /dev/null +++ b/tests/baselines/reference/nodeNextImportModeImplicitIndexResolution.types @@ -0,0 +1,22 @@ +=== tests/cases/compiler/node_modules/pkg/index.d.ts === +export const item = 4; +>item : 4 +>4 : 4 + +=== tests/cases/compiler/pkg/index.d.ts === +export const item = 4; +>item : 4 +>4 : 4 + +=== tests/cases/compiler/index.ts === +import { item } from "pkg"; // should work (`index.js` is assumed to be the entrypoint for packages found via nonrelative import) +>item : 4 + +import { item as item2 } from "./pkg"; // shouldn't work (`index.js` is _not_ assumed to be the entrypoint for packages found via relative import) +>item : any +>item2 : any + +import { item as item3 } from "./node_modules/pkg" // _even if they're in a node_modules folder_ +>item : any +>item3 : any + diff --git a/tests/cases/compiler/nodeNextImportModeImplicitIndexResolution.ts b/tests/cases/compiler/nodeNextImportModeImplicitIndexResolution.ts new file mode 100644 index 0000000000000..bf20a669b4396 --- /dev/null +++ b/tests/cases/compiler/nodeNextImportModeImplicitIndexResolution.ts @@ -0,0 +1,23 @@ +// @module: nodenext +// @filename: node_modules/pkg/package.json +{ + "name": "pkg", + "version": "0.0.1" +} +// @filename: node_modules/pkg/index.d.ts +export const item = 4; +// @filename: pkg/package.json +{ + "private": true +} +// @filename: pkg/index.d.ts +export const item = 4; +// @filename: package.json +{ + "type": "module", + "private": true +} +// @filename: index.ts +import { item } from "pkg"; // should work (`index.js` is assumed to be the entrypoint for packages found via nonrelative import) +import { item as item2 } from "./pkg"; // shouldn't work (`index.js` is _not_ assumed to be the entrypoint for packages found via relative import) +import { item as item3 } from "./node_modules/pkg" // _even if they're in a node_modules folder_ From 67d376c882bcf4318a459c9a504287fc449e7847 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 11 Feb 2022 16:18:55 -0800 Subject: [PATCH 46/55] Update version to 4.7 and update baselines. (#47856) --- package.json | 2 +- src/compiler/corePublic.ts | 2 +- tests/baselines/reference/api/tsserverlibrary.d.ts | 2 +- tests/baselines/reference/api/typescript.d.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index ffc56b0d24a1a..92afe19ddf31a 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "typescript", "author": "Microsoft Corp.", "homepage": "https://www.typescriptlang.org/", - "version": "4.6.0", + "version": "4.7.0", "license": "Apache-2.0", "description": "TypeScript is a language for application scale JavaScript development", "keywords": [ diff --git a/src/compiler/corePublic.ts b/src/compiler/corePublic.ts index 61f604517523c..1d84b6726e6b4 100644 --- a/src/compiler/corePublic.ts +++ b/src/compiler/corePublic.ts @@ -1,7 +1,7 @@ namespace ts { // WARNING: The script `configurePrerelease.ts` uses a regexp to parse out these values. // If changing the text in this section, be sure to test `configurePrerelease` too. - export const versionMajorMinor = "4.6"; + export const versionMajorMinor = "4.7"; // The following is baselined as a literal template type without intervention /** The version of the TypeScript compiler release */ // eslint-disable-next-line @typescript-eslint/no-inferrable-types diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 55d0fe287b3a0..39cbf27f1f948 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -14,7 +14,7 @@ and limitations under the License. ***************************************************************************** */ declare namespace ts { - const versionMajorMinor = "4.6"; + const versionMajorMinor = "4.7"; /** The version of the TypeScript compiler release */ const version: string; /** diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 0c17632055398..467da374f1046 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -14,7 +14,7 @@ and limitations under the License. ***************************************************************************** */ declare namespace ts { - const versionMajorMinor = "4.6"; + const versionMajorMinor = "4.7"; /** The version of the TypeScript compiler release */ const version: string; /** From 77d24f93fba915bd4d509758952f3cb9187db910 Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Sat, 12 Feb 2022 06:06:16 +0000 Subject: [PATCH 47/55] Update package-lock.json --- package-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 1cbd5ded242a0..f829b407185ea 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "typescript", - "version": "4.6.0", + "version": "4.7.0", "lockfileVersion": 1, "requires": true, "dependencies": { From 2bdbc8fe7b49b2fe586a80854c85521cbe7a3b72 Mon Sep 17 00:00:00 2001 From: csigs Date: Sat, 12 Feb 2022 03:19:41 -0800 Subject: [PATCH 48/55] LEGO: Merge pull request 47861 LEGO: Merge pull request 47861 --- .../diagnosticMessages.generated.json.lcl | 27 ++++++++ .../diagnosticMessages.generated.json.lcl | 63 ++++++++++++++++--- .../diagnosticMessages.generated.json.lcl | 63 ++++++++++++++++--- .../diagnosticMessages.generated.json.lcl | 27 ++++++++ .../diagnosticMessages.generated.json.lcl | 27 ++++++++ .../diagnosticMessages.generated.json.lcl | 54 +++++++++++++--- .../diagnosticMessages.generated.json.lcl | 63 ++++++++++++++++--- .../diagnosticMessages.generated.json.lcl | 27 ++++++++ .../diagnosticMessages.generated.json.lcl | 27 ++++++++ .../diagnosticMessages.generated.json.lcl | 54 +++++++++++++--- .../diagnosticMessages.generated.json.lcl | 27 ++++++++ .../diagnosticMessages.generated.json.lcl | 27 ++++++++ 12 files changed, 441 insertions(+), 45 deletions(-) diff --git a/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl index 2d096f65c4bf1..19d0ab30be1ed 100644 --- a/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -4641,6 +4641,15 @@ + + + + + + + + + @@ -4650,6 +4659,15 @@ + + + + + + + + + @@ -10872,6 +10890,15 @@ + + + + + + + + + ']]> diff --git a/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl index 09f67fd366c2a..6ec7597a1a7df 100644 --- a/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -537,11 +537,11 @@ - + - + - + @@ -1860,11 +1860,20 @@ - + - + - + + + + + + + + + + @@ -1944,11 +1953,20 @@ - + - + - + + + + + + + + + + @@ -4623,6 +4641,15 @@ + + + + + + + + + @@ -4632,6 +4659,15 @@ + + + + + + + + + @@ -10854,6 +10890,15 @@ + + + + + + + + + ']]> diff --git a/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl index e34bdf388f652..ea264b001c273 100644 --- a/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -546,11 +546,11 @@ - + - + - + @@ -1869,11 +1869,20 @@ - + - + - + + + + + + + + + + @@ -1953,11 +1962,20 @@ - + - + - + + + + + + + + + + @@ -4632,6 +4650,15 @@ + + + + + + + + + @@ -4641,6 +4668,15 @@ + + + + + + + + + @@ -10863,6 +10899,15 @@ + + + + + + + + + ']]> diff --git a/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl index cd0eac45ef996..5e611bfab9687 100644 --- a/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -4638,6 +4638,15 @@ + + + + + + + + + @@ -4647,6 +4656,15 @@ + + + + + + + + + @@ -10866,6 +10884,15 @@ + + + + + + + + + ']]> diff --git a/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl index d232c611b1225..975cbf345d894 100644 --- a/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -4653,6 +4653,15 @@ + + + + + + + + + @@ -4662,6 +4671,15 @@ + + + + + + + + + @@ -10884,6 +10902,15 @@ + + + + + + + + + ']]> diff --git a/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl index 2d3c5ccc8a156..d5d18393d442d 100644 --- a/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -546,11 +546,11 @@ - + - + - + @@ -1872,11 +1872,20 @@ - + - + - + + + + + + + + + + @@ -1956,11 +1965,20 @@ - + + + + + + + + + + - + - + @@ -4635,6 +4653,12 @@ + + + + + + @@ -4644,6 +4668,12 @@ + + + + + + @@ -10866,6 +10896,12 @@ + + + + + + ']]> diff --git a/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl index a6bba2fa1a990..afb302caba3f2 100644 --- a/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -537,11 +537,11 @@ - + - + - + @@ -1860,11 +1860,20 @@ - + - + - + + + + + + + + + + @@ -1944,11 +1953,20 @@ - + - + - + + + + + + + + + + @@ -4623,6 +4641,15 @@ + + + + + + + + + @@ -4632,6 +4659,15 @@ + + + + + + + + + @@ -10854,6 +10890,15 @@ + + + + + + + + + ']]> diff --git a/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl index 41d5ec0685717..36b7f6e11f4d3 100644 --- a/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -4641,6 +4641,15 @@ + + + + + + + + + @@ -4650,6 +4659,15 @@ + + + + + + + + + @@ -10872,6 +10890,15 @@ + + + + + + + + + ']]> diff --git a/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl index c281ba1b6d671..24b8a1f627f9c 100644 --- a/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -4641,6 +4641,15 @@ + + + + + + + + + @@ -4650,6 +4659,15 @@ + + + + + + + + + @@ -10872,6 +10890,15 @@ + + + + + + + + + ']]> diff --git a/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl index 896867bd6ce74..6493fb0c1ec64 100644 --- a/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -530,11 +530,11 @@ - + - + - + @@ -1850,11 +1850,20 @@ - + - + - + + + + + + + + + + @@ -1934,11 +1943,20 @@ - + + + + + + + + + + - + - + @@ -4613,6 +4631,12 @@ + + + + + + @@ -4622,6 +4646,12 @@ + + + + + + @@ -10841,6 +10871,12 @@ + + + + + + ']]> diff --git a/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl index 15ee7bd72014f..212424b933d82 100644 --- a/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -4634,6 +4634,15 @@ + + + + + + + + + @@ -4643,6 +4652,15 @@ + + + + + + + + + @@ -10862,6 +10880,15 @@ + + + + + + + + + ']]> diff --git a/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl index 923ff0b6aafc7..c24ed6998c789 100644 --- a/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -4640,6 +4640,15 @@ + + + + + + + + + @@ -4649,6 +4658,15 @@ + + + + + + + + + @@ -10871,6 +10889,15 @@ + + + + + + + + + ']]> From 78ef3e70c901bd5dfed061b659c4a330aafe44a3 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 12 Feb 2022 16:39:21 +0100 Subject: [PATCH 49/55] Ensure empty array literal is assignable to never[] (#47816) * Ensure empty array literal is assignable to never[] * Add tests * Add comment --- src/compiler/checker.ts | 11 ++++- .../reference/neverTypeErrors1.errors.txt | 22 ++++++++++ tests/baselines/reference/neverTypeErrors1.js | 30 ++++++++++++++ .../reference/neverTypeErrors1.symbols | 40 +++++++++++++++++++ .../reference/neverTypeErrors1.types | 37 +++++++++++++++++ .../reference/neverTypeErrors2.errors.txt | 22 ++++++++++ tests/baselines/reference/neverTypeErrors2.js | 30 ++++++++++++++ .../reference/neverTypeErrors2.symbols | 40 +++++++++++++++++++ .../reference/neverTypeErrors2.types | 37 +++++++++++++++++ .../types/never/neverTypeErrors1.ts | 22 ++++++++++ .../types/never/neverTypeErrors2.ts | 22 ++++++++++ 11 files changed, 311 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1c78f3315b8fa..c38d9c2a0416a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -17907,8 +17907,10 @@ namespace ts { (source as LiteralType).value === (target as LiteralType).value && isEnumTypeRelatedTo(getParentOfSymbol(source.symbol)!, getParentOfSymbol(target.symbol)!, errorReporter)) return true; } - if (s & TypeFlags.Undefined && (!strictNullChecks || t & (TypeFlags.Undefined | TypeFlags.Void))) return true; - if (s & TypeFlags.Null && (!strictNullChecks || t & TypeFlags.Null)) return true; + // In non-strictNullChecks mode, `undefined` and `null` are assignable to anything except `never`. + // Since unions and intersections may reduce to `never`, we exclude them here. + if (s & TypeFlags.Undefined && (!strictNullChecks && !(t & TypeFlags.UnionOrIntersection) || t & (TypeFlags.Undefined | TypeFlags.Void))) return true; + if (s & TypeFlags.Null && (!strictNullChecks && !(t & TypeFlags.UnionOrIntersection) || t & TypeFlags.Null)) return true; if (s & TypeFlags.Object && t & TypeFlags.NonPrimitive) return true; if (relation === assignableRelation || relation === comparableRelation) { if (s & TypeFlags.Any) return true; @@ -19427,6 +19429,11 @@ namespace ts { } if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (source as TypeReference).target === (target as TypeReference).target && !isTupleType(source) && !(getObjectFlags(source) & ObjectFlags.MarkerType || getObjectFlags(target) & ObjectFlags.MarkerType)) { + // When strictNullChecks is disabled, the element type of the empty array literal is undefinedWideningType, + // and an empty array literal wouldn't be assignable to a `never[]` without this check. + if (isEmptyArrayLiteralType(source)) { + return Ternary.True; + } // We have type references to the same generic type, and the type references are not marker // type references (which are intended by be compared structurally). Obtain the variance // information for the type parameters and relate the type arguments accordingly. diff --git a/tests/baselines/reference/neverTypeErrors1.errors.txt b/tests/baselines/reference/neverTypeErrors1.errors.txt index d5299d0b30080..040ddfbf2ec67 100644 --- a/tests/baselines/reference/neverTypeErrors1.errors.txt +++ b/tests/baselines/reference/neverTypeErrors1.errors.txt @@ -63,4 +63,26 @@ tests/cases/conformance/types/never/neverTypeErrors1.ts(24,17): error TS2407: Th for (const n in f4()) {} ~~~~ !!! error TS2407: The right-hand side of a 'for...in' statement must be of type 'any', an object type or a type parameter, but here has type 'never'. + + function f5() { + let x: never[] = []; // Ok + } + + // Repro from #46032 + + interface A { + foo: "a"; + } + + interface B { + foo: "b"; + } + + type Union = A & B; + + function func(): { value: Union[] } { + return { + value: [], + }; + } \ No newline at end of file diff --git a/tests/baselines/reference/neverTypeErrors1.js b/tests/baselines/reference/neverTypeErrors1.js index 751975019ba81..e28300bae887c 100644 --- a/tests/baselines/reference/neverTypeErrors1.js +++ b/tests/baselines/reference/neverTypeErrors1.js @@ -23,6 +23,28 @@ function f4(): never { for (const n of f4()) {} for (const n in f4()) {} + +function f5() { + let x: never[] = []; // Ok +} + +// Repro from #46032 + +interface A { + foo: "a"; +} + +interface B { + foo: "b"; +} + +type Union = A & B; + +function func(): { value: Union[] } { + return { + value: [], + }; +} //// [neverTypeErrors1.js] @@ -48,3 +70,11 @@ for (var _i = 0, _a = f4(); _i < _a.length; _i++) { var n = _a[_i]; } for (var n in f4()) { } +function f5() { + var x = []; // Ok +} +function func() { + return { + value: [] + }; +} diff --git a/tests/baselines/reference/neverTypeErrors1.symbols b/tests/baselines/reference/neverTypeErrors1.symbols index 6c545be1d61b6..1aa397be79faa 100644 --- a/tests/baselines/reference/neverTypeErrors1.symbols +++ b/tests/baselines/reference/neverTypeErrors1.symbols @@ -52,3 +52,43 @@ for (const n in f4()) {} >n : Symbol(n, Decl(neverTypeErrors1.ts, 23, 10)) >f4 : Symbol(f4, Decl(neverTypeErrors1.ts, 17, 1)) +function f5() { +>f5 : Symbol(f5, Decl(neverTypeErrors1.ts, 23, 24)) + + let x: never[] = []; // Ok +>x : Symbol(x, Decl(neverTypeErrors1.ts, 26, 7)) +} + +// Repro from #46032 + +interface A { +>A : Symbol(A, Decl(neverTypeErrors1.ts, 27, 1)) + + foo: "a"; +>foo : Symbol(A.foo, Decl(neverTypeErrors1.ts, 31, 13)) +} + +interface B { +>B : Symbol(B, Decl(neverTypeErrors1.ts, 33, 1)) + + foo: "b"; +>foo : Symbol(B.foo, Decl(neverTypeErrors1.ts, 35, 13)) +} + +type Union = A & B; +>Union : Symbol(Union, Decl(neverTypeErrors1.ts, 37, 1)) +>A : Symbol(A, Decl(neverTypeErrors1.ts, 27, 1)) +>B : Symbol(B, Decl(neverTypeErrors1.ts, 33, 1)) + +function func(): { value: Union[] } { +>func : Symbol(func, Decl(neverTypeErrors1.ts, 39, 19)) +>value : Symbol(value, Decl(neverTypeErrors1.ts, 41, 18)) +>Union : Symbol(Union, Decl(neverTypeErrors1.ts, 37, 1)) + + return { + value: [], +>value : Symbol(value, Decl(neverTypeErrors1.ts, 42, 12)) + + }; +} + diff --git a/tests/baselines/reference/neverTypeErrors1.types b/tests/baselines/reference/neverTypeErrors1.types index 8fab8212f667b..f577b4457e1f0 100644 --- a/tests/baselines/reference/neverTypeErrors1.types +++ b/tests/baselines/reference/neverTypeErrors1.types @@ -67,3 +67,40 @@ for (const n in f4()) {} >f4() : never >f4 : () => never +function f5() { +>f5 : () => void + + let x: never[] = []; // Ok +>x : never[] +>[] : undefined[] +} + +// Repro from #46032 + +interface A { + foo: "a"; +>foo : "a" +} + +interface B { + foo: "b"; +>foo : "b" +} + +type Union = A & B; +>Union : never + +function func(): { value: Union[] } { +>func : () => { value: Union[];} +>value : never[] + + return { +>{ value: [], } : { value: undefined[]; } + + value: [], +>value : undefined[] +>[] : undefined[] + + }; +} + diff --git a/tests/baselines/reference/neverTypeErrors2.errors.txt b/tests/baselines/reference/neverTypeErrors2.errors.txt index 0cf3b6fbf0033..ad1dcc18d806a 100644 --- a/tests/baselines/reference/neverTypeErrors2.errors.txt +++ b/tests/baselines/reference/neverTypeErrors2.errors.txt @@ -63,4 +63,26 @@ tests/cases/conformance/types/never/neverTypeErrors2.ts(24,17): error TS2407: Th for (const n in f4()) {} ~~~~ !!! error TS2407: The right-hand side of a 'for...in' statement must be of type 'any', an object type or a type parameter, but here has type 'never'. + + function f5() { + let x: never[] = []; // Ok + } + + // Repro from #46032 + + interface A { + foo: "a"; + } + + interface B { + foo: "b"; + } + + type Union = A & B; + + function func(): { value: Union[] } { + return { + value: [], + }; + } \ No newline at end of file diff --git a/tests/baselines/reference/neverTypeErrors2.js b/tests/baselines/reference/neverTypeErrors2.js index 17a8a9eba9837..60f4e6f122afe 100644 --- a/tests/baselines/reference/neverTypeErrors2.js +++ b/tests/baselines/reference/neverTypeErrors2.js @@ -23,6 +23,28 @@ function f4(): never { for (const n of f4()) {} for (const n in f4()) {} + +function f5() { + let x: never[] = []; // Ok +} + +// Repro from #46032 + +interface A { + foo: "a"; +} + +interface B { + foo: "b"; +} + +type Union = A & B; + +function func(): { value: Union[] } { + return { + value: [], + }; +} //// [neverTypeErrors2.js] @@ -48,3 +70,11 @@ for (var _i = 0, _a = f4(); _i < _a.length; _i++) { var n = _a[_i]; } for (var n in f4()) { } +function f5() { + var x = []; // Ok +} +function func() { + return { + value: [] + }; +} diff --git a/tests/baselines/reference/neverTypeErrors2.symbols b/tests/baselines/reference/neverTypeErrors2.symbols index 3a450b60efd0f..5636d8b8dfc72 100644 --- a/tests/baselines/reference/neverTypeErrors2.symbols +++ b/tests/baselines/reference/neverTypeErrors2.symbols @@ -52,3 +52,43 @@ for (const n in f4()) {} >n : Symbol(n, Decl(neverTypeErrors2.ts, 23, 10)) >f4 : Symbol(f4, Decl(neverTypeErrors2.ts, 17, 1)) +function f5() { +>f5 : Symbol(f5, Decl(neverTypeErrors2.ts, 23, 24)) + + let x: never[] = []; // Ok +>x : Symbol(x, Decl(neverTypeErrors2.ts, 26, 7)) +} + +// Repro from #46032 + +interface A { +>A : Symbol(A, Decl(neverTypeErrors2.ts, 27, 1)) + + foo: "a"; +>foo : Symbol(A.foo, Decl(neverTypeErrors2.ts, 31, 13)) +} + +interface B { +>B : Symbol(B, Decl(neverTypeErrors2.ts, 33, 1)) + + foo: "b"; +>foo : Symbol(B.foo, Decl(neverTypeErrors2.ts, 35, 13)) +} + +type Union = A & B; +>Union : Symbol(Union, Decl(neverTypeErrors2.ts, 37, 1)) +>A : Symbol(A, Decl(neverTypeErrors2.ts, 27, 1)) +>B : Symbol(B, Decl(neverTypeErrors2.ts, 33, 1)) + +function func(): { value: Union[] } { +>func : Symbol(func, Decl(neverTypeErrors2.ts, 39, 19)) +>value : Symbol(value, Decl(neverTypeErrors2.ts, 41, 18)) +>Union : Symbol(Union, Decl(neverTypeErrors2.ts, 37, 1)) + + return { + value: [], +>value : Symbol(value, Decl(neverTypeErrors2.ts, 42, 12)) + + }; +} + diff --git a/tests/baselines/reference/neverTypeErrors2.types b/tests/baselines/reference/neverTypeErrors2.types index 5bfae1f5201dc..685638f03a41c 100644 --- a/tests/baselines/reference/neverTypeErrors2.types +++ b/tests/baselines/reference/neverTypeErrors2.types @@ -67,3 +67,40 @@ for (const n in f4()) {} >f4() : never >f4 : () => never +function f5() { +>f5 : () => void + + let x: never[] = []; // Ok +>x : never[] +>[] : never[] +} + +// Repro from #46032 + +interface A { + foo: "a"; +>foo : "a" +} + +interface B { + foo: "b"; +>foo : "b" +} + +type Union = A & B; +>Union : never + +function func(): { value: Union[] } { +>func : () => { value: Union[];} +>value : never[] + + return { +>{ value: [], } : { value: never[]; } + + value: [], +>value : never[] +>[] : never[] + + }; +} + diff --git a/tests/cases/conformance/types/never/neverTypeErrors1.ts b/tests/cases/conformance/types/never/neverTypeErrors1.ts index 44435d5203dc8..0d9cece13145f 100644 --- a/tests/cases/conformance/types/never/neverTypeErrors1.ts +++ b/tests/cases/conformance/types/never/neverTypeErrors1.ts @@ -22,3 +22,25 @@ function f4(): never { for (const n of f4()) {} for (const n in f4()) {} + +function f5() { + let x: never[] = []; // Ok +} + +// Repro from #46032 + +interface A { + foo: "a"; +} + +interface B { + foo: "b"; +} + +type Union = A & B; + +function func(): { value: Union[] } { + return { + value: [], + }; +} diff --git a/tests/cases/conformance/types/never/neverTypeErrors2.ts b/tests/cases/conformance/types/never/neverTypeErrors2.ts index c9c37dcb15da2..15c66a69d2f52 100644 --- a/tests/cases/conformance/types/never/neverTypeErrors2.ts +++ b/tests/cases/conformance/types/never/neverTypeErrors2.ts @@ -24,3 +24,25 @@ function f4(): never { for (const n of f4()) {} for (const n in f4()) {} + +function f5() { + let x: never[] = []; // Ok +} + +// Repro from #46032 + +interface A { + foo: "a"; +} + +interface B { + foo: "b"; +} + +type Union = A & B; + +function func(): { value: Union[] } { + return { + value: [], + }; +} From 39d9e69736727d384ee8a7f0151d682a1016baf0 Mon Sep 17 00:00:00 2001 From: csigs Date: Sun, 13 Feb 2022 02:49:51 -0800 Subject: [PATCH 50/55] LEGO: Merge pull request 47871 LEGO: Merge pull request 47871 --- .../diagnosticMessages.generated.json.lcl | 9 +++++ .../diagnosticMessages.generated.json.lcl | 9 +++++ .../diagnosticMessages.generated.json.lcl | 9 +++++ .../diagnosticMessages.generated.json.lcl | 15 ++++++++ .../diagnosticMessages.generated.json.lcl | 9 +++++ .../diagnosticMessages.generated.json.lcl | 9 +++++ .../diagnosticMessages.generated.json.lcl | 9 +++++ .../diagnosticMessages.generated.json.lcl | 15 ++++++++ .../diagnosticMessages.generated.json.lcl | 9 +++++ .../diagnosticMessages.generated.json.lcl | 36 +++++++++++++++++++ 10 files changed, 129 insertions(+) diff --git a/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl index 19d0ab30be1ed..204308dc71fe5 100644 --- a/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -3228,6 +3228,15 @@ + + + + + + + + + diff --git a/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl index ea264b001c273..770080a391fe5 100644 --- a/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -3237,6 +3237,15 @@ + + + + + + + + + diff --git a/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl index 975cbf345d894..9d76364a5c0ec 100644 --- a/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -3240,6 +3240,15 @@ + + + + + + + + + diff --git a/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl index d5d18393d442d..1cbe843f60d92 100644 --- a/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -3240,6 +3240,12 @@ + + + + + + @@ -4656,6 +4662,9 @@ + + + @@ -4671,6 +4680,9 @@ + + + @@ -10899,6 +10911,9 @@ + + + diff --git a/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl index afb302caba3f2..4ff6323a7e518 100644 --- a/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -3228,6 +3228,15 @@ + + + + + + + + + diff --git a/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl index 36b7f6e11f4d3..1fb3b24d0f4ab 100644 --- a/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -3228,6 +3228,15 @@ + + + + + + + + + diff --git a/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl index 24b8a1f627f9c..76a815cd02e94 100644 --- a/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -3228,6 +3228,15 @@ + + + + + + + + + diff --git a/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl index 6493fb0c1ec64..3cf690406571a 100644 --- a/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -3218,6 +3218,12 @@ + + + + + + @@ -4634,6 +4640,9 @@ + + + @@ -4649,6 +4658,9 @@ + + + @@ -10874,6 +10886,9 @@ + + + diff --git a/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl index c24ed6998c789..9b81f1f9aa7ea 100644 --- a/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -3227,6 +3227,15 @@ + + + + + + + + + diff --git a/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl index 2b367f919a9b6..3a10ea631f766 100644 --- a/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -3221,6 +3221,15 @@ + + + + + + + + + @@ -4634,6 +4643,15 @@ + + + + + + + + + @@ -4643,6 +4661,15 @@ + + + + + + + + + @@ -10865,6 +10892,15 @@ + + + + + + + + + ']]> From 67d433893d3d588452b05ded4b907db25cb13ea4 Mon Sep 17 00:00:00 2001 From: csigs Date: Mon, 14 Feb 2022 02:49:40 -0800 Subject: [PATCH 51/55] LEGO: Merge pull request 47875 LEGO: Merge pull request 47875 --- .../diagnosticMessages.generated.json.lcl | 9 +++++++++ .../diagnosticMessages.generated.json.lcl | 9 +++++++++ .../diagnosticMessages.generated.json.lcl | 3 +++ .../diagnosticMessages.generated.json.lcl | 3 +++ .../diagnosticMessages.generated.json.lcl | 9 +++++++++ 5 files changed, 33 insertions(+) diff --git a/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl index 6ec7597a1a7df..32bc4f856baed 100644 --- a/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -3228,6 +3228,15 @@ + + + + + + + + + diff --git a/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl index 5e611bfab9687..b6eb25ec6e3f0 100644 --- a/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -3225,6 +3225,15 @@ + + + + + + + + + diff --git a/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl index 1cbe843f60d92..a4c0de7093666 100644 --- a/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -3243,6 +3243,9 @@ + + + diff --git a/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl index 3cf690406571a..c794a4ca310f1 100644 --- a/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -3221,6 +3221,9 @@ + + + diff --git a/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl index 212424b933d82..4cac90e0dbe2e 100644 --- a/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -3221,6 +3221,15 @@ + + + + + + + + + From 7e57c81802b41a9a0a9b720dd7a20bb503448d48 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Mon, 14 Feb 2022 09:21:43 -0800 Subject: [PATCH 52/55] Explicitly annotate return type of getCommentRange (#47860) --- src/compiler/factory/emitNode.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/factory/emitNode.ts b/src/compiler/factory/emitNode.ts index ebb7300efdeec..6c207994331a3 100644 --- a/src/compiler/factory/emitNode.ts +++ b/src/compiler/factory/emitNode.ts @@ -127,7 +127,7 @@ namespace ts { /** * Gets a custom text range to use when emitting comments. */ - export function getCommentRange(node: Node) { + export function getCommentRange(node: Node): TextRange { return node.emitNode?.commentRange ?? node; } From 03f90350292ec262a1e632e4b4a7d9808d856150 Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Mon, 14 Feb 2022 12:40:07 -0800 Subject: [PATCH 53/55] [GH Actions] Implicitly use AUTHORIZATION header instead of PAT-in-URL (#47894) * Implicitly use AUTHORIZATION header instead of PAT-in-URL * Does just GITHUB_TOKEN work? * Try unsetting extraheader config * Do config inside repos --- .github/workflows/ensure-related-repos-run-crons.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ensure-related-repos-run-crons.yml b/.github/workflows/ensure-related-repos-run-crons.yml index 51f757b43b367..f6faff6b67f77 100644 --- a/.github/workflows/ensure-related-repos-run-crons.yml +++ b/.github/workflows/ensure-related-repos-run-crons.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest steps: - - name: Configure git and update package-lock.json + - name: Configure git run: | git config --global user.email "typescriptbot@microsoft.com" git config --global user.name "TypeScript Bot" @@ -30,6 +30,7 @@ jobs: run: | cd ts-site git commit --allow-empty -m "Monthly Bump" + git config --unset-all http.https://github.com/.extraheader git push https://${{ secrets.TS_BOT_GITHUB_TOKEN }}@github.com/microsoft/TypeScript-Website.git - uses: actions/checkout@v2 @@ -41,4 +42,5 @@ jobs: run: | cd monaco-builds git commit --allow-empty -m "Monthly Bump" + git config --unset-all http.https://github.com/.extraheader git push https://${{ secrets.TS_BOT_GITHUB_TOKEN }}@github.com/microsoft/TypeScript-Make-Monaco-Builds.git From e32281cc02e8d6fd6afdc5df2f3c5b915a1b8d95 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Mon, 14 Feb 2022 14:13:21 -0800 Subject: [PATCH 54/55] Allow extensionless `main`s for cjs mode packages even from an esm import (#47893) --- src/compiler/moduleNameResolver.ts | 12 +++++- ...ImportsOfPackagesWithExtensionlessMains.js | 42 +++++++++++++++++++ ...tsOfPackagesWithExtensionlessMains.symbols | 35 ++++++++++++++++ ...ortsOfPackagesWithExtensionlessMains.types | 37 ++++++++++++++++ ...ImportsOfPackagesWithExtensionlessMains.ts | 36 ++++++++++++++++ 5 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/nodeNextEsmImportsOfPackagesWithExtensionlessMains.js create mode 100644 tests/baselines/reference/nodeNextEsmImportsOfPackagesWithExtensionlessMains.symbols create mode 100644 tests/baselines/reference/nodeNextEsmImportsOfPackagesWithExtensionlessMains.types create mode 100644 tests/cases/compiler/nodeNextEsmImportsOfPackagesWithExtensionlessMains.ts diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index 24d4c845acae5..e87983470f7f8 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -1819,7 +1819,17 @@ namespace ts { // Even if extensions is DtsOnly, we can still look up a .ts file as a result of package.json "types" const nextExtensions = extensions === Extensions.DtsOnly ? Extensions.TypeScript : extensions; // Don't do package.json lookup recursively, because Node.js' package lookup doesn't. - return nodeLoadModuleByRelativeName(nextExtensions, candidate, onlyRecordFailures, state, /*considerPackageJson*/ false); + + // Disable `EsmMode` for the resolution of the package path for cjs-mode packages (so the `main` field can omit extensions) + // (technically it only emits a deprecation warning in esm packages right now, but that's probably + // enough to mean we don't need to support it) + const features = state.features; + if (jsonContent?.type !== "module") { + state.features &= ~NodeResolutionFeatures.EsmMode; + } + const result = nodeLoadModuleByRelativeName(nextExtensions, candidate, onlyRecordFailures, state, /*considerPackageJson*/ false); + state.features = features; + return result; }; const onlyRecordFailuresForPackageFile = packageFile ? !directoryProbablyExists(getDirectoryPath(packageFile), state.host) : undefined; diff --git a/tests/baselines/reference/nodeNextEsmImportsOfPackagesWithExtensionlessMains.js b/tests/baselines/reference/nodeNextEsmImportsOfPackagesWithExtensionlessMains.js new file mode 100644 index 0000000000000..9eb7e3dd4bf52 --- /dev/null +++ b/tests/baselines/reference/nodeNextEsmImportsOfPackagesWithExtensionlessMains.js @@ -0,0 +1,42 @@ +//// [tests/cases/compiler/nodeNextEsmImportsOfPackagesWithExtensionlessMains.ts] //// + +//// [package.json] +{ + "name": "@types/ip", + "version": "1.1.0", + "main": "", + "types": "index" +} +//// [index.d.ts] +export function address(): string; +//// [package.json] +{ + "name": "nullthrows", + "version": "1.1.1", + "main": "nullthrows.js", + "types": "nullthrows.d.ts" +} +//// [nullthrows.d.ts] +declare function nullthrows(x: any): any; +declare namespace nullthrows { + export {nullthrows as default}; +} +export = nullthrows; +//// [package.json] +{ + "type": "module" +} +//// [index.ts] +import * as ip from 'ip'; +import nullthrows from 'nullthrows'; // shouldn't be callable, `nullthrows` is a cjs package, so the `default` is the module itself + +export function getAddress(): string { + return nullthrows(ip.address()); +} + +//// [index.js] +import * as ip from 'ip'; +import nullthrows from 'nullthrows'; // shouldn't be callable, `nullthrows` is a cjs package, so the `default` is the module itself +export function getAddress() { + return nullthrows(ip.address()); +} diff --git a/tests/baselines/reference/nodeNextEsmImportsOfPackagesWithExtensionlessMains.symbols b/tests/baselines/reference/nodeNextEsmImportsOfPackagesWithExtensionlessMains.symbols new file mode 100644 index 0000000000000..01fae1acf1a92 --- /dev/null +++ b/tests/baselines/reference/nodeNextEsmImportsOfPackagesWithExtensionlessMains.symbols @@ -0,0 +1,35 @@ +=== tests/cases/compiler/index.ts === +import * as ip from 'ip'; +>ip : Symbol(ip, Decl(index.ts, 0, 6)) + +import nullthrows from 'nullthrows'; // shouldn't be callable, `nullthrows` is a cjs package, so the `default` is the module itself +>nullthrows : Symbol(nullthrows, Decl(index.ts, 1, 6)) + +export function getAddress(): string { +>getAddress : Symbol(getAddress, Decl(index.ts, 1, 36)) + + return nullthrows(ip.address()); +>nullthrows : Symbol(nullthrows, Decl(index.ts, 1, 6)) +>ip.address : Symbol(ip.address, Decl(index.d.ts, 0, 0)) +>ip : Symbol(ip, Decl(index.ts, 0, 6)) +>address : Symbol(ip.address, Decl(index.d.ts, 0, 0)) +} +=== tests/cases/compiler/node_modules/@types/ip/index.d.ts === +export function address(): string; +>address : Symbol(address, Decl(index.d.ts, 0, 0)) + +=== tests/cases/compiler/node_modules/nullthrows/nullthrows.d.ts === +declare function nullthrows(x: any): any; +>nullthrows : Symbol(nullthrows, Decl(nullthrows.d.ts, 0, 0), Decl(nullthrows.d.ts, 0, 41)) +>x : Symbol(x, Decl(nullthrows.d.ts, 0, 28)) + +declare namespace nullthrows { +>nullthrows : Symbol(nullthrows, Decl(nullthrows.d.ts, 0, 0), Decl(nullthrows.d.ts, 0, 41)) + + export {nullthrows as default}; +>nullthrows : Symbol(nullthrows, Decl(nullthrows.d.ts, 0, 0), Decl(nullthrows.d.ts, 0, 41)) +>default : Symbol(default, Decl(nullthrows.d.ts, 2, 12)) +} +export = nullthrows; +>nullthrows : Symbol(nullthrows, Decl(nullthrows.d.ts, 0, 0), Decl(nullthrows.d.ts, 0, 41)) + diff --git a/tests/baselines/reference/nodeNextEsmImportsOfPackagesWithExtensionlessMains.types b/tests/baselines/reference/nodeNextEsmImportsOfPackagesWithExtensionlessMains.types new file mode 100644 index 0000000000000..5fbeeb4fa24ae --- /dev/null +++ b/tests/baselines/reference/nodeNextEsmImportsOfPackagesWithExtensionlessMains.types @@ -0,0 +1,37 @@ +=== tests/cases/compiler/index.ts === +import * as ip from 'ip'; +>ip : typeof ip + +import nullthrows from 'nullthrows'; // shouldn't be callable, `nullthrows` is a cjs package, so the `default` is the module itself +>nullthrows : typeof nullthrows + +export function getAddress(): string { +>getAddress : () => string + + return nullthrows(ip.address()); +>nullthrows(ip.address()) : any +>nullthrows : typeof nullthrows +>ip.address() : string +>ip.address : () => string +>ip : typeof ip +>address : () => string +} +=== tests/cases/compiler/node_modules/@types/ip/index.d.ts === +export function address(): string; +>address : () => string + +=== tests/cases/compiler/node_modules/nullthrows/nullthrows.d.ts === +declare function nullthrows(x: any): any; +>nullthrows : typeof nullthrows +>x : any + +declare namespace nullthrows { +>nullthrows : typeof nullthrows + + export {nullthrows as default}; +>nullthrows : typeof nullthrows +>default : typeof nullthrows +} +export = nullthrows; +>nullthrows : typeof nullthrows + diff --git a/tests/cases/compiler/nodeNextEsmImportsOfPackagesWithExtensionlessMains.ts b/tests/cases/compiler/nodeNextEsmImportsOfPackagesWithExtensionlessMains.ts new file mode 100644 index 0000000000000..50d0035001441 --- /dev/null +++ b/tests/cases/compiler/nodeNextEsmImportsOfPackagesWithExtensionlessMains.ts @@ -0,0 +1,36 @@ +// @noImplicitReferences: true +// @module: nodenext +// @outDir: esm +// @filename: node_modules/@types/ip/package.json +{ + "name": "@types/ip", + "version": "1.1.0", + "main": "", + "types": "index" +} +// @filename: node_modules/@types/ip/index.d.ts +export function address(): string; +// @filename: node_modules/nullthrows/package.json +{ + "name": "nullthrows", + "version": "1.1.1", + "main": "nullthrows.js", + "types": "nullthrows.d.ts" +} +// @filename: node_modules/nullthrows/nullthrows.d.ts +declare function nullthrows(x: any): any; +declare namespace nullthrows { + export {nullthrows as default}; +} +export = nullthrows; +// @filename: package.json +{ + "type": "module" +} +// @filename: index.ts +import * as ip from 'ip'; +import nullthrows from 'nullthrows'; // shouldn't be callable, `nullthrows` is a cjs package, so the `default` is the module itself + +export function getAddress(): string { + return nullthrows(ip.address()); +} \ No newline at end of file From c3a055203306682ee0b4c5cba1fa508128ca6c03 Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Tue, 15 Feb 2022 06:07:13 +0000 Subject: [PATCH 55/55] Update package-lock.json --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index f829b407185ea..3dffad674d816 100644 --- a/package-lock.json +++ b/package-lock.json @@ -676,9 +676,9 @@ "dev": true }, "@types/node": { - "version": "17.0.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.17.tgz", - "integrity": "sha512-e8PUNQy1HgJGV3iU/Bp2+D/DXh3PYeyli8LgIwsQcs1Ar1LoaWHSIT6Rw+H2rNJmiq6SNWiDytfx8+gYj7wDHw==", + "version": "17.0.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.18.tgz", + "integrity": "sha512-eKj4f/BsN/qcculZiRSujogjvp5O/k4lOW5m35NopjZM/QwLOR075a8pJW5hD+Rtdm2DaCVPENS6KtSQnUD6BA==", "dev": true }, "@types/node-fetch": {