Przeglądaj źródła

Merge pull request #594 from samhvw8/feat/code-action-with-current-task

feat(code-actions): add "Fix Code in Current Task" action
Matt Rubens 11 miesięcy temu
rodzic
commit
ed1f656258

+ 23 - 6
src/core/CodeActionProvider.ts

@@ -1,5 +1,6 @@
 import * as vscode from "vscode"
 import * as path from "path"
+import { ClineProvider } from "./webview/ClineProvider"
 
 export const ACTION_NAMES = {
 	EXPLAIN: "Roo Code: Explain Code",
@@ -113,6 +114,18 @@ export class CodeActionProvider implements vscode.CodeActionProvider {
 		return action
 	}
 
+	private createActionPair(
+		baseTitle: string,
+		kind: vscode.CodeActionKind,
+		baseCommand: string,
+		args: any[],
+	): vscode.CodeAction[] {
+		return [
+			this.createAction(`${baseTitle} in New Task`, kind, baseCommand, args),
+			this.createAction(`${baseTitle} in Current Task`, kind, `${baseCommand}InCurrentTask`, args),
+		]
+	}
+
 	private hasIntersectingRange(range1: vscode.Range, range2: vscode.Range): boolean {
 		// Optimize range intersection check
 		return !(
@@ -138,8 +151,9 @@ export class CodeActionProvider implements vscode.CodeActionProvider {
 			const actions: vscode.CodeAction[] = []
 
 			// Create actions using helper method
+			// Add explain actions
 			actions.push(
-				this.createAction(ACTION_NAMES.EXPLAIN, vscode.CodeActionKind.QuickFix, COMMAND_IDS.EXPLAIN, [
+				...this.createActionPair(ACTION_NAMES.EXPLAIN, vscode.CodeActionKind.QuickFix, COMMAND_IDS.EXPLAIN, [
 					filePath,
 					effectiveRange.text,
 				]),
@@ -154,7 +168,7 @@ export class CodeActionProvider implements vscode.CodeActionProvider {
 				if (relevantDiagnostics.length > 0) {
 					const diagnosticMessages = relevantDiagnostics.map(this.createDiagnosticData)
 					actions.push(
-						this.createAction(ACTION_NAMES.FIX, vscode.CodeActionKind.QuickFix, COMMAND_IDS.FIX, [
+						...this.createActionPair(ACTION_NAMES.FIX, vscode.CodeActionKind.QuickFix, COMMAND_IDS.FIX, [
 							filePath,
 							effectiveRange.text,
 							diagnosticMessages,
@@ -163,11 +177,14 @@ export class CodeActionProvider implements vscode.CodeActionProvider {
 				}
 			}
 
+			// Add improve actions
 			actions.push(
-				this.createAction(ACTION_NAMES.IMPROVE, vscode.CodeActionKind.RefactorRewrite, COMMAND_IDS.IMPROVE, [
-					filePath,
-					effectiveRange.text,
-				]),
+				...this.createActionPair(
+					ACTION_NAMES.IMPROVE,
+					vscode.CodeActionKind.RefactorRewrite,
+					COMMAND_IDS.IMPROVE,
+					[filePath, effectiveRange.text],
+				),
 			)
 
 			return actions

+ 9 - 6
src/core/__tests__/CodeActionProvider.test.ts

@@ -1,5 +1,5 @@
 import * as vscode from "vscode"
-import { CodeActionProvider } from "../CodeActionProvider"
+import { CodeActionProvider, ACTION_NAMES } from "../CodeActionProvider"
 
 // Mock VSCode API
 jest.mock("vscode", () => ({
@@ -109,9 +109,11 @@ describe("CodeActionProvider", () => {
 		it("should provide explain and improve actions by default", () => {
 			const actions = provider.provideCodeActions(mockDocument, mockRange, mockContext)
 
-			expect(actions).toHaveLength(2)
-			expect((actions as any)[0].title).toBe("Roo Code: Explain Code")
-			expect((actions as any)[1].title).toBe("Roo Code: Improve Code")
+			expect(actions).toHaveLength(4)
+			expect((actions as any)[0].title).toBe(`${ACTION_NAMES.EXPLAIN} in New Task`)
+			expect((actions as any)[1].title).toBe(`${ACTION_NAMES.EXPLAIN} in Current Task`)
+			expect((actions as any)[2].title).toBe(`${ACTION_NAMES.IMPROVE} in New Task`)
+			expect((actions as any)[3].title).toBe(`${ACTION_NAMES.IMPROVE} in Current Task`)
 		})
 
 		it("should provide fix action when diagnostics exist", () => {
@@ -125,8 +127,9 @@ describe("CodeActionProvider", () => {
 
 			const actions = provider.provideCodeActions(mockDocument, mockRange, mockContext)
 
-			expect(actions).toHaveLength(3)
-			expect((actions as any).some((a: any) => a.title === "Roo Code: Fix Code")).toBe(true)
+			expect(actions).toHaveLength(6)
+			expect((actions as any).some((a: any) => a.title === `${ACTION_NAMES.FIX} in New Task`)).toBe(true)
+			expect((actions as any).some((a: any) => a.title === `${ACTION_NAMES.FIX} in Current Task`)).toBe(true)
 		})
 
 		it("should handle errors gracefully", () => {

+ 37 - 4
src/core/webview/ClineProvider.ts

@@ -188,10 +188,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
 		return findLast(Array.from(this.activeInstances), (instance) => instance.view?.visible === true)
 	}
 
-	public static async handleCodeAction(
-		promptType: keyof typeof ACTION_NAMES,
-		params: Record<string, string | any[]>,
-	): Promise<void> {
+	public static async getInstance(): Promise<ClineProvider | undefined> {
 		let visibleProvider = ClineProvider.getVisibleInstance()
 
 		// If no visible provider, try to show the sidebar view
@@ -207,10 +204,46 @@ export class ClineProvider implements vscode.WebviewViewProvider {
 			return
 		}
 
+		return visibleProvider
+	}
+
+	public static async isActiveTask(): Promise<boolean> {
+		const visibleProvider = await ClineProvider.getInstance()
+		if (!visibleProvider) {
+			return false
+		}
+
+		if (visibleProvider.cline) {
+			return true
+		}
+
+		return false
+	}
+
+	public static async handleCodeAction(
+		command: string,
+		promptType: keyof typeof ACTION_NAMES,
+		params: Record<string, string | any[]>,
+	): Promise<void> {
+		const visibleProvider = await ClineProvider.getInstance()
+		if (!visibleProvider) {
+			return
+		}
+
 		const { customSupportPrompts } = await visibleProvider.getState()
 
 		const prompt = supportPrompt.create(promptType, params, customSupportPrompts)
 
+		if (visibleProvider.cline && command.endsWith("InCurrentTask")) {
+			await visibleProvider.postMessageToWebview({
+				type: "invoke",
+				invoke: "sendMessage",
+				text: prompt,
+			})
+
+			return
+		}
+
 		await visibleProvider.initClineWithTask(prompt)
 	}
 

+ 20 - 4
src/extension.ts

@@ -171,6 +171,7 @@ export function activate(context: vscode.ExtensionContext) {
 		context: vscode.ExtensionContext,
 		command: string,
 		promptType: keyof typeof ACTION_NAMES,
+		inNewTask: boolean,
 		inputPrompt?: string,
 		inputPlaceholder?: string,
 	) => {
@@ -194,14 +195,29 @@ export function activate(context: vscode.ExtensionContext) {
 						...(userInput ? { userInput } : {}),
 					}
 
-					await ClineProvider.handleCodeAction(promptType, params)
+					await ClineProvider.handleCodeAction(command, promptType, params)
 				},
 			),
 		)
 	}
 
+	// Helper function to register both versions of a code action
+	const registerCodeActionPair = (
+		context: vscode.ExtensionContext,
+		baseCommand: string,
+		promptType: keyof typeof ACTION_NAMES,
+		inputPrompt?: string,
+		inputPlaceholder?: string,
+	) => {
+		// Register new task version
+		registerCodeAction(context, baseCommand, promptType, true, inputPrompt, inputPlaceholder)
+
+		// Register current task version
+		registerCodeAction(context, `${baseCommand}InCurrentTask`, promptType, false, inputPrompt, inputPlaceholder)
+	}
+
 	// Register code action commands
-	registerCodeAction(
+	registerCodeActionPair(
 		context,
 		"roo-cline.explainCode",
 		"EXPLAIN",
@@ -209,7 +225,7 @@ export function activate(context: vscode.ExtensionContext) {
 		"E.g. How does the error handling work?",
 	)
 
-	registerCodeAction(
+	registerCodeActionPair(
 		context,
 		"roo-cline.fixCode",
 		"FIX",
@@ -217,7 +233,7 @@ export function activate(context: vscode.ExtensionContext) {
 		"E.g. Maintain backward compatibility",
 	)
 
-	registerCodeAction(
+	registerCodeActionPair(
 		context,
 		"roo-cline.improveCode",
 		"IMPROVE",