From ba1c0d92334d675fa8a5c8e7beebd7ede1cbf35a Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Wed, 26 Jul 2017 13:21:18 -0700 Subject: [PATCH 1/2] In services, show the aliasSymbol for a type even if it's not accessible in the current scope --- src/compiler/checker.ts | 10 +++++++--- src/compiler/types.ts | 2 ++ src/services/utilities.ts | 1 + .../quickInfoTypeAliasDefinedInDifferentFile.ts | 11 +++++++++++ 4 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 tests/cases/fourslash/quickInfoTypeAliasDefinedInDifferentFile.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2ff45ee0b737d..bdc72ab61b905 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2126,6 +2126,11 @@ namespace ts { return false; } + function isTypeSymbolAccessible(typeSymbol: Symbol, enclosingDeclaration: Node): boolean { + const access = isSymbolAccessible(typeSymbol, enclosingDeclaration, SymbolFlags.Type, /*shouldComputeAliasesToMakeVisible*/ false); + return access.accessibility === SymbolAccessibility.Accessible; + } + /** * Check if the given symbol in given enclosing declaration is accessible and mark all associated alias to be visible if requested * @@ -2456,8 +2461,7 @@ namespace ts { // Ignore constraint/default when creating a usage (as opposed to declaration) of a type parameter. return createTypeReferenceNode(name, /*typeArguments*/ undefined); } - if (!inTypeAlias && type.aliasSymbol && - isSymbolAccessible(type.aliasSymbol, context.enclosingDeclaration, SymbolFlags.Type, /*shouldComputeAliasesToMakeVisible*/ false).accessibility === SymbolAccessibility.Accessible) { + if (!inTypeAlias && type.aliasSymbol && isTypeSymbolAccessible(type.aliasSymbol, context.enclosingDeclaration)) { const name = symbolToTypeReferenceName(type.aliasSymbol); const typeArgumentNodes = mapToTypeNodes(type.aliasTypeArguments, context); return createTypeReferenceNode(name, typeArgumentNodes); @@ -3226,7 +3230,7 @@ namespace ts { buildSymbolDisplay(type.symbol, writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, nextFlags); } else if (!(flags & TypeFormatFlags.InTypeAlias) && type.aliasSymbol && - isSymbolAccessible(type.aliasSymbol, enclosingDeclaration, SymbolFlags.Type, /*shouldComputeAliasesToMakeVisible*/ false).accessibility === SymbolAccessibility.Accessible) { + ((flags & TypeFormatFlags.UseAliasEvenIfNotAccessible) || isTypeSymbolAccessible(type.aliasSymbol, enclosingDeclaration))) { const typeArguments = type.aliasTypeArguments; writeSymbolTypeReference(type.aliasSymbol, typeArguments, 0, length(typeArguments), nextFlags); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index f076f16f4be13..f61fda7a209f7 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2691,6 +2691,8 @@ namespace ts { AddUndefined = 1 << 13, // Add undefined to types of initialized, non-optional parameters WriteClassExpressionAsTypeLiteral = 1 << 14, // Write a type literal instead of (Anonymous class) InArrayType = 1 << 15, // Writing an array element type + UseAliasEvenIfNotAccessible = 1 << 16, // For a `type T = ... ` defined in a different file, write `T` instead of its value, + // even though `T` can't be accessed in the current scope. } export const enum SymbolFormatFlags { diff --git a/src/services/utilities.ts b/src/services/utilities.ts index a5b035154beae..987e8c77a2102 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1261,6 +1261,7 @@ namespace ts { } export function signatureToDisplayParts(typechecker: TypeChecker, signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags): SymbolDisplayPart[] { + flags |= TypeFormatFlags.UseAliasEvenIfNotAccessible; return mapToDisplayParts(writer => { typechecker.getSymbolDisplayBuilder().buildSignatureDisplay(signature, writer, enclosingDeclaration, flags); }); diff --git a/tests/cases/fourslash/quickInfoTypeAliasDefinedInDifferentFile.ts b/tests/cases/fourslash/quickInfoTypeAliasDefinedInDifferentFile.ts new file mode 100644 index 0000000000000..2597b5e888d3e --- /dev/null +++ b/tests/cases/fourslash/quickInfoTypeAliasDefinedInDifferentFile.ts @@ -0,0 +1,11 @@ +/// + +// @Filename: /a.ts +////export type X = { x: number }; +////export function f(x: X): void {} + +// @Filename: /b.ts +////import { f } from "./a"; +/////**/f({ x: 1 }); + +verify.quickInfoAt("", "(alias) f(x: X): void\nimport f"); From eec545333b9ae3959655e0d24c5537ba9c449364 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Mon, 14 Aug 2017 10:12:02 -0700 Subject: [PATCH 2/2] Rename flag --- src/compiler/checker.ts | 2 +- src/compiler/types.ts | 4 ++-- src/services/utilities.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index bdc72ab61b905..a7d5640bc9da4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3230,7 +3230,7 @@ namespace ts { buildSymbolDisplay(type.symbol, writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, nextFlags); } else if (!(flags & TypeFormatFlags.InTypeAlias) && type.aliasSymbol && - ((flags & TypeFormatFlags.UseAliasEvenIfNotAccessible) || isTypeSymbolAccessible(type.aliasSymbol, enclosingDeclaration))) { + ((flags & TypeFormatFlags.UseAliasDefinedOutsideCurrentScope) || isTypeSymbolAccessible(type.aliasSymbol, enclosingDeclaration))) { const typeArguments = type.aliasTypeArguments; writeSymbolTypeReference(type.aliasSymbol, typeArguments, 0, length(typeArguments), nextFlags); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index f61fda7a209f7..d66a135e7c0cb 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2691,8 +2691,8 @@ namespace ts { AddUndefined = 1 << 13, // Add undefined to types of initialized, non-optional parameters WriteClassExpressionAsTypeLiteral = 1 << 14, // Write a type literal instead of (Anonymous class) InArrayType = 1 << 15, // Writing an array element type - UseAliasEvenIfNotAccessible = 1 << 16, // For a `type T = ... ` defined in a different file, write `T` instead of its value, - // even though `T` can't be accessed in the current scope. + UseAliasDefinedOutsideCurrentScope = 1 << 16, // For a `type T = ... ` defined in a different file, write `T` instead of its value, + // even though `T` can't be accessed in the current scope. } export const enum SymbolFormatFlags { diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 987e8c77a2102..27215190db3fd 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1261,7 +1261,7 @@ namespace ts { } export function signatureToDisplayParts(typechecker: TypeChecker, signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags): SymbolDisplayPart[] { - flags |= TypeFormatFlags.UseAliasEvenIfNotAccessible; + flags |= TypeFormatFlags.UseAliasDefinedOutsideCurrentScope; return mapToDisplayParts(writer => { typechecker.getSymbolDisplayBuilder().buildSignatureDisplay(signature, writer, enclosingDeclaration, flags); });