Skip to content

Commit ee6527e

Browse files
committed
Add function expression like hints
1 parent 23afce2 commit ee6527e

File tree

6 files changed

+73
-16
lines changed

6 files changed

+73
-16
lines changed

src/server/protocol.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2491,8 +2491,10 @@ namespace ts.server.protocol {
24912491
}
24922492

24932493
export interface HintItem {
2494-
text: string
2495-
position: Location
2494+
text: string;
2495+
position: Location;
2496+
whitespaceBefore?: boolean;
2497+
whitespaceAfter?: boolean;
24962498
}
24972499

24982500
export interface ProvideInlineHintsResponse extends Response {

src/server/session.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1428,7 +1428,9 @@ namespace ts.server {
14281428

14291429
return hints.map(hint => ({
14301430
text: hint.text,
1431-
position: scriptInfo.positionToLineOffset(hint.position)
1431+
position: scriptInfo.positionToLineOffset(hint.position),
1432+
whitespaceBefore: hint.whitespaceBefore,
1433+
whitespaceAfter: hint.whitespaceAfter
14321434
}));
14331435
}
14341436

src/services/inlineHints.ts

Lines changed: 56 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
/* @internal */
22
namespace ts.InlineHints {
33
interface HintInfo {
4-
text: string
5-
position: number
4+
text: string;
5+
position: number;
6+
whitespaceBefore?: boolean;
7+
whitespaceAfter?: boolean;
68
}
79

810
export function provideInlineHints(context: InlineHintsContext): HintInfo[] {
@@ -41,21 +43,20 @@ namespace ts.InlineHints {
4143
if (isCallExpression(node) || isNewExpression(node)) {
4244
visitCallOrNewExpression(node);
4345
}
46+
else if (isArrowFunction(node) || isFunctionExpression(node)) {
47+
visitFunctionExpressionLike(node);
48+
}
4449
return forEachChild(node, visitor);
4550
}
4651

4752
function visitCallOrNewExpression(expr: CallExpression | NewExpression) {
48-
const candidates: Signature[] = [];
49-
const signature = checker.getResolvedSignatureForSignatureHelp(expr, candidates);
50-
if (!signature || !candidates.length) {
53+
if (!expr.arguments || !expr.arguments.length) {
5154
return;
5255
}
5356

54-
getCallArgumentsHints(expr, signature);
55-
}
56-
57-
function getCallArgumentsHints(expr: CallExpression | NewExpression, signature: Signature) {
58-
if (!expr.arguments || !expr.arguments.length) {
57+
const candidates: Signature[] = [];
58+
const signature = checker.getResolvedSignatureForSignatureHelp(expr, candidates);
59+
if (!signature || !candidates.length) {
5960
return;
6061
}
6162

@@ -67,11 +68,55 @@ namespace ts.InlineHints {
6768
if (!argumentName || argumentName !== parameterName) {
6869
result.push({
6970
text: `${unescapeLeadingUnderscores(parameterName)}:`,
70-
position: expr.arguments[i].getStart()
71+
position: expr.arguments[i].getStart(),
72+
whitespaceAfter: true,
7173
});
7274
}
7375
}
7476
}
7577
}
78+
79+
function visitFunctionExpressionLike(expr: ArrowFunction | FunctionExpression) {
80+
if (!expr.parameters.length || expr.parameters.every(param => param.type)) {
81+
return;
82+
}
83+
84+
const contextualType = checker.getContextualType(expr);
85+
if (!contextualType) {
86+
return;
87+
}
88+
89+
const signatures = checker.getSignaturesOfType(contextualType, SignatureKind.Call);
90+
const signature = firstOrUndefined(signatures);
91+
if (!signature) {
92+
return;
93+
}
94+
95+
for (let i = 0; i < expr.parameters.length && i < signature.parameters.length; ++i) {
96+
const param = expr.parameters[i];
97+
if (param.type) {
98+
continue;
99+
}
100+
101+
const signatureParam = signature.parameters[i];
102+
const signatureParamType = checker.getTypeOfSymbolAtLocation(signatureParam, signatureParam.valueDeclaration);
103+
104+
const valueDeclaration = signatureParam.valueDeclaration;
105+
if (!valueDeclaration || !isParameter(valueDeclaration) || !valueDeclaration.type) {
106+
continue;
107+
}
108+
109+
const typeDisplayString = displayPartsToString(typeToDisplayParts(checker, signatureParamType));
110+
if (!typeDisplayString) {
111+
continue;
112+
}
113+
114+
result.push({
115+
text: `:${typeDisplayString}`,
116+
position: param.end,
117+
whitespaceBefore: true,
118+
});
119+
}
120+
}
76121
}
77122
}

src/services/types.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -688,8 +688,10 @@ namespace ts {
688688
}
689689

690690
export interface InlineHint {
691-
text: string,
692-
position: number
691+
text: string;
692+
position: number;
693+
whitespaceBefore?: boolean;
694+
whitespaceAfter?: boolean;
693695
}
694696

695697
export interface TodoCommentDescriptor {

tests/baselines/reference/api/tsserverlibrary.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5711,6 +5711,8 @@ declare namespace ts {
57115711
interface InlineHint {
57125712
text: string;
57135713
position: number;
5714+
whitespaceBefore?: boolean;
5715+
whitespaceAfter?: boolean;
57145716
}
57155717
interface TodoCommentDescriptor {
57165718
text: string;
@@ -8403,6 +8405,8 @@ declare namespace ts.server.protocol {
84038405
interface HintItem {
84048406
text: string;
84058407
position: Location;
8408+
whitespaceBefore?: boolean;
8409+
whitespaceAfter?: boolean;
84068410
}
84078411
interface ProvideInlineHintsResponse extends Response {
84088412
body?: HintItem[];

tests/baselines/reference/api/typescript.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5711,6 +5711,8 @@ declare namespace ts {
57115711
interface InlineHint {
57125712
text: string;
57135713
position: number;
5714+
whitespaceBefore?: boolean;
5715+
whitespaceAfter?: boolean;
57145716
}
57155717
interface TodoCommentDescriptor {
57165718
text: string;

0 commit comments

Comments
 (0)