Fixed quick info display for aliased symbols in type-narrowed locations (#54763)

This commit is contained in:
Mateusz Burzyński 2023-07-20 22:55:23 +02:00 committed by GitHub
parent 2136bef652
commit b211fe9792
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 29 additions and 7 deletions

View File

@ -254,10 +254,8 @@ export interface SymbolDisplayPartsDocumentationAndSymbolKind {
tags: JSDocTagInfo[] | undefined;
}
// TODO(drosen): Currently completion entry details passes the SemanticMeaning.All instead of using semanticMeaning of location
/** @internal */
export function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker: TypeChecker, symbol: Symbol, sourceFile: SourceFile, enclosingDeclaration: Node | undefined,
location: Node, semanticMeaning = getMeaningFromLocation(location), alias?: Symbol): SymbolDisplayPartsDocumentationAndSymbolKind {
function getSymbolDisplayPartsDocumentationAndSymbolKindWorker(typeChecker: TypeChecker, symbol: Symbol, sourceFile: SourceFile, enclosingDeclaration: Node | undefined,
location: Node, type: Type | undefined, semanticMeaning: SemanticMeaning, alias?: Symbol): SymbolDisplayPartsDocumentationAndSymbolKind {
const displayParts: SymbolDisplayPart[] = [];
let documentation: SymbolDisplayPart[] = [];
let tags: JSDocTagInfo[] = [];
@ -265,7 +263,6 @@ export function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker: Typ
let symbolKind = semanticMeaning & SemanticMeaning.Value ? getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeChecker, symbol, location) : ScriptElementKind.unknown;
let hasAddedSymbolInfo = false;
const isThisExpression = location.kind === SyntaxKind.ThisKeyword && isInExpressionContext(location) || isThisInTypeQuery(location);
let type: Type | undefined;
let documentationFromAlias: SymbolDisplayPart[] | undefined;
let tagsFromAlias: JSDocTagInfo[] | undefined;
let hasMultipleSignatures = false;
@ -300,7 +297,7 @@ export function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker: Typ
}
let signature: Signature | undefined;
type = isThisExpression ? typeChecker.getTypeAtLocation(location) : typeChecker.getTypeOfSymbolAtLocation(symbol, location);
type ??= isThisExpression ? typeChecker.getTypeAtLocation(location) : typeChecker.getTypeOfSymbolAtLocation(symbol, location);
if (location.parent && location.parent.kind === SyntaxKind.PropertyAccessExpression) {
const right = (location.parent as PropertyAccessExpression).name;
@ -553,12 +550,13 @@ export function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker: Typ
isModuleWithStringLiteralName(resolvedNode) &&
hasSyntacticModifier(resolvedNode, ModifierFlags.Ambient);
const shouldUseAliasName = symbol.name !== "default" && !isExternalModuleDeclaration;
const resolvedInfo = getSymbolDisplayPartsDocumentationAndSymbolKind(
const resolvedInfo = getSymbolDisplayPartsDocumentationAndSymbolKindWorker(
typeChecker,
resolvedSymbol,
getSourceFileOfNode(resolvedNode),
resolvedNode,
declarationName,
type,
semanticMeaning,
shouldUseAliasName ? symbol : resolvedSymbol);
displayParts.push(...resolvedInfo.displayParts);
@ -858,6 +856,13 @@ export function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker: Typ
}
}
// TODO(drosen): Currently completion entry details passes the SemanticMeaning.All instead of using semanticMeaning of location
/** @internal */
export function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker: TypeChecker, symbol: Symbol, sourceFile: SourceFile, enclosingDeclaration: Node | undefined,
location: Node, semanticMeaning = getMeaningFromLocation(location), alias?: Symbol): SymbolDisplayPartsDocumentationAndSymbolKind {
return getSymbolDisplayPartsDocumentationAndSymbolKindWorker(typeChecker, symbol, sourceFile, enclosingDeclaration, location, /*type*/ undefined, semanticMeaning, alias);
}
function isLocalVariableOrFunction(symbol: Symbol) {
if (symbol.parent) {
return false; // This is exported symbol

View File

@ -0,0 +1,17 @@
/// <reference path='fourslash.ts' />
// @strict: true
// @Filename: modules.ts
//// export declare const someEnv: string | undefined;
// @Filename: app.ts
//// import { someEnv } from "./modules";
//// declare function isString(v: any): v is string;
////
//// if (isString(someEnv)) {
//// someEnv/*1*/.charAt(0);
//// }
goTo.file("app.ts");
goTo.marker("1");
verify.quickInfoIs(`(alias) const someEnv: string\nimport someEnv`);