From 82f9fa3904d7fde3b3d4c3d6cdfc29cda9bd58a4 Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 27 Nov 2023 15:36:48 +0200 Subject: [PATCH 1/7] DEV2-4340 add chat interactive --- package.json | 6 +- .../extensionCommands/ChatActionProvider.ts | 119 ++++++++++++++++++ .../extensionCommands/getFuctionsSymbols.ts | 36 ++++++ .../extensionCommands/quickFix.ts | 57 --------- .../registerChatCommnmads.ts | 104 +++++++++++++++ .../extensionCommands/showInput.ts | 27 ++++ .../extensionCommands/slashCommands.ts | 27 ++++ .../tabnineChatWidgetWebview.ts | 21 +--- 8 files changed, 323 insertions(+), 74 deletions(-) create mode 100644 src/tabnineChatWidget/extensionCommands/ChatActionProvider.ts create mode 100644 src/tabnineChatWidget/extensionCommands/getFuctionsSymbols.ts delete mode 100644 src/tabnineChatWidget/extensionCommands/quickFix.ts create mode 100644 src/tabnineChatWidget/extensionCommands/registerChatCommnmads.ts create mode 100644 src/tabnineChatWidget/extensionCommands/showInput.ts create mode 100644 src/tabnineChatWidget/extensionCommands/slashCommands.ts diff --git a/package.json b/package.json index e810d28ddf..ca30da32ee 100644 --- a/package.json +++ b/package.json @@ -463,6 +463,10 @@ { "key": "ctrl+shift+q", "command": "tabnine.chat.focus-input" + }, + { + "key": "ctrl+i", + "command": "tabnine.chat.commands.inline.action" } ] }, @@ -480,4 +484,4 @@ "publisherId": "1924b661-7c19-45d9-9800-edeb32848fd7", "isPreReleaseVersion": false } -} +} \ No newline at end of file diff --git a/src/tabnineChatWidget/extensionCommands/ChatActionProvider.ts b/src/tabnineChatWidget/extensionCommands/ChatActionProvider.ts new file mode 100644 index 0000000000..1e27bae3f0 --- /dev/null +++ b/src/tabnineChatWidget/extensionCommands/ChatActionProvider.ts @@ -0,0 +1,119 @@ +/* eslint-disable no-param-reassign */ +/* eslint-disable max-classes-per-file */ +/* eslint-disable class-methods-use-this */ +import { + CodeAction, + CodeActionContext, + CodeActionKind, + ExtensionContext, + Range, + TextDocument, + languages, + CodeActionProvider, +} from "vscode"; + +export function registerChatActionProvider(context: ExtensionContext) { + context.subscriptions.push( + languages.registerCodeActionsProvider("*", new ChatActionProvider(), { + providedCodeActionKinds: [ + CodeActionKind.RefactorRewrite, + CodeActionKind.QuickFix, + ], + }) + ); +} + +class ChatActionProvider implements CodeActionProvider { + provideCodeActions( + document: TextDocument, + range: Range, + codeActionContext: CodeActionContext & { + triggerKind: number; + } + ): CodeAction[] { + if (codeActionContext.triggerKind !== 1) { + return []; + } + const resultActions: CodeAction[] = []; + + if (codeActionContext.diagnostics[0]?.range) { + const fixAction = new CodeAction( + "Fix with Tabnine", + CodeActionKind.QuickFix + ); + + fixAction.command = { + title: fixAction.title, + command: "tabnine.chat.commands.fix-code", + }; + resultActions.push(fixAction); + } + const refactor = new CodeAction( + "Ask Tabnine", + CodeActionKind.RefactorRewrite + ); + + refactor.command = { + title: refactor.title, + command: "tabnine.chat.commands.inline.action", + }; + resultActions.push(refactor); + return resultActions; + + // if (!window.activeTextEditor?.selection.isEmpty) { + // const refactor = new CodeAction( + // "Ask Tabnine", + // CodeActionKind.RefactorRewrite + // ); + + // refactor.command = { + // title: refactor.title, + // command: "tabnine.chat.commands.refactor-inline", + // arguments: [range], + // }; + + // resultActions.push(refactor); + // return resultActions; + // } + // if (!document.lineAt(range.start.line).text.trim()) { + // const refactor = new CodeAction( + // "Ask Tabnine", + // CodeActionKind.RefactorRewrite + // ); + + // refactor.command = { + // title: refactor.title, + // command: "tabnine.chat.commands.refactor-inline", + // arguments: [range], + // }; + + // resultActions.push(refactor); + // return resultActions; + // } + + // const relevantSymbols: SymbolInformation[] = await getFuctionsSymbols( + // document + // ); + + // const symbolInRange = relevantSymbols?.find((s) => + // s.location.range.contains(range) + // ); + // if (symbolInRange) { + // const refactor = new CodeAction( + // "Ask Tabnine", + // CodeActionKind.RefactorRewrite + // ); + + // refactor.command = { + // title: refactor.title, + // command: "tabnine.chat.commands.refactor-inline", + // arguments: [symbolInRange.location.range], + // }; + + // resultActions.push(refactor); + // return resultActions; + // } + + return resultActions; + } +} diff --git a/src/tabnineChatWidget/extensionCommands/getFuctionsSymbols.ts b/src/tabnineChatWidget/extensionCommands/getFuctionsSymbols.ts new file mode 100644 index 0000000000..7f413edd42 --- /dev/null +++ b/src/tabnineChatWidget/extensionCommands/getFuctionsSymbols.ts @@ -0,0 +1,36 @@ +import { + TextDocument, + commands, + SymbolInformation, + DocumentSymbol, + SymbolKind, +} from "vscode"; + +export async function getFuctionsSymbols(document: TextDocument) { + const documnetSymbols = await commands.executeCommand< + (SymbolInformation & DocumentSymbol)[] + >("vscode.executeDocumentSymbolProvider", document.uri); + + const relevantSymbols: SymbolInformation[] = []; + + documnetSymbols?.forEach((symbol) => { + if ( + symbol.kind === SymbolKind.Function || + symbol.kind === SymbolKind.Method + ) { + relevantSymbols.push(symbol); + } + + if (symbol.children) { + symbol.children.forEach((child) => { + if ( + child.kind === SymbolKind.Function || + child.kind === SymbolKind.Method + ) { + relevantSymbols.push((child as unknown) as SymbolInformation); + } + }); + } + }); + return relevantSymbols; +} diff --git a/src/tabnineChatWidget/extensionCommands/quickFix.ts b/src/tabnineChatWidget/extensionCommands/quickFix.ts deleted file mode 100644 index 787b9c2df1..0000000000 --- a/src/tabnineChatWidget/extensionCommands/quickFix.ts +++ /dev/null @@ -1,57 +0,0 @@ -import * as vscode from "vscode"; -import { CodeAction, Command, ExtensionContext, ProviderResult } from "vscode"; -import ChatViewProvider from "../ChatViewProvider"; - -export function registerChatQuickFix( - context: ExtensionContext, - chatProvider: ChatViewProvider -) { - context.subscriptions.push( - vscode.languages.registerCodeActionsProvider( - "*", - { - provideCodeActions( - _document, - _range, - codeActionContext - ): ProviderResult<(CodeAction | Command)[]> { - if (!codeActionContext.diagnostics[0]?.range) { - return []; - } - const fixAction = new vscode.CodeAction( - "Fix with Tabnine", - vscode.CodeActionKind.QuickFix - ); - - fixAction.command = { - title: fixAction.title, - command: "tabnine.chat.commands.fix-inline-code", - arguments: [codeActionContext.diagnostics[0].range], - }; - - return [fixAction]; - }, - }, - { - providedCodeActionKinds: [vscode.CodeActionKind.QuickFix], - } - ), - vscode.commands.registerCommand( - "tabnine.chat.commands.fix-inline-code", - (range: vscode.Range) => { - const editor = vscode.window.activeTextEditor; - if (editor) { - const newPosition = range.start; - const newSelection = new vscode.Selection( - newPosition.line, - 0, - newPosition.line, - editor.document.lineAt(newPosition.line).text.length - ); - editor.selection = newSelection; - } - void chatProvider.handleMessageSubmitted("/fix-code"); - } - ) - ); -} diff --git a/src/tabnineChatWidget/extensionCommands/registerChatCommnmads.ts b/src/tabnineChatWidget/extensionCommands/registerChatCommnmads.ts new file mode 100644 index 0000000000..5eb29bce7d --- /dev/null +++ b/src/tabnineChatWidget/extensionCommands/registerChatCommnmads.ts @@ -0,0 +1,104 @@ +/* eslint-disable no-param-reassign */ +import { + Disposable, + Selection, + SymbolInformation, + TextEditor, + commands, +} from "vscode"; +import ChatViewProvider from "../ChatViewProvider"; +import { getFuctionsSymbols } from "./getFuctionsSymbols"; +import { SLASH_COMANDS } from "./slashCommands"; +import { showInput } from "./showInput"; + +export function registerChatCommnmads( + chatProvider: ChatViewProvider +): Disposable { + return Disposable.from( + commands.registerTextEditorCommand( + "tabnine.chat.commands.explain-code", + (textEditor: TextEditor) => { + contextActionHandler(chatProvider, textEditor, "/explain-code"); + } + ), + commands.registerTextEditorCommand( + "tabnine.chat.commands.generate-tests", + (textEditor: TextEditor) => { + contextActionHandler(chatProvider, textEditor, "/generate-tests"); + } + ), + commands.registerTextEditorCommand( + "tabnine.chat.commands.document-code", + (textEditor: TextEditor) => { + contextActionHandler(chatProvider, textEditor, "/document-code"); + } + ), + commands.registerTextEditorCommand( + "tabnine.chat.commands.fix-code", + (textEditor: TextEditor) => { + contextActionHandler(chatProvider, textEditor, "/fix-code"); + } + ), + commands.registerTextEditorCommand( + "tabnine.chat.commands.inline.action", + (textEditor: TextEditor) => { + const items = SLASH_COMANDS.map(({ label, description }) => ({ + label, + description, + })); + void showInput(items).then((result) => { + const input = + SLASH_COMANDS.find(({ label }) => label === result)?.intent || + result; + + if (textEditor.selection.isEmpty) { + void getFuctionsSymbols(textEditor.document).then( + (relevantSymbols: SymbolInformation[]) => { + const symbolInRange = relevantSymbols?.find((s) => + s.location.range.contains(textEditor.selection.active) + ); + if (symbolInRange) { + const newSelection = new Selection( + symbolInRange.location.range.start, + symbolInRange.location.range.end + ); + textEditor.selection = newSelection; + } + } + ); + } + + if (input) { + void chatProvider.handleMessageSubmitted(input); + } + }); + } + ) + ); +} + +function contextActionHandler( + chatProvider: ChatViewProvider, + textEditor: TextEditor, + intent: string +): void { + if (textEditor.selection.isEmpty) { + void getFuctionsSymbols(textEditor.document).then( + (relevantSymbols: SymbolInformation[]) => { + const symbolInRange = relevantSymbols?.find((s) => + s.location.range.contains(textEditor.selection) + ); + + if (symbolInRange) { + const { range } = symbolInRange.location; + + const newSelection = new Selection(range.start, range.end); + textEditor.selection = newSelection; + } + void chatProvider.handleMessageSubmitted(intent); + } + ); + } else { + void chatProvider.handleMessageSubmitted(intent); + } +} diff --git a/src/tabnineChatWidget/extensionCommands/showInput.ts b/src/tabnineChatWidget/extensionCommands/showInput.ts new file mode 100644 index 0000000000..03950330b2 --- /dev/null +++ b/src/tabnineChatWidget/extensionCommands/showInput.ts @@ -0,0 +1,27 @@ +import { window, QuickPickItem } from "vscode"; + +export function showInput( + items: QuickPickItem[] = [] +): Promise { + return new Promise((resolve) => { + const view = window.createQuickPick(); + view.items = items; + view.placeholder = `Ask Tabnine ${ + items.length ? " or select from the list" : "" + }`; + view.onDidAccept(() => { + view.dispose(); + if (view.selectedItems.length) { + resolve(view.selectedItems[0].label); + } + resolve(view.value); + }); + view.onDidHide(() => { + setImmediate(() => { + view.dispose(); + resolve(undefined); + }); + }); + view.show(); + }); +} diff --git a/src/tabnineChatWidget/extensionCommands/slashCommands.ts b/src/tabnineChatWidget/extensionCommands/slashCommands.ts new file mode 100644 index 0000000000..891ef12363 --- /dev/null +++ b/src/tabnineChatWidget/extensionCommands/slashCommands.ts @@ -0,0 +1,27 @@ +export type SlashCommand = { + label: string; + intent: string; + description: string; +}; +export const SLASH_COMANDS: SlashCommand[] = [ + { + label: "explain", + intent: "/explain-code", + description: "Explain the selected code", + }, + { + label: "test", + intent: "/generate-test-for-code", + description: "Write tests for the selected code", + }, + { + label: "document", + intent: "/document-code", + description: "Add documentation for the selected code", + }, + { + label: "fix", + intent: "/fix-code", + description: "Find errors in the selected code and fix them", + }, +]; diff --git a/src/tabnineChatWidget/tabnineChatWidgetWebview.ts b/src/tabnineChatWidget/tabnineChatWidgetWebview.ts index e23d67e54e..d2a7c47f80 100644 --- a/src/tabnineChatWidget/tabnineChatWidgetWebview.ts +++ b/src/tabnineChatWidget/tabnineChatWidgetWebview.ts @@ -8,8 +8,9 @@ import { } from "../capabilities/capabilities"; import { getState } from "../binary/requests/requests"; import { Logger } from "../utils/logger"; -import { registerChatQuickFix } from "./extensionCommands/quickFix"; +import { registerChatActionProvider } from "./extensionCommands/ChatActionProvider"; import registerChatCodeLens from "./extensionCommands/codeLens"; +import { registerChatCommnmads } from "./extensionCommands/registerChatCommnmads"; const VIEW_ID = "tabnine.chat"; @@ -97,21 +98,9 @@ function registerWebview(context: ExtensionContext, serverUrl?: string): void { ...evalCommands, vscode.commands.registerCommand("tabnine.chat.focus-input", () => { void chatProvider.focusChatInput(); - }), - vscode.commands.registerCommand("tabnine.chat.commands.explain-code", () => - chatProvider.handleMessageSubmitted("/explain-code") - ), - vscode.commands.registerCommand( - "tabnine.chat.commands.generate-tests", - () => chatProvider.handleMessageSubmitted("/generate-test-for-code") - ), - vscode.commands.registerCommand("tabnine.chat.commands.document-code", () => - chatProvider.handleMessageSubmitted("/document-code") - ), - vscode.commands.registerCommand("tabnine.chat.commands.fix-code", () => - chatProvider.handleMessageSubmitted("/fix-code") - ) + }) ); - registerChatQuickFix(context, chatProvider); + context.subscriptions.push(registerChatCommnmads(chatProvider)); + registerChatActionProvider(context, chatProvider); registerChatCodeLens(context, chatProvider); } From fc79ee4fed1e799507157cbf72e1e14d06534d6c Mon Sep 17 00:00:00 2001 From: Dima Date: Wed, 29 Nov 2023 10:08:57 +0200 Subject: [PATCH 2/7] refactor --- .../codeLens/ChatCodeLensProvider.ts | 39 ++++--------------- .../extensionCommands/slashCommands.ts | 14 +++++-- .../tabnineChatWidgetWebview.ts | 2 +- 3 files changed, 19 insertions(+), 36 deletions(-) diff --git a/src/tabnineChatWidget/extensionCommands/codeLens/ChatCodeLensProvider.ts b/src/tabnineChatWidget/extensionCommands/codeLens/ChatCodeLensProvider.ts index a9de2df4bf..8cf7808609 100644 --- a/src/tabnineChatWidget/extensionCommands/codeLens/ChatCodeLensProvider.ts +++ b/src/tabnineChatWidget/extensionCommands/codeLens/ChatCodeLensProvider.ts @@ -1,14 +1,6 @@ -import { - CodeLens, - CodeLensProvider, - commands, - DocumentSymbol, - Location, - SymbolInformation, - SymbolKind, - TextDocument, -} from "vscode"; +import { CodeLens, CodeLensProvider, Location, TextDocument } from "vscode"; import { fireEvent } from "../../../binary/requests/requests"; +import { getFuctionsSymbols } from "../getFuctionsSymbols"; const CODE_LENS_ACTIONS = [ ["test", "generate-test-for-code"], @@ -16,8 +8,6 @@ const CODE_LENS_ACTIONS = [ ["explain", "explain-code"], ]; -const VALID_SYMBOLS = [SymbolKind.Function, SymbolKind.Method]; - const MAX_LINES = 2500; export default class ChatCodeLensProvider implements CodeLensProvider { @@ -28,31 +18,18 @@ export default class ChatCodeLensProvider implements CodeLensProvider { if (document.lineCount > MAX_LINES) { return []; } - const documnetSymbols = await commands.executeCommand< - (SymbolInformation & DocumentSymbol)[] - >("vscode.executeDocumentSymbolProvider", document.uri); + + const documnetSymbols = await getFuctionsSymbols(document); + if (!documnetSymbols?.length) { return []; } const lenses: CodeLens[] = []; - documnetSymbols - ?.filter((fn) => VALID_SYMBOLS.includes(fn.kind)) - .forEach(({ location }) => - lenses.push(...toIntentLens(location), toAskLens(location)) - ); - - documnetSymbols - ?.filter((symbol) => symbol.kind === SymbolKind.Class) - .forEach((classSymbol) => { - classSymbol.children - .filter((child) => VALID_SYMBOLS.includes(child.kind)) - .forEach((method) => { - const { location } = (method as unknown) as SymbolInformation; - lenses.push(...toIntentLens(location), toAskLens(location)); - }); - }); + documnetSymbols.forEach(({ location }) => { + lenses.push(...toIntentLens(location), toAskLens(location)); + }); void fireEvent({ name: "chat-lens-label-rendered", diff --git a/src/tabnineChatWidget/extensionCommands/slashCommands.ts b/src/tabnineChatWidget/extensionCommands/slashCommands.ts index 891ef12363..7b5ac05c5a 100644 --- a/src/tabnineChatWidget/extensionCommands/slashCommands.ts +++ b/src/tabnineChatWidget/extensionCommands/slashCommands.ts @@ -5,23 +5,29 @@ export type SlashCommand = { }; export const SLASH_COMANDS: SlashCommand[] = [ { - label: "explain", + label: "$(feedback) explain", intent: "/explain-code", description: "Explain the selected code", }, { - label: "test", + label: "$(beaker) test", intent: "/generate-test-for-code", description: "Write tests for the selected code", }, { - label: "document", + label: "$(checklist) document", intent: "/document-code", description: "Add documentation for the selected code", }, { - label: "fix", + label: "$(symbol-property) fix", intent: "/fix-code", description: "Find errors in the selected code and fix them", }, + { + label: "$(search) workspace", + intent: "/workspace", + description: + "Ask a question related to any code within your current workspace", + }, ]; diff --git a/src/tabnineChatWidget/tabnineChatWidgetWebview.ts b/src/tabnineChatWidget/tabnineChatWidgetWebview.ts index d2a7c47f80..cb72bccec7 100644 --- a/src/tabnineChatWidget/tabnineChatWidgetWebview.ts +++ b/src/tabnineChatWidget/tabnineChatWidgetWebview.ts @@ -101,6 +101,6 @@ function registerWebview(context: ExtensionContext, serverUrl?: string): void { }) ); context.subscriptions.push(registerChatCommnmads(chatProvider)); - registerChatActionProvider(context, chatProvider); + registerChatActionProvider(context); registerChatCodeLens(context, chatProvider); } From a6a4c620de83a7310e5d001bbb46d613bacaadd8 Mon Sep 17 00:00:00 2001 From: Dima Date: Tue, 5 Dec 2023 00:33:29 +0200 Subject: [PATCH 3/7] use multistep --- .../registerChatCommnmads.ts | 22 ++++---- .../extensionCommands/showInput.ts | 53 ++++++++++++++----- .../extensionCommands/slashCommands.ts | 14 +++++ 3 files changed, 64 insertions(+), 25 deletions(-) diff --git a/src/tabnineChatWidget/extensionCommands/registerChatCommnmads.ts b/src/tabnineChatWidget/extensionCommands/registerChatCommnmads.ts index 5eb29bce7d..0b57d6ec81 100644 --- a/src/tabnineChatWidget/extensionCommands/registerChatCommnmads.ts +++ b/src/tabnineChatWidget/extensionCommands/registerChatCommnmads.ts @@ -42,15 +42,15 @@ export function registerChatCommnmads( commands.registerTextEditorCommand( "tabnine.chat.commands.inline.action", (textEditor: TextEditor) => { - const items = SLASH_COMANDS.map(({ label, description }) => ({ - label, - description, - })); + const items = SLASH_COMANDS.map( + ({ label, description, multistep, intent }) => ({ + label, + description, + multistep, + intent, + }) + ); void showInput(items).then((result) => { - const input = - SLASH_COMANDS.find(({ label }) => label === result)?.intent || - result; - if (textEditor.selection.isEmpty) { void getFuctionsSymbols(textEditor.document).then( (relevantSymbols: SymbolInformation[]) => { @@ -66,10 +66,10 @@ export function registerChatCommnmads( } } ); - } - if (input) { - void chatProvider.handleMessageSubmitted(input); + if (result) { + void chatProvider.handleMessageSubmitted(result); + } } }); } diff --git a/src/tabnineChatWidget/extensionCommands/showInput.ts b/src/tabnineChatWidget/extensionCommands/showInput.ts index 03950330b2..08e44c9d46 100644 --- a/src/tabnineChatWidget/extensionCommands/showInput.ts +++ b/src/tabnineChatWidget/extensionCommands/showInput.ts @@ -1,26 +1,51 @@ -import { window, QuickPickItem } from "vscode"; +import { QuickPickItem, window } from "vscode"; -export function showInput( - items: QuickPickItem[] = [] -): Promise { +export function showInput< + T extends QuickPickItem & { multistep: boolean; intent: string } +>(items: T[] = []): Promise { return new Promise((resolve) => { - const view = window.createQuickPick(); + const view = window.createQuickPick(); view.items = items; - view.placeholder = `Ask Tabnine ${ + view.title = "Ask Tabnine"; + view.canSelectMany = false; + view.ignoreFocusOut = true; + view.placeholder = `Type your question${ items.length ? " or select from the list" : "" }`; view.onDidAccept(() => { - view.dispose(); - if (view.selectedItems.length) { - resolve(view.selectedItems[0].label); - } - resolve(view.value); + view.hide(); }); + view.onDidHide(() => { - setImmediate(() => { + if (view.selectedItems.length) { + if (view.selectedItems[0].multistep) { + void window + .showInputBox({ + placeHolder: view.selectedItems[0].description, + ignoreFocusOut: true, + }) + .then( + (value) => { + if (value) { + resolve(`${view.selectedItems[0].intent} ${value}`); + } else { + resolve(undefined); + } + view.dispose(); + }, + () => { + resolve(undefined); + view.dispose(); + } + ); + } else { + resolve(view.selectedItems[0].intent); + view.dispose(); + } + } else { + resolve(view.value); view.dispose(); - resolve(undefined); - }); + } }); view.show(); }); diff --git a/src/tabnineChatWidget/extensionCommands/slashCommands.ts b/src/tabnineChatWidget/extensionCommands/slashCommands.ts index 7b5ac05c5a..1e23c8ed51 100644 --- a/src/tabnineChatWidget/extensionCommands/slashCommands.ts +++ b/src/tabnineChatWidget/extensionCommands/slashCommands.ts @@ -1,33 +1,47 @@ +type SCOPE = "block" | "selection" | "none"; export type SlashCommand = { label: string; intent: string; description: string; + scope: SCOPE[]; + multistep: boolean; }; + export const SLASH_COMANDS: SlashCommand[] = [ { label: "$(feedback) explain", intent: "/explain-code", description: "Explain the selected code", + scope: ["selection", "block"], + multistep: false, }, { label: "$(beaker) test", intent: "/generate-test-for-code", description: "Write tests for the selected code", + scope: ["block"], + multistep: false, }, { label: "$(checklist) document", intent: "/document-code", description: "Add documentation for the selected code", + scope: ["block"], + multistep: false, }, { label: "$(symbol-property) fix", intent: "/fix-code", description: "Find errors in the selected code and fix them", + scope: ["block"], + multistep: false, }, { label: "$(search) workspace", intent: "/workspace", description: "Ask a question related to any code within your current workspace", + scope: ["none"], + multistep: true, }, ]; From 76a675b8c917ed2f93cef255235a1460da933285 Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 11 Dec 2023 17:51:38 +0200 Subject: [PATCH 4/7] fix show view --- .../extensionCommands/ChatActionProvider.ts | 75 +++---------------- .../extensionCommands/codeLens/index.ts | 34 ++------- .../extensionCommands/const.ts | 16 ++++ .../registerChatCommnmads.ts | 10 +-- .../extensionCommands/showInput.ts | 7 ++ 5 files changed, 43 insertions(+), 99 deletions(-) create mode 100644 src/tabnineChatWidget/extensionCommands/const.ts diff --git a/src/tabnineChatWidget/extensionCommands/ChatActionProvider.ts b/src/tabnineChatWidget/extensionCommands/ChatActionProvider.ts index 1e27bae3f0..2cdbc51eff 100644 --- a/src/tabnineChatWidget/extensionCommands/ChatActionProvider.ts +++ b/src/tabnineChatWidget/extensionCommands/ChatActionProvider.ts @@ -1,5 +1,3 @@ -/* eslint-disable no-param-reassign */ -/* eslint-disable max-classes-per-file */ /* eslint-disable class-methods-use-this */ import { CodeAction, @@ -11,15 +9,20 @@ import { languages, CodeActionProvider, } from "vscode"; +import { languagesFilter } from "./const"; export function registerChatActionProvider(context: ExtensionContext) { context.subscriptions.push( - languages.registerCodeActionsProvider("*", new ChatActionProvider(), { - providedCodeActionKinds: [ - CodeActionKind.RefactorRewrite, - CodeActionKind.QuickFix, - ], - }) + languages.registerCodeActionsProvider( + languagesFilter, + new ChatActionProvider(), + { + providedCodeActionKinds: [ + CodeActionKind.RefactorRewrite, + CodeActionKind.QuickFix, + ], + } + ) ); } @@ -59,61 +62,5 @@ class ChatActionProvider implements CodeActionProvider { }; resultActions.push(refactor); return resultActions; - - // if (!window.activeTextEditor?.selection.isEmpty) { - // const refactor = new CodeAction( - // "Ask Tabnine", - // CodeActionKind.RefactorRewrite - // ); - - // refactor.command = { - // title: refactor.title, - // command: "tabnine.chat.commands.refactor-inline", - // arguments: [range], - // }; - - // resultActions.push(refactor); - // return resultActions; - // } - // if (!document.lineAt(range.start.line).text.trim()) { - // const refactor = new CodeAction( - // "Ask Tabnine", - // CodeActionKind.RefactorRewrite - // ); - - // refactor.command = { - // title: refactor.title, - // command: "tabnine.chat.commands.refactor-inline", - // arguments: [range], - // }; - - // resultActions.push(refactor); - // return resultActions; - // } - - // const relevantSymbols: SymbolInformation[] = await getFuctionsSymbols( - // document - // ); - - // const symbolInRange = relevantSymbols?.find((s) => - // s.location.range.contains(range) - // ); - // if (symbolInRange) { - // const refactor = new CodeAction( - // "Ask Tabnine", - // CodeActionKind.RefactorRewrite - // ); - - // refactor.command = { - // title: refactor.title, - // command: "tabnine.chat.commands.refactor-inline", - // arguments: [symbolInRange.location.range], - // }; - - // resultActions.push(refactor); - // return resultActions; - // } - - return resultActions; } } diff --git a/src/tabnineChatWidget/extensionCommands/codeLens/index.ts b/src/tabnineChatWidget/extensionCommands/codeLens/index.ts index c0d8d3f109..0aa2e00d7f 100644 --- a/src/tabnineChatWidget/extensionCommands/codeLens/index.ts +++ b/src/tabnineChatWidget/extensionCommands/codeLens/index.ts @@ -11,23 +11,10 @@ import ChatCodeLensProvider from "./ChatCodeLensProvider"; import ChatViewProvider from "../../ChatViewProvider"; import tabnineExtensionProperties from "../../../globals/tabnineExtensionProperties"; import { fireEvent } from "../../../binary/requests/requests"; +import { showInput } from "../showInput"; +import { SLASH_COMANDS } from "../slashCommands"; +import { languagesFilter } from "../const"; -const languagesFilter = [ - { language: "javascript" }, - { pattern: "**/*[!d].ts", scheme: "file" }, - { language: "javascriptreact" }, - { language: "typescriptreact" }, - { language: "python" }, - { language: "ruby" }, - { language: "go" }, - { language: "rust" }, - { language: "swift" }, - { language: "java" }, - { language: "c" }, - { language: "cpp" }, - { language: "csharp" }, - { language: "php" }, -]; export default function registerChatCodeLens( context: ExtensionContext, chatProvider: ChatViewProvider @@ -69,16 +56,11 @@ export default function registerChatCodeLens( const newSelection = new Selection(range.start, range.end); editor.selection = newSelection; } - void window - .showInputBox({ - prompt: "ask tabnine", - ignoreFocusOut: true, - }) - .then((question) => { - if (question) { - void chatProvider.handleMessageSubmitted(question); - } - }); + void showInput(SLASH_COMANDS).then((question) => { + if (question) { + void chatProvider.handleMessageSubmitted(question); + } + }); }) ); } diff --git a/src/tabnineChatWidget/extensionCommands/const.ts b/src/tabnineChatWidget/extensionCommands/const.ts new file mode 100644 index 0000000000..63ef83cc19 --- /dev/null +++ b/src/tabnineChatWidget/extensionCommands/const.ts @@ -0,0 +1,16 @@ +export const languagesFilter = [ + { language: "javascript" }, + { pattern: "**/*[!d].ts", scheme: "file" }, + { language: "javascriptreact" }, + { language: "typescriptreact" }, + { language: "python" }, + { language: "ruby" }, + { language: "go" }, + { language: "rust" }, + { language: "swift" }, + { language: "java" }, + { language: "c" }, + { language: "cpp" }, + { language: "csharp" }, + { language: "php" }, +]; diff --git a/src/tabnineChatWidget/extensionCommands/registerChatCommnmads.ts b/src/tabnineChatWidget/extensionCommands/registerChatCommnmads.ts index 0b57d6ec81..10abffa976 100644 --- a/src/tabnineChatWidget/extensionCommands/registerChatCommnmads.ts +++ b/src/tabnineChatWidget/extensionCommands/registerChatCommnmads.ts @@ -42,15 +42,7 @@ export function registerChatCommnmads( commands.registerTextEditorCommand( "tabnine.chat.commands.inline.action", (textEditor: TextEditor) => { - const items = SLASH_COMANDS.map( - ({ label, description, multistep, intent }) => ({ - label, - description, - multistep, - intent, - }) - ); - void showInput(items).then((result) => { + void showInput(SLASH_COMANDS).then((result) => { if (textEditor.selection.isEmpty) { void getFuctionsSymbols(textEditor.document).then( (relevantSymbols: SymbolInformation[]) => { diff --git a/src/tabnineChatWidget/extensionCommands/showInput.ts b/src/tabnineChatWidget/extensionCommands/showInput.ts index 08e44c9d46..6030323b3c 100644 --- a/src/tabnineChatWidget/extensionCommands/showInput.ts +++ b/src/tabnineChatWidget/extensionCommands/showInput.ts @@ -4,6 +4,7 @@ export function showInput< T extends QuickPickItem & { multistep: boolean; intent: string } >(items: T[] = []): Promise { return new Promise((resolve) => { + let isAccepted = false; const view = window.createQuickPick(); view.items = items; view.title = "Ask Tabnine"; @@ -14,9 +15,15 @@ export function showInput< }`; view.onDidAccept(() => { view.hide(); + isAccepted = true; }); view.onDidHide(() => { + if (!isAccepted) { + resolve(undefined); + view.dispose(); + return; + } if (view.selectedItems.length) { if (view.selectedItems[0].multistep) { void window From 7ab83934ff58664ed9815403fb9775ded13bf655 Mon Sep 17 00:00:00 2001 From: Dima Date: Tue, 12 Dec 2023 01:27:02 +0200 Subject: [PATCH 5/7] fixes --- .../{codeLens => }/ChatCodeLensProvider.ts | 62 +++++++++++------- .../extensionCommands/codeLens/index.ts | 65 ------------------- .../{slashCommands.ts => commands.ts} | 32 ++++++++- .../registerChatCommnmads.ts | 54 ++++++++++++++- .../tabnineChatWidgetWebview.ts | 4 +- 5 files changed, 119 insertions(+), 98 deletions(-) rename src/tabnineChatWidget/extensionCommands/{codeLens => }/ChatCodeLensProvider.ts (63%) delete mode 100644 src/tabnineChatWidget/extensionCommands/codeLens/index.ts rename src/tabnineChatWidget/extensionCommands/{slashCommands.ts => commands.ts} (62%) diff --git a/src/tabnineChatWidget/extensionCommands/codeLens/ChatCodeLensProvider.ts b/src/tabnineChatWidget/extensionCommands/ChatCodeLensProvider.ts similarity index 63% rename from src/tabnineChatWidget/extensionCommands/codeLens/ChatCodeLensProvider.ts rename to src/tabnineChatWidget/extensionCommands/ChatCodeLensProvider.ts index a05c9eddf3..a3aa8a6e58 100644 --- a/src/tabnineChatWidget/extensionCommands/codeLens/ChatCodeLensProvider.ts +++ b/src/tabnineChatWidget/extensionCommands/ChatCodeLensProvider.ts @@ -3,31 +3,37 @@ import { CancellationToken, CodeLens, CodeLensProvider, - commands, Diagnostic, DiagnosticSeverity, - DocumentSymbol, Event, EventEmitter, + ExtensionContext, languages, Location, - SymbolInformation, - SymbolKind, TextDocument, Uri, } from "vscode"; -import { fireEvent } from "../../../binary/requests/requests"; - -const CODE_LENS_ACTIONS = [ - ["test", "generate-test-for-code"], - ["fix", "fix-code"], - ["explain", "explain-code"], - ["document", "document-code"], -]; +import { fireEvent } from "../../binary/requests/requests"; +import { getFuctionsSymbols } from "./getFuctionsSymbols"; +import { Action, COMANDS } from "./commands"; +import tabnineExtensionProperties from "../../globals/tabnineExtensionProperties"; +import { languagesFilter } from "./const"; const MAX_LINES = 2500; -export class ChatCodeLensProvider implements CodeLensProvider { +export default function registerChatCodeLens(context: ExtensionContext) { + if (!tabnineExtensionProperties.codeLensEnabled) { + return; + } + context.subscriptions.push( + languages.registerCodeLensProvider( + languagesFilter, + new ChatCodeLensProvider() + ) + ); +} + +class ChatCodeLensProvider implements CodeLensProvider { private visitedFiles: Set = new Set(); private didChangeCodeLenses = new EventEmitter(); @@ -63,7 +69,7 @@ export class ChatCodeLensProvider implements CodeLensProvider { const lenses: CodeLens[] = []; documnetSymbols.forEach(({ location }) => { - lenses.push(...toIntentLens(location), toAskLens(location)); + lenses.push(...toIntentLens(location, diagnostic), toAskLens(location)); }); if (!this.visitedFiles.has(document.uri)) { @@ -102,20 +108,26 @@ function toIntentLens( location: Location, diagnostics: Diagnostic[] ): CodeLens[] { - return CODE_LENS_ACTIONS.filter(([text]) => - filterRelevantActions(text, location, diagnostics) - ).map( - ([text, action], index) => - new CodeLens(location.range, { - title: `${index === 0 ? "tabnine: " : ""}${text}`, - tooltip: `tabnine ${text}`, - command: "tabnine.chat.commands.any", - arguments: [location.range, action], - }) + return ( + COMANDS.filter( + ({ text, lensOrder }) => + lensOrder && filterRelevantActions(text, location, diagnostics) + ) + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + .sort((a, b) => a.lensOrder! - b.lensOrder!) + .map( + ({ text, intent }, index) => + new CodeLens(location.range, { + title: `${index === 0 ? "tabnine: " : ""}${text}`, + tooltip: `tabnine ${text}`, + command: "tabnine.chat.commands.any", + arguments: [location.range, intent], + }) + ) ); } function filterRelevantActions( - text: Intents, + text: Action, location: Location, diagnostics: Diagnostic[] ): boolean { diff --git a/src/tabnineChatWidget/extensionCommands/codeLens/index.ts b/src/tabnineChatWidget/extensionCommands/codeLens/index.ts deleted file mode 100644 index a08aa5648b..0000000000 --- a/src/tabnineChatWidget/extensionCommands/codeLens/index.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { - commands, - ExtensionContext, - languages, - Range, - Selection, - window, -} from "vscode"; - -import ChatViewProvider from "../../ChatViewProvider"; -import tabnineExtensionProperties from "../../../globals/tabnineExtensionProperties"; -import { fireEvent } from "../../../binary/requests/requests"; -import { showInput } from "../showInput"; -import { SLASH_COMANDS } from "../slashCommands"; -import { languagesFilter } from "../const"; - -export default function registerChatCodeLens( - context: ExtensionContext, - chatProvider: ChatViewProvider -) { - if (!tabnineExtensionProperties.codeLensEnabled) { - return; - } - context.subscriptions.push( - languages.registerCodeLensProvider( - languagesFilter, - new ChatCodeLensProvider() - ), - commands.registerCommand( - "tabnine.chat.commands.any", - (range: Range, intent: Actions) => { - void fireEvent({ - name: "chat-lens-action", - intent, - language: window.activeTextEditor?.document.languageId, - }); - - const editor = window.activeTextEditor; - if (editor) { - const newSelection = new Selection(range.start, range.end); - editor.selection = newSelection; - } - void chatProvider.handleMessageSubmitted(`/${intent}`); - } - ), - commands.registerCommand("tabnine.chat.commands.ask", (range: Range) => { - void fireEvent({ - name: "chat-lens-action", - intent: "ask-question", - language: window.activeTextEditor?.document.languageId, - }); - - const editor = window.activeTextEditor; - if (editor) { - const newSelection = new Selection(range.start, range.end); - editor.selection = newSelection; - } - void showInput(SLASH_COMANDS).then((question) => { - if (question) { - void chatProvider.handleMessageSubmitted(question); - } - }); - }) - ); -} diff --git a/src/tabnineChatWidget/extensionCommands/slashCommands.ts b/src/tabnineChatWidget/extensionCommands/commands.ts similarity index 62% rename from src/tabnineChatWidget/extensionCommands/slashCommands.ts rename to src/tabnineChatWidget/extensionCommands/commands.ts index 1e23c8ed51..d79d00451b 100644 --- a/src/tabnineChatWidget/extensionCommands/slashCommands.ts +++ b/src/tabnineChatWidget/extensionCommands/commands.ts @@ -1,43 +1,69 @@ type SCOPE = "block" | "selection" | "none"; -export type SlashCommand = { +export type Action = "test" | "fix" | "explain" | "document" | "workspace"; +export type Intent = + | "/generate-test-for-code" + | "/fix-code" + | "/explain-code" + | "/document-code" + | "/workspace"; + +enum LensOrder { + test = 1, + fix = 2, + explain = 3, + document = 4, +} + +export type Command = { label: string; - intent: string; + text: Action; + intent: Intent; description: string; scope: SCOPE[]; multistep: boolean; + lensOrder?: LensOrder | undefined; }; -export const SLASH_COMANDS: SlashCommand[] = [ +export const COMANDS: Command[] = [ { label: "$(feedback) explain", + text: "explain", intent: "/explain-code", description: "Explain the selected code", scope: ["selection", "block"], multistep: false, + lensOrder: LensOrder.explain, }, { label: "$(beaker) test", + text: "test", intent: "/generate-test-for-code", description: "Write tests for the selected code", scope: ["block"], multistep: false, + lensOrder: LensOrder.test, }, { label: "$(checklist) document", + text: "document", intent: "/document-code", description: "Add documentation for the selected code", scope: ["block"], multistep: false, + lensOrder: LensOrder.document, }, { label: "$(symbol-property) fix", + text: "fix", intent: "/fix-code", description: "Find errors in the selected code and fix them", scope: ["block"], multistep: false, + lensOrder: LensOrder.fix, }, { label: "$(search) workspace", + text: "workspace", intent: "/workspace", description: "Ask a question related to any code within your current workspace", diff --git a/src/tabnineChatWidget/extensionCommands/registerChatCommnmads.ts b/src/tabnineChatWidget/extensionCommands/registerChatCommnmads.ts index 10abffa976..e192acc6d7 100644 --- a/src/tabnineChatWidget/extensionCommands/registerChatCommnmads.ts +++ b/src/tabnineChatWidget/extensionCommands/registerChatCommnmads.ts @@ -1,15 +1,18 @@ /* eslint-disable no-param-reassign */ import { Disposable, + Range, Selection, SymbolInformation, TextEditor, commands, + window, } from "vscode"; import ChatViewProvider from "../ChatViewProvider"; import { getFuctionsSymbols } from "./getFuctionsSymbols"; -import { SLASH_COMANDS } from "./slashCommands"; +import { COMANDS, Intent } from "./commands"; import { showInput } from "./showInput"; +import { fireEvent } from "../../binary/requests/requests"; export function registerChatCommnmads( chatProvider: ChatViewProvider @@ -42,7 +45,7 @@ export function registerChatCommnmads( commands.registerTextEditorCommand( "tabnine.chat.commands.inline.action", (textEditor: TextEditor) => { - void showInput(SLASH_COMANDS).then((result) => { + void showInput(COMANDS).then((result) => { if (textEditor.selection.isEmpty) { void getFuctionsSymbols(textEditor.document).then( (relevantSymbols: SymbolInformation[]) => { @@ -60,12 +63,52 @@ export function registerChatCommnmads( ); if (result) { + void fireEvent({ + name: "chat-ide-action", + intent: result, + language: window.activeTextEditor?.document.languageId, + }); void chatProvider.handleMessageSubmitted(result); } } }); } - ) + ), + commands.registerCommand( + "tabnine.chat.commands.any", + (range: Range, intent: Intent) => { + void fireEvent({ + name: "chat-lens-action", + intent, + language: window.activeTextEditor?.document.languageId, + }); + + const editor = window.activeTextEditor; + if (editor) { + const newSelection = new Selection(range.start, range.end); + editor.selection = newSelection; + } + void chatProvider.handleMessageSubmitted(intent); + } + ), + commands.registerCommand("tabnine.chat.commands.ask", (range: Range) => { + void fireEvent({ + name: "chat-lens-action", + intent: "ask-question", + language: window.activeTextEditor?.document.languageId, + }); + + const editor = window.activeTextEditor; + if (editor) { + const newSelection = new Selection(range.start, range.end); + editor.selection = newSelection; + } + void showInput(COMANDS).then((question) => { + if (question) { + void chatProvider.handleMessageSubmitted(question); + } + }); + }) ); } @@ -74,6 +117,11 @@ function contextActionHandler( textEditor: TextEditor, intent: string ): void { + void fireEvent({ + name: "chat-ide-action", + intent, + language: window.activeTextEditor?.document.languageId, + }); if (textEditor.selection.isEmpty) { void getFuctionsSymbols(textEditor.document).then( (relevantSymbols: SymbolInformation[]) => { diff --git a/src/tabnineChatWidget/tabnineChatWidgetWebview.ts b/src/tabnineChatWidget/tabnineChatWidgetWebview.ts index fedf4f8ae6..27d148f56d 100644 --- a/src/tabnineChatWidget/tabnineChatWidgetWebview.ts +++ b/src/tabnineChatWidget/tabnineChatWidgetWebview.ts @@ -4,9 +4,9 @@ import ChatViewProvider from "./ChatViewProvider"; import { getState } from "../binary/requests/requests"; import { Logger } from "../utils/logger"; import { registerChatActionProvider } from "./extensionCommands/ChatActionProvider"; -import registerChatCodeLens from "./extensionCommands/codeLens"; import { registerChatCommnmads } from "./extensionCommands/registerChatCommnmads"; import ChatEnabledState, { ChatNotEnabledReason } from "./ChatEnabledState"; +import registerChatCodeLens from "./extensionCommands/ChatCodeLensProvider"; const VIEW_ID = "tabnine.chat"; @@ -103,7 +103,7 @@ function registerWebview( ); context.subscriptions.push(registerChatCommnmads(chatProvider)); registerChatActionProvider(context); - registerChatCodeLens(context, chatProvider); + registerChatCodeLens(context); hasRegisteredChatWebview = true; } From cff1aaf067e2b3bba7c4b3e36b899ebb452a53a6 Mon Sep 17 00:00:00 2001 From: Dima Date: Tue, 12 Dec 2023 01:28:43 +0200 Subject: [PATCH 6/7] prettier --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 60cf73d841..d9a5f2a9ff 100644 --- a/package.json +++ b/package.json @@ -502,4 +502,4 @@ "publisherId": "1924b661-7c19-45d9-9800-edeb32848fd7", "isPreReleaseVersion": false } -} \ No newline at end of file +} From 4361407d206fc10c5a41194280576f851fb29d91 Mon Sep 17 00:00:00 2001 From: Dima Date: Fri, 15 Dec 2023 01:25:43 +0200 Subject: [PATCH 7/7] review --- .../extensionCommands/ChatCodeLensProvider.ts | 32 ++++++++----------- .../extensionCommands/commands.ts | 12 ++++--- .../registerChatCommnmads.ts | 20 ++++++------ .../extensionCommands/showInput.ts | 19 +++++------ 4 files changed, 43 insertions(+), 40 deletions(-) diff --git a/src/tabnineChatWidget/extensionCommands/ChatCodeLensProvider.ts b/src/tabnineChatWidget/extensionCommands/ChatCodeLensProvider.ts index a3aa8a6e58..c9480f8f74 100644 --- a/src/tabnineChatWidget/extensionCommands/ChatCodeLensProvider.ts +++ b/src/tabnineChatWidget/extensionCommands/ChatCodeLensProvider.ts @@ -15,7 +15,7 @@ import { } from "vscode"; import { fireEvent } from "../../binary/requests/requests"; import { getFuctionsSymbols } from "./getFuctionsSymbols"; -import { Action, COMANDS } from "./commands"; +import { Action, CODE_LENS_COMMANDS } from "./commands"; import tabnineExtensionProperties from "../../globals/tabnineExtensionProperties"; import { languagesFilter } from "./const"; @@ -108,23 +108,19 @@ function toIntentLens( location: Location, diagnostics: Diagnostic[] ): CodeLens[] { - return ( - COMANDS.filter( - ({ text, lensOrder }) => - lensOrder && filterRelevantActions(text, location, diagnostics) - ) - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - .sort((a, b) => a.lensOrder! - b.lensOrder!) - .map( - ({ text, intent }, index) => - new CodeLens(location.range, { - title: `${index === 0 ? "tabnine: " : ""}${text}`, - tooltip: `tabnine ${text}`, - command: "tabnine.chat.commands.any", - arguments: [location.range, intent], - }) - ) - ); + return CODE_LENS_COMMANDS.filter(({ text }) => + filterRelevantActions(text, location, diagnostics) + ) + .sort((a, b) => a.lensOrder - b.lensOrder) + .map( + ({ text, intent }, index) => + new CodeLens(location.range, { + title: `${index === 0 ? "tabnine: " : ""}${text}`, + tooltip: `tabnine ${text}`, + command: "tabnine.chat.commands.any", + arguments: [location.range, intent], + }) + ); } function filterRelevantActions( text: Action, diff --git a/src/tabnineChatWidget/extensionCommands/commands.ts b/src/tabnineChatWidget/extensionCommands/commands.ts index d79d00451b..3dd5559d91 100644 --- a/src/tabnineChatWidget/extensionCommands/commands.ts +++ b/src/tabnineChatWidget/extensionCommands/commands.ts @@ -1,4 +1,4 @@ -type SCOPE = "block" | "selection" | "none"; +export type Scope = "block" | "selection" | "none"; export type Action = "test" | "fix" | "explain" | "document" | "workspace"; export type Intent = | "/generate-test-for-code" @@ -19,12 +19,12 @@ export type Command = { text: Action; intent: Intent; description: string; - scope: SCOPE[]; + scope: Scope[]; multistep: boolean; - lensOrder?: LensOrder | undefined; }; +export type LensCommand = Command & { lensOrder: number }; -export const COMANDS: Command[] = [ +export const CODE_LENS_COMMANDS: LensCommand[] = [ { label: "$(feedback) explain", text: "explain", @@ -61,6 +61,10 @@ export const COMANDS: Command[] = [ multistep: false, lensOrder: LensOrder.fix, }, +]; + +export const COMANDS: Command[] = [ + ...CODE_LENS_COMMANDS, { label: "$(search) workspace", text: "workspace", diff --git a/src/tabnineChatWidget/extensionCommands/registerChatCommnmads.ts b/src/tabnineChatWidget/extensionCommands/registerChatCommnmads.ts index e192acc6d7..4197d5b38c 100644 --- a/src/tabnineChatWidget/extensionCommands/registerChatCommnmads.ts +++ b/src/tabnineChatWidget/extensionCommands/registerChatCommnmads.ts @@ -45,8 +45,11 @@ export function registerChatCommnmads( commands.registerTextEditorCommand( "tabnine.chat.commands.inline.action", (textEditor: TextEditor) => { - void showInput(COMANDS).then((result) => { - if (textEditor.selection.isEmpty) { + void showInput(COMANDS).then(([result, command]) => { + if ( + textEditor.selection.isEmpty && + !command?.scope.includes("none") + ) { void getFuctionsSymbols(textEditor.document).then( (relevantSymbols: SymbolInformation[]) => { const symbolInRange = relevantSymbols?.find((s) => @@ -97,13 +100,12 @@ export function registerChatCommnmads( intent: "ask-question", language: window.activeTextEditor?.document.languageId, }); - - const editor = window.activeTextEditor; - if (editor) { - const newSelection = new Selection(range.start, range.end); - editor.selection = newSelection; - } - void showInput(COMANDS).then((question) => { + void showInput(COMANDS).then(([question, command]) => { + const editor = window.activeTextEditor; + if (question && editor && !command?.scope.includes("none")) { + const newSelection = new Selection(range.start, range.end); + editor.selection = newSelection; + } if (question) { void chatProvider.handleMessageSubmitted(question); } diff --git a/src/tabnineChatWidget/extensionCommands/showInput.ts b/src/tabnineChatWidget/extensionCommands/showInput.ts index 6030323b3c..82e576d7bf 100644 --- a/src/tabnineChatWidget/extensionCommands/showInput.ts +++ b/src/tabnineChatWidget/extensionCommands/showInput.ts @@ -2,14 +2,13 @@ import { QuickPickItem, window } from "vscode"; export function showInput< T extends QuickPickItem & { multistep: boolean; intent: string } ->(items: T[] = []): Promise { +>(items: T[] = []): Promise<[string?, T?]> { return new Promise((resolve) => { let isAccepted = false; const view = window.createQuickPick(); view.items = items; view.title = "Ask Tabnine"; view.canSelectMany = false; - view.ignoreFocusOut = true; view.placeholder = `Type your question${ items.length ? " or select from the list" : "" }`; @@ -20,7 +19,7 @@ export function showInput< view.onDidHide(() => { if (!isAccepted) { - resolve(undefined); + resolve([]); view.dispose(); return; } @@ -29,28 +28,30 @@ export function showInput< void window .showInputBox({ placeHolder: view.selectedItems[0].description, - ignoreFocusOut: true, }) .then( (value) => { if (value) { - resolve(`${view.selectedItems[0].intent} ${value}`); + resolve([ + `${view.selectedItems[0].intent} ${value}`, + view.selectedItems[0], + ]); } else { - resolve(undefined); + resolve([]); } view.dispose(); }, () => { - resolve(undefined); + resolve([]); view.dispose(); } ); } else { - resolve(view.selectedItems[0].intent); + resolve([view.selectedItems[0].intent, view.selectedItems[0]]); view.dispose(); } } else { - resolve(view.value); + resolve([view.value]); view.dispose(); } });