Skip to content
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

chore(vscode): Auto apply select quick fixes after inline code completion/code edit #3159

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions clients/vscode/src/CodeAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import { ContextVariables } from "./ContextVariables";
export class CodeActionProvider implements CodeActionProviderInterface {
constructor(private readonly contextVariables: ContextVariables) {}

public static readonly providedCodeActionKinds = [CodeActionKind.RefactorRewrite];

provideCodeActions(
_document: TextDocument,
_range: Range | Selection,
Expand Down
43 changes: 37 additions & 6 deletions clients/vscode/src/Commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import {
ProgressLocation,
ThemeIcon,
QuickPickItem,
CodeActionKind,
CodeAction,
Range,
} from "vscode";
import os from "os";
import path from "path";
Expand All @@ -25,6 +28,7 @@ import CommandPalette from "./CommandPalette";
import { showOutputPanel } from "./logger";
import { Issues } from "./Issues";
import { InlineEditController } from "./inline-edit";
import { getLogger } from "./logger";

export class Commands {
private chatEditCancellationTokenSource: CancellationTokenSource | null = null;
Expand Down Expand Up @@ -218,8 +222,15 @@ export class Commands {
"inlineCompletion.trigger": () => {
commands.executeCommand("editor.action.inlineSuggest.trigger");
},
"inlineCompletion.accept": () => {
commands.executeCommand("editor.action.inlineSuggest.commit");
"inlineCompletion.accept": async () => {
const editor = window.activeTextEditor;
if (!editor) {
return;
}
const uri = editor.document.uri;
const range = new Range(editor.selection.start.line, 0, editor.selection.end.line + 1, 0);
await commands.executeCommand("editor.action.inlineSuggest.commit");
await applyQuickFixes(uri, range);
},
"inlineCompletion.acceptNextWord": () => {
this.inlineCompletionProvider.handleEvent("accept_word");
Expand Down Expand Up @@ -312,12 +323,10 @@ export class Commands {
}
const location = {
uri: editor.document.uri.toString(),
range: {
start: { line: editor.selection.start.line, character: 0 },
end: { line: editor.selection.end.line + 1, character: 0 },
},
range: new Range(editor.selection.start.line, 0, editor.selection.end.line + 1, 0),
};
await this.client.chat.resolveEdit({ location, action: "accept" });
await applyQuickFixes(editor.document.uri, location.range);
},
"chat.edit.discard": async () => {
const editor = window.activeTextEditor;
Expand Down Expand Up @@ -429,3 +438,25 @@ export class Commands {
},
};
}

async function applyQuickFixes(uri: Uri, range: Range): Promise<void> {
const codeActions = await commands.executeCommand<CodeAction[]>("vscode.executeCodeActionProvider", uri, range);
const quickFixActions = codeActions.filter(
(action) =>
action.kind && action.kind.contains(CodeActionKind.QuickFix) && action.title.toLowerCase().includes("import"),
);
quickFixActions.forEach(async (action) => {
try {
getLogger().info(`Applying CodeActions for ${action.title}.`);
if (action.edit) {
await workspace.applyEdit(action.edit);
}
if (action.command) {
await commands.executeCommand(action.command.command, action.command.arguments);
}
} catch (error) {
getLogger().error(`Exception when apply CodeActions for ${action.title}`);
// ignore the error
}
});
}
6 changes: 5 additions & 1 deletion clients/vscode/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ let client: Client | undefined = undefined;

export async function activate(context: ExtensionContext) {
logger.info("Activating Tabby extension...");

const clientOptions: LanguageClientOptions = {
documentSelector: [
{ scheme: "file" },
Expand Down Expand Up @@ -57,7 +58,10 @@ export async function activate(context: ExtensionContext) {
client.registerConfigManager(config);
client.registerInlineCompletionProvider(inlineCompletionProvider);
client.registerGitProvider(gitProvider);
client.registerCodeActionProvider(new CodeActionProvider(contextVariables));
client.registerCodeActionProvider(
new CodeActionProvider(contextVariables),
CodeActionProvider.providedCodeActionKinds,
);

// Register config callback for past ServerConfig
client.agent.addListener("didChangeStatus", async (status: Status) => {
Expand Down
8 changes: 5 additions & 3 deletions clients/vscode/src/lsp/Client.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { CodeActionProvider, ExtensionContext, languages } from "vscode";
import { CodeActionKind, CodeActionProvider, ExtensionContext, languages } from "vscode";
import { BaseLanguageClient } from "vscode-languageclient";
import { AgentFeature } from "./AgentFeature";
import { ChatFeature } from "./ChatFeature";
Expand Down Expand Up @@ -74,7 +74,9 @@ export class Client {
const feature = new GitProviderFeature(this.languageClient, provider);
this.languageClient.registerFeature(feature);
}
registerCodeActionProvider(provider: CodeActionProvider) {
this.context.subscriptions.push(languages.registerCodeActionsProvider("*", provider));
registerCodeActionProvider(provider: CodeActionProvider, kind: CodeActionKind[]) {
this.context.subscriptions.push(
languages.registerCodeActionsProvider("*", provider, { providedCodeActionKinds: kind }),
);
}
}