From 905f9a02ad17da9e18c4cbeeee81eee7b1928ca7 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Mon, 23 Apr 2018 15:24:31 -0700 Subject: [PATCH] `module.exports = Entity` is an alias, just like `export = Entity` (#23570) * Make `module.export =` an alias like `export=` is This breaks a couple of tests for previous workarounds. Fix in upcoming commits. * Basically fixes all the breaks, but needs cleanup * More notes to myself * Clean up TODOs * Call mergeSymbolTable and delete export= afterward instead of basically copying the code myself. * More cleanup * Remove unnecessary check in import type checking * Revert to DIY code. It is more correct and will go away in a few days. * Exported class expressions can be used as type In both JS and TS * Do not require named class expressions --- src/compiler/binder.ts | 9 ++- src/compiler/checker.ts | 31 +++++++--- src/compiler/utilities.ts | 8 ++- .../commonJsImportClassExpression.js | 25 ++++++++ .../commonJsImportClassExpression.symbols | 19 ++++++ .../commonJsImportClassExpression.types | 22 +++++++ .../baselines/reference/es5ExportEquals.types | 2 +- .../baselines/reference/es6ExportEquals.types | 2 +- .../reference/jsdocImportType.symbols | 56 +++++++++++++++++ .../baselines/reference/jsdocImportType.types | 60 +++++++++++++++++++ .../reference/jsdocImportType2.symbols | 54 +++++++++++++++++ .../reference/jsdocImportType2.types | 59 ++++++++++++++++++ ...xportWithExportPropertyAssignment4.symbols | 16 ++--- .../compiler/commonJsImportClassExpression.ts | 9 +++ .../conformance/jsdoc/jsdocImportType.ts | 27 +++++++++ .../conformance/jsdoc/jsdocImportType2.ts | 26 ++++++++ .../fourslash/findAllRefsClassExpression0.ts | 2 +- .../fourslash/findAllRefsClassExpression1.ts | 2 +- 18 files changed, 402 insertions(+), 27 deletions(-) create mode 100644 tests/baselines/reference/commonJsImportClassExpression.js create mode 100644 tests/baselines/reference/commonJsImportClassExpression.symbols create mode 100644 tests/baselines/reference/commonJsImportClassExpression.types create mode 100644 tests/baselines/reference/jsdocImportType.symbols create mode 100644 tests/baselines/reference/jsdocImportType.types create mode 100644 tests/baselines/reference/jsdocImportType2.symbols create mode 100644 tests/baselines/reference/jsdocImportType2.types create mode 100644 tests/cases/compiler/commonJsImportClassExpression.ts create mode 100644 tests/cases/conformance/jsdoc/jsdocImportType.ts create mode 100644 tests/cases/conformance/jsdoc/jsdocImportType2.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index fe77e9b4df4..2557e3b7078 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -2220,14 +2220,14 @@ namespace ts { bindAnonymousDeclaration(file, SymbolFlags.ValueModule, `"${removeFileExtension(file.fileName)}"` as __String); } - function bindExportAssignment(node: ExportAssignment | BinaryExpression) { + function bindExportAssignment(node: ExportAssignment) { if (!container.symbol || !container.symbol.exports) { // Export assignment in some sort of block construct bindAnonymousDeclaration(node, SymbolFlags.Alias, getDeclarationName(node)); } else { const flags = node.kind === SyntaxKind.ExportAssignment && exportAssignmentIsAlias(node) - // An export default clause with an EntityNameExpression exports all meanings of that identifier + // An export default clause with an EntityNameExpression or a class expression exports all meanings of that identifier or expression; ? SymbolFlags.Alias // An export default clause with any other expression exports a value : SymbolFlags.Property; @@ -2322,7 +2322,10 @@ namespace ts { // 'module.exports = expr' assignment setCommonJsModuleIndicator(node); - declareSymbol(file.symbol.exports, file.symbol, node, SymbolFlags.Property | SymbolFlags.ExportValue | SymbolFlags.ValueModule, SymbolFlags.None); + const flags = exportAssignmentIsAlias(node) + ? SymbolFlags.Alias // An export= with an EntityNameExpression or a ClassExpression exports all meanings of that identifier or class + : SymbolFlags.Property | SymbolFlags.ExportValue | SymbolFlags.ValueModule; + declareSymbol(file.symbol.exports, file.symbol, node, flags, SymbolFlags.None); } function bindThisPropertyAssignment(node: BinaryExpression | PropertyAccessExpression) { diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 76f9722342a..75f8715fca7 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1926,13 +1926,17 @@ namespace ts { resolveEntityName(node.propertyName || node.name, meaning, /*ignoreErrors*/ false, dontResolveAlias); } - function getTargetOfExportAssignment(node: ExportAssignment, dontResolveAlias: boolean): Symbol | undefined { - const aliasLike = resolveEntityName(node.expression, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace, /*ignoreErrors*/ true, dontResolveAlias); + function getTargetOfExportAssignment(node: ExportAssignment | BinaryExpression, dontResolveAlias: boolean): Symbol | undefined { + const expression = (isExportAssignment(node) ? node.expression : node.right) as EntityNameExpression | ClassExpression; + if (isClassExpression(expression)) { + return checkExpression(expression).symbol; + } + const aliasLike = resolveEntityName(expression, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace, /*ignoreErrors*/ true, dontResolveAlias); if (aliasLike) { return aliasLike; } - checkExpression(node.expression); - return getNodeLinks(node.expression).resolvedSymbol; + checkExpression(expression); + return getNodeLinks(expression).resolvedSymbol; } function getTargetOfAliasDeclaration(node: Declaration, dontRecursivelyResolve?: boolean): Symbol | undefined { @@ -1948,7 +1952,8 @@ namespace ts { case SyntaxKind.ExportSpecifier: return getTargetOfExportSpecifier(node, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace, dontRecursivelyResolve); case SyntaxKind.ExportAssignment: - return getTargetOfExportAssignment(node, dontRecursivelyResolve); + case SyntaxKind.BinaryExpression: + return getTargetOfExportAssignment((node), dontRecursivelyResolve); case SyntaxKind.NamespaceExportDeclaration: return getTargetOfNamespaceExportDeclaration(node, dontRecursivelyResolve); } @@ -2229,20 +2234,28 @@ namespace ts { // An external module with an 'export =' declaration resolves to the target of the 'export =' declaration, // and an external module with no 'export =' declaration resolves to the module itself. function resolveExternalModuleSymbol(moduleSymbol: Symbol, dontResolveAlias?: boolean): Symbol { - return moduleSymbol && getMergedSymbol(resolveSymbol(getCommonJsExportEquals(moduleSymbol), dontResolveAlias)) || moduleSymbol; + return moduleSymbol && getMergedSymbol(getCommonJsExportEquals(resolveSymbol(moduleSymbol.exports.get(InternalSymbolName.ExportEquals), dontResolveAlias), moduleSymbol)) || moduleSymbol; } - function getCommonJsExportEquals(moduleSymbol: Symbol): Symbol { - const exported = moduleSymbol.exports.get(InternalSymbolName.ExportEquals); - if (!exported || !exported.exports || moduleSymbol.exports.size === 1) { + function getCommonJsExportEquals(exported: Symbol, moduleSymbol: Symbol): Symbol { + if (!exported || moduleSymbol.exports.size === 1) { return exported; } const merged = cloneSymbol(exported); + if (merged.exports === undefined) { + merged.flags = merged.flags | SymbolFlags.ValueModule; + merged.exports = createSymbolTable(); + } moduleSymbol.exports.forEach((s, name) => { if (name === InternalSymbolName.ExportEquals) return; if (!merged.exports.has(name)) { merged.exports.set(name, s); } + else { + const ms = cloneSymbol(merged.exports.get(name)); + mergeSymbol(ms, s); + merged.exports.set(name, ms); + } }); return merged; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 5c94745f339..c5cb19e876a 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2140,11 +2140,13 @@ namespace ts { node.kind === SyntaxKind.NamespaceImport || node.kind === SyntaxKind.ImportSpecifier || node.kind === SyntaxKind.ExportSpecifier || - node.kind === SyntaxKind.ExportAssignment && exportAssignmentIsAlias(node); + node.kind === SyntaxKind.ExportAssignment && exportAssignmentIsAlias(node) || + isBinaryExpression(node) && getSpecialPropertyAssignmentKind(node) === SpecialPropertyAssignmentKind.ModuleExports; } - export function exportAssignmentIsAlias(node: ExportAssignment): boolean { - return isEntityNameExpression(node.expression); + export function exportAssignmentIsAlias(node: ExportAssignment | BinaryExpression): boolean { + const e = isExportAssignment(node) ? node.expression : node.right; + return isEntityNameExpression(e) || isClassExpression(e); } export function getClassExtendsHeritageClauseElement(node: ClassLikeDeclaration | InterfaceDeclaration) { diff --git a/tests/baselines/reference/commonJsImportClassExpression.js b/tests/baselines/reference/commonJsImportClassExpression.js new file mode 100644 index 00000000000..b460814b872 --- /dev/null +++ b/tests/baselines/reference/commonJsImportClassExpression.js @@ -0,0 +1,25 @@ +//// [tests/cases/compiler/commonJsImportClassExpression.ts] //// + +//// [mod1.ts] +export = class { + chunk = 1 +} + +//// [use.ts] +import Chunk = require('./mod1') +declare var c: Chunk; +c.chunk; + + +//// [mod1.js] +"use strict"; +module.exports = /** @class */ (function () { + function class_1() { + this.chunk = 1; + } + return class_1; +}()); +//// [use.js] +"use strict"; +exports.__esModule = true; +c.chunk; diff --git a/tests/baselines/reference/commonJsImportClassExpression.symbols b/tests/baselines/reference/commonJsImportClassExpression.symbols new file mode 100644 index 00000000000..5f6bc93188f --- /dev/null +++ b/tests/baselines/reference/commonJsImportClassExpression.symbols @@ -0,0 +1,19 @@ +=== tests/cases/compiler/use.ts === +import Chunk = require('./mod1') +>Chunk : Symbol(Chunk, Decl(use.ts, 0, 0)) + +declare var c: Chunk; +>c : Symbol(c, Decl(use.ts, 1, 11)) +>Chunk : Symbol(Chunk, Decl(use.ts, 0, 0)) + +c.chunk; +>c.chunk : Symbol(Chunk.chunk, Decl(mod1.ts, 0, 16)) +>c : Symbol(c, Decl(use.ts, 1, 11)) +>chunk : Symbol(Chunk.chunk, Decl(mod1.ts, 0, 16)) + +=== tests/cases/compiler/mod1.ts === +export = class { + chunk = 1 +>chunk : Symbol((Anonymous class).chunk, Decl(mod1.ts, 0, 16)) +} + diff --git a/tests/baselines/reference/commonJsImportClassExpression.types b/tests/baselines/reference/commonJsImportClassExpression.types new file mode 100644 index 00000000000..7bb32dea8e5 --- /dev/null +++ b/tests/baselines/reference/commonJsImportClassExpression.types @@ -0,0 +1,22 @@ +=== tests/cases/compiler/use.ts === +import Chunk = require('./mod1') +>Chunk : typeof Chunk + +declare var c: Chunk; +>c : Chunk +>Chunk : Chunk + +c.chunk; +>c.chunk : number +>c : Chunk +>chunk : number + +=== tests/cases/compiler/mod1.ts === +export = class { +>class { chunk = 1} : typeof (Anonymous class) + + chunk = 1 +>chunk : number +>1 : 1 +} + diff --git a/tests/baselines/reference/es5ExportEquals.types b/tests/baselines/reference/es5ExportEquals.types index 3397cf1df72..6c9e8930537 100644 --- a/tests/baselines/reference/es5ExportEquals.types +++ b/tests/baselines/reference/es5ExportEquals.types @@ -1,6 +1,6 @@ === tests/cases/compiler/es5ExportEquals.ts === export function f() { } ->f : () => void +>f : typeof f export = f; >f : () => void diff --git a/tests/baselines/reference/es6ExportEquals.types b/tests/baselines/reference/es6ExportEquals.types index 3503812aead..3ba761dc8e5 100644 --- a/tests/baselines/reference/es6ExportEquals.types +++ b/tests/baselines/reference/es6ExportEquals.types @@ -1,6 +1,6 @@ === tests/cases/compiler/es6ExportEquals.ts === export function f() { } ->f : () => void +>f : typeof f export = f; >f : () => void diff --git a/tests/baselines/reference/jsdocImportType.symbols b/tests/baselines/reference/jsdocImportType.symbols new file mode 100644 index 00000000000..657ad6801f1 --- /dev/null +++ b/tests/baselines/reference/jsdocImportType.symbols @@ -0,0 +1,56 @@ +=== tests/cases/conformance/jsdoc/use.js === +/// +/** @typedef {import("./mod1")} C + * @type {C} */ +var c; +>c : Symbol(c, Decl(use.js, 3, 3)) + +c.chunk; +>c.chunk : Symbol(Chunk.chunk, Decl(mod1.js, 2, 19)) +>c : Symbol(c, Decl(use.js, 3, 3)) +>chunk : Symbol(Chunk.chunk, Decl(mod1.js, 2, 19)) + +const D = require("./mod1"); +>D : Symbol(D, Decl(use.js, 6, 5)) +>require : Symbol(require, Decl(types.d.ts, 0, 0)) +>"./mod1" : Symbol("tests/cases/conformance/jsdoc/mod1", Decl(mod1.js, 0, 0)) + +/** @type {D} */ +var d; +>d : Symbol(d, Decl(use.js, 8, 3)) + +d.chunk; +>d.chunk : Symbol(Chunk.chunk, Decl(mod1.js, 2, 19)) +>d : Symbol(d, Decl(use.js, 8, 3)) +>chunk : Symbol(Chunk.chunk, Decl(mod1.js, 2, 19)) + +=== tests/cases/conformance/jsdoc/types.d.ts === +declare function require(name: string): any; +>require : Symbol(require, Decl(types.d.ts, 0, 0)) +>name : Symbol(name, Decl(types.d.ts, 0, 25)) + +declare var exports: any; +>exports : Symbol(exports, Decl(types.d.ts, 1, 11)) + +declare var module: { exports: any }; +>module : Symbol(module, Decl(types.d.ts, 2, 11)) +>exports : Symbol(exports, Decl(types.d.ts, 2, 21)) + +=== tests/cases/conformance/jsdoc/mod1.js === +/// +class Chunk { +>Chunk : Symbol(Chunk, Decl(mod1.js, 0, 0)) + + constructor() { + this.chunk = 1; +>this.chunk : Symbol(Chunk.chunk, Decl(mod1.js, 2, 19)) +>this : Symbol(Chunk, Decl(mod1.js, 0, 0)) +>chunk : Symbol(Chunk.chunk, Decl(mod1.js, 2, 19)) + } +} +module.exports = Chunk; +>module.exports : Symbol(exports, Decl(types.d.ts, 2, 21)) +>module : Symbol(export=, Decl(mod1.js, 5, 1)) +>exports : Symbol(export=, Decl(mod1.js, 5, 1)) +>Chunk : Symbol(Chunk, Decl(mod1.js, 0, 0)) + diff --git a/tests/baselines/reference/jsdocImportType.types b/tests/baselines/reference/jsdocImportType.types new file mode 100644 index 00000000000..b2ac2764cd5 --- /dev/null +++ b/tests/baselines/reference/jsdocImportType.types @@ -0,0 +1,60 @@ +=== tests/cases/conformance/jsdoc/use.js === +/// +/** @typedef {import("./mod1")} C + * @type {C} */ +var c; +>c : Chunk + +c.chunk; +>c.chunk : number +>c : Chunk +>chunk : number + +const D = require("./mod1"); +>D : typeof Chunk +>require("./mod1") : typeof Chunk +>require : (name: string) => any +>"./mod1" : "./mod1" + +/** @type {D} */ +var d; +>d : Chunk + +d.chunk; +>d.chunk : number +>d : Chunk +>chunk : number + +=== tests/cases/conformance/jsdoc/types.d.ts === +declare function require(name: string): any; +>require : (name: string) => any +>name : string + +declare var exports: any; +>exports : any + +declare var module: { exports: any }; +>module : { exports: any; } +>exports : any + +=== tests/cases/conformance/jsdoc/mod1.js === +/// +class Chunk { +>Chunk : Chunk + + constructor() { + this.chunk = 1; +>this.chunk = 1 : 1 +>this.chunk : number +>this : this +>chunk : number +>1 : 1 + } +} +module.exports = Chunk; +>module.exports = Chunk : typeof Chunk +>module.exports : any +>module : { exports: any; } +>exports : any +>Chunk : typeof Chunk + diff --git a/tests/baselines/reference/jsdocImportType2.symbols b/tests/baselines/reference/jsdocImportType2.symbols new file mode 100644 index 00000000000..e67d250ca3d --- /dev/null +++ b/tests/baselines/reference/jsdocImportType2.symbols @@ -0,0 +1,54 @@ +=== tests/cases/conformance/jsdoc/use.js === +/// +/** @typedef {import("./mod1")} C + * @type {C} */ +var c; +>c : Symbol(c, Decl(use.js, 3, 3)) + +c.chunk; +>c.chunk : Symbol(Chunk.chunk, Decl(mod1.js, 2, 19)) +>c : Symbol(c, Decl(use.js, 3, 3)) +>chunk : Symbol(Chunk.chunk, Decl(mod1.js, 2, 19)) + +const D = require("./mod1"); +>D : Symbol(D, Decl(use.js, 6, 5)) +>require : Symbol(require, Decl(types.d.ts, 0, 0)) +>"./mod1" : Symbol("tests/cases/conformance/jsdoc/mod1", Decl(mod1.js, 0, 0)) + +/** @type {D} */ +var d; +>d : Symbol(d, Decl(use.js, 8, 3)) + +d.chunk; +>d.chunk : Symbol(Chunk.chunk, Decl(mod1.js, 2, 19)) +>d : Symbol(d, Decl(use.js, 8, 3)) +>chunk : Symbol(Chunk.chunk, Decl(mod1.js, 2, 19)) + +=== tests/cases/conformance/jsdoc/types.d.ts === +declare function require(name: string): any; +>require : Symbol(require, Decl(types.d.ts, 0, 0)) +>name : Symbol(name, Decl(types.d.ts, 0, 25)) + +declare var exports: any; +>exports : Symbol(exports, Decl(types.d.ts, 1, 11)) + +declare var module: { exports: any }; +>module : Symbol(module, Decl(types.d.ts, 2, 11)) +>exports : Symbol(exports, Decl(types.d.ts, 2, 21)) + +=== tests/cases/conformance/jsdoc/mod1.js === +/// +module.exports = class Chunk { +>module.exports : Symbol(exports, Decl(types.d.ts, 2, 21)) +>module : Symbol(export=, Decl(mod1.js, 0, 0)) +>exports : Symbol(export=, Decl(mod1.js, 0, 0)) +>Chunk : Symbol(Chunk, Decl(mod1.js, 1, 16)) + + constructor() { + this.chunk = 1; +>this.chunk : Symbol(Chunk.chunk, Decl(mod1.js, 2, 19)) +>this : Symbol(Chunk, Decl(mod1.js, 1, 16)) +>chunk : Symbol(Chunk.chunk, Decl(mod1.js, 2, 19)) + } +} + diff --git a/tests/baselines/reference/jsdocImportType2.types b/tests/baselines/reference/jsdocImportType2.types new file mode 100644 index 00000000000..c0dfb2d925a --- /dev/null +++ b/tests/baselines/reference/jsdocImportType2.types @@ -0,0 +1,59 @@ +=== tests/cases/conformance/jsdoc/use.js === +/// +/** @typedef {import("./mod1")} C + * @type {C} */ +var c; +>c : Chunk + +c.chunk; +>c.chunk : number +>c : Chunk +>chunk : number + +const D = require("./mod1"); +>D : typeof Chunk +>require("./mod1") : typeof Chunk +>require : (name: string) => any +>"./mod1" : "./mod1" + +/** @type {D} */ +var d; +>d : Chunk + +d.chunk; +>d.chunk : number +>d : Chunk +>chunk : number + +=== tests/cases/conformance/jsdoc/types.d.ts === +declare function require(name: string): any; +>require : (name: string) => any +>name : string + +declare var exports: any; +>exports : any + +declare var module: { exports: any }; +>module : { exports: any; } +>exports : any + +=== tests/cases/conformance/jsdoc/mod1.js === +/// +module.exports = class Chunk { +>module.exports = class Chunk { constructor() { this.chunk = 1; }} : typeof Chunk +>module.exports : any +>module : { exports: any; } +>exports : any +>class Chunk { constructor() { this.chunk = 1; }} : typeof Chunk +>Chunk : typeof Chunk + + constructor() { + this.chunk = 1; +>this.chunk = 1 : 1 +>this.chunk : number +>this : this +>chunk : number +>1 : 1 + } +} + diff --git a/tests/baselines/reference/moduleExportWithExportPropertyAssignment4.symbols b/tests/baselines/reference/moduleExportWithExportPropertyAssignment4.symbols index b62a68c83f3..e7cbcfa0828 100644 --- a/tests/baselines/reference/moduleExportWithExportPropertyAssignment4.symbols +++ b/tests/baselines/reference/moduleExportWithExportPropertyAssignment4.symbols @@ -13,14 +13,14 @@ mod1.justExport.toFixed() >toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) mod1.bothBefore.toFixed() // error ->mod1.bothBefore : Symbol(bothBefore) +>mod1.bothBefore : Symbol(A.bothBefore, Decl(mod1.js, 2, 16), Decl(mod1.js, 0, 0)) >mod1 : Symbol(mod1, Decl(a.js, 1, 3)) ->bothBefore : Symbol(bothBefore) +>bothBefore : Symbol(A.bothBefore, Decl(mod1.js, 2, 16), Decl(mod1.js, 0, 0)) mod1.bothAfter.toFixed() ->mod1.bothAfter : Symbol(bothAfter) +>mod1.bothAfter : Symbol(A.bothAfter, Decl(mod1.js, 3, 16), Decl(mod1.js, 8, 1)) >mod1 : Symbol(mod1, Decl(a.js, 1, 3)) ->bothAfter : Symbol(bothAfter) +>bothAfter : Symbol(A.bothAfter, Decl(mod1.js, 3, 16), Decl(mod1.js, 8, 1)) mod1.justProperty.length >mod1.justProperty.length : Symbol(String.length, Decl(lib.d.ts, --, --)) @@ -41,10 +41,10 @@ declare function require(name: string): any; === tests/cases/conformance/salsa/mod1.js === /// module.exports.bothBefore = 'string' ->module.exports : Symbol(bothBefore, Decl(mod1.js, 0, 0)) +>module.exports : Symbol(A.bothBefore, Decl(mod1.js, 2, 16), Decl(mod1.js, 0, 0)) >module : Symbol(module, Decl(requires.d.ts, 0, 11)) >exports : Symbol(exports, Decl(requires.d.ts, 0, 21)) ->bothBefore : Symbol(bothBefore, Decl(mod1.js, 0, 0)) +>bothBefore : Symbol(A.bothBefore, Decl(mod1.js, 2, 16), Decl(mod1.js, 0, 0)) A.justExport = 4 >A.justExport : Symbol(A.justExport, Decl(mod1.js, 1, 36)) @@ -74,10 +74,10 @@ function A() { >p : Symbol(A.p, Decl(mod1.js, 6, 14)) } module.exports.bothAfter = 'string' ->module.exports : Symbol(bothAfter, Decl(mod1.js, 8, 1)) +>module.exports : Symbol(A.bothAfter, Decl(mod1.js, 3, 16), Decl(mod1.js, 8, 1)) >module : Symbol(module, Decl(requires.d.ts, 0, 11)) >exports : Symbol(exports, Decl(requires.d.ts, 0, 21)) ->bothAfter : Symbol(bothAfter, Decl(mod1.js, 8, 1)) +>bothAfter : Symbol(A.bothAfter, Decl(mod1.js, 3, 16), Decl(mod1.js, 8, 1)) module.exports.justProperty = 'string' >module.exports : Symbol(justProperty, Decl(mod1.js, 9, 35)) diff --git a/tests/cases/compiler/commonJsImportClassExpression.ts b/tests/cases/compiler/commonJsImportClassExpression.ts new file mode 100644 index 00000000000..1cd856d4b1b --- /dev/null +++ b/tests/cases/compiler/commonJsImportClassExpression.ts @@ -0,0 +1,9 @@ +// @Filename: mod1.ts +export = class { + chunk = 1 +} + +// @Filename: use.ts +import Chunk = require('./mod1') +declare var c: Chunk; +c.chunk; diff --git a/tests/cases/conformance/jsdoc/jsdocImportType.ts b/tests/cases/conformance/jsdoc/jsdocImportType.ts new file mode 100644 index 00000000000..7b960601dc7 --- /dev/null +++ b/tests/cases/conformance/jsdoc/jsdocImportType.ts @@ -0,0 +1,27 @@ +// @allowJs: true +// @checkJs: true +// @noEmit: true +// @Filename: types.d.ts +declare function require(name: string): any; +declare var exports: any; +declare var module: { exports: any }; +// @Filename: mod1.js +/// +class Chunk { + constructor() { + this.chunk = 1; + } +} +module.exports = Chunk; + +// @Filename: use.js +/// +/** @typedef {import("./mod1")} C + * @type {C} */ +var c; +c.chunk; + +const D = require("./mod1"); +/** @type {D} */ +var d; +d.chunk; diff --git a/tests/cases/conformance/jsdoc/jsdocImportType2.ts b/tests/cases/conformance/jsdoc/jsdocImportType2.ts new file mode 100644 index 00000000000..98ffc506144 --- /dev/null +++ b/tests/cases/conformance/jsdoc/jsdocImportType2.ts @@ -0,0 +1,26 @@ +// @allowJs: true +// @checkJs: true +// @noEmit: true +// @Filename: types.d.ts +declare function require(name: string): any; +declare var exports: any; +declare var module: { exports: any }; +// @Filename: mod1.js +/// +module.exports = class Chunk { + constructor() { + this.chunk = 1; + } +} + +// @Filename: use.js +/// +/** @typedef {import("./mod1")} C + * @type {C} */ +var c; +c.chunk; + +const D = require("./mod1"); +/** @type {D} */ +var d; +d.chunk; diff --git a/tests/cases/fourslash/findAllRefsClassExpression0.ts b/tests/cases/fourslash/findAllRefsClassExpression0.ts index 50abfae0230..e8d4aa671a3 100644 --- a/tests/cases/fourslash/findAllRefsClassExpression0.ts +++ b/tests/cases/fourslash/findAllRefsClassExpression0.ts @@ -11,6 +11,6 @@ const [r0, r1, r2, r3] = test.ranges(); const defs = { definition: "(local class) A", ranges: [r0, r1] }; -const imports = { definition: 'import A = require("./a")', ranges: [r2, r3] }; +const imports = { definition: '(alias) (local class) A\nimport A = require("./a")', ranges: [r2, r3] }; verify.referenceGroups([r0, r1], [defs, imports]); verify.referenceGroups([r2, r3], [imports, defs]); diff --git a/tests/cases/fourslash/findAllRefsClassExpression1.ts b/tests/cases/fourslash/findAllRefsClassExpression1.ts index bd581871842..64aad512a5e 100644 --- a/tests/cases/fourslash/findAllRefsClassExpression1.ts +++ b/tests/cases/fourslash/findAllRefsClassExpression1.ts @@ -11,7 +11,7 @@ const [r0, r1, r2] = test.ranges(); const defs = { definition: "(local class) A", ranges: [r0] }; -const imports = { definition: 'import A = require("./a")', ranges: [r1, r2] }; +const imports = { definition: '(alias) (local class) A\nimport A = require("./a")', ranges: [r1, r2] }; verify.referenceGroups([r0], [defs, imports]); verify.referenceGroups([r1, r2], [imports, defs]);