From 6ec55478237c384f204215c5d4d4442baf0a8a0a Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Wed, 4 Oct 2023 20:52:01 +0300 Subject: [PATCH] fix(55945): Inlay hints don't work for bigint literals (#55947) --- src/services/inlayHints.ts | 27 ++++++++++----- ...nteractiveFunctionParameterTypes5.baseline | 16 +++++++++ .../inlayHintsInteractiveMultifile1.baseline | 2 +- .../inlayHintsQuotePreference1.baseline | 33 +++++++++++++++++++ .../inlayHintsQuotePreference2.baseline | 33 +++++++++++++++++++ ...HintsInteractiveFunctionParameterTypes5.ts | 9 +++++ .../fourslash/inlayHintsQuotePreference1.ts | 11 +++++++ .../fourslash/inlayHintsQuotePreference2.ts | 11 +++++++ 8 files changed, 133 insertions(+), 9 deletions(-) create mode 100644 tests/baselines/reference/inlayHintsInteractiveFunctionParameterTypes5.baseline create mode 100644 tests/baselines/reference/inlayHintsQuotePreference1.baseline create mode 100644 tests/baselines/reference/inlayHintsQuotePreference2.baseline create mode 100644 tests/cases/fourslash/inlayHintsInteractiveFunctionParameterTypes5.ts create mode 100644 tests/cases/fourslash/inlayHintsQuotePreference1.ts create mode 100644 tests/cases/fourslash/inlayHintsQuotePreference2.ts diff --git a/src/services/inlayHints.ts b/src/services/inlayHints.ts index 934bf0ca739..fffe89dac5f 100644 --- a/src/services/inlayHints.ts +++ b/src/services/inlayHints.ts @@ -3,6 +3,7 @@ import { ArrayTypeNode, ArrowFunction, CallExpression, + CharacterCodes, ConditionalTypeNode, ConstructorTypeNode, createPrinterWithRemoveComments, @@ -12,6 +13,7 @@ import { EmitHint, EnumMember, equateStringsCaseInsensitive, + escapeString, Expression, findChildOfKind, findIndex, @@ -26,6 +28,7 @@ import { getLanguageVariant, getLeadingCommentRanges, getNameOfDeclaration, + getQuotePreference, hasContextSensitiveParameters, Identifier, idText, @@ -59,9 +62,11 @@ import { isPropertyAccessExpression, isPropertyDeclaration, isSpreadElement, + isStringLiteral, isTypeNode, isVarConst, isVariableDeclaration, + LiteralExpression, LiteralTypeNode, MappedTypeNode, MethodDeclaration, @@ -70,7 +75,6 @@ import { Node, NodeArray, NodeBuilderFlags, - NumericLiteral, OptionalTypeNode, ParameterDeclaration, ParenthesizedTypeNode, @@ -78,11 +82,11 @@ import { PropertyDeclaration, PropertySignature, QualifiedName, + QuotePreference, RestTypeNode, Signature, skipParentheses, some, - StringLiteral, Symbol, SymbolFlags, SyntaxKind, @@ -125,6 +129,7 @@ export function provideInlayHints(context: InlayHintsContext): InlayHint[] { const { file, program, span, cancellationToken, preferences } = context; const sourceFileText = file.text; const compilerOptions = program.getCompilerOptions(); + const quotePreference = getQuotePreference(file, preferences); const checker = program.getTypeChecker(); const result: InlayHint[] = []; @@ -473,6 +478,11 @@ export function provideInlayHints(context: InlayHintsContext): InlayHint[] { return; } + if (isLiteralExpression(node)) { + parts.push({ text: getLiteralText(node) }); + return; + } + switch (node.kind) { case SyntaxKind.Identifier: const identifier = node as Identifier; @@ -485,12 +495,6 @@ export function provideInlayHints(context: InlayHintsContext): InlayHint[] { parts.push({ text: identifierText }); } break; - case SyntaxKind.NumericLiteral: - parts.push({ text: (node as NumericLiteral).text }); - break; - case SyntaxKind.StringLiteral: - parts.push({ text: `"${(node as StringLiteral).text}"` }); - break; case SyntaxKind.QualifiedName: const qualifiedName = node as QualifiedName; visitForDisplayParts(qualifiedName.left); @@ -749,6 +753,13 @@ export function provideInlayHints(context: InlayHintsContext): InlayHint[] { visitForDisplayParts(node); }); } + + function getLiteralText(node: LiteralExpression) { + if (isStringLiteral(node)) { + return quotePreference === QuotePreference.Single ? `'${escapeString(node.text, CharacterCodes.singleQuote)}'` : `"${escapeString(node.text, CharacterCodes.doubleQuote)}"`; + } + return node.text; + } } function isUndefined(name: __String) { diff --git a/tests/baselines/reference/inlayHintsInteractiveFunctionParameterTypes5.baseline b/tests/baselines/reference/inlayHintsInteractiveFunctionParameterTypes5.baseline new file mode 100644 index 00000000000..c4df79dc90d --- /dev/null +++ b/tests/baselines/reference/inlayHintsInteractiveFunctionParameterTypes5.baseline @@ -0,0 +1,16 @@ +export function fn(b = foo) {} + ^ +{ + "text": "", + "displayParts": [ + { + "text": ": " + }, + { + "text": "1n" + } + ], + "position": 40, + "kind": "Type", + "whitespaceBefore": true +} \ No newline at end of file diff --git a/tests/baselines/reference/inlayHintsInteractiveMultifile1.baseline b/tests/baselines/reference/inlayHintsInteractiveMultifile1.baseline index 809e9d6eda1..11f79a69320 100644 --- a/tests/baselines/reference/inlayHintsInteractiveMultifile1.baseline +++ b/tests/baselines/reference/inlayHintsInteractiveMultifile1.baseline @@ -60,7 +60,7 @@ function bar () { return import('./a') } "text": "import(" }, { - "text": "\"/a\"" + "text": "'/a'" }, { "text": ")" diff --git a/tests/baselines/reference/inlayHintsQuotePreference1.baseline b/tests/baselines/reference/inlayHintsQuotePreference1.baseline new file mode 100644 index 00000000000..a3bb747939b --- /dev/null +++ b/tests/baselines/reference/inlayHintsQuotePreference1.baseline @@ -0,0 +1,33 @@ +export function fn(a = a1, b = b1) {} + ^ +{ + "text": "", + "displayParts": [ + { + "text": ": " + }, + { + "text": "\"\\\"\"" + } + ], + "position": 64, + "kind": "Type", + "whitespaceBefore": true +} + +export function fn(a = a1, b = b1) {} + ^ +{ + "text": "", + "displayParts": [ + { + "text": ": " + }, + { + "text": "\"\\\\\"" + } + ], + "position": 72, + "kind": "Type", + "whitespaceBefore": true +} \ No newline at end of file diff --git a/tests/baselines/reference/inlayHintsQuotePreference2.baseline b/tests/baselines/reference/inlayHintsQuotePreference2.baseline new file mode 100644 index 00000000000..0084f769ce8 --- /dev/null +++ b/tests/baselines/reference/inlayHintsQuotePreference2.baseline @@ -0,0 +1,33 @@ +export function fn(a = a1, b = b1) {} + ^ +{ + "text": "", + "displayParts": [ + { + "text": ": " + }, + { + "text": "'\\''" + } + ], + "position": 64, + "kind": "Type", + "whitespaceBefore": true +} + +export function fn(a = a1, b = b1) {} + ^ +{ + "text": "", + "displayParts": [ + { + "text": ": " + }, + { + "text": "'\\\\'" + } + ], + "position": 72, + "kind": "Type", + "whitespaceBefore": true +} \ No newline at end of file diff --git a/tests/cases/fourslash/inlayHintsInteractiveFunctionParameterTypes5.ts b/tests/cases/fourslash/inlayHintsInteractiveFunctionParameterTypes5.ts new file mode 100644 index 00000000000..0dc3b2da447 --- /dev/null +++ b/tests/cases/fourslash/inlayHintsInteractiveFunctionParameterTypes5.ts @@ -0,0 +1,9 @@ +/// + +////const foo: 1n = 1n; +////export function fn(b = foo) {} + +verify.baselineInlayHints(undefined, { + includeInlayFunctionParameterTypeHints: true, + interactiveInlayHints: true +}); diff --git a/tests/cases/fourslash/inlayHintsQuotePreference1.ts b/tests/cases/fourslash/inlayHintsQuotePreference1.ts new file mode 100644 index 00000000000..0339d46545f --- /dev/null +++ b/tests/cases/fourslash/inlayHintsQuotePreference1.ts @@ -0,0 +1,11 @@ +/// + +////const a1: '"' = '"'; +////const b1: '\\' = '\\'; +////export function fn(a = a1, b = b1) {} + +verify.baselineInlayHints(undefined, { + includeInlayFunctionParameterTypeHints: true, + interactiveInlayHints: true, + quotePreference: "double" +}); diff --git a/tests/cases/fourslash/inlayHintsQuotePreference2.ts b/tests/cases/fourslash/inlayHintsQuotePreference2.ts new file mode 100644 index 00000000000..377276bbdb2 --- /dev/null +++ b/tests/cases/fourslash/inlayHintsQuotePreference2.ts @@ -0,0 +1,11 @@ +/// + +////const a1: "'" = "'"; +////const b1: "\\" = "\\"; +////export function fn(a = a1, b = b1) {} + +verify.baselineInlayHints(undefined, { + includeInlayFunctionParameterTypeHints: true, + interactiveInlayHints: true, + quotePreference: "single" +});