diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 65335117cf2..e2f832c9580 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1207,7 +1207,7 @@ namespace ts { } // Resolves a qualified name and any involved aliases - function resolveEntityName(name: EntityName | Expression, meaning: SymbolFlags, ignoreErrors?: boolean, dontResolveAlias?: boolean): Symbol { + function resolveEntityName(name: EntityName | Expression, meaning: SymbolFlags, ignoreErrors = false, dontResolveAlias = false): Symbol { if (nodeIsMissing(name)) { return undefined; } @@ -16873,10 +16873,7 @@ namespace ts { return getIntrinsicTagSymbol(entityName.parent); } - // Include aliases in the meaning, this ensures that we do not follow aliases to where they point and instead - // return the alias symbol. - const meaning: SymbolFlags = SymbolFlags.Value | SymbolFlags.Alias; - return resolveEntityName(entityName, meaning); + return resolveEntityName(entityName, SymbolFlags.Value, /*ignoreErrors*/ false, /*dontResolveAlias*/ true); } else if (entityName.kind === SyntaxKind.PropertyAccessExpression) { const symbol = getNodeLinks(entityName).resolvedSymbol; @@ -16894,11 +16891,8 @@ namespace ts { } } else if (isTypeReferenceIdentifier(entityName)) { - let meaning = (entityName.parent.kind === SyntaxKind.TypeReference || entityName.parent.kind === SyntaxKind.JSDocTypeReference) ? SymbolFlags.Type : SymbolFlags.Namespace; - // Include aliases in the meaning, this ensures that we do not follow aliases to where they point and instead - // return the alias symbol. - meaning |= SymbolFlags.Alias; - return resolveEntityName(entityName, meaning); + const meaning = (entityName.parent.kind === SyntaxKind.TypeReference || entityName.parent.kind === SyntaxKind.JSDocTypeReference) ? SymbolFlags.Type : SymbolFlags.Namespace; + return resolveEntityName(entityName, meaning, /*ignoreErrors*/ false, /*dontResolveAlias*/true); } else if (entityName.parent.kind === SyntaxKind.JsxAttribute) { return getJsxAttributePropertySymbol(entityName.parent); diff --git a/tests/cases/fourslash/quickInfoMeaning.ts b/tests/cases/fourslash/quickInfoMeaning.ts new file mode 100644 index 00000000000..51b17337486 --- /dev/null +++ b/tests/cases/fourslash/quickInfoMeaning.ts @@ -0,0 +1,67 @@ +/// + +// Testing that quickInfo gets information with a corresponding meaning: values to values, types to types. +// For quick info purposes, we don't resolve past aliases. +// However, when we have an alias for a type, the quickInfo for a value with the same should skip the alias, and vice versa. +// goToDefinition should work the same way. + +// @Filename: foo.d.ts +////declare const /*foo_value_declaration*/foo: number; +////declare module "foo_module" { +//// interface I { x: number; y: number } +//// export = I; +////} + +// @Filename: foo_user.ts +/////// +/////*foo_type_declaration*/import foo = require("foo_module"); +////const x = foo/*foo_value*/; +////const i: foo/*foo_type*/ = { x: 1, y: 2 }; + +verify.numberOfErrorsInCurrentFile(0); + +verify.navigationItemsListCount(2, "foo", "exact"); +verify.navigationItemsListContains("foo", "alias", "foo", "exact"); +verify.navigationItemsListContains("foo", "const", "foo", "exact"); + +goTo.marker("foo_value"); +verify.quickInfoIs("const foo: number"); +goTo.definition(); +verify.caretAtMarker("foo_value_declaration"); + +goTo.marker("foo_type"); +verify.quickInfoIs("import foo = require(\"foo_module\")"); +goTo.definition(); +verify.caretAtMarker("foo_type_declaration"); + + +// Above tested for global const and imported interface. Now test with global interface and imported const. + + +// @Filename: bar.d.ts +/////*bar_type_declaration*/declare interface bar { x: number; y: number } +////declare module "bar_module" { +//// const x: number; +//// export = x; +////} + +// @Filename: bar_user.ts +/////// +/////*bar_value_declaration*/import bar = require("bar_module"); +////const x = bar/*bar_value*/; +////const i: bar/*bar_type*/ = { x: 1, y: 2 }; + +verify.numberOfErrorsInCurrentFile(0); +verify.navigationItemsListCount(2, "bar", "exact"); +verify.navigationItemsListContains("bar", "alias", "bar", "exact"); +verify.navigationItemsListContains("bar", "interface", "bar", "exact"); + +goTo.marker("bar_value"); +verify.quickInfoIs("import bar = require(\"bar_module\")"); +goTo.definition(); +verify.caretAtMarker("bar_value_declaration"); + +goTo.marker("bar_type"); +verify.quickInfoIs("interface bar"); +goTo.definition(); +verify.caretAtMarker("bar_type_declaration");