From 06774962eda2abc72115f25018e2be9aac3371e4 Mon Sep 17 00:00:00 2001 From: Andy Date: Wed, 5 Sep 2018 11:19:32 -0700 Subject: [PATCH] Properly handle JS enum symbols (#26893) --- src/compiler/binder.ts | 11 +++++---- src/compiler/checker.ts | 10 +++++---- tests/cases/fourslash/quickInfoJsdocEnum.ts | 25 +++++++++++++++++++++ 3 files changed, 36 insertions(+), 10 deletions(-) create mode 100644 tests/cases/fourslash/quickInfoJsdocEnum.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 1fe5605b498..5e7ce50a86f 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1731,10 +1731,6 @@ namespace ts { } } - function bindBlockScopedVariableDeclaration(node: Declaration) { - bindBlockScopedDeclaration(node, SymbolFlags.BlockScopedVariable, SymbolFlags.BlockScopedVariableExcludes); - } - function delayedBindJSDocTypedefTag() { if (!delayedTypeAliases) { return; @@ -2659,8 +2655,11 @@ namespace ts { } if (!isBindingPattern(node.name)) { + const isEnum = !!getJSDocEnumTag(node); + const enumFlags = (isEnum ? SymbolFlags.RegularEnum : SymbolFlags.None); + const enumExcludes = (isEnum ? SymbolFlags.RegularEnumExcludes : SymbolFlags.None); if (isBlockOrCatchScoped(node)) { - bindBlockScopedVariableDeclaration(node); + bindBlockScopedDeclaration(node, SymbolFlags.BlockScopedVariable | enumFlags, SymbolFlags.BlockScopedVariableExcludes | enumExcludes); } else if (isParameterDeclaration(node)) { // It is safe to walk up parent chain to find whether the node is a destructuring parameter declaration @@ -2675,7 +2674,7 @@ namespace ts { declareSymbolAndAddToSymbolTable(node, SymbolFlags.FunctionScopedVariable, SymbolFlags.ParameterExcludes); } else { - declareSymbolAndAddToSymbolTable(node, SymbolFlags.FunctionScopedVariable, SymbolFlags.FunctionScopedVariableExcludes); + declareSymbolAndAddToSymbolTable(node, SymbolFlags.FunctionScopedVariable | enumFlags, SymbolFlags.FunctionScopedVariableExcludes | enumExcludes); } } } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ec880fc0cc4..efe1061a531 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8208,6 +8208,12 @@ namespace ts { return type; } + // JS are 'string' or 'number', not an enum type. + const enumTag = symbol.valueDeclaration && getJSDocEnumTag(symbol.valueDeclaration); + if (enumTag) { + return enumTag.typeExpression ? getTypeFromTypeNode(enumTag.typeExpression) : errorType; + } + // Get type from reference to named type that cannot be generic (enum or type parameter) const res = tryGetDeclaredTypeOfSymbol(symbol); if (res) { @@ -8243,10 +8249,6 @@ namespace ts { // TODO: GH#18217 (should the `|| assignedType` be at a lower precedence?) return (referenceType && assignedType ? getIntersectionType([assignedType, referenceType]) : referenceType || assignedType)!; } - const enumTag = getJSDocEnumTag(symbol.valueDeclaration); - if (enumTag && enumTag.typeExpression) { - return getTypeFromTypeNode(enumTag.typeExpression); - } } function getTypeReferenceTypeWorker(node: NodeWithTypeArguments, symbol: Symbol, typeArguments: Type[] | undefined): Type | undefined { diff --git a/tests/cases/fourslash/quickInfoJsdocEnum.ts b/tests/cases/fourslash/quickInfoJsdocEnum.ts new file mode 100644 index 00000000000..de67cacc7d2 --- /dev/null +++ b/tests/cases/fourslash/quickInfoJsdocEnum.ts @@ -0,0 +1,25 @@ +/// + +// @allowJs: true +// @noLib: true + +// @Filename: /a.js +/////** +//// * Doc +//// * @enum {number} +//// */ +////const E = { +//// A: 0, +////} +//// +/////** @type {/**/E} */ +////const x = E.A; + +verify.noErrors(); + +verify.quickInfoAt("", +`enum E +const E: { + A: number; +}`, +"Doc");