From dbaa545360daf6820a0a1943a16324695efc9944 Mon Sep 17 00:00:00 2001 From: Huy Date: Sat, 2 Apr 2022 11:41:03 -0700 Subject: [PATCH 1/4] fix(47562): Add option to suppress type hint if variable name matches type --- src/compiler/types.ts | 1 + src/services/inlayHints.ts | 8 ++++++ tests/cases/fourslash/fourslash.ts | 1 + .../cases/fourslash/inlayHintsShouldWork67.ts | 25 +++++++++++++++++++ 4 files changed, 35 insertions(+) create mode 100644 tests/cases/fourslash/inlayHintsShouldWork67.ts diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 5180c765990bb..217c60e3d51ac 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -8769,6 +8769,7 @@ namespace ts { readonly includeInlayParameterNameHintsWhenArgumentMatchesName?: boolean; readonly includeInlayFunctionParameterTypeHints?: boolean, readonly includeInlayVariableTypeHints?: boolean; + readonly includeInlayVariableTypeHintsWhenTypeMatchesName?: boolean; readonly includeInlayPropertyDeclarationTypeHints?: boolean; readonly includeInlayFunctionLikeReturnTypeHints?: boolean; readonly includeInlayEnumMemberValueHints?: boolean; diff --git a/src/services/inlayHints.ts b/src/services/inlayHints.ts index 110e9718405cb..7bf6f143cd957 100644 --- a/src/services/inlayHints.ts +++ b/src/services/inlayHints.ts @@ -137,10 +137,18 @@ namespace ts.InlayHints { const typeDisplayString = printTypeInSingleLine(declarationType); if (typeDisplayString) { + const isVariableNameMatchesType = !preferences.includeInlayVariableTypeHintsWhenTypeMatchesName && variableDeclarationNameMatchesTypeString(decl.name.getText(), typeDisplayString); + if (isVariableNameMatchesType) { + return; + } addTypeHints(typeDisplayString, decl.name.end); } } + function variableDeclarationNameMatchesTypeString(declarationName: string, typeDisplayString: string) { + return declarationName.toLowerCase() === typeDisplayString.toLowerCase(); + } + function visitCallOrNewExpression(expr: CallExpression | NewExpression) { const args = expr.arguments; if (!args || !args.length) { diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index a02e06a574c05..a6e14fdbaeb5d 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -662,6 +662,7 @@ declare namespace FourSlashInterface { readonly includeInlayParameterNameHintsWhenArgumentMatchesName?: boolean; readonly includeInlayFunctionParameterTypeHints?: boolean; readonly includeInlayVariableTypeHints?: boolean; + readonly includeInlayVariableTypeHintsWhenTypeMatchesName?: boolean; readonly includeInlayPropertyDeclarationTypeHints?: boolean; readonly includeInlayFunctionLikeReturnTypeHints?: boolean; readonly includeInlayEnumMemberValueHints?: boolean; diff --git a/tests/cases/fourslash/inlayHintsShouldWork67.ts b/tests/cases/fourslash/inlayHintsShouldWork67.ts new file mode 100644 index 0000000000000..ad36a18e699e0 --- /dev/null +++ b/tests/cases/fourslash/inlayHintsShouldWork67.ts @@ -0,0 +1,25 @@ +/// + +//// @Debug +//// type Client = {}; +//// function getClient(): Client { return {}; }; +//// const client/**/ = getClient(); + +const markers = test.markers(); + +verify.getInlayHints([ + { + text: ': Client', + position: markers[0].position, + kind: ts.InlayHintKind.Type, + whitespaceBefore: true + } +], undefined, { + includeInlayVariableTypeHints: true, + includeInlayVariableTypeHintsWhenTypeMatchesName: true +}); + +verify.getInlayHints([], undefined, { + includeInlayVariableTypeHints: true, + includeInlayVariableTypeHintsWhenTypeMatchesName: false +}); From 182bdc3c3c79e8e0a9f7271ac7cdfcb1b2b94d3c Mon Sep 17 00:00:00 2001 From: Huy Date: Sat, 2 Apr 2022 11:46:06 -0700 Subject: [PATCH 2/4] Remove the unnecessary debug code --- tests/cases/fourslash/inlayHintsShouldWork67.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/cases/fourslash/inlayHintsShouldWork67.ts b/tests/cases/fourslash/inlayHintsShouldWork67.ts index ad36a18e699e0..2b35b152b7956 100644 --- a/tests/cases/fourslash/inlayHintsShouldWork67.ts +++ b/tests/cases/fourslash/inlayHintsShouldWork67.ts @@ -1,6 +1,5 @@ /// -//// @Debug //// type Client = {}; //// function getClient(): Client { return {}; }; //// const client/**/ = getClient(); From ad2ec6611df30606e970df12be9c8a9276b4580e Mon Sep 17 00:00:00 2001 From: Huy Date: Sat, 2 Apr 2022 12:27:10 -0700 Subject: [PATCH 3/4] Re-run gulp runtests --- src/server/protocol.ts | 9 +++++---- tests/baselines/reference/api/tsserverlibrary.d.ts | 2 ++ tests/baselines/reference/api/typescript.d.ts | 1 + 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/server/protocol.ts b/src/server/protocol.ts index 426eccb2b1325..38768c0a8784d 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -727,7 +727,7 @@ namespace ts.server.protocol { } // All we need is the `success` and `message` fields of Response. - export interface ApplyCodeActionCommandResponse extends Response {} + export interface ApplyCodeActionCommandResponse extends Response { } export interface FileRangeRequestArgs extends FileRequestArgs { /** @@ -1062,7 +1062,7 @@ namespace ts.server.protocol { readonly arguments: JsxClosingTagRequestArgs; } - export interface JsxClosingTagRequestArgs extends FileLocationRequestArgs {} + export interface JsxClosingTagRequestArgs extends FileLocationRequestArgs { } export interface JsxClosingTagResponse extends Response { readonly body: TextInsertion; @@ -2382,7 +2382,7 @@ namespace ts.server.protocol { /** * Human-readable description of the `source` from the CompletionEntry. */ - sourceDisplay?: SymbolDisplayPart[]; + sourceDisplay?: SymbolDisplayPart[]; } /** @deprecated Prefer CompletionInfoResponse, which supports several top-level fields in addition to the array of entries. */ @@ -3406,7 +3406,7 @@ namespace ts.server.protocol { /** * Allows completions to be formatted with snippet text, indicated by `CompletionItem["isSnippet"]`. */ - readonly includeCompletionsWithSnippetText?: boolean; + readonly includeCompletionsWithSnippetText?: boolean; /** * If enabled, the completion list will include completions with invalid identifier names. * For those entries, The `insertText` and `replacementSpan` properties will be set to change from `.x` property access to `["x"]`. @@ -3456,6 +3456,7 @@ namespace ts.server.protocol { readonly includeInlayParameterNameHintsWhenArgumentMatchesName?: boolean; readonly includeInlayFunctionParameterTypeHints?: boolean, readonly includeInlayVariableTypeHints?: boolean; + readonly includeInlayVariableTypeHintsWhenTypeMatchesName?: boolean; readonly includeInlayPropertyDeclarationTypeHints?: boolean; readonly includeInlayFunctionLikeReturnTypeHints?: boolean; readonly includeInlayEnumMemberValueHints?: boolean; diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 680978e77c2a5..f2b7df00a54ba 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -4115,6 +4115,7 @@ declare namespace ts { readonly includeInlayParameterNameHintsWhenArgumentMatchesName?: boolean; readonly includeInlayFunctionParameterTypeHints?: boolean; readonly includeInlayVariableTypeHints?: boolean; + readonly includeInlayVariableTypeHintsWhenTypeMatchesName?: boolean; readonly includeInlayPropertyDeclarationTypeHints?: boolean; readonly includeInlayFunctionLikeReturnTypeHints?: boolean; readonly includeInlayEnumMemberValueHints?: boolean; @@ -9683,6 +9684,7 @@ declare namespace ts.server.protocol { readonly includeInlayParameterNameHintsWhenArgumentMatchesName?: boolean; readonly includeInlayFunctionParameterTypeHints?: boolean; readonly includeInlayVariableTypeHints?: boolean; + readonly includeInlayVariableTypeHintsWhenTypeMatchesName?: boolean; readonly includeInlayPropertyDeclarationTypeHints?: boolean; readonly includeInlayFunctionLikeReturnTypeHints?: boolean; readonly includeInlayEnumMemberValueHints?: boolean; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 1a7f94807720a..07ede37502bbe 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -4115,6 +4115,7 @@ declare namespace ts { readonly includeInlayParameterNameHintsWhenArgumentMatchesName?: boolean; readonly includeInlayFunctionParameterTypeHints?: boolean; readonly includeInlayVariableTypeHints?: boolean; + readonly includeInlayVariableTypeHintsWhenTypeMatchesName?: boolean; readonly includeInlayPropertyDeclarationTypeHints?: boolean; readonly includeInlayFunctionLikeReturnTypeHints?: boolean; readonly includeInlayEnumMemberValueHints?: boolean; From 6f165193a999f5fd7098f75fc414ec1e6edf63eb Mon Sep 17 00:00:00 2001 From: Huy Date: Mon, 25 Apr 2022 16:33:56 -0700 Subject: [PATCH 4/4] Use equateStringsCaseInsensitive to compare strings --- src/services/inlayHints.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/services/inlayHints.ts b/src/services/inlayHints.ts index 7bf6f143cd957..ca95df202b810 100644 --- a/src/services/inlayHints.ts +++ b/src/services/inlayHints.ts @@ -137,7 +137,7 @@ namespace ts.InlayHints { const typeDisplayString = printTypeInSingleLine(declarationType); if (typeDisplayString) { - const isVariableNameMatchesType = !preferences.includeInlayVariableTypeHintsWhenTypeMatchesName && variableDeclarationNameMatchesTypeString(decl.name.getText(), typeDisplayString); + const isVariableNameMatchesType = preferences.includeInlayVariableTypeHintsWhenTypeMatchesName === false && equateStringsCaseInsensitive(decl.name.getText(), typeDisplayString); if (isVariableNameMatchesType) { return; } @@ -145,10 +145,6 @@ namespace ts.InlayHints { } } - function variableDeclarationNameMatchesTypeString(declarationName: string, typeDisplayString: string) { - return declarationName.toLowerCase() === typeDisplayString.toLowerCase(); - } - function visitCallOrNewExpression(expr: CallExpression | NewExpression) { const args = expr.arguments; if (!args || !args.length) {