diff --git a/extensions/typescript-language-features/src/languageFeatures/quickFix.ts b/extensions/typescript-language-features/src/languageFeatures/quickFix.ts index 8c8ce642d4f..e96ade47e2a 100644 --- a/extensions/typescript-language-features/src/languageFeatures/quickFix.ts +++ b/extensions/typescript-language-features/src/languageFeatures/quickFix.ts @@ -25,7 +25,57 @@ type ApplyCodeActionCommand_args = { readonly action: Proto.CodeFixAction; readonly followupAction?: Command; }; +type EditorChatReplacementCommand_args = { + readonly message: string; + readonly document: vscode.TextDocument; + readonly diagnostic: vscode.Diagnostic; +}; +class EditorChatReplacementCommand implements Command { + public static readonly ID = '_typescript.quickFix.editorChatReplacement'; + public readonly id = EditorChatReplacementCommand.ID; + constructor( + private readonly client: ITypeScriptServiceClient, + private readonly diagnosticManager: DiagnosticsManager, + ) { + } + async execute({ message, document, diagnostic }: EditorChatReplacementCommand_args) { + // TODO: "this code" is not specific; might get better results with a more specific referent + // TODO: Doesn't work in JS files? Is this the span-finder's fault? Try falling back to startLine plus something. + // TODO: Need to emit jsdoc in JS files once it's working at all + // TODO: When there are "enough" types around, leave off the "Add separate interfaces when possible" because it's not helpful. + // (brainstorming: enough non-primitives, or evidence of type aliases in the same file, or imported) + this.diagnosticManager.deleteDiagnostic(document.uri, diagnostic); + await editorChat(this.client, document, diagnostic.range.start.line, message); + } +} +function findScopeEndLineFromNavTree(startLine: number, navigationTree: Proto.NavigationTree[]): vscode.Range | undefined { + for (const node of navigationTree) { + const range = typeConverters.Range.fromTextSpan(node.spans[0]); + if (startLine === range.start.line) { + return range; + } else if (startLine > range.start.line && startLine <= range.end.line && node.childItems) { + return findScopeEndLineFromNavTree(startLine, node.childItems); + } + } + return undefined; +} +async function editorChat(client: ITypeScriptServiceClient, document: vscode.TextDocument, startLine: number, message: string) { + const filepath = client.toOpenTsFilePath(document); + if (!filepath) { + return; + } + const response = await client.execute('navtree', { file: filepath }, nulToken); + if (response.type !== 'response' || !response.body?.childItems) { + return; + } + const initialRange = findScopeEndLineFromNavTree(startLine, response.body.childItems); + if (!initialRange) { + return; + } + + await vscode.commands.executeCommand('vscode.editorChat.start', { initialRange, message, autoSend: true }); +} class EditorChatFollowUp implements Command { id: string = '_typescript.quickFix.editorChatFollowUp'; @@ -34,17 +84,7 @@ class EditorChatFollowUp implements Command { } async execute() { - const findScopeEndLineFromNavTree = (startLine: number, navigationTree: Proto.NavigationTree[]): vscode.Range | undefined => { - for (const node of navigationTree) { - const range = typeConverters.Range.fromTextSpan(node.spans[0]); - if (startLine === range.start.line) { - return range; - } else if (startLine > range.start.line && startLine <= range.end.line && node.childItems) { - return findScopeEndLineFromNavTree(startLine, node.childItems); - } - } - return undefined; - }; + await editorChat(this.client, this.document, this.range.start.line, this.prompt); const filepath = this.client.toOpenTsFilePath(this.document); if (!filepath) { return; @@ -257,6 +297,7 @@ class TypeScriptQuickFixProvider implements vscode.CodeActionProvider{ action: tsAction, diagnostic, document, followupAction }], title: '' }; - return codeAction; + actions.push(codeAction); + return actions; } private addFixAllForTsCodeAction( diff --git a/src/vscode-dts/vscode.d.ts b/src/vscode-dts/vscode.d.ts index 8c72191f57e..f521179e742 100644 --- a/src/vscode-dts/vscode.d.ts +++ b/src/vscode-dts/vscode.d.ts @@ -2406,6 +2406,7 @@ declare module 'vscode' { * to refactor code. * * A CodeAction must set either {@linkcode CodeAction.edit edit} and/or a {@linkcode CodeAction.command command}. If both are supplied, the `edit` is applied first, then the command is executed. + * NOTE: This is wrong: at least for VsCodeCodeAction; both edit and command are required. */ export class CodeAction {