diff --git a/src/services/inlayHints.ts b/src/services/inlayHints.ts
index b37a9be01c2a0..1e579e5cc0cf1 100644
--- a/src/services/inlayHints.ts
+++ b/src/services/inlayHints.ts
@@ -8,11 +8,7 @@ namespace ts.InlayHints {
};
function shouldShowParameterNameHints(preferences: InlayHintsOptions) {
- return preferences.includeInlayParameterNameHints === "literals" || preferences.includeInlayParameterNameHints === "all";
- }
-
- function shouldShowLiteralParameterNameHintsOnly(preferences: InlayHintsOptions) {
- return preferences.includeInlayParameterNameHints === "literals";
+ return !!preferences.includeInlayParameterNameHints && preferences.includeInlayParameterNameHints !== "none";
}
export function provideInlayHints(context: InlayHintsContext): InlayHint[] {
@@ -156,9 +152,9 @@ namespace ts.InlayHints {
for (let i = 0; i < args.length; ++i) {
const originalArg = args[i];
const arg = skipParentheses(originalArg);
- if (shouldShowLiteralParameterNameHintsOnly(preferences) && !isHintableExpression(arg)) {
- continue;
- }
+
+ if ((preferences.includeInlayParameterNameHints === "literals" && !isLiteralLike(arg)) ||
+ (preferences.includeInlayParameterNameHints === "primitiveLiterals" && !isPrimitiveLiteral(arg))) continue;
const identifierNameInfo = checker.getParameterIdentifierNameAtPosition(signature, i);
if (identifierNameInfo) {
@@ -202,28 +198,40 @@ namespace ts.InlayHints {
return some(ranges, range => regex.test(sourceFileText.substring(range.pos, range.end)));
}
- function isHintableExpression(node: Node) {
+ function isLiteralLike(node: Node): boolean {
switch (node.kind) {
- case SyntaxKind.PrefixUnaryExpression: {
- const operand = (node as PrefixUnaryExpression).operand;
- return isLiteralExpression(operand) || isIdentifier(operand) && isInfinityOrNaNString(operand.escapedText);
- }
- case SyntaxKind.TrueKeyword:
- case SyntaxKind.FalseKeyword:
+ case SyntaxKind.ArrayLiteralExpression:
+ case SyntaxKind.ObjectLiteralExpression:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
- case SyntaxKind.ObjectLiteralExpression:
- case SyntaxKind.ArrayLiteralExpression:
- case SyntaxKind.NullKeyword:
+ case SyntaxKind.RegularExpressionLiteral:
case SyntaxKind.NoSubstitutionTemplateLiteral:
case SyntaxKind.TemplateExpression:
return true;
- case SyntaxKind.Identifier: {
- const name = (node as Identifier).escapedText;
- return isUndefined(name) || isInfinityOrNaNString(name);
- }
+ case SyntaxKind.PrefixUnaryExpression:
+ return isLiteralLike(skipParentheses((node as PrefixUnaryExpression).operand));
+ default:
+ return isPrimitiveLiteral(node);
+ }
+ }
+
+ function isPrimitiveLiteral(node: Node): boolean {
+ switch (node.kind) {
+ case SyntaxKind.TrueKeyword:
+ case SyntaxKind.FalseKeyword:
+ case SyntaxKind.NullKeyword:
+ case SyntaxKind.StringLiteral:
+ case SyntaxKind.NumericLiteral:
+ case SyntaxKind.BigIntLiteral:
+ return true;
+ case SyntaxKind.Identifier:
+ return isUndefined(node) || isInfinityOrNaNString((node as Identifier).escapedText);
+ case SyntaxKind.PrefixUnaryExpression:
+ const operand = skipParentheses((node as PrefixUnaryExpression).operand);
+ return !(operand.kind === SyntaxKind.NullKeyword || operand.kind === SyntaxKind.BigIntLiteral || isUndefined(operand)) && isPrimitiveLiteral(operand);
+ default:
+ return false;
}
- return isLiteralExpression(node);
}
function visitFunctionDeclarationLikeForReturnType(decl: FunctionDeclaration | ArrowFunction | FunctionExpression | MethodDeclaration | GetAccessorDeclaration) {
@@ -320,8 +328,8 @@ namespace ts.InlayHints {
});
}
- function isUndefined(name: __String) {
- return name === "undefined";
+ function isUndefined(node: Node) {
+ return isIdentifier(node) && node.escapedText === "undefined";
}
}
}
diff --git a/src/services/types.ts b/src/services/types.ts
index 4ad9ddfa88946..9c3d89b90c942 100644
--- a/src/services/types.ts
+++ b/src/services/types.ts
@@ -579,7 +579,7 @@ namespace ts {
}
export interface InlayHintsOptions extends UserPreferences {
- readonly includeInlayParameterNameHints?: "none" | "literals" | "all";
+ readonly includeInlayParameterNameHints?: "none" | "literals" | "primitiveLiterals" | "all";
readonly includeInlayParameterNameHintsWhenArgumentMatchesName?: boolean;
readonly includeInlayFunctionParameterTypeHints?: boolean,
readonly includeInlayVariableTypeHints?: boolean;
diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts
index 14de9571dc63a..ce5b11b3b0926 100644
--- a/tests/baselines/reference/api/tsserverlibrary.d.ts
+++ b/tests/baselines/reference/api/tsserverlibrary.d.ts
@@ -5766,7 +5766,7 @@ declare namespace ts {
includeInsertTextCompletions?: boolean;
}
interface InlayHintsOptions extends UserPreferences {
- readonly includeInlayParameterNameHints?: "none" | "literals" | "all";
+ readonly includeInlayParameterNameHints?: "none" | "literals" | "primitiveLiterals" | "all";
readonly includeInlayParameterNameHintsWhenArgumentMatchesName?: boolean;
readonly includeInlayFunctionParameterTypeHints?: boolean;
readonly includeInlayVariableTypeHints?: boolean;
diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts
index a83b83826341f..9ce3f4d784541 100644
--- a/tests/baselines/reference/api/typescript.d.ts
+++ b/tests/baselines/reference/api/typescript.d.ts
@@ -5766,7 +5766,7 @@ declare namespace ts {
includeInsertTextCompletions?: boolean;
}
interface InlayHintsOptions extends UserPreferences {
- readonly includeInlayParameterNameHints?: "none" | "literals" | "all";
+ readonly includeInlayParameterNameHints?: "none" | "literals" | "primitiveLiterals" | "all";
readonly includeInlayParameterNameHintsWhenArgumentMatchesName?: boolean;
readonly includeInlayFunctionParameterTypeHints?: boolean;
readonly includeInlayVariableTypeHints?: boolean;
diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts
index 3a1ff85432604..5cea0480a1e8b 100644
--- a/tests/cases/fourslash/fourslash.ts
+++ b/tests/cases/fourslash/fourslash.ts
@@ -645,7 +645,7 @@ declare namespace FourSlashInterface {
readonly importModuleSpecifierEnding?: "minimal" | "index" | "js";
}
interface InlayHintsOptions extends UserPreferences {
- readonly includeInlayParameterNameHints?: "none" | "literals" | "all";
+ readonly includeInlayParameterNameHints?: "none" | "literals" | "primitiveLiterals" | "all";
readonly includeInlayParameterNameHintsWhenArgumentMatchesName?: boolean;
readonly includeInlayFunctionParameterTypeHints?: boolean;
readonly includeInlayVariableTypeHints?: boolean;
diff --git a/tests/cases/fourslash/inlayHintsShouldWork65.ts b/tests/cases/fourslash/inlayHintsShouldWork65.ts
new file mode 100644
index 0000000000000..e0a57eb541281
--- /dev/null
+++ b/tests/cases/fourslash/inlayHintsShouldWork65.ts
@@ -0,0 +1,85 @@
+///
+
+////function foo(
+//// a: number,
+//// b: number,
+//// c: number,
+//// d: number,
+//// e: number,
+//// f: number,
+//// g: number,
+//// h: number,
+//// i: number
+////) {}
+////
+////foo(
+//// /*a*/+"",
+//// /*b*/+``,
+//// /*c*/+{},
+//// /*d*/+[],
+//// /*e*/+/a/,
+//// /*f*/+Infinity,
+//// /*g*/+NaN,
+//// /*h*/+function() {},
+//// /*i*/+(() => {}),
+////);
+
+const [a, b, c, d, e, f, g, h, i] = test.markers();
+verify.getInlayHints([
+ {
+ text: "a:",
+ position: a.position,
+ kind: ts.InlayHintKind.Parameter,
+ whitespaceAfter: true
+ },
+ {
+ text: "b:",
+ position: b.position,
+ kind: ts.InlayHintKind.Parameter,
+ whitespaceAfter: true
+ },
+ {
+ text: "c:",
+ position: c.position,
+ kind: ts.InlayHintKind.Parameter,
+ whitespaceAfter: true
+ },
+ {
+ text: "d:",
+ position: d.position,
+ kind: ts.InlayHintKind.Parameter,
+ whitespaceAfter: true
+ },
+ {
+ text: "e:",
+ position: e.position,
+ kind: ts.InlayHintKind.Parameter,
+ whitespaceAfter: true
+ },
+ {
+ text: "f:",
+ position: f.position,
+ kind: ts.InlayHintKind.Parameter,
+ whitespaceAfter: true
+ },
+ {
+ text: "g:",
+ position: g.position,
+ kind: ts.InlayHintKind.Parameter,
+ whitespaceAfter: true
+ },
+ {
+ text: "h:",
+ position: h.position,
+ kind: ts.InlayHintKind.Parameter,
+ whitespaceAfter: true
+ },
+ {
+ text: "i:",
+ position: i.position,
+ kind: ts.InlayHintKind.Parameter,
+ whitespaceAfter: true
+ }
+], undefined, {
+ includeInlayParameterNameHints: "literals"
+});
diff --git a/tests/cases/fourslash/inlayHints_primitiveLiterals1.ts b/tests/cases/fourslash/inlayHints_primitiveLiterals1.ts
new file mode 100644
index 0000000000000..9d0643a5c0adb
--- /dev/null
+++ b/tests/cases/fourslash/inlayHints_primitiveLiterals1.ts
@@ -0,0 +1,86 @@
+///
+
+////function foo(
+//// a: string,
+//// b: undefined,
+//// c: null,
+//// d: boolean,
+//// e: boolean,
+//// f: number,
+//// g: number,
+//// h: number,
+//// i: bigint
+////) {
+////}
+////
+////foo(
+//// /*a*/"hello",
+//// /*b*/undefined,
+//// /*c*/null,
+//// /*d*/true,
+//// /*e*/false,
+//// /*f*/Infinity,
+//// /*g*/-Infinity,
+//// /*h*/NaN,
+//// /*i*/123n
+////);
+
+const [a, b, c, d, e, f, g, h, i] = test.markers();
+verify.getInlayHints([
+ {
+ text: "a:",
+ position: a.position,
+ kind: ts.InlayHintKind.Parameter,
+ whitespaceAfter: true
+ },
+ {
+ text: "b:",
+ position: b.position,
+ kind: ts.InlayHintKind.Parameter,
+ whitespaceAfter: true
+ },
+ {
+ text: "c:",
+ position: c.position,
+ kind: ts.InlayHintKind.Parameter,
+ whitespaceAfter: true
+ },
+ {
+ text: "d:",
+ position: d.position,
+ kind: ts.InlayHintKind.Parameter,
+ whitespaceAfter: true
+ },
+ {
+ text: "e:",
+ position: e.position,
+ kind: ts.InlayHintKind.Parameter,
+ whitespaceAfter: true
+ },
+ {
+ text: "f:",
+ position: f.position,
+ kind: ts.InlayHintKind.Parameter,
+ whitespaceAfter: true
+ },
+ {
+ text: "g:",
+ position: g.position,
+ kind: ts.InlayHintKind.Parameter,
+ whitespaceAfter: true
+ },
+ {
+ text: "h:",
+ position: h.position,
+ kind: ts.InlayHintKind.Parameter,
+ whitespaceAfter: true
+ },
+ {
+ text: "i:",
+ position: i.position,
+ kind: ts.InlayHintKind.Parameter,
+ whitespaceAfter: true
+ }
+], undefined, {
+ includeInlayParameterNameHints: "primitiveLiterals"
+});
diff --git a/tests/cases/fourslash/inlayHints_primitiveLiterals2.ts b/tests/cases/fourslash/inlayHints_primitiveLiterals2.ts
new file mode 100644
index 0000000000000..88dc68e00528d
--- /dev/null
+++ b/tests/cases/fourslash/inlayHints_primitiveLiterals2.ts
@@ -0,0 +1,25 @@
+///
+
+////function foo(
+//// a: number[],
+//// b: { x: number; y: number; },
+//// c: () => void,
+//// d: () => void,
+//// e: RegExp,
+//// f: string,
+//// g: string
+////) {}
+////
+////foo(
+//// /*a*/[1],
+//// /*b*/{ x: 1, y: 1 },
+//// /*c*/() => {},
+//// /*d*/function () {},
+//// /*e*//foo/i,
+//// /*f*/``
+//// /*g*/`${1} ${2} ${3}`
+////);
+
+verify.getInlayHints([], undefined, {
+ includeInlayParameterNameHints: "primitiveLiterals"
+});