-
Notifications
You must be signed in to change notification settings - Fork 36k
Add ts inline hints #113412
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ts inline hints #113412
Changes from 16 commits
a94ed00
6bf8b9d
65d2a64
5a760dd
3944756
396dbbb
66ff1fa
ca600b0
af45892
5302ebb
7b0cb49
b24a241
b914b0b
51612e8
b932538
4b0e101
bf6579e
c485647
5b77ff6
2a6f9da
af1b51a
16b2ff1
ead709b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -270,6 +270,100 @@ | |
| "description": "%configuration.suggest.includeAutomaticOptionalChainCompletions%", | ||
| "scope": "resource" | ||
| }, | ||
| "typescript.inlayHints.includeInlayParameterNameHints": { | ||
| "type": "string", | ||
| "enum": [ | ||
| "none", | ||
| "literals", | ||
| "all" | ||
| ], | ||
|
Comment on lines
+275
to
+279
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should add descriptions for these too.
@DanielRosenwasser, can you think of a more approachable way to describe this?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess if we can’t find a concise way to explain what literal expressions are or are not, these descriptions don’t add much.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated. |
||
| "default": "none", | ||
| "description": "%configuration.inlayHints.includeInlayParameterNameHints%", | ||
| "scope": "resource" | ||
| }, | ||
| "typescript.inlayHints.includeInlayFunctionParameterTypeHints": { | ||
| "type": "boolean", | ||
| "default": false, | ||
| "description": "%configuration.inlayHints.includeInlayFunctionParameterTypeHints%", | ||
| "scope": "resource" | ||
| }, | ||
| "typescript.inlayHints.includeInlayVariableTypeHints": { | ||
| "type": "boolean", | ||
| "default": false, | ||
| "description": "%configuration.inlayHints.includeInlayVariableTypeHints%", | ||
| "scope": "resource" | ||
Kingwl marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| }, | ||
| "typescript.inlayHints.includeInlayParameterNameHintsWhenArgumentMatchesName": { | ||
| "type": "boolean", | ||
| "default": false, | ||
| "description": "%configuration.inlayHints.includeInlayParameterNameHintsWhenArgumentMatchesName%", | ||
| "scope": "resource" | ||
| }, | ||
| "typescript.inlayHints.includeInlayPropertyDeclarationTypeHints": { | ||
| "type": "boolean", | ||
| "default": false, | ||
| "description": "%configuration.inlayHints.includeInlayPropertyDeclarationTypeHints%", | ||
| "scope": "resource" | ||
| }, | ||
| "typescript.inlayHints.includeInlayFunctionLikeReturnTypeHints": { | ||
| "type": "boolean", | ||
| "default": false, | ||
| "description": "%configuration.inlayHints.includeInlayFunctionLikeReturnTypeHints%", | ||
| "scope": "resource" | ||
| }, | ||
| "typescript.inlayHints.includeInlayEnumMemberValueHints": { | ||
| "type": "boolean", | ||
| "default": false, | ||
| "description": "%configuration.inlayHints.includeInlayEnumMemberValueHints%", | ||
| "scope": "resource" | ||
| }, | ||
| "javascript.inlayHints.includeInlayParameterNameHints": { | ||
| "type": "string", | ||
| "enum": [ | ||
| "none", | ||
| "literals", | ||
| "all" | ||
| ], | ||
| "default": "none", | ||
| "description": "%configuration.inlayHints.includeInlayParameterNameHints%", | ||
| "scope": "resource" | ||
| }, | ||
| "javascript.inlayHints.includeInlayFunctionParameterTypeHints": { | ||
| "type": "boolean", | ||
| "default": false, | ||
| "description": "%configuration.inlayHints.includeInlayFunctionParameterTypeHints%", | ||
| "scope": "resource" | ||
| }, | ||
| "javascript.inlayHints.includeInlayVariableTypeHints": { | ||
| "type": "boolean", | ||
| "default": false, | ||
| "description": "%configuration.inlayHints.includeInlayVariableTypeHints%", | ||
| "scope": "resource" | ||
| }, | ||
| "javascript.inlayHints.includeInlayParameterNameHintsWhenArgumentMatchesName": { | ||
| "type": "boolean", | ||
| "default": false, | ||
| "description": "%configuration.inlayHints.includeInlayParameterNameHintsWhenArgumentMatchesName%", | ||
| "scope": "resource" | ||
| }, | ||
| "javascript.inlayHints.includeInlayPropertyDeclarationTypeHints": { | ||
| "type": "boolean", | ||
| "default": false, | ||
| "description": "%configuration.inlayHints.includeInlayPropertyDeclarationTypeHints%", | ||
| "scope": "resource" | ||
| }, | ||
| "javascript.inlayHints.includeInlayFunctionLikeReturnTypeHints": { | ||
| "type": "boolean", | ||
| "default": false, | ||
| "description": "%configuration.inlayHints.includeInlayFunctionLikeReturnTypeHints%", | ||
| "scope": "resource" | ||
| }, | ||
| "javascript.inlayHints.includeInlayEnumMemberValueHints": { | ||
| "type": "boolean", | ||
| "default": false, | ||
| "description": "%configuration.inlayHints.includeInlayEnumMemberValueHints%", | ||
| "scope": "resource" | ||
| }, | ||
| "javascript.suggest.includeCompletionsForImportStatements": { | ||
| "type": "boolean", | ||
| "default": true, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,143 @@ | ||
| /*--------------------------------------------------------------------------------------------- | ||
| * Copyright (c) Microsoft Corporation. All rights reserved. | ||
| * Licensed under the MIT License. See License.txt in the project root for license information. | ||
| *--------------------------------------------------------------------------------------------*/ | ||
|
|
||
| import * as vscode from 'vscode'; | ||
| import * as Proto from '../protocol'; | ||
| import { DocumentSelector } from '../utils/documentSelector'; | ||
| import { ClientCapability, ITypeScriptServiceClient, ServerResponse, ExecConfig } from '../typescriptService'; | ||
| import { conditionalRegistration, requireMinVersion, requireSomeCapability } from '../utils/dependentRegistration'; | ||
| import { Position } from '../utils/typeConverters'; | ||
| import FileConfigurationManager, { getInlayHintsPreferences } from './fileConfigurationManager'; | ||
| import API from '../utils/api'; | ||
| import { isTypeScriptDocument } from '../utils/languageModeIds'; | ||
|
|
||
| namespace ExperimentalProto { | ||
| export const enum CommandTypes { | ||
| ProvideInlineHints = 'ProvideInlayHints' | ||
| } | ||
|
|
||
| export interface InlayHintsArgs extends Proto.FileRequestArgs { | ||
| /** | ||
| * Start position of the span. | ||
| */ | ||
| start: number; | ||
| /** | ||
| * Length of the span. | ||
| */ | ||
| length: number; | ||
| } | ||
|
|
||
| export interface InlineHintsRequest extends Proto.Request { | ||
| command: CommandTypes.ProvideInlineHints; | ||
| arguments: InlayHintsArgs; | ||
| } | ||
|
|
||
| export enum InlayHintKind { | ||
| Type = 'Type', | ||
| Parameter = 'Parameter', | ||
| Enum = 'Enum' | ||
| } | ||
|
|
||
| interface InlayHintItem { | ||
| text: string; | ||
| position: Proto.Location; | ||
| kind?: InlayHintKind; | ||
| whitespaceBefore?: boolean; | ||
| whitespaceAfter?: boolean; | ||
| } | ||
|
|
||
| export interface InlayHintsResponse extends Proto.Response { | ||
| body?: InlayHintItem[]; | ||
| } | ||
|
|
||
| export interface IExtendedTypeScriptServiceClient { | ||
| execute<K extends keyof ExtendedTsServerRequests>( | ||
| command: K, | ||
| args: ExtendedTsServerRequests[K][0], | ||
| token: vscode.CancellationToken, | ||
| config?: ExecConfig | ||
| ): Promise<ServerResponse.Response<ExtendedTsServerRequests[K][1]>>; | ||
| } | ||
|
|
||
| export interface ExtendedTsServerRequests { | ||
| 'provideInlayHints': [InlayHintsArgs, InlayHintsResponse]; | ||
| } | ||
|
|
||
| export namespace InlayHintKind { | ||
| export function fromProtocolInlayHintKind(kind: InlayHintKind): vscode.InlayHintKind { | ||
| switch (kind) { | ||
| case InlayHintKind.Parameter: | ||
| return vscode.InlayHintKind.Parameter; | ||
| case InlayHintKind.Type: | ||
| return vscode.InlayHintKind.Type; | ||
| case InlayHintKind.Enum: | ||
| return vscode.InlayHintKind.Other; | ||
| default: | ||
| return vscode.InlayHintKind.Other; | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| class TypeScriptInlayHintsProvider implements vscode.InlayHintsProvider { | ||
| public static readonly minVersion = API.v440; | ||
|
|
||
| constructor( | ||
| private readonly client: ITypeScriptServiceClient, | ||
| private readonly fileConfigurationManager: FileConfigurationManager | ||
| ) { } | ||
|
|
||
| async provideInlayHints(model: vscode.TextDocument, range: vscode.Range, token: vscode.CancellationToken): Promise<vscode.InlayHint[]> { | ||
| const filepath = this.client.toOpenedFilePath(model); | ||
| if (!filepath) { | ||
| return []; | ||
| } | ||
|
|
||
| await this.fileConfigurationManager.ensureConfigurationForDocument(model, token); | ||
|
|
||
| if (!this.someInlayHintsEnabled(model)) { | ||
Kingwl marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return []; | ||
| } | ||
|
|
||
| const start = model.offsetAt(range.start); | ||
| const length = model.offsetAt(range.end) - start; | ||
|
|
||
| const response = await (this.client as ExperimentalProto.IExtendedTypeScriptServiceClient).execute('provideInlayHints', { file: filepath, start, length }, token); | ||
| if (response.type !== 'response' || !response.success || !response.body) { | ||
| return []; | ||
| } | ||
|
|
||
| return response.body.map(hint => { | ||
| const result = new vscode.InlayHint( | ||
| hint.text, | ||
| Position.fromLocation(hint.position), | ||
| hint.kind && ExperimentalProto.InlayHintKind.fromProtocolInlayHintKind(hint.kind) | ||
| ); | ||
| result.whitespaceBefore = hint.whitespaceBefore; | ||
| result.whitespaceAfter = hint.whitespaceAfter; | ||
| return result; | ||
| }); | ||
| } | ||
|
|
||
| private someInlayHintsEnabled(model: vscode.TextDocument) { | ||
Kingwl marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| const config = vscode.workspace.getConfiguration(isTypeScriptDocument(model) ? 'typescript' : 'javascript', model.uri); | ||
|
||
| const preferences = getInlayHintsPreferences(config); | ||
| return Object.values(preferences).some(Boolean); | ||
| } | ||
| } | ||
|
|
||
| export function register( | ||
| selector: DocumentSelector, | ||
| client: ITypeScriptServiceClient, | ||
| fileConfigurationManager: FileConfigurationManager | ||
| ) { | ||
| return conditionalRegistration([ | ||
| requireMinVersion(client, TypeScriptInlayHintsProvider.minVersion), | ||
| requireSomeCapability(client, ClientCapability.Semantic), | ||
| ], () => { | ||
| return vscode.languages.registerInlayHintsProvider(selector.semantic, | ||
| new TypeScriptInlayHintsProvider(client, fileConfigurationManager)); | ||
| }); | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.