From 589f734e5edd1eef8cc69e99f67e418598e24d44 Mon Sep 17 00:00:00 2001 From: "Oleksandr T." Date: Fri, 17 Jan 2025 23:30:35 +0200 Subject: [PATCH] fix(60375): Parameter inlay hint is incorrect when function has a this type (#60378) --- src/services/inlayHints.ts | 33 +++++++------- .../inlayHintsThisParameter.baseline | 45 +++++++++++++++++++ .../fourslash/inlayHintsThisParameter.ts | 17 +++++++ 3 files changed, 80 insertions(+), 15 deletions(-) create mode 100644 tests/baselines/reference/inlayHintsThisParameter.baseline create mode 100644 tests/cases/fourslash/inlayHintsThisParameter.ts diff --git a/src/services/inlayHints.ts b/src/services/inlayHints.ts index f5a29b332b5..d79def83639 100644 --- a/src/services/inlayHints.ts +++ b/src/services/inlayHints.ts @@ -103,6 +103,7 @@ import { NodeArray, NodeBuilderFlags, ParameterDeclaration, + parameterIsThisKeyword, PrefixUnaryExpression, PropertyDeclaration, QuotePreference, @@ -437,26 +438,28 @@ export function provideInlayHints(context: InlayHintsContext): InlayHint[] { return; } - for (let i = 0; i < node.parameters.length && i < signature.parameters.length; ++i) { - const param = node.parameters[i]; - if (!isHintableDeclaration(param)) { + let pos = 0; + for (const param of node.parameters) { + if (isHintableDeclaration(param)) { + addParameterTypeHint(param, parameterIsThisKeyword(param) ? signature.thisParameter : signature.parameters[pos]); + } + if (parameterIsThisKeyword(param)) { continue; } - - const effectiveTypeAnnotation = getEffectiveTypeAnnotationNode(param); - if (effectiveTypeAnnotation) { - continue; - } - - const typeHints = getParameterDeclarationTypeHints(signature.parameters[i]); - if (!typeHints) { - continue; - } - - addTypeHints(typeHints, param.questionToken ? param.questionToken.end : param.name.end); + pos++; } } + function addParameterTypeHint(node: ParameterDeclaration, symbol: Symbol | undefined) { + const effectiveTypeAnnotation = getEffectiveTypeAnnotationNode(node); + if (effectiveTypeAnnotation || symbol === undefined) return; + + const typeHints = getParameterDeclarationTypeHints(symbol); + if (typeHints === undefined) return; + + addTypeHints(typeHints, node.questionToken ? node.questionToken.end : node.name.end); + } + function getParameterDeclarationTypeHints(symbol: Symbol) { const valueDeclaration = symbol.valueDeclaration; if (!valueDeclaration || !isParameter(valueDeclaration)) { diff --git a/tests/baselines/reference/inlayHintsThisParameter.baseline b/tests/baselines/reference/inlayHintsThisParameter.baseline new file mode 100644 index 00000000000..d41eb76410e --- /dev/null +++ b/tests/baselines/reference/inlayHintsThisParameter.baseline @@ -0,0 +1,45 @@ +// === Inlay Hints === +fn(function (this, a, b) { }); + ^ +{ + "text": ": any", + "position": 126, + "kind": "Type", + "whitespaceBefore": true +} + +fn(function (this, a, b) { }); + ^ +{ + "text": ": number", + "position": 129, + "kind": "Type", + "whitespaceBefore": true +} + +fn(function (this, a, b) { }); + ^ +{ + "text": ": string", + "position": 132, + "kind": "Type", + "whitespaceBefore": true +} + +fn(function (this: I, a, b) { }); + ^ +{ + "text": ": number", + "position": 163, + "kind": "Type", + "whitespaceBefore": true +} + +fn(function (this: I, a, b) { }); + ^ +{ + "text": ": string", + "position": 166, + "kind": "Type", + "whitespaceBefore": true +} \ No newline at end of file diff --git a/tests/cases/fourslash/inlayHintsThisParameter.ts b/tests/cases/fourslash/inlayHintsThisParameter.ts new file mode 100644 index 00000000000..dd4e181b193 --- /dev/null +++ b/tests/cases/fourslash/inlayHintsThisParameter.ts @@ -0,0 +1,17 @@ +/// + +////interface I { +//// a: number; +////} +//// +////declare function fn( +//// callback: (a: number, b: string) => void +////): void; +//// +//// +////fn(function (this, a, b) { }); +////fn(function (this: I, a, b) { }); + +verify.baselineInlayHints(undefined, { + includeInlayFunctionParameterTypeHints: true, +});