Repository: microsoft/TypeScript
File: src/services/inlayHints.ts (TypeScript)

Code before:
                return;
            }
            addTypeHints(typeDisplayString, decl.name.end);
        }
    }

    function visitCallOrNewExpression(expr: CallExpression | NewExpression) {
        const args = expr.arguments;
        if (!args || !args.length) {
            return;
        }

        const candidates: Signature[] = [];
        const signature = checker.getResolvedSignatureForSignatureHelp(expr, candidates);
        if (!signature || !candidates.length) {
            return;
        }

        let pos = 0;
        for (const originalArg of args) {
            const arg = skipParentheses(originalArg);
            if (shouldShowLiteralParameterNameHintsOnly(preferences) && !isHintableLiteral(arg)) {
                continue;
            }

            const identifierNameInfo = checker.getParameterIdentifierNameAtPosition(signature, pos++);
            if (identifierNameInfo) {
                const [parameterName, isFirstVariadicArgument] = identifierNameInfo;
                const isParameterNameNotSameAsArgument = preferences.includeInlayParameterNameHintsWhenArgumentMatchesName || !identifierOrAccessExpressionPostfixMatchesParameterName(arg, parameterName);
                if (!isParameterNameNotSameAsArgument && !isFirstVariadicArgument) {
                    continue;
                }

                const name = unescapeLeadingUnderscores(parameterName);
                if (leadingCommentsContainsParameterName(arg, name)) {
                    continue;
                }

                if (isSpreadElement(arg)) {
                    const spreadType = checker.getTypeAtLocation(arg.expression);
                    if (checker.isTupleType(spreadType)) {
                        const { fixedLength, elementFlags } = (spreadType as TupleTypeReference).target;
                        for (let i = pos; i < fixedLength; i++) {
                            if (elementFlags[i] & ElementFlags.Required) {
                                pos++;
                            }
                        }
                    }
                }

                addParameterHints(name, originalArg.getStart(), isFirstVariadicArgument);

Review comment (bug):
I think you also don't want to increment unconditionally here, since we could be passing an empty tuple. Like so:

```ts
function foo1(a: unknown, b: unknown, c: unknown) { }
function bar1(...x: []) { // Empty tuple
    foo1(...x, 3, 4, 5); // Wrong: currently `foo1(/*a*/...x, /*b*/3, /*c*/4, 5)`, should be `foo1(...x, /*a*/3, /*b*/4, /*c*/5)`
}
```

Code after:
            if (isVariableNameMatchesType) {
                return;
            }
            addTypeHints(typeDisplayString, decl.name.end);
        }
    }

    function visitCallOrNewExpression(expr: CallExpression | NewExpression) {
        const args = expr.arguments;
        if (!args || !args.length) {
            return;
        }

        const candidates: Signature[] = [];
        const signature = checker.getResolvedSignatureForSignatureHelp(expr, candidates);
        if (!signature || !candidates.length) {
            return;
        }

        let signatureParamPos = 0;
        for (const originalArg of args) {
            const arg = skipParentheses(originalArg);
            if (shouldShowLiteralParameterNameHintsOnly(preferences) && !isHintableLiteral(arg)) {
                continue;
            }

            let spreadArgs = 0;
            if (isSpreadElement(arg)) {
                const spreadType = checker.getTypeAtLocation(arg.expression);
                if (checker.isTupleType(spreadType)) {
                    const { elementFlags, fixedLength } = (spreadType as TupleTypeReference).target;
                    if (fixedLength === 0) {
                        continue;
                    }
                    const firstOptionalIndex = findIndex(elementFlags, f => !(f & ElementFlags.Required));
                    const requiredArgs = firstOptionalIndex < 0 ? fixedLength : firstOptionalIndex;
                    if (requiredArgs > 0) {
                        spreadArgs = firstOptionalIndex < 0 ? fixedLength : firstOptionalIndex;
                    }
                }
            }

            const identifierNameInfo = checker.getParameterIdentifierNameAtPosition(signature, signatureParamPos);
            signatureParamPos = signatureParamPos + (spreadArgs || 1);
            if (identifierNameInfo) {
                const [parameterName, isFirstVariadicArgument] = identifierNameInfo;
                const isParameterNameNotSameAsArgument = preferences.includeInlayParameterNameHintsWhenArgumentMatchesName || !identifierOrAccessExpressionPostfixMatchesParameterName(arg, parameterName);
                if (!isParameterNameNotSameAsArgument && !isFirstVariadicArgument) {
                    continue;
                }