From 888ebf4b2d266760f2b47c4213111a7cebfe09fd Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Mon, 24 Feb 2020 15:30:16 -0800 Subject: [PATCH] Fix crash on aliased,exported @enum tag in jsdoc THe code to bind `@enum` and `@typedef` didn't handle the case that the `@enum` was on a property assignment to an alias of module.exports. Specifically, `x` needs to be correctly aliased to the file's symbol in the example below: ``` var x = module.exports = {}; /** @enum {string} */ x.E = { A: "A" }; ``` --- src/compiler/binder.ts | 4 +++- .../reference/exportedAliasedEnumTag.symbols | 18 +++++++++++++++ .../reference/exportedAliasedEnumTag.types | 23 +++++++++++++++++++ .../jsdoc/exportedAliasedEnumTag.ts | 9 ++++++++ 4 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/exportedAliasedEnumTag.symbols create mode 100644 tests/baselines/reference/exportedAliasedEnumTag.types create mode 100644 tests/cases/conformance/jsdoc/exportedAliasedEnumTag.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 817c5122199a0..2be7c657093c7 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -2113,7 +2113,9 @@ namespace ts { container = (declName.parent.expression as PropertyAccessExpression).name; break; case AssignmentDeclarationKind.Property: - container = isPropertyAccessExpression(declName.parent.expression) ? declName.parent.expression.name : declName.parent.expression; + container = isExportsOrModuleExportsOrAlias(file, declName.parent.expression) ? file + : isPropertyAccessExpression(declName.parent.expression) ? declName.parent.expression.name + : declName.parent.expression; break; case AssignmentDeclarationKind.None: return Debug.fail("Shouldn't have detected typedef or enum on non-assignment declaration"); diff --git a/tests/baselines/reference/exportedAliasedEnumTag.symbols b/tests/baselines/reference/exportedAliasedEnumTag.symbols new file mode 100644 index 0000000000000..81cc69aa7e0e4 --- /dev/null +++ b/tests/baselines/reference/exportedAliasedEnumTag.symbols @@ -0,0 +1,18 @@ +=== tests/cases/conformance/jsdoc/exportedAliasedEnumTag.js === +var middlewarify = module.exports = {}; +>middlewarify : Symbol(middlewarify, Decl(exportedAliasedEnumTag.js, 0, 3)) +>module.exports : Symbol("tests/cases/conformance/jsdoc/exportedAliasedEnumTag", Decl(exportedAliasedEnumTag.js, 0, 0)) +>module : Symbol(module, Decl(exportedAliasedEnumTag.js, 0, 18)) +>exports : Symbol("tests/cases/conformance/jsdoc/exportedAliasedEnumTag", Decl(exportedAliasedEnumTag.js, 0, 0)) + +/** @enum */ +middlewarify.Type = { +>middlewarify.Type : Symbol(Type, Decl(exportedAliasedEnumTag.js, 0, 39), Decl(exportedAliasedEnumTag.js, 3, 13), Decl(exportedAliasedEnumTag.js, 2, 4)) +>middlewarify : Symbol(middlewarify, Decl(exportedAliasedEnumTag.js, 0, 3)) +>Type : Symbol(Type, Decl(exportedAliasedEnumTag.js, 0, 39), Decl(exportedAliasedEnumTag.js, 3, 13), Decl(exportedAliasedEnumTag.js, 2, 4)) + + BEFORE: 'before' +>BEFORE : Symbol(BEFORE, Decl(exportedAliasedEnumTag.js, 3, 21)) + +}; + diff --git a/tests/baselines/reference/exportedAliasedEnumTag.types b/tests/baselines/reference/exportedAliasedEnumTag.types new file mode 100644 index 0000000000000..b4c14bc52b2ab --- /dev/null +++ b/tests/baselines/reference/exportedAliasedEnumTag.types @@ -0,0 +1,23 @@ +=== tests/cases/conformance/jsdoc/exportedAliasedEnumTag.js === +var middlewarify = module.exports = {}; +>middlewarify : typeof import("tests/cases/conformance/jsdoc/exportedAliasedEnumTag") +>module.exports = {} : typeof import("tests/cases/conformance/jsdoc/exportedAliasedEnumTag") +>module.exports : typeof import("tests/cases/conformance/jsdoc/exportedAliasedEnumTag") +>module : { "\"tests/cases/conformance/jsdoc/exportedAliasedEnumTag\"": typeof import("tests/cases/conformance/jsdoc/exportedAliasedEnumTag"); } +>exports : typeof import("tests/cases/conformance/jsdoc/exportedAliasedEnumTag") +>{} : {} + +/** @enum */ +middlewarify.Type = { +>middlewarify.Type = { BEFORE: 'before'} : { BEFORE: string; } +>middlewarify.Type : { BEFORE: string; } +>middlewarify : typeof import("tests/cases/conformance/jsdoc/exportedAliasedEnumTag") +>Type : { BEFORE: string; } +>{ BEFORE: 'before'} : { BEFORE: string; } + + BEFORE: 'before' +>BEFORE : string +>'before' : "before" + +}; + diff --git a/tests/cases/conformance/jsdoc/exportedAliasedEnumTag.ts b/tests/cases/conformance/jsdoc/exportedAliasedEnumTag.ts new file mode 100644 index 0000000000000..e2916ea8b2277 --- /dev/null +++ b/tests/cases/conformance/jsdoc/exportedAliasedEnumTag.ts @@ -0,0 +1,9 @@ +// @noemit: true +// @allowjs: true +// @filename: exportedAliasedEnumTag.js +var middlewarify = module.exports = {}; + +/** @enum */ +middlewarify.Type = { + BEFORE: 'before' +};