From c344a3ea5b6bacf4ecc5b5ca77c2319a2fed05de Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Tue, 10 Jul 2018 08:33:19 -0700 Subject: [PATCH] Fix bogus use before def in jsdoc (#25532) Block scoped variables, classes and enums would issue a bogus use-before-def error in jsdoc because name resolution always adds Value, even when resolving a type. Fixes #25097 --- src/compiler/checker.ts | 3 ++- .../reference/jsdocTypeReferenceUseBeforeDef.symbols | 9 +++++++++ .../reference/jsdocTypeReferenceUseBeforeDef.types | 10 ++++++++++ .../jsdoc/jsdocTypeReferenceUseBeforeDef.ts | 8 ++++++++ 4 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/jsdocTypeReferenceUseBeforeDef.symbols create mode 100644 tests/baselines/reference/jsdocTypeReferenceUseBeforeDef.types create mode 100644 tests/cases/conformance/jsdoc/jsdocTypeReferenceUseBeforeDef.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 3ddf460f80f..2e48c4ca1bc 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1059,6 +1059,7 @@ namespace ts { // 5. inside a TS export= declaration (since we will move the export statement during emit to avoid TDZ) // or if usage is in a type context: // 1. inside a type query (typeof in type position) + // 2. inside a jsdoc comment if (usage.parent.kind === SyntaxKind.ExportSpecifier || (usage.parent.kind === SyntaxKind.ExportAssignment && (usage.parent as ExportAssignment).isExportEquals)) { // export specifiers do not use the variable, they only make it available for use return true; @@ -1069,7 +1070,7 @@ namespace ts { } const container = getEnclosingBlockScopeContainer(declaration); - return isInTypeQuery(usage) || isUsedInFunctionOrInstanceProperty(usage, declaration, container); + return !!(usage.flags & NodeFlags.JSDoc) || isInTypeQuery(usage) || isUsedInFunctionOrInstanceProperty(usage, declaration, container); function isImmediatelyUsedInInitializerOfBlockScopedVariable(declaration: VariableDeclaration, usage: Node): boolean { const container = getEnclosingBlockScopeContainer(declaration); diff --git a/tests/baselines/reference/jsdocTypeReferenceUseBeforeDef.symbols b/tests/baselines/reference/jsdocTypeReferenceUseBeforeDef.symbols new file mode 100644 index 00000000000..798c892f520 --- /dev/null +++ b/tests/baselines/reference/jsdocTypeReferenceUseBeforeDef.symbols @@ -0,0 +1,9 @@ +=== tests/cases/conformance/jsdoc/bug25097.js === +/** @type {C | null} */ +const c = null +>c : Symbol(c, Decl(bug25097.js, 1, 5)) + +class C { +>C : Symbol(C, Decl(bug25097.js, 1, 14)) +} + diff --git a/tests/baselines/reference/jsdocTypeReferenceUseBeforeDef.types b/tests/baselines/reference/jsdocTypeReferenceUseBeforeDef.types new file mode 100644 index 00000000000..0a79a140c7d --- /dev/null +++ b/tests/baselines/reference/jsdocTypeReferenceUseBeforeDef.types @@ -0,0 +1,10 @@ +=== tests/cases/conformance/jsdoc/bug25097.js === +/** @type {C | null} */ +const c = null +>c : C +>null : null + +class C { +>C : C +} + diff --git a/tests/cases/conformance/jsdoc/jsdocTypeReferenceUseBeforeDef.ts b/tests/cases/conformance/jsdoc/jsdocTypeReferenceUseBeforeDef.ts new file mode 100644 index 00000000000..93e735e1fa6 --- /dev/null +++ b/tests/cases/conformance/jsdoc/jsdocTypeReferenceUseBeforeDef.ts @@ -0,0 +1,8 @@ +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @Filename: bug25097.js +/** @type {C | null} */ +const c = null +class C { +}