fix inlay hints for template literal type (#56309)

This commit is contained in:
Zzzen
2023-11-28 13:34:33 -08:00
committed by GitHub
parent e98ae5a5c4
commit c250aed310
4 changed files with 181 additions and 6 deletions
+2 -1
View File
@@ -5823,7 +5823,8 @@ export function createDiagnosticCollection(): DiagnosticCollection {
}
const templateSubstitutionRegExp = /\$\{/g;
function escapeTemplateSubstitution(str: string): string {
/** @internal */
export function escapeTemplateSubstitution(str: string): string {
return str.replace(templateSubstitutionRegExp, "\\${");
}
+47 -5
View File
@@ -11,6 +11,7 @@ import {
EnumMember,
equateStringsCaseInsensitive,
escapeString,
escapeTemplateSubstitution,
Expression,
findChildOfKind,
findIndex,
@@ -76,7 +77,11 @@ import {
isQualifiedName,
isRestTypeNode,
isSpreadElement,
isStringLiteral,
isTemplateHead,
isTemplateLiteralTypeNode,
isTemplateLiteralTypeSpan,
isTemplateMiddle,
isTemplateTail,
isThisTypeNode,
isTupleTypeNode,
isTypeLiteralNode,
@@ -89,7 +94,7 @@ import {
isUnionTypeNode,
isVarConst,
isVariableDeclaration,
LiteralExpression,
LiteralLikeNode,
MethodDeclaration,
NewExpression,
Node,
@@ -106,6 +111,7 @@ import {
Symbol,
SymbolFlags,
SyntaxKind,
TemplateLiteralLikeNode,
textSpanIntersectsWith,
tokenToString,
TupleTypeReference,
@@ -793,6 +799,28 @@ export function provideInlayHints(context: InlayHintsContext): InlayHint[] {
parts.push({ text: tokenToString(node.operator) });
visitForDisplayParts(node.operand);
break;
case SyntaxKind.TemplateLiteralType:
Debug.assertNode(node, isTemplateLiteralTypeNode);
visitForDisplayParts(node.head);
node.templateSpans.forEach(visitForDisplayParts);
break;
case SyntaxKind.TemplateHead:
Debug.assertNode(node, isTemplateHead);
parts.push({ text: getLiteralText(node) });
break;
case SyntaxKind.TemplateLiteralTypeSpan:
Debug.assertNode(node, isTemplateLiteralTypeSpan);
visitForDisplayParts(node.type);
visitForDisplayParts(node.literal);
break;
case SyntaxKind.TemplateMiddle:
Debug.assertNode(node, isTemplateMiddle);
parts.push({ text: getLiteralText(node) });
break;
case SyntaxKind.TemplateTail:
Debug.assertNode(node, isTemplateTail);
parts.push({ text: getLiteralText(node) });
break;
case SyntaxKind.ThisType:
Debug.assertNode(node, isThisTypeNode);
parts.push({ text: "this" });
@@ -828,9 +856,23 @@ export function provideInlayHints(context: InlayHintsContext): InlayHint[] {
});
}
function getLiteralText(node: LiteralExpression) {
if (isStringLiteral(node)) {
return quotePreference === QuotePreference.Single ? `'${escapeString(node.text, CharacterCodes.singleQuote)}'` : `"${escapeString(node.text, CharacterCodes.doubleQuote)}"`;
function getLiteralText(node: LiteralLikeNode) {
switch (node.kind) {
case SyntaxKind.StringLiteral:
return quotePreference === QuotePreference.Single ? `'${escapeString(node.text, CharacterCodes.singleQuote)}'` : `"${escapeString(node.text, CharacterCodes.doubleQuote)}"`;
case SyntaxKind.TemplateHead:
case SyntaxKind.TemplateMiddle:
case SyntaxKind.TemplateTail: {
const rawText = (node as TemplateLiteralLikeNode).rawText ?? escapeTemplateSubstitution(escapeString(node.text, CharacterCodes.backtick));
switch (node.kind) {
case SyntaxKind.TemplateHead:
return "`" + rawText + "${";
case SyntaxKind.TemplateMiddle:
return "}" + rawText + "${";
case SyntaxKind.TemplateTail:
return "}" + rawText + "`";
}
}
}
return node.text;
}